diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 53fe7550a..513f9294b 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -191,20 +191,21 @@ private fun oneDoubleArg(args: List, position: Position, program: P if(args.size!=1) throw SyntaxError("built-in function requires one floating point argument", position) val constval = args[0].constValue(program) ?: throw NotConstArgumentException() - if(constval.type!= DataType.FLOAT) - throw SyntaxError("built-in function requires one floating point argument", position) - - val float = constval.asNumericValue?.toDouble()!! + val float = getFloatArg(constval, args[0].position) return numericLiteral(function(float), args[0].position) } +private fun getFloatArg(v: LiteralValue, position: Position): Double { + val nv = v.asNumericValue ?: throw SyntaxError("numerical argument required", position) + return nv.toDouble() +} + private fun oneDoubleArgOutputWord(args: List, position: Position, program: Program, function: (arg: Double)->Number): LiteralValue { if(args.size!=1) throw SyntaxError("built-in function requires one floating point argument", position) val constval = args[0].constValue(program) ?: throw NotConstArgumentException() - if(constval.type!= DataType.FLOAT) - throw SyntaxError("built-in function requires one floating point argument", position) - return LiteralValue(DataType.WORD, wordvalue = function(constval.asNumericValue!!.toDouble()).toInt(), position = args[0].position) + val float = getFloatArg(constval, args[0].position) + return LiteralValue(DataType.WORD, wordvalue = function(float).toInt(), position = args[0].position) } private fun oneIntArgOutputInt(args: List, position: Position, program: Program, function: (arg: Int)->Number): LiteralValue { diff --git a/compiler/src/prog8/vm/astvm/Expressions.kt b/compiler/src/prog8/vm/astvm/Expressions.kt index 639deb20b..1626d9b74 100644 --- a/compiler/src/prog8/vm/astvm/Expressions.kt +++ b/compiler/src/prog8/vm/astvm/Expressions.kt @@ -32,7 +32,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { "~" -> evaluate(expr.expression, ctx).inv() "not" -> evaluate(expr.expression, ctx).not() // unary '+' should have been optimized away - else -> TODO("prefixexpr ${expr.operator}") + else -> throw VmExecutionException("unsupported prefix operator "+expr.operator) } } is BinaryExpression -> { @@ -67,7 +67,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { "and" -> left.and(right) "or" -> left.or(right) "xor" -> left.xor(right) - else -> TODO("binexpression operator ${expr.operator}") + else -> throw VmExecutionException("unsupported operator "+expr.operator) } } is ArrayIndexedExpression -> { @@ -108,11 +108,11 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { DataType.FLOAT -> RuntimeValue(DataType.FLOAT, ctx.mem.getFloat(address)) DataType.STR -> RuntimeValue(DataType.STR, str = ctx.mem.getString(address)) DataType.STR_S -> RuntimeValue(DataType.STR_S, str = ctx.mem.getScreencodeString(address)) - else -> TODO("memvar $variable") + else -> throw VmExecutionException("unexpected datatype $variable") } } } else - TODO("weird ref $variable") + throw VmExecutionException("weird identifier reference $variable") } is FunctionCall -> { val sub = expr.target.targetStatement(ctx.program.namespace) @@ -130,7 +130,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { result } else -> { - TODO("call expr function ${expr.target}") + throw VmExecutionException("unimplemented function call target $sub") } } } @@ -156,7 +156,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue { return RuntimeValueRange(expr.inferType(ctx.program)!!, range) } else -> { - TODO("implement eval $expr") + throw VmExecutionException("unimplemented expression node $expr") } } } diff --git a/compiler/src/prog8/vm/astvm/VariablesCreator.kt b/compiler/src/prog8/vm/astvm/VariablesCreator.kt index 848fc9314..92127c0c9 100644 --- a/compiler/src/prog8/vm/astvm/VariablesCreator.kt +++ b/compiler/src/prog8/vm/astvm/VariablesCreator.kt @@ -32,33 +32,13 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v override fun process(decl: VarDecl): IStatement { when(decl.type) { + // we can assume the value in the vardecl already has been converted into a constant LiteralValue here. VarDeclType.VAR -> { - val value = when (decl.datatype) { - in NumericDatatypes -> { - if(decl.value !is LiteralValue) { - TODO("evaluate vardecl expression $decl") - //RuntimeValue(decl.datatype, num = evaluate(decl.value!!, program, runtimeVariables, executeSubroutine).numericValue()) - } else { - RuntimeValue.from(decl.value as LiteralValue, heap) - } - } - in StringDatatypes -> { - RuntimeValue.from(decl.value as LiteralValue, heap) - } - in ArrayDatatypes -> { - RuntimeValue.from(decl.value as LiteralValue, heap) - } - else -> throw VmExecutionException("weird type ${decl.datatype}") - } + val value = RuntimeValue.from(decl.value as LiteralValue, heap) runtimeVariables.define(decl.definingScope(), decl.name, value) } VarDeclType.MEMORY -> { - if(decl.value !is LiteralValue) { - TODO("evaluate vardecl expression $decl") - //RuntimeValue(decl.datatype, num = evaluate(decl.value!!, program, runtimeVariables, executeSubroutine).numericValue()) - } else { - runtimeVariables.defineMemory(decl.definingScope(), decl.name, (decl.value as LiteralValue).asIntegerValue!!) - } + runtimeVariables.defineMemory(decl.definingScope(), decl.name, (decl.value as LiteralValue).asIntegerValue!!) } VarDeclType.CONST -> { // consts should have been const-folded away diff --git a/examples/test.p8 b/examples/test.p8 index 182b3087f..d4f9b01d4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,58 +4,32 @@ ~ main { + uword ww = 33 ; @todo error? or should it be 33? + uword w2 = foo() ; @todo same issue + + sub start() { - c64.TIME_HI = 22 - c64.TIME_MID = 33 - c64.TIME_LO = 44 + uword xw = 33 ; @todo error? or should it be 33? + uword x2 = foo() ; @todo same issue - loop: - ubyte hi = c64.TIME_HI - ubyte mid = c64.TIME_MID - ubyte lo = c64.TIME_LO + c64scr.print_uw(ww) + c64.CHROUT('\n') + c64scr.print_uw(w2) + c64.CHROUT('\n') + c64scr.print_uw(xw) + c64.CHROUT('\n') + c64scr.print_uw(x2) + c64.CHROUT('\n') - c64scr.plot(0,0) - c64scr.print_ub0(hi) - c64scr.print(" \n") - c64scr.print_ub0(mid) - c64scr.print(" \n") - c64scr.print_ub0(lo) - c64scr.print(" \n") - - uword x = mkword(c64.TIME_LO, c64.TIME_MID) - c64scr.print_uw(x) - c64scr.print(" \n") - - float clock_seconds_f = ((mkword(c64.TIME_LO, c64.TIME_MID) as float) + (c64.TIME_HI as float)*65536.0) / 60.0 - c64flt.print_f(clock_seconds_f) - c64scr.print(" \n") - float hours_f = floor(clock_seconds_f / 3600.0) - clock_seconds_f -= hours_f*3600.0 - float minutes_f = floor(clock_seconds_f / 60.0) - clock_seconds_f = floor(clock_seconds_f - minutes_f * 60.0) - - c64flt.print_f(hours_f) - c64.CHROUT(':') - c64flt.print_f(minutes_f) - c64.CHROUT(':') - c64flt.print_f(clock_seconds_f) - c64scr.print(" \n") - - ubyte hours = hours_f as ubyte - ubyte minutes = minutes_f as ubyte - ubyte seconds = clock_seconds_f as ubyte - c64scr.print_ub(hours) - c64.CHROUT(':') - c64scr.print_ub(minutes) - c64.CHROUT(':') - c64scr.print_ub(seconds) - c64scr.print(" \n") - - goto loop + @($d020) = 34 } + sub foo() -> uword { + A=4 + return rndw()+A + } ; for ubyte y in 0 to 3 { ; for ubyte x in 0 to 10 {