builtin funcs with multiple param types

This commit is contained in:
Irmen de Jong 2018-09-30 20:19:25 +02:00
parent 02075f2cf2
commit d1589bef26
3 changed files with 132 additions and 89 deletions

View File

@ -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)
}
}

View File

@ -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) {

View File

@ -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<SubroutineParameter>,
val paramTypesVariable: Boolean,
val returnvalues: List<DataType>,
val type: DataType?,
val expressionFunc: ((args: List<IExpression>, position: Position, namespace: INameScope, heap: HeapValues) -> LiteralValue)?) {
companion object {
private val dummyPos = Position("dummy", 0, 0, 0)
fun sig(pure: Boolean,
args: List<Pair<String, DataType?>>,
hasReturnValue: Boolean,
type: DataType?,
expressionFunc: ((args: List<IExpression>, 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<DataType>)
class FunctionSignature(val pure: Boolean, // does it have side effects?
val parameters: List<BuiltinFunctionParam>,
val returntype: DataType?,
val constExpressionFunc: ((args: List<IExpression>, 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<IExpression>, 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) {