diff --git a/compiler/src/prog8/ast/base/Errors.kt b/compiler/src/prog8/ast/base/Errors.kt index 0c2f24978..e18a616c0 100644 --- a/compiler/src/prog8/ast/base/Errors.kt +++ b/compiler/src/prog8/ast/base/Errors.kt @@ -2,7 +2,7 @@ package prog8.ast.base import prog8.ast.expressions.IdentifierReference -class FatalAstException (override var message: String) : Exception(message) +open class FatalAstException (override var message: String) : Exception(message) open class AstException (override var message: String) : Exception(message) diff --git a/compiler/src/prog8/ast/expressions/AstExpressions.kt b/compiler/src/prog8/ast/expressions/AstExpressions.kt index b4d507d19..fe6fbd5c4 100644 --- a/compiler/src/prog8/ast/expressions/AstExpressions.kt +++ b/compiler/src/prog8/ast/expressions/AstExpressions.kt @@ -8,6 +8,7 @@ import prog8.ast.processing.IAstVisitor import prog8.ast.statements.* import prog8.compiler.target.CompilationTarget import prog8.functions.BuiltinFunctions +import prog8.functions.CannotEvaluateException import prog8.functions.NotConstArgumentException import prog8.functions.builtinFunctionReturnType import java.util.* @@ -833,6 +834,10 @@ class FunctionCall(override var target: IdentifierReference, // const-evaluating the builtin function call failed. return null } + catch(x: CannotEvaluateException) { + // const-evaluating the builtin function call failed. + return null + } } override fun toString(): String { diff --git a/compiler/src/prog8/ast/processing/AstWalker.kt b/compiler/src/prog8/ast/processing/AstWalker.kt index 8eee7bcc3..0c1267d1c 100644 --- a/compiler/src/prog8/ast/processing/AstWalker.kt +++ b/compiler/src/prog8/ast/processing/AstWalker.kt @@ -1,9 +1,6 @@ package prog8.ast.processing -import prog8.ast.INameScope -import prog8.ast.Module -import prog8.ast.Node -import prog8.ast.Program +import prog8.ast.* import prog8.ast.base.FatalAstException import prog8.ast.expressions.* import prog8.ast.statements.* @@ -15,7 +12,7 @@ interface IAstModification { class Remove(val node: Node, val parent: Node) : IAstModification { override fun perform() { if(parent is INameScope) { - if (!parent.statements.remove(node)) + if (!parent.statements.remove(node) && parent !is GlobalNamespace) throw FatalAstException("attempt to remove non-existing node $node") } else { throw FatalAstException("parent of a remove modification is not an INameScope") diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index 60cf1205b..651399b41 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -193,7 +193,7 @@ private fun writeAssembly(programAst: Program, errors: ErrorReporter, outputDir: programAst.processAstBeforeAsmGeneration(errors) errors.handle() - printAst(programAst) // TODO weg + // printAst(programAst) val assembly = CompilationTarget.asmGenerator( programAst, diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 9dde118d7..6f13c9e11 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -185,6 +185,7 @@ fun builtinFunctionReturnType(function: String, args: List, program: class NotConstArgumentException: AstException("not a const argument to a built-in function") +class CannotEvaluateException(func:String, msg: String): FatalAstException("cannot evaluate built-in function $func: $msg") private fun oneDoubleArg(args: List, position: Position, program: Program, function: (arg: Double)->Number): NumericLiteralValue { @@ -265,17 +266,22 @@ private fun builtinLen(args: List, position: Position, program: Prog return NumericLiteralValue.optimalInteger((args[0] as ArrayLiteralValue).value.size, position) if(args[0] !is IdentifierReference) throw SyntaxError("len argument should be an identifier, but is ${args[0]}", position) - val target = (args[0] as IdentifierReference).targetVarDecl(program.namespace)!! + val target = (args[0] as IdentifierReference).targetVarDecl(program.namespace) + ?: throw CannotEvaluateException("len", "no target vardecl") return when(target.datatype) { DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> { - arraySize = target.arraysize!!.size()!! + arraySize = target.arraysize?.size() + if(arraySize==null) + throw CannotEvaluateException("len", "arraysize unknown") if(arraySize>256) throw CompilerException("array length exceeds byte limit ${target.position}") NumericLiteralValue.optimalInteger(arraySize, args[0].position) } DataType.ARRAY_F -> { - arraySize = target.arraysize!!.size()!! + arraySize = target.arraysize?.size() + if(arraySize==null) + throw CannotEvaluateException("len", "arraysize unknown") if(arraySize>256) throw CompilerException("array length exceeds byte limit ${target.position}") NumericLiteralValue.optimalInteger(arraySize, args[0].position) diff --git a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt index 2c188864c..71e7c6f3b 100644 --- a/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/compiler/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -289,11 +289,21 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va // was a prefix expression earlier), we recalculate the array's datatype. if(array.type.isKnown) return noModifications - val arrayDt = array.guessDatatype(program) - if(arrayDt.isKnown) { - val newArray = array.cast(arrayDt.typeOrElse(DataType.STRUCT)) - if(newArray!=null && newArray != array) + + // if the array literalvalue is inside an array vardecl, take the type from that + // otherwise infer it from the elements of the array + val vardeclType = (array.parent as? VarDecl)?.datatype + if(vardeclType!=null) { + val newArray = array.cast(vardeclType) + if (newArray != null && newArray != array) return listOf(IAstModification.ReplaceNode(array, newArray, parent)) + } else { + val arrayDt = array.guessDatatype(program) + if (arrayDt.isKnown) { + val newArray = array.cast(arrayDt.typeOrElse(DataType.STRUCT)) + if (newArray != null && newArray != array) + return listOf(IAstModification.ReplaceNode(array, newArray, parent)) + } } return noModifications diff --git a/examples/test.p8 b/examples/test.p8 index 3fabb5a07..2251c7b2b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -17,56 +17,14 @@ blabla: } - sub func(ubyte arg) -> ubyte { - c64.CHROUT(arg) - return sin8(arg) - } - - sub func2(ubyte arg) -> ubyte { - return sin8(arg) - } - sub start() { - ubyte[] a1 = 3 to 20 -; ubyte[18] a2 = 3 to 20 -; float[18] floats2 = 3 to 20 -; ubyte[11] bytes = 22 -; float[11] floats = 3.33 -; -; float[] array = [1, 1+1, -33] -; byte[] array2 = [1, 1+1, -33, -2] + ubyte[] array = [1,2,3] + + ubyte[len(array)] bytesE = 22 ; TODO fix nullpointer error + float[len(array)] floatsE = 3.33 ; TODO fix error - ; float[] array2 = 42 ; TODO nice error - ;ubyte[len(array)] bytesE = 22 ; TODO fix error - ;float[len(array2)] floatsE = 3.33 ; TODO fix error -; const ubyte q = 123 -; byte bbb -; float ff -; -; A = bytes[1] -; ff = array[1] -; A = len(array) -; A = len(array2) -; str sss = "zzz" -; str x = "zxcvzxcv" -; -; ff = 1234.44 + 99.0 -; float ff2 = -3.3333 -; ff=ff2*2 -; A = 123+22+11 -; bbb = -99 -; -; A = q -; A = func(1+q) -; func(1+q) -; -; Y=99 -; A = func2(1+q) -; func2(1+q) -; -; x = @(&sss) } }