for loops can now be over an iterable literal value directly (don't require a variable to hold the iterable)

This commit is contained in:
Irmen de Jong 2019-03-17 23:58:07 +01:00
parent 0820716e7b
commit 1e5b2e0be3
3 changed files with 20 additions and 35 deletions

View File

@ -139,9 +139,6 @@ private class AstChecker(private val namespace: INameScope,
if(forLoop.body.isEmpty())
printWarning("for loop body is empty", forLoop.position)
if(forLoop.iterable is LiteralValue)
checkResult.add(SyntaxError("currently not possible to loop over a literal value directly, define it as a variable instead", forLoop.position)) // todo loop over literals (by creating a generated variable)
if(!forLoop.iterable.isIterable(namespace, heap)) {
checkResult.add(ExpressionError("can only loop over an iterable type", forLoop.position))
} else {

View File

@ -14,23 +14,29 @@ fun Module.checkIdentifiers(heap: HeapValues): MutableMap<String, IStatement> {
val checker = AstIdentifiersChecker(heap)
this.process(checker)
// add any anonymous variables for heap values that are used, and replace literalvalue by identifierref
// add any anonymous variables for heap values that are used,
// and replace an iterable literalvalue by identifierref to new local variable
for (variable in checker.anonymousVariablesFromHeap) {
val scope = variable.first.definingScope()
scope.statements.add(variable.second)
val parent = variable.first.parent
when {
parent is Assignment && parent.value === variable.first -> {
val idref = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position)
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.value = idref
}
parent is IFunctionCall -> {
val parameterPos = parent.arglist.indexOf(variable.first)
val idref = IdentifierReference(listOf("auto_heap_value_${variable.first.heapId}"), variable.first.position)
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.arglist[parameterPos] = idref
}
parent is ForLoop -> {
val idref = IdentifierReference(listOf("$autoHeapValuePrefix${variable.first.heapId}"), variable.first.position)
idref.linkParents(parent)
parent.iterable = idref
}
else -> TODO("replace literalvalue by identifierref: $variable (in $parent)")
}
variable.second.linkParents(scope as Node)
@ -228,13 +234,16 @@ private class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
internal val anonymousVariablesFromHeap = mutableSetOf<Pair<LiteralValue, VarDecl>>()
override fun process(literalValue: LiteralValue): LiteralValue {
if(literalValue.heapId!=null && literalValue.parent !is VarDecl) {
// a literal value that's not declared as a variable, which refers to something on the heap.
// we need to introduce an auto-generated variable for this to be able to refer to the value!
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "auto_heap_value_${literalValue.heapId}", literalValue, literalValue.position)
val variable = VarDecl(VarDeclType.VAR, literalValue.type, false, null, "$autoHeapValuePrefix${literalValue.heapId}", literalValue, literalValue.position)
anonymousVariablesFromHeap.add(Pair(literalValue, variable))
}
return super.process(literalValue)
}
}
private const val autoHeapValuePrefix = "auto_heap_value_"

View File

@ -6,35 +6,14 @@
; @todo see problem in looplabelproblem.p8
sub start() {
uword z2 = sqrt16(50000)
for ubyte i in "hello\n" {
c64.CHROUT(i)
}
c64scr.print_ub(sqrt16(0))
c64.CHROUT('\n')
c64scr.print_ub(sqrt16(200))
c64.CHROUT('\n')
c64scr.print_ub(sqrt16(20000))
c64.CHROUT('\n')
c64scr.print_ub(sqrt16(63333))
c64.CHROUT('\n')
c64scr.print_ub(sqrt16(65535))
c64.CHROUT('\n')
c64.CHROUT('\n')
z2=0
c64scr.print_ub(sqrt16(z2))
c64.CHROUT('\n')
z2=200
c64scr.print_ub(sqrt16(z2))
c64.CHROUT('\n')
z2=20000
c64scr.print_ub(sqrt16(z2))
c64.CHROUT('\n')
z2=63333
c64scr.print_ub(sqrt16(z2))
c64.CHROUT('\n')
z2=65535
c64scr.print_ub(sqrt16(z2))
c64.CHROUT('\n')
A=99
for ubyte j in [1,2,3,4,5] {
c64scr.print_ub(j)
c64.CHROUT('\n')
}
}
}