diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index cf92af7dc..e9f00a60a 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -9,12 +9,81 @@ sub start() { str_p spvar = "spvar" str_s ssvar = "ssvar" str_ps spsvar = "spsvar" - byte[2,3] matrixvar1 - byte[2,3] matrixvar2 = 2 + byte[2,3] matrixvar byte[5] barrayvar - byte[5] barrayvar1 = 44 word[5] warrayvar - word[5] warrayvar1 = 22 + + + set_carry() + clear_carry() + set_irqd() + clear_irqd() + + rol(bvar) + rol(wvar) + rol(fvar) + rol(svar) + rol(spvar) + rol(ssvar) + rol(spsvar) + rol(matrixvar) + rol(barrayvar) + rol(warrayvar) + + rol2(bvar) + rol2(wvar) + rol2(fvar) + rol2(svar) + rol2(spvar) + rol2(ssvar) + rol2(spsvar) + rol2(matrixvar) + rol2(barrayvar) + rol2(warrayvar) + + ror(bvar) + ror(wvar) + ror(fvar) + ror(svar) + ror(spvar) + ror(ssvar) + ror(spsvar) + ror(matrixvar) + ror(barrayvar) + ror(warrayvar) + + ror2(bvar) + ror2(wvar) + ror2(fvar) + ror2(svar) + ror2(spvar) + ror2(ssvar) + ror2(spsvar) + ror2(matrixvar) + ror2(barrayvar) + ror2(warrayvar) + + lsl(bvar) + lsl(wvar) + lsl(fvar) + lsl(svar) + lsl(spvar) + lsl(ssvar) + lsl(spsvar) + lsl(matrixvar) + lsl(barrayvar) + lsl(warrayvar) + + lsr(bvar) + lsr(wvar) + lsr(fvar) + lsr(svar) + lsr(spvar) + lsr(ssvar) + lsr(spsvar) + lsr(matrixvar) + lsr(barrayvar) + lsr(warrayvar) } } diff --git a/compiler/src/prog8/ast/AST.kt b/compiler/src/prog8/ast/AST.kt index 16b0c3767..37f618452 100644 --- a/compiler/src/prog8/ast/AST.kt +++ b/compiler/src/prog8/ast/AST.kt @@ -1152,11 +1152,11 @@ class FunctionCall(override var target: IdentifierReference, var resultValue: LiteralValue? = null val func = BuiltinFunctions[target.nameInSource[0]] if(func!=null) { - val exprfunc = func.expressionFunc + val exprfunc = func.constExpressionFunc if(exprfunc!=null) resultValue = exprfunc(arglist, position, namespace, heap) - else if(func.returnvalues.isEmpty()) - throw ExpressionError("builtin function ${target.nameInSource[0]} can't be used in expressions because it doesn't return a value", position) + else if(func.returntype==null) + throw ExpressionError("builtin function ${target.nameInSource[0]} can't be used here because it doesn't return a value", position) } if(withDatatypeCheck) { diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index 0bae7bb59..69e9caa4a 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -5,87 +5,64 @@ import prog8.compiler.HeapValues import kotlin.math.log2 -class FunctionSignature(val pure: Boolean, // does it have side effects? - val parameters: List, - val paramTypesVariable: Boolean, - val returnvalues: List, - val type: DataType?, - val expressionFunc: ((args: List, position: Position, namespace: INameScope, heap: HeapValues) -> LiteralValue)?) { - companion object { - private val dummyPos = Position("dummy", 0, 0, 0) - fun sig(pure: Boolean, - args: List>, - hasReturnValue: Boolean, - type: DataType?, - expressionFunc: ((args: List, position: Position, namespace: INameScope, heap: HeapValues) -> LiteralValue)? = null - ) : FunctionSignature { - if(!hasReturnValue && expressionFunc!=null) - throw IllegalArgumentException("can't have expression func when hasReturnValue is false") - return FunctionSignature(pure, - args.map { SubroutineParameter(it.first, it.second ?: DataType.BYTE, dummyPos) }, - args.any { it.second==null }, - if(hasReturnValue && type!=null) - listOf(type) - else - emptyList(), - type, - expressionFunc - ) - } - } -} +class BuiltinFunctionParam(val name: String, possibleDatatypes: List) + +class FunctionSignature(val pure: Boolean, // does it have side effects? + val parameters: List, + val returntype: DataType?, + val constExpressionFunc: ((args: List, position: Position, namespace: INameScope, heap: HeapValues) -> LiteralValue)? = null) val BuiltinFunctions = mapOf( - "set_carry" to FunctionSignature.sig(false, emptyList(), false, null), - "clear_carry" to FunctionSignature.sig(false, emptyList(), false, null), - "set_irqd" to FunctionSignature.sig(false, emptyList(), false, null), - "clear_irqd" to FunctionSignature.sig(false, emptyList(), false, null), - "rol" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "ror" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "rol2" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "ror2" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "lsl" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "lsr" to FunctionSignature.sig(false, listOf(Pair("item", null)), false, null), - "sin" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) }, - "cos" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) }, - "acos" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) }, - "asin" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::asin) }, - "tan" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::tan) }, - "atan" to FunctionSignature.sig(true, listOf(Pair("rads", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::atan) }, - "rnd" to FunctionSignature.sig(true, emptyList(), true, DataType.BYTE), - "rndw" to FunctionSignature.sig(true, emptyList(), true, DataType.WORD), - "rndf" to FunctionSignature.sig(true, emptyList(), true, DataType.FLOAT), - "ln" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log) }, - "log2" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, ::log2) }, - "log10" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log10) }, - "sqrt" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) }, - "rad" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) }, - "deg" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) }, - "avg" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, DataType.FLOAT, ::builtinAvg), - "abs" to FunctionSignature.sig(true, listOf(Pair("value", null)), true, null, ::builtinAbs), // type depends on arg - "round" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::round) }, // type depends on arg - "floor" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::floor) }, // type depends on arg - "ceil" to FunctionSignature.sig(true, listOf(Pair("value", DataType.FLOAT)), true, null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::ceil) }, // type depends on arg - "max" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args - "min" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args - "sum" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args - "len" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, null, ::builtinLen), // type depends on args - "any" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }}, - "all" to FunctionSignature.sig(true, listOf(Pair("values", null)), true, DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }}, - "lsb" to FunctionSignature.sig(true, listOf(Pair("value", DataType.WORD)), true, DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }}, - "msb" to FunctionSignature.sig(true, listOf(Pair("value", DataType.WORD)), true, DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}}, - "flt" to FunctionSignature.sig(true, listOf(Pair("value", null)), true, DataType.FLOAT, ::builtinFlt), - "_vm_write_memchr" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_write_memstr" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_write_num" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_write_char" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_write_str" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_input_str" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_gfx_clearscr" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_gfx_pixel" to FunctionSignature.sig(false, emptyList(), false, null), - "_vm_gfx_text" to FunctionSignature.sig(false, emptyList(), false, null) + "rol" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "ror" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "rol2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "ror2" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", listOf(DataType.BYTE, DataType.WORD))), null), + "sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) }, + "cos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::cos) }, + "acos" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::acos) }, + "asin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::asin) }, + "tan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::tan) }, + "atan" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::atan) }, + "ln" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log) }, + "log2" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, ::log2) }, + "log10" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::log10) }, + "sqrt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sqrt) }, + "rad" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toRadians) }, + "deg" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::toDegrees) }, + "avg" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), DataType.FLOAT, ::builtinAvg), + "abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), DataType.FLOAT, ::builtinAbs), + "round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::round) }, // type depends on arg + "floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::floor) }, // type depends on arg + "ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.FLOAT))), null) { a, p, n, h -> oneDoubleArgOutputInt(a, p, n, h, Math::ceil) }, // type depends on arg + "max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args + "min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args + "sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args + "len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS, DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), null, ::builtinLen), // type depends on args + "any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }}, + "all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", listOf(DataType.ARRAY, DataType.ARRAY_W, DataType.MATRIX))), DataType.BYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }}, + "lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.WORD))), DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }}, + "msb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.WORD))), DataType.BYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x ushr 8 and 255}}, + "flt" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", listOf(DataType.BYTE, DataType.WORD))), DataType.FLOAT, ::builtinFlt), + "rnd" to FunctionSignature(true, emptyList(), DataType.BYTE), + "rndw" to FunctionSignature(true, emptyList(), DataType.WORD), + "rndf" to FunctionSignature(true, emptyList(), DataType.FLOAT), + "set_carry" to FunctionSignature(false, emptyList(), null), + "clear_carry" to FunctionSignature(false, emptyList(), null), + "set_irqd" to FunctionSignature(false, emptyList(), null), + "clear_irqd" to FunctionSignature(false, emptyList(), null), + "_vm_write_memchr" to FunctionSignature(false, emptyList(), null), + "_vm_write_memstr" to FunctionSignature(false, emptyList(), null), + "_vm_write_num" to FunctionSignature(false, emptyList(), null), + "_vm_write_char" to FunctionSignature(false, emptyList(), null), + "_vm_write_str" to FunctionSignature(false, emptyList(), null), + "_vm_input_str" to FunctionSignature(false, emptyList(), null), + "_vm_gfx_clearscr" to FunctionSignature(false, emptyList(), null), + "_vm_gfx_pixel" to FunctionSignature(false, emptyList(), null), + "_vm_gfx_text" to FunctionSignature(false, emptyList(), null) ) @@ -127,14 +104,11 @@ fun builtinFunctionReturnType(function: String, args: List, namespa } val func = BuiltinFunctions[function]!! - if(func.returnvalues.isEmpty()) - return null - if(func.type!=null) - return func.type + if(func.returntype!=null) + return func.returntype // function has return values, but the return type depends on the arguments return when (function) { - "abs" -> args.single().resultingDatatype(namespace, heap) "max", "min" -> { val dt = datatypeFromListArg(args.single()) when(dt) {