diff --git a/compiler/res/version.txt b/compiler/res/version.txt index 37c2d9960..833e069fa 100644 --- a/compiler/res/version.txt +++ b/compiler/res/version.txt @@ -1 +1 @@ -5.4 +5.5-SNAPSHOT diff --git a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt index fd6edc94b..ba93ee4a6 100644 --- a/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt +++ b/compiler/src/prog8/optimizer/ConstantIdentifierReplacer.kt @@ -13,18 +13,23 @@ import prog8.ast.statements.VarDecl import prog8.compiler.target.CompilationTarget // Fix up the literal value's type to match that of the vardecl -internal class VarConstantValueTypeAdjuster(private val program: Program) : AstWalker() { +internal class VarConstantValueTypeAdjuster(private val program: Program, private val errors: ErrorReporter) : AstWalker() { private val noModifications = emptyList() override fun after(decl: VarDecl, parent: Node): Iterable { - val declConstValue = decl.value?.constValue(program) - if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST) + try { + val declConstValue = decl.value?.constValue(program) + if(declConstValue!=null && (decl.type==VarDeclType.VAR || decl.type==VarDeclType.CONST) && !declConstValue.inferType(program).istype(decl.datatype)) { - // cast the numeric literal to the appropriate datatype of the variable - val cast = declConstValue.cast(decl.datatype) - if(cast.isValid) - return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl)) + // cast the numeric literal to the appropriate datatype of the variable + val cast = declConstValue.cast(decl.datatype) + if(cast.isValid) + return listOf(IAstModification.ReplaceNode(decl.value!!, cast.valueOrZero(), decl)) + } + } catch (x: UndefinedSymbolError) { + errors.err(x.message, x.position) } + return noModifications } } @@ -47,11 +52,22 @@ internal class ConstantIdentifierReplacer(private val program: Program, private if(forloop!=null && identifier===forloop.loopVar) return noModifications - val cval = identifier.constValue(program) ?: return noModifications - return when (cval.type) { - in NumericDatatypes -> listOf(IAstModification.ReplaceNode(identifier, NumericLiteralValue(cval.type, cval.number, identifier.position), identifier.parent)) - in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant") - else -> noModifications + try { + val cval = identifier.constValue(program) ?: return noModifications + return when (cval.type) { + in NumericDatatypes -> listOf( + IAstModification.ReplaceNode( + identifier, + NumericLiteralValue(cval.type, cval.number, identifier.position), + identifier.parent + ) + ) + in PassByReferenceDatatypes -> throw FatalAstException("pass-by-reference type should not be considered a constant") + else -> noModifications + } + } catch (x: UndefinedSymbolError) { + errors.err(x.message, x.position) + return noModifications } } @@ -78,11 +94,16 @@ internal class ConstantIdentifierReplacer(private val program: Program, private } } else if(arraysize.constIndex()==null) { // see if we can calculate the size from other fields - val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program) - if(cval!=null) { - arraysize.indexVar = null - arraysize.origExpression = null - arraysize.indexNum = cval + try { + val cval = arraysize.indexVar?.constValue(program) ?: arraysize.origExpression?.constValue(program) + if (cval != null) { + arraysize.indexVar = null + arraysize.origExpression = null + arraysize.indexNum = cval + } + } catch (x: UndefinedSymbolError) { + errors.err(x.message, x.position) + return noModifications } } } diff --git a/compiler/src/prog8/optimizer/Extensions.kt b/compiler/src/prog8/optimizer/Extensions.kt index 562fd1b56..307e21370 100644 --- a/compiler/src/prog8/optimizer/Extensions.kt +++ b/compiler/src/prog8/optimizer/Extensions.kt @@ -5,7 +5,7 @@ import prog8.ast.base.ErrorReporter internal fun Program.constantFold(errors: ErrorReporter) { - val valuetypefixer = VarConstantValueTypeAdjuster(this) + val valuetypefixer = VarConstantValueTypeAdjuster(this, errors) valuetypefixer.visit(this) if(errors.isEmpty()) { valuetypefixer.applyModifications() diff --git a/docs/source/todo.rst b/docs/source/todo.rst index ad1fbb40c..4f1e0fe43 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,7 +2,6 @@ TODO ==== -- see if we can group some errors together for instance the (now single) errors about unidentified symbols - Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines. - hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine) - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' diff --git a/examples/test.p8 b/examples/test.p8 index bc044e4e6..33064d00b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,7 +8,14 @@ main { sub start () { + float x = floo() + floats.print_f(x2) + test_stack.test2() + blerp=foobar+xxx + } - test_stack.test() + sub floo() -> float { + float fl = 1.1 + return flxxx * 2 } }