diff --git a/compiler/src/prog8/functions/BuiltinFunctions.kt b/compiler/src/prog8/functions/BuiltinFunctions.kt index c84bed9e8..3ea53757e 100644 --- a/compiler/src/prog8/functions/BuiltinFunctions.kt +++ b/compiler/src/prog8/functions/BuiltinFunctions.kt @@ -26,10 +26,11 @@ val BuiltinFunctions = mapOf( "lsl" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null), "lsr" to FunctionSignature(false, listOf(BuiltinFunctionParam("item", IntegerDatatypes)), null), // these few have a return value depending on the argument(s): - "max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args - "min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args - "sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args + "max" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.max()!! }}, // type depends on args + "min" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.min()!! }}, // type depends on args + "sum" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), null) { a, p, n, h -> collectionArgOutputNumber(a, p, n, h) { it.sum() }}, // type depends on args "abs" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument + "len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length // normal functions follow: "sin" to FunctionSignature(true, listOf(BuiltinFunctionParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArg(a, p, n, h, Math::sin) }, "sin8" to FunctionSignature(true, listOf(BuiltinFunctionParam("angle8", setOf(DataType.UBYTE))), DataType.BYTE, ::builtinSin8 ), @@ -53,7 +54,6 @@ val BuiltinFunctions = mapOf( "round" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::round) }, "floor" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::floor) }, "ceil" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, n, h -> oneDoubleArgOutputWord(a, p, n, h, Math::ceil) }, - "len" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", IterableDatatypes)), DataType.UWORD, ::builtinLen), "any" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.any { v -> v != 0.0} }}, "all" to FunctionSignature(true, listOf(BuiltinFunctionParam("values", ArrayDatatypes)), DataType.UBYTE) { a, p, n, h -> collectionArgOutputBoolean(a, p, n, h) { it.all { v -> v != 0.0} }}, "lsb" to FunctionSignature(true, listOf(BuiltinFunctionParam("value", setOf(DataType.UWORD, DataType.WORD))), DataType.UBYTE) { a, p, n, h -> oneIntArgOutputInt(a, p, n, h) { x: Int -> x and 255 }}, @@ -178,6 +178,11 @@ fun builtinFunctionReturnType(function: String, args: List, namespa DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> DataType.UWORD } } + "len" -> { + // a length can be >255 so in that case, the result is an UWORD instead of an UBYTE + // but to avoid a lot of code duplication we simply assume UWORD in all cases for now + return DataType.UWORD + } else -> return null } } @@ -295,7 +300,7 @@ private fun builtinAvg(args: List, position: Position, namespace:IN } private fun builtinLen(args: List, position: Position, namespace:INameScope, heap: HeapValues): LiteralValue { - // note: in some cases the length is > 255 and so we have to return a UWORD type instead of a byte. + // note: in some cases the length is > 255 and then we have to return a UWORD type instead of a UBYTE. if(args.size!=1) throw SyntaxError("len requires one argument", position) var argument = args[0].constValue(namespace, heap) @@ -312,19 +317,19 @@ private fun builtinLen(args: List, position: Position, namespace:IN val arraySize = argument.arrayvalue?.size ?: heap.get(argument.heapId!!).arraysize if(arraySize>256) throw CompilerException("array length exceeds byte limit ${argument.position}") - LiteralValue(DataType.UWORD, wordvalue=arraySize, position=args[0].position) + LiteralValue.optimalInteger(arraySize, args[0].position) } DataType.ARRAY_F -> { val arraySize = argument.arrayvalue?.size ?: heap.get(argument.heapId!!).arraysize if(arraySize>256) throw CompilerException("array length exceeds byte limit ${argument.position}") - LiteralValue(DataType.UWORD, wordvalue=arraySize, position=args[0].position) + LiteralValue.optimalInteger(arraySize, args[0].position) } DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> { val str = argument.strvalue(heap) if(str.length>255) throw CompilerException("string length exceeds byte limit ${argument.position}") - LiteralValue(DataType.UWORD, wordvalue=str.length, position=args[0].position) + LiteralValue.optimalInteger(str.length, args[0].position) } DataType.UBYTE, DataType.BYTE, DataType.UWORD, DataType.WORD, diff --git a/examples/test.p8 b/examples/test.p8 index ee7f40c3b..8baca0171 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -10,30 +10,10 @@ ;ubyte x = rnd82() % 6 ; @todo fix compiler crash + always 0??? - ;ubyte[7] blockColors = [3, 6, 8, 7, 5, 4, 2] - ;drawNext(n % len(blockColors)) ; @todo why is len a word here? - ; if(X and c64scr.getcc(1,1)!=32) ... @todo the result value of the asmsub getcc is not put on the eval stack when used in an expression - sub start() { - ubyte sc = 3 - ubyte[4] currentBlock - Y=currentBlock[0] & sc - - ubyte ub1 = %1001 - ubyte ub2 = %0111 - ubyte ub3 - byte b1 = %1001 - byte b2 = %0111 - byte b3 - uword uw1 = %0000100100000000 - uword uw2 = %0000001111000000 - uword uw3 - word w1 = %0000100100000000 - word w2 = %0000001111000000 - word w3 } diff --git a/prog8.iml b/prog8.iml index a873d0513..ff4ca737d 100644 --- a/prog8.iml +++ b/prog8.iml @@ -1,10 +1,5 @@ - - - - -