mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
renamed InferredType.typeOrElse to getOr()
this is closer to the convention of most functional return types
This commit is contained in:
parent
1c7c67060d
commit
66574d058a
@ -146,7 +146,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I
|
|||||||
// see if we can remove superfluous typecasts (outside of expressions)
|
// see if we can remove superfluous typecasts (outside of expressions)
|
||||||
// such as casting byte<->ubyte, word<->uword
|
// such as casting byte<->ubyte, word<->uword
|
||||||
// Also the special typecast of a reference type (str, array) to an UWORD will be changed into address-of.
|
// Also the special typecast of a reference type (str, array) to an UWORD will be changed into address-of.
|
||||||
val sourceDt = typecast.expression.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val sourceDt = typecast.expression.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
if (typecast.type in ByteDatatypes && sourceDt in ByteDatatypes
|
if (typecast.type in ByteDatatypes && sourceDt in ByteDatatypes
|
||||||
|| typecast.type in WordDatatypes && sourceDt in WordDatatypes) {
|
|| typecast.type in WordDatatypes && sourceDt in WordDatatypes) {
|
||||||
if(typecast.parent !is Expression) {
|
if(typecast.parent !is Expression) {
|
||||||
@ -266,8 +266,8 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I
|
|||||||
// if the datatype of the arguments of cmp() are different, cast the byte one to word.
|
// if the datatype of the arguments of cmp() are different, cast the byte one to word.
|
||||||
val arg1 = functionCallStatement.args[0]
|
val arg1 = functionCallStatement.args[0]
|
||||||
val arg2 = functionCallStatement.args[1]
|
val arg2 = functionCallStatement.args[1]
|
||||||
val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt1 = arg1.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
val dt2 = arg2.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt2 = arg2.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
if(dt1 in ByteDatatypes) {
|
if(dt1 in ByteDatatypes) {
|
||||||
if(dt2 in ByteDatatypes)
|
if(dt2 in ByteDatatypes)
|
||||||
return noModifications
|
return noModifications
|
||||||
|
@ -79,7 +79,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(!valueDt.isKnown) {
|
if(!valueDt.isKnown) {
|
||||||
errors.err("return value type mismatch or unknown symbol", returnStmt.value!!.position)
|
errors.err("return value type mismatch or unknown symbol", returnStmt.value!!.position)
|
||||||
} else {
|
} else {
|
||||||
if (expectedReturnValues[0] != valueDt.typeOrElse(DataType.UNDEFINED))
|
if (expectedReturnValues[0] != valueDt.getOr(DataType.UNDEFINED))
|
||||||
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}", returnStmt.value!!.position)
|
errors.err("type $valueDt of return value doesn't match subroutine's return type ${expectedReturnValues[0]}", returnStmt.value!!.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val iterableDt = forLoop.iterable.inferType(program).typeOrElse(DataType.BYTE)
|
val iterableDt = forLoop.iterable.inferType(program).getOr(DataType.BYTE)
|
||||||
if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpr) {
|
if(iterableDt !in IterableDatatypes && forLoop.iterable !is RangeExpr) {
|
||||||
errors.err("can only loop over an iterable type", forLoop.position)
|
errors.err("can only loop over an iterable type", forLoop.position)
|
||||||
} else {
|
} else {
|
||||||
@ -414,7 +414,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(!idt.isKnown) {
|
if(!idt.isKnown) {
|
||||||
errors.err("return type mismatch", assignment.value.position)
|
errors.err("return type mismatch", assignment.value.position)
|
||||||
}
|
}
|
||||||
if(stmt.returntypes.isEmpty() || (stmt.returntypes.size == 1 && stmt.returntypes.single() isNotAssignableTo idt.typeOrElse(DataType.BYTE))) {
|
if(stmt.returntypes.isEmpty() || (stmt.returntypes.size == 1 && stmt.returntypes.single() isNotAssignableTo idt.getOr(DataType.BYTE))) {
|
||||||
errors.err("return type mismatch", assignment.value.position)
|
errors.err("return type mismatch", assignment.value.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -479,15 +479,15 @@ internal class AstChecker(private val program: Program,
|
|||||||
if (targetDatatype.isKnown) {
|
if (targetDatatype.isKnown) {
|
||||||
val constVal = assignment.value.constValue(program)
|
val constVal = assignment.value.constValue(program)
|
||||||
if (constVal != null) {
|
if (constVal != null) {
|
||||||
checkValueTypeAndRange(targetDatatype.typeOrElse(DataType.BYTE), constVal)
|
checkValueTypeAndRange(targetDatatype.getOr(DataType.BYTE), constVal)
|
||||||
} else {
|
} else {
|
||||||
val sourceDatatype = assignment.value.inferType(program)
|
val sourceDatatype = assignment.value.inferType(program)
|
||||||
if (sourceDatatype.isUnknown) {
|
if (sourceDatatype.isUnknown) {
|
||||||
if (assignment.value !is FunctionCall)
|
if (assignment.value !is FunctionCall)
|
||||||
errors.err("assignment value is invalid or has no proper datatype", assignment.value.position)
|
errors.err("assignment value is invalid or has no proper datatype", assignment.value.position)
|
||||||
} else {
|
} else {
|
||||||
checkAssignmentCompatible(targetDatatype.typeOrElse(DataType.BYTE), assignTarget,
|
checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE), assignTarget,
|
||||||
sourceDatatype.typeOrElse(DataType.BYTE), assignment.value, assignment.position)
|
sourceDatatype.getOr(DataType.BYTE), assignment.value, assignment.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -741,11 +741,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
override fun visit(array: ArrayLiteralValue) {
|
override fun visit(array: ArrayLiteralValue) {
|
||||||
if(array.type.isKnown) {
|
if(array.type.isKnown) {
|
||||||
if (!compilerOptions.floats && array.type.typeOrElse(DataType.UNDEFINED) in setOf(DataType.FLOAT, DataType.ARRAY_F)) {
|
if (!compilerOptions.floats && array.type.getOr(DataType.UNDEFINED) in setOf(DataType.FLOAT, DataType.ARRAY_F)) {
|
||||||
errors.err("floating point used, but that is not enabled via options", array.position)
|
errors.err("floating point used, but that is not enabled via options", array.position)
|
||||||
}
|
}
|
||||||
val arrayspec = ArrayIndex.forArray(array)
|
val arrayspec = ArrayIndex.forArray(array)
|
||||||
checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.UNDEFINED), arrayspec, array)
|
checkValueTypeAndRangeArray(array.type.getOr(DataType.UNDEFINED), arrayspec, array)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPassByReferenceElement(e: Expression): Boolean {
|
fun isPassByReferenceElement(e: Expression): Boolean {
|
||||||
@ -794,7 +794,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
return // any error should be reported elsewhere
|
return // any error should be reported elsewhere
|
||||||
|
|
||||||
val dt = idt.typeOrElse(DataType.UNDEFINED)
|
val dt = idt.getOr(DataType.UNDEFINED)
|
||||||
if(expr.operator=="-") {
|
if(expr.operator=="-") {
|
||||||
if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) {
|
if (dt != DataType.BYTE && dt != DataType.WORD && dt != DataType.FLOAT) {
|
||||||
errors.err("can only take negative of a signed number type", expr.position)
|
errors.err("can only take negative of a signed number type", expr.position)
|
||||||
@ -819,8 +819,8 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(!leftIDt.isKnown || !rightIDt.isKnown)
|
if(!leftIDt.isKnown || !rightIDt.isKnown)
|
||||||
return // hopefully this error will be detected elsewhere
|
return // hopefully this error will be detected elsewhere
|
||||||
|
|
||||||
val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
|
val leftDt = leftIDt.getOr(DataType.UNDEFINED)
|
||||||
val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED)
|
val rightDt = rightIDt.getOr(DataType.UNDEFINED)
|
||||||
|
|
||||||
when(expr.operator){
|
when(expr.operator){
|
||||||
"/", "%" -> {
|
"/", "%" -> {
|
||||||
@ -1028,7 +1028,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if((args[0] as? AddressOf)?.identifier?.targetVarDecl(program)?.datatype == DataType.STR) {
|
if((args[0] as? AddressOf)?.identifier?.targetVarDecl(program)?.datatype == DataType.STR) {
|
||||||
errors.err("any/all on a string is useless (is always true unless the string is empty)", position)
|
errors.err("any/all on a string is useless (is always true unless the string is empty)", position)
|
||||||
}
|
}
|
||||||
if(args[0].inferType(program).typeOrElse(DataType.STR) == DataType.STR) {
|
if(args[0].inferType(program).getOr(DataType.STR) == DataType.STR) {
|
||||||
errors.err("any/all on a string is useless (is always true unless the string is empty)", position)
|
errors.err("any/all on a string is useless (is always true unless the string is empty)", position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1157,7 +1157,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
when {
|
when {
|
||||||
constvalue == null -> errors.err("choice value must be a constant", whenChoice.position)
|
constvalue == null -> errors.err("choice value must be a constant", whenChoice.position)
|
||||||
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position)
|
constvalue.type !in IntegerDatatypes -> errors.err("choice value must be a byte or word", whenChoice.position)
|
||||||
constvalue.type != conditionType.typeOrElse(DataType.UNDEFINED) -> errors.err("choice value datatype differs from condition value", whenChoice.position)
|
constvalue.type != conditionType.getOr(DataType.UNDEFINED) -> errors.err("choice value datatype differs from condition value", whenChoice.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -38,7 +38,7 @@ internal class LiteralsToAutoVars(private val program: Program) : AstWalker() {
|
|||||||
val arrayDt = array.guessDatatype(program)
|
val arrayDt = array.guessDatatype(program)
|
||||||
if(arrayDt.isKnown) {
|
if(arrayDt.isKnown) {
|
||||||
// this array literal is part of an expression, turn it into an identifier reference
|
// this array literal is part of an expression, turn it into an identifier reference
|
||||||
val litval2 = array.cast(arrayDt.typeOrElse(DataType.UNDEFINED))
|
val litval2 = array.cast(arrayDt.getOr(DataType.UNDEFINED))
|
||||||
if(litval2!=null) {
|
if(litval2!=null) {
|
||||||
val vardecl2 = VarDecl.createAuto(litval2)
|
val vardecl2 = VarDecl.createAuto(litval2)
|
||||||
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
val identifier = IdentifierReference(listOf(vardecl2.name), vardecl2.position)
|
||||||
|
@ -106,7 +106,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
|
|||||||
is Assignment -> {
|
is Assignment -> {
|
||||||
val targetDt = parent.target.inferType(program)
|
val targetDt = parent.target.inferType(program)
|
||||||
if(leftDt != targetDt) {
|
if(leftDt != targetDt) {
|
||||||
val cast = TypecastExpression(expr.left, targetDt.typeOrElse(DataType.UNDEFINED), true, parent.position)
|
val cast = TypecastExpression(expr.left, targetDt.getOr(DataType.UNDEFINED), true, parent.position)
|
||||||
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
val rightDt = expr.right.inferType(program)
|
val rightDt = expr.right.inferType(program)
|
||||||
if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) {
|
if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) {
|
||||||
// determine common datatype and add typecast as required to make left and right equal types
|
// determine common datatype and add typecast as required to make left and right equal types
|
||||||
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.typeOrElse(DataType.UNDEFINED), rightDt.typeOrElse(DataType.UNDEFINED), expr.left, expr.right)
|
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.right)
|
||||||
if(toFix!=null) {
|
if(toFix!=null) {
|
||||||
return when {
|
return when {
|
||||||
toFix===expr.left -> listOf(IAstModification.ReplaceNode(
|
toFix===expr.left -> listOf(IAstModification.ReplaceNode(
|
||||||
@ -66,8 +66,8 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
val valueItype = assignment.value.inferType(program)
|
val valueItype = assignment.value.inferType(program)
|
||||||
val targetItype = assignment.target.inferType(program)
|
val targetItype = assignment.target.inferType(program)
|
||||||
if(targetItype.isKnown && valueItype.isKnown) {
|
if(targetItype.isKnown && valueItype.isKnown) {
|
||||||
val targettype = targetItype.typeOrElse(DataType.UNDEFINED)
|
val targettype = targetItype.getOr(DataType.UNDEFINED)
|
||||||
val valuetype = valueItype.typeOrElse(DataType.UNDEFINED)
|
val valuetype = valueItype.getOr(DataType.UNDEFINED)
|
||||||
if (valuetype != targettype) {
|
if (valuetype != targettype) {
|
||||||
if (valuetype isAssignableTo targettype) {
|
if (valuetype isAssignableTo targettype) {
|
||||||
if(valuetype in IterableDatatypes && targettype==DataType.UWORD)
|
if(valuetype in IterableDatatypes && targettype==DataType.UWORD)
|
||||||
@ -126,7 +126,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
sub.parameters.zip(call.args).forEachIndexed { index, pair ->
|
sub.parameters.zip(call.args).forEachIndexed { index, pair ->
|
||||||
val argItype = pair.second.inferType(program)
|
val argItype = pair.second.inferType(program)
|
||||||
if(argItype.isKnown) {
|
if(argItype.isKnown) {
|
||||||
val argtype = argItype.typeOrElse(DataType.UNDEFINED)
|
val argtype = argItype.getOr(DataType.UNDEFINED)
|
||||||
val requiredType = pair.first.type
|
val requiredType = pair.first.type
|
||||||
if (requiredType != argtype) {
|
if (requiredType != argtype) {
|
||||||
if (argtype isAssignableTo requiredType) {
|
if (argtype isAssignableTo requiredType) {
|
||||||
@ -159,7 +159,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
func.parameters.zip(call.args).forEachIndexed { index, pair ->
|
func.parameters.zip(call.args).forEachIndexed { index, pair ->
|
||||||
val argItype = pair.second.inferType(program)
|
val argItype = pair.second.inferType(program)
|
||||||
if (argItype.isKnown) {
|
if (argItype.isKnown) {
|
||||||
val argtype = argItype.typeOrElse(DataType.UNDEFINED)
|
val argtype = argItype.getOr(DataType.UNDEFINED)
|
||||||
if (pair.first.possibleDatatypes.all { argtype != it }) {
|
if (pair.first.possibleDatatypes.all { argtype != it }) {
|
||||||
for (possibleType in pair.first.possibleDatatypes) {
|
for (possibleType in pair.first.possibleDatatypes) {
|
||||||
if (argtype isAssignableTo possibleType) {
|
if (argtype isAssignableTo possibleType) {
|
||||||
@ -191,7 +191,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
override fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
override fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> {
|
||||||
// make sure the memory address is an uword
|
// make sure the memory address is an uword
|
||||||
val dt = memread.addressExpression.inferType(program)
|
val dt = memread.addressExpression.inferType(program)
|
||||||
if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) {
|
if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) {
|
||||||
val typecast = (memread.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero()
|
val typecast = (memread.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero()
|
||||||
?: TypecastExpression(memread.addressExpression, DataType.UWORD, true, memread.addressExpression.position)
|
?: TypecastExpression(memread.addressExpression, DataType.UWORD, true, memread.addressExpression.position)
|
||||||
return listOf(IAstModification.ReplaceNode(memread.addressExpression, typecast, memread))
|
return listOf(IAstModification.ReplaceNode(memread.addressExpression, typecast, memread))
|
||||||
@ -202,7 +202,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
|
|||||||
override fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> {
|
override fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> {
|
||||||
// make sure the memory address is an uword
|
// make sure the memory address is an uword
|
||||||
val dt = memwrite.addressExpression.inferType(program)
|
val dt = memwrite.addressExpression.inferType(program)
|
||||||
if(dt.isKnown && dt.typeOrElse(DataType.UWORD)!=DataType.UWORD) {
|
if(dt.isKnown && dt.getOr(DataType.UWORD)!=DataType.UWORD) {
|
||||||
val typecast = (memwrite.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero()
|
val typecast = (memwrite.addressExpression as? NumericLiteralValue)?.cast(DataType.UWORD)?.valueOrZero()
|
||||||
?: TypecastExpression(memwrite.addressExpression, DataType.UWORD, true, memwrite.addressExpression.position)
|
?: TypecastExpression(memwrite.addressExpression, DataType.UWORD, true, memwrite.addressExpression.position)
|
||||||
return listOf(IAstModification.ReplaceNode(memwrite.addressExpression, typecast, memwrite))
|
return listOf(IAstModification.ReplaceNode(memwrite.addressExpression, typecast, memwrite))
|
||||||
|
@ -44,7 +44,7 @@ class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
|
|||||||
val firstUnknownDt = argITypes.indexOfFirst { it.isUnknown }
|
val firstUnknownDt = argITypes.indexOfFirst { it.isUnknown }
|
||||||
if(firstUnknownDt>=0)
|
if(firstUnknownDt>=0)
|
||||||
return "argument ${firstUnknownDt+1} invalid argument type"
|
return "argument ${firstUnknownDt+1} invalid argument type"
|
||||||
val argtypes = argITypes.map { it.typeOrElse(DataType.UNDEFINED) }
|
val argtypes = argITypes.map { it.getOr(DataType.UNDEFINED) }
|
||||||
val target = call.target.targetStatement(program)
|
val target = call.target.targetStatement(program)
|
||||||
if (target is Subroutine) {
|
if (target is Subroutine) {
|
||||||
if(call.args.size != target.parameters.size)
|
if(call.args.size != target.parameters.size)
|
||||||
|
@ -164,7 +164,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
|
|||||||
|
|
||||||
fun datatypeFromIterableArg(arglist: Expression): DataType {
|
fun datatypeFromIterableArg(arglist: Expression): DataType {
|
||||||
if(arglist is ArrayLiteralValue) {
|
if(arglist is ArrayLiteralValue) {
|
||||||
val dt = arglist.value.map {it.inferType(program).typeOrElse(DataType.UNDEFINED)}.toSet()
|
val dt = arglist.value.map {it.inferType(program).getOr(DataType.UNDEFINED)}.toSet()
|
||||||
if(dt.any { it !in NumericDatatypes }) {
|
if(dt.any { it !in NumericDatatypes }) {
|
||||||
throw FatalAstException("fuction $function only accepts array of numeric values")
|
throw FatalAstException("fuction $function only accepts array of numeric values")
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
|
|||||||
val idt = arglist.inferType(program)
|
val idt = arglist.inferType(program)
|
||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
throw FatalAstException("couldn't determine type of iterable $arglist")
|
throw FatalAstException("couldn't determine type of iterable $arglist")
|
||||||
return when(val dt = idt.typeOrElse(DataType.UNDEFINED)) {
|
return when(val dt = idt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.STR, in NumericDatatypes -> dt
|
DataType.STR, in NumericDatatypes -> dt
|
||||||
in ArrayDatatypes -> ArrayToElementTypes.getValue(dt)
|
in ArrayDatatypes -> ArrayToElementTypes.getValue(dt)
|
||||||
else -> throw FatalAstException("function '$function' requires one argument which is an iterable")
|
else -> throw FatalAstException("function '$function' requires one argument which is an iterable")
|
||||||
@ -302,11 +302,11 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
|
|||||||
return when {
|
return when {
|
||||||
dt.isArray -> {
|
dt.isArray -> {
|
||||||
val length = (target as VarDecl).arraysize!!.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size")
|
val length = (target as VarDecl).arraysize!!.constIndex() ?: throw CannotEvaluateException("sizeof", "unknown array size")
|
||||||
val elementDt = ArrayToElementTypes.getValue(dt.typeOrElse(DataType.UNDEFINED))
|
val elementDt = ArrayToElementTypes.getValue(dt.getOr(DataType.UNDEFINED))
|
||||||
numericLiteral(memsizer.memorySize(elementDt) * length, position)
|
numericLiteral(memsizer.memorySize(elementDt) * length, position)
|
||||||
}
|
}
|
||||||
dt.istype(DataType.STR) -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
|
dt.istype(DataType.STR) -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
|
||||||
else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.typeOrElse(DataType.UNDEFINED)), position)
|
else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.getOr(DataType.UNDEFINED)), position)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw SyntaxError("sizeof invalid argument type", position)
|
throw SyntaxError("sizeof invalid argument type", position)
|
||||||
|
@ -1061,7 +1061,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
val dt = stmt.iterations!!.inferType(program)
|
val dt = stmt.iterations!!.inferType(program)
|
||||||
if(!dt.isKnown)
|
if(!dt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes -> {
|
in ByteDatatypes -> {
|
||||||
assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A)
|
assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A)
|
||||||
repeatByteCountInA(null, repeatLabel, endLabel, stmt)
|
repeatByteCountInA(null, repeatLabel, endLabel, stmt)
|
||||||
@ -1193,7 +1193,7 @@ $repeatLabel lda $counterVar
|
|||||||
val conditionDt = stmt.condition.inferType(program)
|
val conditionDt = stmt.condition.inferType(program)
|
||||||
if(!conditionDt.isKnown)
|
if(!conditionDt.isKnown)
|
||||||
throw AssemblyError("unknown condition dt")
|
throw AssemblyError("unknown condition dt")
|
||||||
if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes)
|
if(conditionDt.getOr(DataType.BYTE) in ByteDatatypes)
|
||||||
assignExpressionToRegister(stmt.condition, RegisterOrPair.A)
|
assignExpressionToRegister(stmt.condition, RegisterOrPair.A)
|
||||||
else
|
else
|
||||||
assignExpressionToRegister(stmt.condition, RegisterOrPair.AY)
|
assignExpressionToRegister(stmt.condition, RegisterOrPair.AY)
|
||||||
@ -1208,7 +1208,7 @@ $repeatLabel lda $counterVar
|
|||||||
choiceBlocks.add(choiceLabel to choice.statements)
|
choiceBlocks.add(choiceLabel to choice.statements)
|
||||||
for (cv in choice.values!!) {
|
for (cv in choice.values!!) {
|
||||||
val value = (cv as NumericLiteralValue).number.toInt()
|
val value = (cv as NumericLiteralValue).number.toInt()
|
||||||
if(conditionDt.typeOrElse(DataType.BYTE) in ByteDatatypes) {
|
if(conditionDt.getOr(DataType.BYTE) in ByteDatatypes) {
|
||||||
out(" cmp #${value.toHex()} | beq $choiceLabel")
|
out(" cmp #${value.toHex()} | beq $choiceLabel")
|
||||||
} else {
|
} else {
|
||||||
out("""
|
out("""
|
||||||
|
@ -177,8 +177,8 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
private fun funcCmp(fcall: IFunctionCall) {
|
private fun funcCmp(fcall: IFunctionCall) {
|
||||||
val arg1 = fcall.args[0]
|
val arg1 = fcall.args[0]
|
||||||
val arg2 = fcall.args[1]
|
val arg2 = fcall.args[1]
|
||||||
val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt1 = arg1.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
val dt2 = arg2.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt2 = arg2.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
if(dt1 in ByteDatatypes) {
|
if(dt1 in ByteDatatypes) {
|
||||||
if(dt2 in ByteDatatypes) {
|
if(dt2 in ByteDatatypes) {
|
||||||
when (arg2) {
|
when (arg2) {
|
||||||
@ -368,7 +368,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
private fun funcRor2(fcall: IFunctionCall) {
|
private fun funcRor2(fcall: IFunctionCall) {
|
||||||
val what = fcall.args.single()
|
val what = fcall.args.single()
|
||||||
val dt = what.inferType(program)
|
val dt = what.inferType(program)
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (what) {
|
when (what) {
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
@ -411,7 +411,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
private fun funcRor(fcall: IFunctionCall) {
|
private fun funcRor(fcall: IFunctionCall) {
|
||||||
val what = fcall.args.single()
|
val what = fcall.args.single()
|
||||||
val dt = what.inferType(program)
|
val dt = what.inferType(program)
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (what) {
|
when (what) {
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
@ -469,7 +469,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
private fun funcRol2(fcall: IFunctionCall) {
|
private fun funcRol2(fcall: IFunctionCall) {
|
||||||
val what = fcall.args.single()
|
val what = fcall.args.single()
|
||||||
val dt = what.inferType(program)
|
val dt = what.inferType(program)
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (what) {
|
when (what) {
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
@ -512,7 +512,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
private fun funcRol(fcall: IFunctionCall) {
|
private fun funcRol(fcall: IFunctionCall) {
|
||||||
val what = fcall.args.single()
|
val what = fcall.args.single()
|
||||||
val dt = what.inferType(program)
|
val dt = what.inferType(program)
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when (what) {
|
when (what) {
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
@ -586,7 +586,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
translateArguments(fcall.args, func, scope)
|
translateArguments(fcall.args, func, scope)
|
||||||
val dt = fcall.args.single().inferType(program)
|
val dt = fcall.args.single().inferType(program)
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_stack")
|
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_stack")
|
||||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_stack")
|
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_stack")
|
||||||
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_stack")
|
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_stack")
|
||||||
@ -595,7 +595,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
else -> throw AssemblyError("weird type $dt")
|
else -> throw AssemblyError("weird type $dt")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A")
|
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A")
|
||||||
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A")
|
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A")
|
||||||
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A")
|
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A")
|
||||||
@ -611,14 +611,14 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
outputAddressAndLenghtOfArray(fcall.args[0])
|
outputAddressAndLenghtOfArray(fcall.args[0])
|
||||||
val dt = fcall.args.single().inferType(program)
|
val dt = fcall.args.single().inferType(program)
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack")
|
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack")
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_stack")
|
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_stack")
|
||||||
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_stack")
|
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_stack")
|
||||||
else -> throw AssemblyError("weird type $dt")
|
else -> throw AssemblyError("weird type $dt")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_into_A")
|
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_into_A")
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_into_A")
|
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${function.name}_w_into_A")
|
||||||
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_into_A")
|
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${function.name}_f_into_A")
|
||||||
@ -632,7 +632,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
outputAddressAndLenghtOfArray(fcall.args[0])
|
outputAddressAndLenghtOfArray(fcall.args[0])
|
||||||
val dt = fcall.args.single().inferType(program)
|
val dt = fcall.args.single().inferType(program)
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_ub_stack")
|
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${function.name}_ub_stack")
|
||||||
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack")
|
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_${function.name}_b_stack")
|
||||||
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${function.name}_uw_stack")
|
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_${function.name}_uw_stack")
|
||||||
@ -641,7 +641,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
else -> throw AssemblyError("weird type $dt")
|
else -> throw AssemblyError("weird type $dt")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_UB, DataType.STR -> {
|
DataType.ARRAY_UB, DataType.STR -> {
|
||||||
asmgen.out(" jsr prog8_lib.func_${function.name}_ub_into_A")
|
asmgen.out(" jsr prog8_lib.func_${function.name}_ub_into_A")
|
||||||
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, scope, program, asmgen), CpuRegister.A)
|
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, scope, program, asmgen), CpuRegister.A)
|
||||||
@ -671,7 +671,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
outputAddressAndLenghtOfArray(fcall.args[0])
|
outputAddressAndLenghtOfArray(fcall.args[0])
|
||||||
val dt = fcall.args.single().inferType(program)
|
val dt = fcall.args.single().inferType(program)
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_sum_ub_stack")
|
DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_sum_ub_stack")
|
||||||
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_sum_b_stack")
|
DataType.ARRAY_B -> asmgen.out(" jsr prog8_lib.func_sum_b_stack")
|
||||||
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_sum_uw_stack")
|
DataType.ARRAY_UW -> asmgen.out(" jsr prog8_lib.func_sum_uw_stack")
|
||||||
@ -680,7 +680,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
else -> throw AssemblyError("weird type $dt")
|
else -> throw AssemblyError("weird type $dt")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (dt.typeOrElse(DataType.UNDEFINED)) {
|
when (dt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.ARRAY_UB, DataType.STR -> {
|
DataType.ARRAY_UB, DataType.STR -> {
|
||||||
asmgen.out(" jsr prog8_lib.func_sum_ub_into_AY")
|
asmgen.out(" jsr prog8_lib.func_sum_ub_into_AY")
|
||||||
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, scope, program, asmgen), RegisterOrPair.AY)
|
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, scope, program, asmgen), RegisterOrPair.AY)
|
||||||
@ -825,7 +825,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
val elementIDt = first.inferType(program)
|
val elementIDt = first.inferType(program)
|
||||||
if(!elementIDt.isKnown)
|
if(!elementIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val elementDt = elementIDt.typeOrElse(DataType.UNDEFINED)
|
val elementDt = elementIDt.getOr(DataType.UNDEFINED)
|
||||||
|
|
||||||
val firstNum = first.indexer.indexExpr as? NumericLiteralValue
|
val firstNum = first.indexer.indexExpr as? NumericLiteralValue
|
||||||
val firstVar = first.indexer.indexExpr as? IdentifierReference
|
val firstVar = first.indexer.indexExpr as? IdentifierReference
|
||||||
@ -858,7 +858,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when(val datatype: DataType = first.inferType(program).typeOrElse(DataType.UNDEFINED)) {
|
when(val datatype: DataType = first.inferType(program).getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes, in WordDatatypes -> {
|
in ByteDatatypes, in WordDatatypes -> {
|
||||||
asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null)
|
asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null)
|
||||||
asmgen.assignExpressionToVariable(second, "P8ZP_SCRATCH_W2", datatype, null)
|
asmgen.assignExpressionToVariable(second, "P8ZP_SCRATCH_W2", datatype, null)
|
||||||
@ -1128,7 +1128,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
|
|
||||||
private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
private fun funcAbs(fcall: IFunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: Subroutine?) {
|
||||||
translateArguments(fcall.args, func, scope)
|
translateArguments(fcall.args, func, scope)
|
||||||
val dt = fcall.args.single().inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt = fcall.args.single().inferType(program).getOr(DataType.UNDEFINED)
|
||||||
if(resultToStack) {
|
if(resultToStack) {
|
||||||
when (dt) {
|
when (dt) {
|
||||||
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_stack")
|
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_stack")
|
||||||
@ -1474,7 +1474,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateArguments(args: MutableList<Expression>, signature: FSignature, scope: Subroutine?) {
|
private fun translateArguments(args: MutableList<Expression>, signature: FSignature, scope: Subroutine?) {
|
||||||
val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.UNDEFINED) })
|
val callConv = signature.callConvention(args.map { it.inferType(program).getOr(DataType.UNDEFINED) })
|
||||||
|
|
||||||
fun getSourceForFloat(value: Expression): AsmAssignSource {
|
fun getSourceForFloat(value: Expression): AsmAssignSource {
|
||||||
return when (value) {
|
return when (value) {
|
||||||
|
@ -57,7 +57,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
val idt = left.inferType(program)
|
val idt = left.inferType(program)
|
||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val dt = idt.typeOrElse(DataType.UNDEFINED)
|
val dt = idt.getOr(DataType.UNDEFINED)
|
||||||
when (operator) {
|
when (operator) {
|
||||||
"==" -> {
|
"==" -> {
|
||||||
// if the left operand is an expression, and the right is 0, we can just evaluate that expression,
|
// if the left operand is an expression, and the right is 0, we can just evaluate that expression,
|
||||||
@ -1626,7 +1626,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
|
|
||||||
private fun translateExpression(typecast: TypecastExpression) {
|
private fun translateExpression(typecast: TypecastExpression) {
|
||||||
translateExpression(typecast.expression)
|
translateExpression(typecast.expression)
|
||||||
when(typecast.expression.inferType(program).typeOrElse(DataType.UNDEFINED)) {
|
when(typecast.expression.inferType(program).getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when(typecast.type) {
|
when(typecast.type) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {}
|
DataType.UBYTE, DataType.BYTE -> {}
|
||||||
@ -1757,7 +1757,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
|
|
||||||
private fun translateExpression(expr: IdentifierReference) {
|
private fun translateExpression(expr: IdentifierReference) {
|
||||||
val varname = asmgen.asmVariableName(expr)
|
val varname = asmgen.asmVariableName(expr)
|
||||||
when(expr.inferType(program).typeOrElse(DataType.UNDEFINED)) {
|
when(expr.inferType(program).getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
asmgen.out(" lda $varname | sta P8ESTACK_LO,x | dex")
|
asmgen.out(" lda $varname | sta P8ESTACK_LO,x | dex")
|
||||||
}
|
}
|
||||||
@ -1781,8 +1781,8 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
if(!leftIDt.isKnown || !rightIDt.isKnown)
|
if(!leftIDt.isKnown || !rightIDt.isKnown)
|
||||||
throw AssemblyError("can't infer type of both expression operands")
|
throw AssemblyError("can't infer type of both expression operands")
|
||||||
|
|
||||||
val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
|
val leftDt = leftIDt.getOr(DataType.UNDEFINED)
|
||||||
val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED)
|
val rightDt = rightIDt.getOr(DataType.UNDEFINED)
|
||||||
// see if we can apply some optimized routines
|
// see if we can apply some optimized routines
|
||||||
// TODO avoid using evaluation on stack everywhere
|
// TODO avoid using evaluation on stack everywhere
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
@ -2108,7 +2108,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
val itype = expr.inferType(program)
|
val itype = expr.inferType(program)
|
||||||
if(!itype.isKnown)
|
if(!itype.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val type = itype.typeOrElse(DataType.UNDEFINED)
|
val type = itype.getOr(DataType.UNDEFINED)
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
"+" -> {}
|
"+" -> {}
|
||||||
"-" -> {
|
"-" -> {
|
||||||
@ -2146,7 +2146,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
|||||||
val elementIDt = arrayExpr.inferType(program)
|
val elementIDt = arrayExpr.inferType(program)
|
||||||
if(!elementIDt.isKnown)
|
if(!elementIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val elementDt = elementIDt.typeOrElse(DataType.UNDEFINED)
|
val elementDt = elementIDt.getOr(DataType.UNDEFINED)
|
||||||
val arrayVarName = asmgen.asmVariableName(arrayExpr.arrayvar)
|
val arrayVarName = asmgen.asmVariableName(arrayExpr.arrayvar)
|
||||||
val constIndexNum = arrayExpr.indexer.constIndex()
|
val constIndexNum = arrayExpr.indexer.constIndex()
|
||||||
if(constIndexNum!=null) {
|
if(constIndexNum!=null) {
|
||||||
|
@ -22,13 +22,13 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
is RangeExpr -> {
|
is RangeExpr -> {
|
||||||
val range = (stmt.iterable as RangeExpr).toConstantIntegerRange(asmgen.options.compTarget)
|
val range = (stmt.iterable as RangeExpr).toConstantIntegerRange(asmgen.options.compTarget)
|
||||||
if(range==null) {
|
if(range==null) {
|
||||||
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as RangeExpr)
|
translateForOverNonconstRange(stmt, iterableDt.getOr(DataType.UNDEFINED), stmt.iterable as RangeExpr)
|
||||||
} else {
|
} else {
|
||||||
translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), range)
|
translateForOverConstRange(stmt, iterableDt.getOr(DataType.UNDEFINED), range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
translateForOverIterableVar(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as IdentifierReference)
|
translateForOverIterableVar(stmt, iterableDt.getOr(DataType.UNDEFINED), stmt.iterable as IdentifierReference)
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("can't iterate over ${stmt.iterable.javaClass} - should have been replaced by a variable")
|
else -> throw AssemblyError("can't iterate over ${stmt.iterable.javaClass} - should have been replaced by a variable")
|
||||||
}
|
}
|
||||||
@ -589,5 +589,5 @@ $loopLabel""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) =
|
private fun assignLoopvar(stmt: ForLoop, range: RangeExpr) =
|
||||||
asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).typeOrElse(DataType.UNDEFINED), stmt.definingSubroutine)
|
asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).getOr(DataType.UNDEFINED), stmt.definingSubroutine)
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val valueIDt = value.inferType(program)
|
val valueIDt = value.inferType(program)
|
||||||
if(!valueIDt.isKnown)
|
if(!valueIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED)
|
val valueDt = valueIDt.getOr(DataType.UNDEFINED)
|
||||||
if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
|
if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
|
||||||
throw AssemblyError("argument type incompatible")
|
throw AssemblyError("argument type incompatible")
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
val valueIDt = value.inferType(program)
|
val valueIDt = value.inferType(program)
|
||||||
if(!valueIDt.isKnown)
|
if(!valueIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED)
|
val valueDt = valueIDt.getOr(DataType.UNDEFINED)
|
||||||
if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
|
if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
|
||||||
throw AssemblyError("argument type incompatible")
|
throw AssemblyError("argument type incompatible")
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
|
|||||||
when {
|
when {
|
||||||
targetIdent!=null -> {
|
targetIdent!=null -> {
|
||||||
val what = asmgen.asmVariableName(targetIdent)
|
val what = asmgen.asmVariableName(targetIdent)
|
||||||
when (stmt.target.inferType(program).typeOrElse(DataType.UNDEFINED)) {
|
when (stmt.target.inferType(program).getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes -> asmgen.out(if (incr) " inc $what" else " dec $what")
|
in ByteDatatypes -> asmgen.out(if (incr) " inc $what" else " dec $what")
|
||||||
in WordDatatypes -> {
|
in WordDatatypes -> {
|
||||||
if(incr)
|
if(incr)
|
||||||
@ -65,7 +65,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
|
|||||||
}
|
}
|
||||||
targetArrayIdx!=null -> {
|
targetArrayIdx!=null -> {
|
||||||
val asmArrayvarname = asmgen.asmVariableName(targetArrayIdx.arrayvar)
|
val asmArrayvarname = asmgen.asmVariableName(targetArrayIdx.arrayvar)
|
||||||
val elementDt = targetArrayIdx.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val elementDt = targetArrayIdx.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
val constIndex = targetArrayIdx.indexer.constIndex()
|
val constIndex = targetArrayIdx.indexer.constIndex()
|
||||||
if(constIndex!=null) {
|
if(constIndex!=null) {
|
||||||
val indexValue = constIndex * program.memsizer.memorySize(elementDt)
|
val indexValue = constIndex * program.memsizer.memorySize(elementDt)
|
||||||
|
@ -59,7 +59,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
|||||||
val idt = inferType(program)
|
val idt = inferType(program)
|
||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val dt = idt.typeOrElse(DataType.UNDEFINED)
|
val dt = idt.getOr(DataType.UNDEFINED)
|
||||||
when {
|
when {
|
||||||
identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
identifier != null -> AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, dt, assign.definingSubroutine, variableAsmName = asmgen.asmVariableName(identifier!!), origAstTarget = this)
|
||||||
arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
arrayindexed != null -> AsmAssignTarget(TargetStorageKind.ARRAY, program, asmgen, dt, assign.definingSubroutine, array = arrayindexed, origAstTarget = this)
|
||||||
@ -132,7 +132,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation")
|
is StringLiteralValue -> throw AssemblyError("string literal value should not occur anymore for asm generation")
|
||||||
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
|
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
val dt = value.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt = value.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
val varName=asmgen.asmVariableName(value)
|
val varName=asmgen.asmVariableName(value)
|
||||||
// special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system
|
// special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system
|
||||||
if(dt == DataType.UWORD && varName.lowercase().startsWith("cx16.r")) {
|
if(dt == DataType.UWORD && varName.lowercase().startsWith("cx16.r")) {
|
||||||
@ -147,7 +147,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
AsmAssignSource(SourceStorageKind.MEMORY, program, asmgen, DataType.UBYTE, memory = value)
|
AsmAssignSource(SourceStorageKind.MEMORY, program, asmgen, DataType.UBYTE, memory = value)
|
||||||
}
|
}
|
||||||
is ArrayIndexedExpression -> {
|
is ArrayIndexedExpression -> {
|
||||||
val dt = value.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val dt = value.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value)
|
AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value)
|
||||||
}
|
}
|
||||||
is FunctionCall -> {
|
is FunctionCall -> {
|
||||||
@ -162,7 +162,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
val returnType = value.inferType(program)
|
val returnType = value.inferType(program)
|
||||||
if(!returnType.isKnown)
|
if(!returnType.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.typeOrElse(DataType.UNDEFINED), expression = value)
|
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.getOr(DataType.UNDEFINED), expression = value)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw AssemblyError("weird call")
|
throw AssemblyError("weird call")
|
||||||
@ -173,7 +173,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
|||||||
val dt = value.inferType(program)
|
val dt = value.inferType(program)
|
||||||
if(!dt.isKnown)
|
if(!dt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt.typeOrElse(DataType.UNDEFINED), expression = value)
|
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt.getOr(DataType.UNDEFINED), expression = value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
val returntype = builtinFunctionReturnType(sub.name, value.args, program)
|
val returntype = builtinFunctionReturnType(sub.name, value.args, program)
|
||||||
if(!returntype.isKnown)
|
if(!returntype.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
when(returntype.typeOrElse(DataType.UNDEFINED)) {
|
when(returntype.getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A
|
in ByteDatatypes -> assignRegisterByte(assign.target, CpuRegister.A) // function's byte result is in A
|
||||||
in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY
|
in WordDatatypes -> assignRegisterpairWord(assign.target, RegisterOrPair.AY) // function's word result is in AY
|
||||||
DataType.STR -> {
|
DataType.STR -> {
|
||||||
@ -299,7 +299,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
val valueIDt = value.inferType(program)
|
val valueIDt = value.inferType(program)
|
||||||
if(!valueIDt.isKnown)
|
if(!valueIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED)
|
val valueDt = valueIDt.getOr(DataType.UNDEFINED)
|
||||||
if(valueDt==targetDt)
|
if(valueDt==targetDt)
|
||||||
throw AssemblyError("type cast to identical dt should have been removed")
|
throw AssemblyError("type cast to identical dt should have been removed")
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
val itype = value.inferType(program)
|
val itype = value.inferType(program)
|
||||||
if(!itype.isKnown)
|
if(!itype.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val type = itype.typeOrElse(DataType.UNDEFINED)
|
val type = itype.getOr(DataType.UNDEFINED)
|
||||||
when (value.operator) {
|
when (value.operator) {
|
||||||
"+" -> {}
|
"+" -> {}
|
||||||
"-" -> inplaceNegate(assign.target, type)
|
"-" -> inplaceNegate(assign.target, type)
|
||||||
@ -280,7 +280,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
val childIDt = value.expression.inferType(program)
|
val childIDt = value.expression.inferType(program)
|
||||||
if(!childIDt.isKnown)
|
if(!childIDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val childDt = childIDt.typeOrElse(DataType.UNDEFINED)
|
val childDt = childIDt.getOr(DataType.UNDEFINED)
|
||||||
if (value.type!=DataType.FLOAT && (value.type.equalsSize(childDt) || value.type.largerThan(childDt))) {
|
if (value.type!=DataType.FLOAT && (value.type.equalsSize(childDt) || value.type.largerThan(childDt))) {
|
||||||
// this typecast is redundant here; the rest of the code knows how to deal with the uncasted value.
|
// this typecast is redundant here; the rest of the code knows how to deal with the uncasted value.
|
||||||
// (works for integer types, not for float.)
|
// (works for integer types, not for float.)
|
||||||
@ -1218,7 +1218,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
|||||||
val valueiDt = value.inferType(program)
|
val valueiDt = value.inferType(program)
|
||||||
if(!valueiDt.isKnown)
|
if(!valueiDt.isKnown)
|
||||||
throw AssemblyError("unknown dt")
|
throw AssemblyError("unknown dt")
|
||||||
val valueDt = valueiDt.typeOrElse(DataType.UNDEFINED)
|
val valueDt = valueiDt.getOr(DataType.UNDEFINED)
|
||||||
|
|
||||||
fun multiplyVarByWordInAY() {
|
fun multiplyVarByWordInAY() {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
|
@ -105,7 +105,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
|
|||||||
// optimize various simple cases of ** :
|
// optimize various simple cases of ** :
|
||||||
// optimize away 1 ** x into just 1 and 0 ** x into just 0
|
// optimize away 1 ** x into just 1 and 0 ** x into just 0
|
||||||
// optimize 2 ** x into (1<<x) if both operands are integer.
|
// optimize 2 ** x into (1<<x) if both operands are integer.
|
||||||
val leftDt = leftconst.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val leftDt = leftconst.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
when (leftconst.number.toDouble()) {
|
when (leftconst.number.toDouble()) {
|
||||||
0.0 -> {
|
0.0 -> {
|
||||||
val value = NumericLiteralValue(leftDt, 0, expr.position)
|
val value = NumericLiteralValue(leftDt, 0, expr.position)
|
||||||
@ -120,11 +120,11 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
|
|||||||
val value = NumericLiteralValue(leftDt, 2.0.pow(rightconst.number.toDouble()), expr.position)
|
val value = NumericLiteralValue(leftDt, 2.0.pow(rightconst.number.toDouble()), expr.position)
|
||||||
modifications += IAstModification.ReplaceNode(expr, value, parent)
|
modifications += IAstModification.ReplaceNode(expr, value, parent)
|
||||||
} else {
|
} else {
|
||||||
val rightDt = expr.right.inferType(program).typeOrElse(DataType.UNDEFINED)
|
val rightDt = expr.right.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) {
|
if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) {
|
||||||
val targetDt =
|
val targetDt =
|
||||||
when (parent) {
|
when (parent) {
|
||||||
is Assignment -> parent.target.inferType(program).typeOrElse(DataType.UNDEFINED)
|
is Assignment -> parent.target.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
is VarDecl -> parent.datatype
|
is VarDecl -> parent.datatype
|
||||||
else -> leftDt
|
else -> leftDt
|
||||||
}
|
}
|
||||||
@ -186,7 +186,7 @@ internal class ConstantFoldingOptimizer(private val program: Program) : AstWalke
|
|||||||
} else {
|
} else {
|
||||||
val arrayDt = array.guessDatatype(program)
|
val arrayDt = array.guessDatatype(program)
|
||||||
if (arrayDt.isKnown) {
|
if (arrayDt.isKnown) {
|
||||||
val newArray = array.cast(arrayDt.typeOrElse(DataType.UNDEFINED))
|
val newArray = array.cast(arrayDt.getOr(DataType.UNDEFINED))
|
||||||
if (newArray != null && newArray != array)
|
if (newArray != null && newArray != array)
|
||||||
return listOf(IAstModification.ReplaceNode(array, newArray, parent))
|
return listOf(IAstModification.ReplaceNode(array, newArray, parent))
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ internal class ConstantIdentifierReplacer(private val program: Program, private
|
|||||||
errors.err("range expression size doesn't match declared array size", decl.value?.position!!)
|
errors.err("range expression size doesn't match declared array size", decl.value?.position!!)
|
||||||
val constRange = rangeExpr.toConstantIntegerRange(compTarget)
|
val constRange = rangeExpr.toConstantIntegerRange(compTarget)
|
||||||
if(constRange!=null) {
|
if(constRange!=null) {
|
||||||
val eltType = rangeExpr.inferType(program).typeOrElse(DataType.UBYTE)
|
val eltType = rangeExpr.inferType(program).getOr(DataType.UBYTE)
|
||||||
val newValue = if(eltType in ByteDatatypes) {
|
val newValue = if(eltType in ByteDatatypes) {
|
||||||
ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype),
|
ArrayLiteralValue(InferredTypes.InferredType.known(decl.datatype),
|
||||||
constRange.map { NumericLiteralValue(eltType, it.toShort(), decl.value!!.position) }.toTypedArray(),
|
constRange.map { NumericLiteralValue(eltType, it.toShort(), decl.value!!.position) }.toTypedArray(),
|
||||||
|
@ -134,8 +134,8 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
|
val leftDt = leftIDt.getOr(DataType.UNDEFINED)
|
||||||
val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED)
|
val rightDt = rightIDt.getOr(DataType.UNDEFINED)
|
||||||
|
|
||||||
if (expr.operator == "+" || expr.operator == "-"
|
if (expr.operator == "+" || expr.operator == "-"
|
||||||
&& leftVal == null && rightVal == null
|
&& leftVal == null && rightVal == null
|
||||||
@ -309,7 +309,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
// useless msb() of byte value that was typecasted to word, replace with 0
|
// useless msb() of byte value that was typecasted to word, replace with 0
|
||||||
return listOf(IAstModification.ReplaceNode(
|
return listOf(IAstModification.ReplaceNode(
|
||||||
functionCall,
|
functionCall,
|
||||||
NumericLiteralValue(valueDt.typeOrElse(DataType.UBYTE), 0, arg.expression.position),
|
NumericLiteralValue(valueDt.getOr(DataType.UBYTE), 0, arg.expression.position),
|
||||||
parent))
|
parent))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -318,7 +318,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
// useless msb() of byte value, replace with 0
|
// useless msb() of byte value, replace with 0
|
||||||
return listOf(IAstModification.ReplaceNode(
|
return listOf(IAstModification.ReplaceNode(
|
||||||
functionCall,
|
functionCall,
|
||||||
NumericLiteralValue(argDt.typeOrElse(DataType.UBYTE), 0, arg.position),
|
NumericLiteralValue(argDt.getOr(DataType.UBYTE), 0, arg.position),
|
||||||
parent))
|
parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,7 +489,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
val idt = expr.inferType(program)
|
val idt = expr.inferType(program)
|
||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
throw FatalAstException("unknown dt")
|
throw FatalAstException("unknown dt")
|
||||||
return NumericLiteralValue(idt.typeOrElse(DataType.UNDEFINED), 0, expr.position)
|
return NumericLiteralValue(idt.getOr(DataType.UNDEFINED), 0, expr.position)
|
||||||
} else if (cv in powersOfTwo) {
|
} else if (cv in powersOfTwo) {
|
||||||
expr.operator = "&"
|
expr.operator = "&"
|
||||||
expr.right = NumericLiteralValue.optimalInteger(cv!!.toInt()-1, expr.position)
|
expr.right = NumericLiteralValue.optimalInteger(cv!!.toInt()-1, expr.position)
|
||||||
@ -513,7 +513,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
val leftIDt = expr.left.inferType(program)
|
val leftIDt = expr.left.inferType(program)
|
||||||
if (!leftIDt.isKnown)
|
if (!leftIDt.isKnown)
|
||||||
return null
|
return null
|
||||||
val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
|
val leftDt = leftIDt.getOr(DataType.UNDEFINED)
|
||||||
when (cv) {
|
when (cv) {
|
||||||
-1.0 -> {
|
-1.0 -> {
|
||||||
// '/' -> -left
|
// '/' -> -left
|
||||||
@ -621,7 +621,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
val targetIDt = expr.left.inferType(program)
|
val targetIDt = expr.left.inferType(program)
|
||||||
if(!targetIDt.isKnown)
|
if(!targetIDt.isKnown)
|
||||||
throw FatalAstException("unknown dt")
|
throw FatalAstException("unknown dt")
|
||||||
when (val targetDt = targetIDt.typeOrElse(DataType.UNDEFINED)) {
|
when (val targetDt = targetIDt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
if (amount >= 8) {
|
if (amount >= 8) {
|
||||||
return NumericLiteralValue(targetDt, 0, expr.position)
|
return NumericLiteralValue(targetDt, 0, expr.position)
|
||||||
@ -656,7 +656,7 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
|
|||||||
val idt = expr.left.inferType(program)
|
val idt = expr.left.inferType(program)
|
||||||
if(!idt.isKnown)
|
if(!idt.isKnown)
|
||||||
throw FatalAstException("unknown dt")
|
throw FatalAstException("unknown dt")
|
||||||
when (idt.typeOrElse(DataType.UNDEFINED)) {
|
when (idt.getOr(DataType.UNDEFINED)) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
if (amount >= 8) {
|
if (amount >= 8) {
|
||||||
return NumericLiteralValue.optimalInteger(0, expr.position)
|
return NumericLiteralValue.optimalInteger(0, expr.position)
|
||||||
|
@ -373,7 +373,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
throw FatalAstException("can't infer type of assignment target")
|
throw FatalAstException("can't infer type of assignment target")
|
||||||
|
|
||||||
// optimize binary expressions a bit
|
// optimize binary expressions a bit
|
||||||
val targetDt = targetIDt.typeOrElse(DataType.UNDEFINED)
|
val targetDt = targetIDt.getOr(DataType.UNDEFINED)
|
||||||
val bexpr=assignment.value as? BinaryExpression
|
val bexpr=assignment.value as? BinaryExpression
|
||||||
if(bexpr!=null) {
|
if(bexpr!=null) {
|
||||||
val rightCv = bexpr.right.constValue(program)?.number?.toDouble()
|
val rightCv = bexpr.right.constValue(program)?.number?.toDouble()
|
||||||
|
@ -257,7 +257,7 @@ class TestCompilerOnRanges {
|
|||||||
.map { it.iterable }
|
.map { it.iterable }
|
||||||
.filterIsInstance<IdentifierReference>()[0]
|
.filterIsInstance<IdentifierReference>()[0]
|
||||||
|
|
||||||
assertEquals(DataType.STR, iterable.inferType(program).typeOrElse(DataType.UNDEFINED))
|
assertEquals(DataType.STR, iterable.inferType(program).getOr(DataType.UNDEFINED))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -88,14 +88,14 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
|
|||||||
return when(operator) {
|
return when(operator) {
|
||||||
"+" -> inferred
|
"+" -> inferred
|
||||||
"~", "not" -> {
|
"~", "not" -> {
|
||||||
when(inferred.typeOrElse(DataType.UNDEFINED)) {
|
when(inferred.getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes -> InferredTypes.knownFor(DataType.UBYTE)
|
in ByteDatatypes -> InferredTypes.knownFor(DataType.UBYTE)
|
||||||
in WordDatatypes -> InferredTypes.knownFor(DataType.UWORD)
|
in WordDatatypes -> InferredTypes.knownFor(DataType.UWORD)
|
||||||
else -> inferred
|
else -> inferred
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"-" -> {
|
"-" -> {
|
||||||
when(inferred.typeOrElse(DataType.UNDEFINED)) {
|
when(inferred.getOr(DataType.UNDEFINED)) {
|
||||||
in ByteDatatypes -> InferredTypes.knownFor(DataType.BYTE)
|
in ByteDatatypes -> InferredTypes.knownFor(DataType.BYTE)
|
||||||
in WordDatatypes -> InferredTypes.knownFor(DataType.WORD)
|
in WordDatatypes -> InferredTypes.knownFor(DataType.WORD)
|
||||||
else -> inferred
|
else -> inferred
|
||||||
@ -155,8 +155,8 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
try {
|
try {
|
||||||
InferredTypes.knownFor(
|
InferredTypes.knownFor(
|
||||||
commonDatatype(
|
commonDatatype(
|
||||||
leftDt.typeOrElse(DataType.BYTE),
|
leftDt.getOr(DataType.BYTE),
|
||||||
rightDt.typeOrElse(DataType.BYTE),
|
rightDt.getOr(DataType.BYTE),
|
||||||
null, null
|
null, null
|
||||||
).first
|
).first
|
||||||
)
|
)
|
||||||
@ -597,7 +597,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
|
|||||||
|
|
||||||
fun memsize(memsizer: IMemSizer): Int {
|
fun memsize(memsizer: IMemSizer): Int {
|
||||||
if(type.isKnown) {
|
if(type.isKnown) {
|
||||||
val eltType = ArrayToElementTypes.getValue(type.typeOrElse(DataType.UNDEFINED))
|
val eltType = ArrayToElementTypes.getValue(type.getOr(DataType.UNDEFINED))
|
||||||
return memsizer.memorySize(eltType) * value.size
|
return memsizer.memorySize(eltType) * value.size
|
||||||
}
|
}
|
||||||
else throw IllegalArgumentException("array datatype is not yet known")
|
else throw IllegalArgumentException("array datatype is not yet known")
|
||||||
@ -613,14 +613,14 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
|
|||||||
return if(!loopvarDt.isArrayElement)
|
return if(!loopvarDt.isArrayElement)
|
||||||
InferredTypes.InferredType.unknown()
|
InferredTypes.InferredType.unknown()
|
||||||
else
|
else
|
||||||
InferredTypes.InferredType.known(ElementToArrayTypes.getValue(loopvarDt.typeOrElse(DataType.UNDEFINED)))
|
InferredTypes.InferredType.known(ElementToArrayTypes.getValue(loopvarDt.getOr(DataType.UNDEFINED)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, select the "biggegst" datatype based on the elements in the array.
|
// otherwise, select the "biggegst" datatype based on the elements in the array.
|
||||||
val datatypesInArray = value.map { it.inferType(program) }
|
val datatypesInArray = value.map { it.inferType(program) }
|
||||||
require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
|
require(datatypesInArray.isNotEmpty() && datatypesInArray.all { it.isKnown }) { "can't determine type of empty array" }
|
||||||
val dts = datatypesInArray.map { it.typeOrElse(DataType.UNDEFINED) }
|
val dts = datatypesInArray.map { it.getOr(DataType.UNDEFINED) }
|
||||||
return when {
|
return when {
|
||||||
DataType.FLOAT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_F)
|
DataType.FLOAT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_F)
|
||||||
DataType.STR in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
|
DataType.STR in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
|
||||||
@ -705,8 +705,8 @@ class RangeExpr(var from: Expression,
|
|||||||
fromDt istype DataType.WORD || toDt istype DataType.WORD -> InferredTypes.knownFor(DataType.ARRAY_W)
|
fromDt istype DataType.WORD || toDt istype DataType.WORD -> InferredTypes.knownFor(DataType.ARRAY_W)
|
||||||
fromDt istype DataType.BYTE || toDt istype DataType.BYTE -> InferredTypes.knownFor(DataType.ARRAY_B)
|
fromDt istype DataType.BYTE || toDt istype DataType.BYTE -> InferredTypes.knownFor(DataType.ARRAY_B)
|
||||||
else -> {
|
else -> {
|
||||||
val fdt = fromDt.typeOrElse(DataType.UNDEFINED)
|
val fdt = fromDt.getOr(DataType.UNDEFINED)
|
||||||
val tdt = toDt.typeOrElse(DataType.UNDEFINED)
|
val tdt = toDt.getOr(DataType.UNDEFINED)
|
||||||
if(fdt largerThan tdt)
|
if(fdt largerThan tdt)
|
||||||
InferredTypes.knownFor(ElementToArrayTypes.getValue(fdt))
|
InferredTypes.knownFor(ElementToArrayTypes.getValue(fdt))
|
||||||
else
|
else
|
||||||
|
@ -11,7 +11,9 @@ object InferredTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isKnown = datatype!=null && datatype!=DataType.UNDEFINED
|
val isKnown = datatype!=null && datatype!=DataType.UNDEFINED
|
||||||
fun typeOrElse(alternative: DataType) = if(isUnknown || isVoid) alternative else datatype!!
|
fun getOr(default: DataType) = if(isUnknown || isVoid) default else datatype!!
|
||||||
|
fun getOrElse(transform: (InferredType) -> DataType): DataType =
|
||||||
|
if(isUnknown || isVoid) transform(this) else datatype!!
|
||||||
infix fun istype(type: DataType): Boolean = if(isUnknown || isVoid) false else this.datatype==type
|
infix fun istype(type: DataType): Boolean = if(isUnknown || isVoid) false else this.datatype==type
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -181,7 +181,7 @@ open class VarDecl(val type: VarDeclType,
|
|||||||
if(!array.type.isKnown)
|
if(!array.type.isKnown)
|
||||||
throw FatalAstException("unknown dt")
|
throw FatalAstException("unknown dt")
|
||||||
else
|
else
|
||||||
array.type.typeOrElse(DataType.UNDEFINED)
|
array.type.getOr(DataType.UNDEFINED)
|
||||||
val declaredType = ArrayToElementTypes.getValue(arrayDt)
|
val declaredType = ArrayToElementTypes.getValue(arrayDt)
|
||||||
val arraysize = ArrayIndex.forArray(array)
|
val arraysize = ArrayIndex.forArray(array)
|
||||||
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
return VarDecl(VarDeclType.VAR, declaredType, ZeropageWish.NOT_IN_ZEROPAGE, arraysize, autoVarName, array,
|
||||||
|
@ -8,7 +8,6 @@ For next release
|
|||||||
- can Position.file be a Path- making the source variable for nodes unnecessary?
|
- can Position.file be a Path- making the source variable for nodes unnecessary?
|
||||||
|
|
||||||
|
|
||||||
- refactor code to improve testability and other things, see [CompilerDevelopment](CompilerDevelopment.md)
|
|
||||||
- simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203
|
- simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203
|
||||||
(I hope this will still be included into the final v39 roms release for the cx16)
|
(I hope this will still be included into the final v39 roms release for the cx16)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user