mirror of
https://github.com/irmen/prog8.git
synced 2025-02-06 01:30:23 +00:00
for loops over iterables now allow different numeric loopvar types
This commit is contained in:
parent
b01deb2170
commit
9ddda9fcf7
@ -46,7 +46,7 @@
|
||||
rotate_vertices(irq.global_time as float / 30.0)
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
draw_edges() ; @todo doesn't return from the loop...
|
||||
draw_edges()
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
@ -93,7 +93,7 @@
|
||||
}
|
||||
|
||||
; draw all edges of the object
|
||||
for uword edge in edges { ; @todo invalid loop code generated? (loop doesn't end?)
|
||||
for uword edge in edges {
|
||||
|
||||
ubyte e_from = msb(edge)
|
||||
ubyte e_to = lsb(edge)
|
||||
|
58
compiler/examples/forloops.p8
Normal file
58
compiler/examples/forloops.p8
Normal file
@ -0,0 +1,58 @@
|
||||
%import c64utils
|
||||
|
||||
~ main {
|
||||
|
||||
ubyte[3] ubarray = [11,55,222]
|
||||
byte[3] barray = [-11,-22,-33]
|
||||
uword[3] uwarray = [111,2222,55555]
|
||||
word[3] warray = [-111,-222,-555]
|
||||
float[3] farray = [1.11, 2.22, -3.33]
|
||||
str text = "hello\n"
|
||||
|
||||
sub start() {
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
c64scr.print("loop str\n")
|
||||
for ubyte c in text {
|
||||
c64scr.print_ub(c)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop ub\n")
|
||||
for ubyte ub in ubarray{
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop b\n")
|
||||
for byte b in barray {
|
||||
c64scr.print_b(b)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop uw\n")
|
||||
for uword uw in uwarray {
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop w\n")
|
||||
for word w in warray {
|
||||
c64scr.print_w(w)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop f\n")
|
||||
for float f in farray {
|
||||
c64flt.print_f(f)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
|
||||
ending:
|
||||
c64scr.print("\nending\n")
|
||||
c64scr.print_ub(X)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
%import c64utils
|
||||
%option enable_floats
|
||||
|
||||
~ main {
|
||||
|
||||
@ -6,6 +7,7 @@
|
||||
byte[3] barray = [-11,-22,-33]
|
||||
uword[3] uwarray = [111,2222,55555]
|
||||
word[3] warray = [-111,-222,-555]
|
||||
float[3] farray = [1.11, 2.22, -3.33]
|
||||
str text = "hello\n"
|
||||
|
||||
sub start() {
|
||||
@ -14,33 +16,41 @@
|
||||
|
||||
c64scr.print("loop str\n")
|
||||
for ubyte c in text {
|
||||
c64scr.print(" c ")
|
||||
c64scr.print_ub(c)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("loop ub\n")
|
||||
c64scr.print("\nloop ub\n")
|
||||
for ubyte ub in ubarray{
|
||||
c64scr.print(" ub ")
|
||||
c64scr.print_ub(ub)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
; c64scr.print("loop b\n") ; @todo allow signed loopvars
|
||||
; for byte b in barray { ; @todo loop doesn't end because of register clobbering??
|
||||
; c64scr.print(" b ")
|
||||
; c64scr.print_b(b)
|
||||
; c64.CHROUT('\n')
|
||||
; }
|
||||
c64scr.print("\nloop b\n")
|
||||
for byte b in barray {
|
||||
c64scr.print_b(b)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
errorloop:
|
||||
c64scr.print("loop uw\n")
|
||||
for uword uw in uwarray { ; @todo loop doesn't end because of register clobbering
|
||||
c64scr.print(" uw ")
|
||||
c64scr.print("\nloop uw\n")
|
||||
for uword uw in uwarray {
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop w\n")
|
||||
for word w in warray {
|
||||
c64scr.print_w(w)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64scr.print("\nloop f\n")
|
||||
for float f in farray {
|
||||
c64flt.print_f(f)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
|
||||
ending:
|
||||
c64scr.print("\nending\n")
|
||||
c64scr.print_ub(X)
|
||||
|
@ -89,6 +89,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
is VarDecl->true
|
||||
is InlineAssembly->true
|
||||
is INameScope->true
|
||||
is VariableInitializationAssignment->true
|
||||
else->false
|
||||
}
|
||||
if(!ok) {
|
||||
@ -154,15 +155,27 @@ class AstChecker(private val namespace: INameScope,
|
||||
when (loopvar.datatype) {
|
||||
DataType.UBYTE -> {
|
||||
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.ARRAY_UB && iterableDt !in StringDatatypes)
|
||||
checkResult.add(ExpressionError("byte loop variable can only loop over bytes", forLoop.position))
|
||||
checkResult.add(ExpressionError("ubyte loop variable can only loop over unsigned bytes or strings", forLoop.position))
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
if(iterableDt!=DataType.UBYTE && iterableDt!=DataType.UWORD && iterableDt !in StringDatatypes &&
|
||||
iterableDt !=DataType.ARRAY_UB && iterableDt!=DataType.ARRAY_UW)
|
||||
checkResult.add(ExpressionError("uword loop variable can only loop over unsigned bytes, words or strings", forLoop.position))
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
if(iterableDt!=DataType.BYTE && iterableDt!=DataType.ARRAY_B)
|
||||
checkResult.add(ExpressionError("byte loop variable can only loop over bytes", forLoop.position))
|
||||
}
|
||||
DataType.WORD -> {
|
||||
if(iterableDt!=DataType.BYTE && iterableDt!=DataType.WORD &&
|
||||
iterableDt !=DataType.ARRAY_B && iterableDt!=DataType.ARRAY_W)
|
||||
checkResult.add(ExpressionError("word loop variable can only loop over bytes or words", forLoop.position))
|
||||
}
|
||||
// there's no support for a floating-point loop variable
|
||||
else -> checkResult.add(ExpressionError("loop variable must be byte or word type", forLoop.position))
|
||||
DataType.FLOAT -> {
|
||||
if(iterableDt!=DataType.FLOAT && iterableDt != DataType.ARRAY_F)
|
||||
checkResult.add(ExpressionError("float loop variable can only loop over floats", forLoop.position))
|
||||
}
|
||||
else -> checkResult.add(ExpressionError("loop variable must be numeric type", forLoop.position))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -477,6 +490,13 @@ class AstChecker(private val namespace: INameScope,
|
||||
err("const modifier can only be used on numeric types (byte, word, float)")
|
||||
}
|
||||
|
||||
// FLOATS
|
||||
// @todo move floating point routines from c64utils into separately included file, then re-enable this check
|
||||
// if(!compilerOptions.floats && decl.datatype==DataType.FLOAT && decl.type!=VarDeclType.MEMORY) {
|
||||
// checkResult.add(SyntaxError("floating point used, but that is not enabled via options", decl.position))
|
||||
// }
|
||||
|
||||
|
||||
when(decl.type) {
|
||||
VarDeclType.VAR, VarDeclType.CONST -> {
|
||||
if (decl.value == null) {
|
||||
@ -619,7 +639,7 @@ class AstChecker(private val namespace: INameScope,
|
||||
|
||||
override fun process(literalValue: LiteralValue): LiteralValue {
|
||||
if(!compilerOptions.floats && literalValue.type==DataType.FLOAT) {
|
||||
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
|
||||
checkResult.add(SyntaxError("floating point used, but that is not enabled via options", literalValue.position))
|
||||
}
|
||||
val arrayspec =
|
||||
if(literalValue.isArray)
|
||||
|
@ -162,23 +162,21 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
||||
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
|
||||
} else if(forLoop.loopVar!=null) {
|
||||
val varName = forLoop.loopVar.nameInSource.last()
|
||||
when (forLoop.decltype) {
|
||||
DataType.UBYTE, DataType.UWORD -> {
|
||||
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
|
||||
if(existing==null) {
|
||||
// create the local scoped for loop variable itself
|
||||
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, forLoop.loopVar.position)
|
||||
vardecl.linkParents(forLoop.body)
|
||||
forLoop.body.statements.add(0, vardecl)
|
||||
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
||||
}
|
||||
}
|
||||
DataType.BYTE, DataType.WORD -> {
|
||||
checkResult.add(SyntaxError("loop variables can only be unsigned byte or unsigned word", forLoop.position)) // TODO allow signed loopvars
|
||||
}
|
||||
null -> {}
|
||||
else -> checkResult.add(SyntaxError("loop variables can only be a byte or word", forLoop.position))
|
||||
if(forLoop.iterable is RangeExpr && forLoop.decltype!=null && forLoop.decltype !in setOf(DataType.UBYTE, DataType.UWORD)) {
|
||||
checkResult.add(SyntaxError("loop variables over a numeric range can only be ubyte or uword", forLoop.position)) // TODO allow signed range loopvars
|
||||
}
|
||||
if(forLoop.decltype!=null) {
|
||||
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(forLoop.loopVar.nameInSource, forLoop.body.statements.first())
|
||||
if(existing==null) {
|
||||
// create the local scoped for loop variable itself
|
||||
val vardecl = VarDecl(VarDeclType.VAR, forLoop.decltype, null, varName, null, forLoop.loopVar.position)
|
||||
vardecl.linkParents(forLoop.body)
|
||||
forLoop.body.statements.add(0, vardecl)
|
||||
forLoop.loopVar.parent = forLoop.body // loopvar 'is defined in the body'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(forLoop.iterable !is RangeExpr) {
|
||||
val existing = if(forLoop.body.isEmpty()) null else forLoop.body.lookup(listOf(ForLoop.iteratorLoopcounterVarname), forLoop.body.statements.first())
|
||||
if(existing==null) {
|
||||
|
@ -1603,21 +1603,18 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
} else {
|
||||
// ok, must be a literalvalue
|
||||
val iterableValue: LiteralValue
|
||||
when {
|
||||
loop.iterable is LiteralValue -> {
|
||||
TODO("loop over literal value (move literal to auto-generated heap variable)")
|
||||
}
|
||||
loop.iterable is IdentifierReference -> {
|
||||
val idRef = loop.iterable as IdentifierReference
|
||||
val vardecl = (idRef.targetStatement(namespace) as VarDecl)
|
||||
iterableValue = vardecl.value as LiteralValue
|
||||
val iterableValue = vardecl.value as LiteralValue
|
||||
if(!iterableValue.isIterable(namespace, heap))
|
||||
throw CompilerException("loop over something that isn't iterable ${loop.iterable}")
|
||||
translateForOverIterableVar(loop, loopVarDt, iterableValue)
|
||||
}
|
||||
loop.iterable is LiteralValue -> throw CompilerException("literal value in loop must have been moved to heap already $loop")
|
||||
else -> throw CompilerException("loopvar is something strange ${loop.iterable}")
|
||||
}
|
||||
translateForOverIterableVar(loop, loopVarDt, iterableValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -413,6 +413,7 @@ _done rts
|
||||
|
||||
~ c64flt {
|
||||
; ---- this block contains C-64 floating point related functions ----
|
||||
; @todo move to c64fp.p8 and enable float-checkin astchecker.process(decl: VarDecl) again
|
||||
|
||||
|
||||
asmsub FREADS32 () -> clobbers(A,X,Y) -> () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user