fix abs() and also try to convert const arguments to the desired datatype of subroutine params

This commit is contained in:
Irmen de Jong 2019-02-01 00:50:24 +01:00
parent b911a95fc2
commit 86ff08e854
6 changed files with 62 additions and 30 deletions

View File

@ -1 +1 @@
1.1 (beta)
1.2 (beta)

View File

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

View File

@ -111,7 +111,7 @@ val BuiltinFunctions = mapOf(
fun builtinFunctionReturnType(function: String, args: List<IExpression>, 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<IExpression>, 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<IExpression>, 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<IExpression>, 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

View File

@ -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.

View File

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

View File

@ -16,5 +16,6 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Python 3.7 interpreter library" level="application" />
</component>
</module>