From 86ff08e8545b0cf158b23f9d8bc7faf41f54fae4 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 1 Feb 2019 00:50:24 +0100 Subject: [PATCH] fix abs() and also try to convert const arguments to the desired datatype of subroutine params --- compiler/res/version.txt | 2 +- compiler/src/prog8/ast/AST.kt | 6 +-- .../src/prog8/functions/BuiltinFunctions.kt | 21 +++++++--- .../src/prog8/optimizing/ConstantFolding.kt | 24 ++++++++++++ examples/test.p8 | 38 +++++++++---------- prog8.iml | 1 + 6 files changed, 62 insertions(+), 30 deletions(-) diff --git a/compiler/res/version.txt b/compiler/res/version.txt index 79df6e299..4450960a9 100644 --- a/compiler/res/version.txt +++ b/compiler/res/version.txt @@ -1 +1 @@ -1.1 (beta) +1.2 (beta) diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 6e58e2023..83d69da8c 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -37,10 +37,10 @@ enum class DataType { fun assignableTo(targetType: DataType) = // what types are assignable to others without loss of precision? when(this) { - UBYTE -> targetType == BYTE || targetType == UBYTE || targetType == UWORD || targetType==WORD || targetType == FLOAT - BYTE -> targetType == BYTE || targetType == UBYTE || targetType == WORD || targetType == FLOAT + UBYTE -> targetType == UBYTE || targetType == UWORD || targetType==WORD || targetType == FLOAT + BYTE -> targetType == BYTE || targetType == UBYTE || targetType == UWORD || targetType==WORD || targetType == FLOAT UWORD -> targetType == UWORD || targetType == FLOAT - WORD -> targetType == WORD || targetType == FLOAT + WORD -> targetType == WORD || targetType==UWORD || targetType == FLOAT FLOAT -> targetType == FLOAT STR -> targetType == STR || targetType==STR_S || targetType == UWORD STR_P -> targetType == STR_P || targetType==STR_PS || targetType == UWORD diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 06fc502c5..c84bed9e8 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -111,7 +111,7 @@ val BuiltinFunctions = mapOf( fun builtinFunctionReturnType(function: String, args: List, namespace: INameScope, heap: HeapValues): DataType? { - fun datatypeFromListArg(arglist: IExpression): DataType { + fun datatypeFromIterableArg(arglist: IExpression): DataType { if(arglist is LiteralValue) { if(arglist.type==DataType.ARRAY_UB || arglist.type==DataType.ARRAY_UW || arglist.type==DataType.ARRAY_F) { val dt = arglist.arrayvalue!!.map {it.resultingDatatype(namespace, heap)} @@ -133,10 +133,10 @@ fun builtinFunctionReturnType(function: String, args: List, namespa DataType.ARRAY_UW -> DataType.UWORD DataType.ARRAY_W -> DataType.WORD DataType.ARRAY_F -> DataType.FLOAT - null -> throw FatalAstException("function requires one argument which is an arrayspec $function") + null -> throw FatalAstException("function '$function' requires one argument which is an iterable") } } - throw FatalAstException("function requires one argument which is an arrayspec $function") + throw FatalAstException("function '$function' requires one argument which is an iterable") } val func = BuiltinFunctions.getValue(function) @@ -145,8 +145,17 @@ fun builtinFunctionReturnType(function: String, args: List, namespa // function has return values, but the return type depends on the arguments return when (function) { - "max", "min", "abs" -> { - val dt = datatypeFromListArg(args.single()) + "abs" -> { + val dt = args.single().resultingDatatype(namespace, heap) + when(dt) { + DataType.UBYTE, DataType.BYTE -> DataType.UBYTE + DataType.UWORD, DataType.WORD -> DataType.UWORD + DataType.FLOAT -> DataType.FLOAT + else -> throw FatalAstException("weird datatype passed to abs $dt") + } + } + "max", "min" -> { + val dt = datatypeFromIterableArg(args.single()) when(dt) { DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, DataType.FLOAT -> dt DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UBYTE @@ -158,7 +167,7 @@ fun builtinFunctionReturnType(function: String, args: List, namespa } } "sum" -> { - val dt=datatypeFromListArg(args.single()) + val dt=datatypeFromIterableArg(args.single()) when(dt) { DataType.UBYTE, DataType.UWORD -> DataType.UWORD DataType.BYTE, DataType.WORD -> DataType.WORD diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 0a71f8cf7..cb8ef3e14 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -142,6 +142,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV override fun process(functionCall: FunctionCall): IExpression { return try { super.process(functionCall) + typeCastConstArguments(functionCall) functionCall.constValue(namespace, heap) ?: functionCall } catch (ax: AstException) { addError(ax) @@ -149,6 +150,29 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV } } + override fun process(functionCallStatement: FunctionCallStatement): IStatement { + super.process(functionCallStatement) + typeCastConstArguments(functionCallStatement) + return functionCallStatement + } + + private fun typeCastConstArguments(functionCall: IFunctionCall) { + val subroutine = functionCall.target.targetStatement(namespace) as? Subroutine + if(subroutine!=null) { + // if types differ, try to typecast constant arguments to the function call to the desired data type of the parameter + for(arg in functionCall.arglist.withIndex().zip(subroutine.parameters)) { + val expectedDt = arg.second.type + val argConst = arg.first.value.constValue(namespace, heap) + if(argConst!=null && argConst.type!=expectedDt) { + val convertedValue = argConst.intoDatatype(expectedDt) + if(convertedValue!=null) + functionCall.arglist[arg.first.index] = convertedValue + } + } + } + } + + /** * Try to process a unary prefix expression. * Compile-time constant sub expressions will be evaluated on the spot. diff --git a/examples/test.p8 b/examples/test.p8 index e25e1f822..21a5f1a22 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,32 +1,30 @@ %import c64utils -%import c64flt -%option enable_floats ~ main { sub start() { - byte[10] ba = [1,2,3,4,5,6,7,8,9,-88] - ubyte[10] uba = [1,2,3,4,5,6,7,8,9,10] + foo(1) + foo2(20) + bar(2,3) + baz(3333) + baz(-3333) - c64scr.print_w(sum(ba)) - c64.CHROUT('\n') - c64scr.print_uw(sum(uba)) - c64.CHROUT('\n') - - c64scr.print_ub(X) - c64.CHROUT('\n') - - -; c64scr.print_w(w2) -; c64.CHROUT('\n') -; c64scr.print_w(w3) -; c64.CHROUT('\n') -; c64scr.print_uw(uw2) -; c64.CHROUT('\n') } + sub foo(ubyte arg) { + A=arg + } - ; @todo float & float -> nice error instead of crash + sub foo2(byte arg) { + A=33 + } + sub bar(ubyte arg1, ubyte arg2) { + A=arg1 + } + + sub baz(word arg) { + A=lsb(arg) + } } diff --git a/prog8.iml b/prog8.iml index e187d18c5..e5e2d011e 100644 --- a/prog8.iml +++ b/prog8.iml @@ -16,5 +16,6 @@ + \ No newline at end of file