removed Datatype.STRUCT

This commit is contained in:
Irmen de Jong 2021-04-29 00:11:41 +02:00
parent a9a7068818
commit 8d3d5f726a
27 changed files with 115 additions and 120 deletions

View File

@ -147,7 +147,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.STRUCT) val sourceDt = typecast.expression.inferType(program).typeOrElse(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) {
@ -225,7 +225,7 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I
} }
// private fun addIfOperandVar(sub: Subroutine, side: String, operand: Expression): Triple<VarDecl, Boolean, Assignment> { // private fun addIfOperandVar(sub: Subroutine, side: String, operand: Expression): Triple<VarDecl, Boolean, Assignment> {
// val dt = operand.inferType(program).typeOrElse(DataType.STRUCT) // val dt = operand.inferType(program).typeOrElse(DataType.UNDEFINED)
// val varname = "prog8_ifvar_${side}_${dt.name.toLowerCase()}" // val varname = "prog8_ifvar_${side}_${dt.name.toLowerCase()}"
// val tgt = AssignTarget(IdentifierReference(listOf(varname), operand.position), null, null, operand.position) // val tgt = AssignTarget(IdentifierReference(listOf(varname), operand.position), null, null, operand.position)
// val assign = Assignment(tgt, operand, operand.position) // val assign = Assignment(tgt, operand, operand.position)
@ -267,8 +267,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.STRUCT) val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED)
val dt2 = arg2.inferType(program).typeOrElse(DataType.STRUCT) val dt2 = arg2.inferType(program).typeOrElse(DataType.UNDEFINED)
if(dt1 in ByteDatatypes) { if(dt1 in ByteDatatypes) {
if(dt2 in ByteDatatypes) if(dt2 in ByteDatatypes)
return noModifications return noModifications

View File

@ -78,7 +78,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.STRUCT)) if (expectedReturnValues[0] != valueDt.typeOrElse(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)
} }
} }
@ -86,7 +86,7 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(ifStatement: IfStatement) { override fun visit(ifStatement: IfStatement) {
if(ifStatement.condition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes) if(ifStatement.condition.inferType(program).typeOrElse(DataType.UNDEFINED) !in IntegerDatatypes)
errors.err("condition value should be an integer type", ifStatement.condition.position) errors.err("condition value should be an integer type", ifStatement.condition.position)
super.visit(ifStatement) super.visit(ifStatement)
} }
@ -386,13 +386,13 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(untilLoop: UntilLoop) { override fun visit(untilLoop: UntilLoop) {
if(untilLoop.condition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes) if(untilLoop.condition.inferType(program).typeOrElse(DataType.UNDEFINED) !in IntegerDatatypes)
errors.err("condition value should be an integer type", untilLoop.condition.position) errors.err("condition value should be an integer type", untilLoop.condition.position)
super.visit(untilLoop) super.visit(untilLoop)
} }
override fun visit(whileLoop: WhileLoop) { override fun visit(whileLoop: WhileLoop) {
if(whileLoop.condition.inferType(program).typeOrElse(DataType.STRUCT) !in IntegerDatatypes) if(whileLoop.condition.inferType(program).typeOrElse(DataType.UNDEFINED) !in IntegerDatatypes)
errors.err("condition value should be an integer type", whileLoop.condition.position) errors.err("condition value should be an integer type", whileLoop.condition.position)
super.visit(whileLoop) super.visit(whileLoop)
} }
@ -421,7 +421,7 @@ internal class AstChecker(private val program: Program,
val targetDt = assignment.target.inferType(program) val targetDt = assignment.target.inferType(program)
val valueDt = assignment.value.inferType(program) val valueDt = assignment.value.inferType(program)
if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) { if(valueDt.isKnown && !(valueDt isAssignableTo targetDt)) {
if(targetDt.typeOrElse(DataType.STRUCT) in IterableDatatypes) if(targetDt.typeOrElse(DataType.UNDEFINED) in IterableDatatypes)
errors.err("cannot assign value to string or array", assignment.value.position) errors.err("cannot assign value to string or array", assignment.value.position)
else if(!(valueDt.istype(DataType.STR) && targetDt.istype(DataType.UWORD))) else if(!(valueDt.istype(DataType.STR) && targetDt.istype(DataType.UWORD)))
errors.err("type of value doesn't match target", assignment.value.position) errors.err("type of value doesn't match target", assignment.value.position)
@ -735,11 +735,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.STRUCT) in setOf(DataType.FLOAT, DataType.ARRAY_F)) { if (!compilerOptions.floats && array.type.typeOrElse(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.STRUCT), arrayspec, array) checkValueTypeAndRangeArray(array.type.typeOrElse(DataType.UNDEFINED), arrayspec, array)
} }
fun isPassByReferenceElement(e: Expression): Boolean { fun isPassByReferenceElement(e: Expression): Boolean {
@ -771,7 +771,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.STRUCT) val dt = idt.typeOrElse(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)
@ -796,8 +796,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.STRUCT) val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
val rightDt = rightIDt.typeOrElse(DataType.STRUCT) val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED)
when(expr.operator){ when(expr.operator){
"/", "%" -> { "/", "%" -> {
@ -998,7 +998,7 @@ internal class AstChecker(private val program: Program,
errors.err("swap requires 2 variables, not constant value(s)", position) errors.err("swap requires 2 variables, not constant value(s)", position)
else if(args[0] isSameAs args[1]) else if(args[0] isSameAs args[1])
errors.err("swap should have 2 different args", position) errors.err("swap should have 2 different args", position)
else if(dt1.typeOrElse(DataType.STRUCT) !in NumericDatatypes) else if(dt1.typeOrElse(DataType.UNDEFINED) !in NumericDatatypes)
errors.err("swap requires args of numerical type", position) errors.err("swap requires args of numerical type", position)
} }
else if(target.name=="all" || target.name=="any") { else if(target.name=="all" || target.name=="any") {
@ -1103,7 +1103,7 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(whenStatement: WhenStatement) { override fun visit(whenStatement: WhenStatement) {
val conditionType = whenStatement.condition.inferType(program).typeOrElse(DataType.STRUCT) val conditionType = whenStatement.condition.inferType(program).typeOrElse(DataType.UNDEFINED)
if(conditionType !in IntegerDatatypes) if(conditionType !in IntegerDatatypes)
errors.err("when condition must be an integer value", whenStatement.position) errors.err("when condition must be an integer value", whenStatement.position)
val tally = mutableSetOf<Int>() val tally = mutableSetOf<Int>()
@ -1135,7 +1135,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.STRUCT) -> errors.err("choice value datatype differs from condition value", whenChoice.position) constvalue.type != conditionType.typeOrElse(DataType.UNDEFINED) -> errors.err("choice value datatype differs from condition value", whenChoice.position)
} }
} }
} else { } else {

View File

@ -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.STRUCT)) val litval2 = array.cast(arrayDt.typeOrElse(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)

View File

@ -124,7 +124,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.STRUCT), true, parent.position) val cast = TypecastExpression(expr.left, targetDt.typeOrElse(DataType.UNDEFINED), true, parent.position)
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr)) return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
} }
} }
@ -208,7 +208,7 @@ internal class StatementReorderer(val program: Program, val errors: IErrorReport
val valueType = assignment.value.inferType(program) val valueType = assignment.value.inferType(program)
val targetType = assignment.target.inferType(program) val targetType = assignment.target.inferType(program)
if(targetType.typeOrElse(DataType.STRUCT) in ArrayDatatypes && valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes ) { if(targetType.typeOrElse(DataType.UNDEFINED) in ArrayDatatypes && valueType.typeOrElse(DataType.UNDEFINED) in ArrayDatatypes ) {
if (assignment.value is ArrayLiteralValue) { if (assignment.value is ArrayLiteralValue) {
errors.err("cannot assign array literal here, use separate assignment per element", assignment.position) errors.err("cannot assign array literal here, use separate assignment per element", assignment.position)
} else { } else {

View File

@ -25,7 +25,7 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
if(!valueDt.istype(decl.datatype)) { if(!valueDt.istype(decl.datatype)) {
// don't add a typecast on an array initializer value // don't add a typecast on an array initializer value
if(valueDt.typeOrElse(DataType.STRUCT) in IntegerDatatypes && decl.datatype in ArrayDatatypes) if(valueDt.typeOrElse(DataType.UNDEFINED) in IntegerDatatypes && decl.datatype in ArrayDatatypes)
return noModifications return noModifications
// don't add a typecast if the initializer value is inherently not assignable // don't add a typecast if the initializer value is inherently not assignable
@ -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.STRUCT), rightDt.typeOrElse(DataType.STRUCT), expr.left, expr.right) val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.typeOrElse(DataType.UNDEFINED), rightDt.typeOrElse(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.STRUCT) val targettype = targetItype.typeOrElse(DataType.UNDEFINED)
val valuetype = valueItype.typeOrElse(DataType.STRUCT) val valuetype = valueItype.typeOrElse(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.STRUCT) val argtype = argItype.typeOrElse(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.STRUCT) val argtype = argItype.typeOrElse(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) {

View File

@ -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.STRUCT) } val argtypes = argITypes.map { it.typeOrElse(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)

View File

@ -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.STRUCT)}.toSet() val dt = arglist.value.map {it.inferType(program).typeOrElse(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.STRUCT)) { return when(val dt = idt.typeOrElse(DataType.UNDEFINED)) {
DataType.STR, in NumericDatatypes -> dt DataType.STR, in NumericDatatypes -> dt
in ArrayDatatypes -> ArrayElementTypes.getValue(dt) in ArrayDatatypes -> ArrayElementTypes.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")
@ -195,7 +195,7 @@ fun builtinFunctionReturnType(function: String, args: List<Expression>, program:
return when (function) { return when (function) {
"abs" -> { "abs" -> {
val dt = args.single().inferType(program) val dt = args.single().inferType(program)
return if(dt.typeOrElse(DataType.STRUCT) in NumericDatatypes) return if(dt.typeOrElse(DataType.UNDEFINED) in NumericDatatypes)
dt dt
else else
InferredTypes.InferredType.unknown() InferredTypes.InferredType.unknown()
@ -300,13 +300,13 @@ private fun builtinSizeof(args: List<Expression>, position: Position, program: P
?: throw CannotEvaluateException("sizeof", "no target") ?: throw CannotEvaluateException("sizeof", "no target")
return when { return when {
dt.typeOrElse(DataType.STRUCT) in ArrayDatatypes -> { dt.typeOrElse(DataType.UNDEFINED) in ArrayDatatypes -> {
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 = ArrayElementTypes.getValue(dt.typeOrElse(DataType.STRUCT)) val elementDt = ArrayElementTypes.getValue(dt.typeOrElse(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.STRUCT)), position) else -> NumericLiteralValue(DataType.UBYTE, memsizer.memorySize(dt.typeOrElse(DataType.UNDEFINED)), position)
} }
} else { } else {
throw SyntaxError("sizeof invalid argument type", position) throw SyntaxError("sizeof invalid argument type", position)

View File

@ -290,7 +290,6 @@ internal class AsmGen(private val program: Program,
DataType.UWORD -> out("$name\t.word 0") DataType.UWORD -> out("$name\t.word 0")
DataType.WORD -> out("$name\t.sint 0") DataType.WORD -> out("$name\t.sint 0")
DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float") DataType.FLOAT -> out("$name\t.byte 0,0,0,0,0 ; float")
DataType.STRUCT -> {} // is flattened
DataType.STR -> { DataType.STR -> {
val str = decl.value as StringLiteralValue val str = decl.value as StringLiteralValue
outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0)) outputStringvar(decl, compTarget.encodeString(str.value, str.altEncoding).plus(0))
@ -990,7 +989,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.STRUCT)) { when (dt.typeOrElse(DataType.UNDEFINED)) {
in ByteDatatypes -> { in ByteDatatypes -> {
assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A) assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A)
repeatByteCountInA(null, repeatLabel, endLabel, stmt.body) repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)

View File

@ -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.STRUCT) val dt1 = arg1.inferType(program).typeOrElse(DataType.UNDEFINED)
val dt2 = arg2.inferType(program).typeOrElse(DataType.STRUCT) val dt2 = arg2.inferType(program).typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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.STRUCT)) { when (dt.typeOrElse(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)
@ -782,7 +782,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.STRUCT) val elementDt = elementIDt.typeOrElse(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
@ -815,7 +815,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
} }
} }
val datatype = first.inferType(program).typeOrElse(DataType.STRUCT) val datatype = first.inferType(program).typeOrElse(DataType.UNDEFINED)
when(datatype) { when(datatype) {
in ByteDatatypes, in WordDatatypes -> { in ByteDatatypes, in WordDatatypes -> {
asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null) asmgen.assignExpressionToVariable(first, "P8ZP_SCRATCH_W1", datatype, null)
@ -1086,7 +1086,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.STRUCT) val dt = fcall.args.single().inferType(program).typeOrElse(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")
@ -1321,7 +1321,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
private fun funcMsb(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) { private fun funcMsb(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single() val arg = fcall.args.single()
if (arg.inferType(program).typeOrElse(DataType.STRUCT) !in WordDatatypes) if (arg.inferType(program).typeOrElse(DataType.UNDEFINED) !in WordDatatypes)
throw AssemblyError("msb required word argument") throw AssemblyError("msb required word argument")
if (arg is NumericLiteralValue) if (arg is NumericLiteralValue)
throw AssemblyError("msb(const) should have been const-folded away") throw AssemblyError("msb(const) should have been const-folded away")
@ -1365,7 +1365,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
private fun funcLsb(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) { private fun funcLsb(fcall: IFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single() val arg = fcall.args.single()
if (arg.inferType(program).typeOrElse(DataType.STRUCT) !in WordDatatypes) if (arg.inferType(program).typeOrElse(DataType.UNDEFINED) !in WordDatatypes)
throw AssemblyError("lsb required word argument") throw AssemblyError("lsb required word argument")
if (arg is NumericLiteralValue) if (arg is NumericLiteralValue)
throw AssemblyError("lsb(const) should have been const-folded away") throw AssemblyError("lsb(const) should have been const-folded away")
@ -1429,7 +1429,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.STRUCT) }) val callConv = signature.callConvention(args.map { it.inferType(program).typeOrElse(DataType.UNDEFINED) })
fun getSourceForFloat(value: Expression): AsmAssignSource { fun getSourceForFloat(value: Expression): AsmAssignSource {
return when (value) { return when (value) {

View File

@ -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.STRUCT) val dt = idt.typeOrElse(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,
@ -1625,7 +1625,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.STRUCT)) { when(typecast.expression.inferType(program).typeOrElse(DataType.UNDEFINED)) {
DataType.UBYTE -> { DataType.UBYTE -> {
when(typecast.type) { when(typecast.type) {
DataType.UBYTE, DataType.BYTE -> {} DataType.UBYTE, DataType.BYTE -> {}
@ -1756,7 +1756,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.STRUCT)) { when(expr.inferType(program).typeOrElse(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")
} }
@ -1780,8 +1780,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.STRUCT) val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
val rightDt = rightIDt.typeOrElse(DataType.STRUCT) val rightDt = rightIDt.typeOrElse(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) {
@ -2107,7 +2107,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.STRUCT) val type = itype.typeOrElse(DataType.UNDEFINED)
when(expr.operator) { when(expr.operator) {
"+" -> {} "+" -> {}
"-" -> { "-" -> {
@ -2145,7 +2145,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.STRUCT) val elementDt = elementIDt.typeOrElse(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) {

View File

@ -21,13 +21,13 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
is RangeExpr -> { is RangeExpr -> {
val range = (stmt.iterable as RangeExpr).toConstantIntegerRange() val range = (stmt.iterable as RangeExpr).toConstantIntegerRange()
if(range==null) { if(range==null) {
translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), stmt.iterable as RangeExpr) translateForOverNonconstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), stmt.iterable as RangeExpr)
} else { } else {
translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.STRUCT), range) translateForOverConstRange(stmt, iterableDt.typeOrElse(DataType.UNDEFINED), range)
} }
} }
is IdentifierReference -> { is IdentifierReference -> {
translateForOverIterableVar(stmt, iterableDt.typeOrElse(DataType.STRUCT), stmt.iterable as IdentifierReference) translateForOverIterableVar(stmt, iterableDt.typeOrElse(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")
} }
@ -588,5 +588,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.STRUCT), stmt.definingSubroutine()) asmgen.assignExpressionToVariable(range.from, asmgen.asmVariableName(stmt.loopVar), stmt.loopVarDt(program).typeOrElse(DataType.UNDEFINED), stmt.definingSubroutine())
} }

View File

@ -244,7 +244,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.STRUCT) val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED)
if(!isArgumentTypeCompatible(valueDt, parameter.value.type)) if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
throw AssemblyError("argument type incompatible") throw AssemblyError("argument type incompatible")
@ -257,7 +257,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.STRUCT) val valueDt = valueIDt.typeOrElse(DataType.UNDEFINED)
if(!isArgumentTypeCompatible(valueDt, parameter.value.type)) if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
throw AssemblyError("argument type incompatible") throw AssemblyError("argument type incompatible")

View File

@ -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.STRUCT)) { when (stmt.target.inferType(program).typeOrElse(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.STRUCT) val elementDt = targetArrayIdx.inferType(program).typeOrElse(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)

View File

@ -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.STRUCT) val dt = idt.typeOrElse(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.STRUCT) val dt = value.inferType(program).typeOrElse(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.toLowerCase().startsWith("cx16.r")) { if(dt==DataType.UWORD && varName.toLowerCase().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.STRUCT) val dt = value.inferType(program).typeOrElse(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.STRUCT), expression = value) AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.typeOrElse(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.STRUCT), expression = value) AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, dt.typeOrElse(DataType.UNDEFINED), expression = value)
} }
} }
} }
@ -206,7 +206,7 @@ internal class AsmAssignment(val source: AsmAssignSource,
init { init {
if(target.register !in setOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY)) if(target.register !in setOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY))
require(source.datatype != DataType.STRUCT) { "must not be placeholder datatype" } require(source.datatype != DataType.UNDEFINED) { "must not be placeholder/undefined datatype" }
require(memsizer.memorySize(source.datatype) <= memsizer.memorySize(target.datatype)) { require(memsizer.memorySize(source.datatype) <= memsizer.memorySize(target.datatype)) {
"source storage size must be less or equal to target datatype storage size" "source storage size must be less or equal to target datatype storage size"
} }

View File

@ -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.STRUCT)) { when(returntype.typeOrElse(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.STRUCT) val valueDt = valueIDt.typeOrElse(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")
@ -359,7 +359,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
// special case optimizations // special case optimizations
if(target.kind== TargetStorageKind.VARIABLE) { if(target.kind== TargetStorageKind.VARIABLE) {
if(value is IdentifierReference && valueDt != DataType.STRUCT) if(value is IdentifierReference && valueDt != DataType.UNDEFINED)
return assignTypeCastedIdentifier(target.asmVarname, targetDt, asmgen.asmVariableName(value), valueDt) return assignTypeCastedIdentifier(target.asmVarname, targetDt, asmgen.asmVariableName(value), valueDt)
when (valueDt) { when (valueDt) {

View File

@ -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.STRUCT) val type = itype.typeOrElse(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.STRUCT) val childDt = childIDt.typeOrElse(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.)
@ -1225,7 +1225,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.STRUCT) val valueDt = valueiDt.typeOrElse(DataType.UNDEFINED)
fun multiplyVarByWordInAY() { fun multiplyVarByWordInAY() {
asmgen.out(""" asmgen.out("""

View File

@ -175,7 +175,7 @@ class CallGraph(private val program: Program) : IAstVisitor {
} }
fun unused(decl: VarDecl): Boolean { fun unused(decl: VarDecl): Boolean {
if(decl.type!=VarDeclType.VAR || decl.datatype==DataType.STRUCT || decl.autogeneratedDontRemove) if(decl.type!=VarDeclType.VAR || decl.autogeneratedDontRemove)
return false return false
if(decl.definingBlock() !in usedBlocks) if(decl.definingBlock() !in usedBlocks)

View File

@ -106,7 +106,7 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
// 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.STRUCT) val leftDt = leftconst.inferType(program).typeOrElse(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)
@ -121,11 +121,11 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
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.STRUCT) val rightDt = expr.right.inferType(program).typeOrElse(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.STRUCT) is Assignment -> parent.target.inferType(program).typeOrElse(DataType.UNDEFINED)
is VarDecl -> parent.datatype is VarDecl -> parent.datatype
else -> leftDt else -> leftDt
} }
@ -187,7 +187,7 @@ internal class ConstantFoldingOptimizer(private val program: Program, private va
} 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.STRUCT)) val newArray = array.cast(arrayDt.typeOrElse(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))
} }

View File

@ -134,8 +134,8 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
)) ))
} }
val leftDt = leftIDt.typeOrElse(DataType.STRUCT) val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
val rightDt = rightIDt.typeOrElse(DataType.STRUCT) val rightDt = rightIDt.typeOrElse(DataType.UNDEFINED)
if (expr.operator == "+" || expr.operator == "-" if (expr.operator == "+" || expr.operator == "-"
&& leftVal == null && rightVal == null && leftVal == null && rightVal == null
@ -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.STRUCT), 0, expr.position) return NumericLiteralValue(idt.typeOrElse(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.STRUCT) val leftDt = leftIDt.typeOrElse(DataType.UNDEFINED)
when (cv) { when (cv) {
-1.0 -> { -1.0 -> {
// '/' -> -left // '/' -> -left
@ -590,14 +590,14 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker()
return expr2.left return expr2.left
} }
in powersOfTwo -> { in powersOfTwo -> {
if (leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) { if (leftValue.inferType(program).typeOrElse(DataType.UNDEFINED) in IntegerDatatypes) {
// times a power of two => shift left // times a power of two => shift left
val numshifts = log2(cv).toInt() val numshifts = log2(cv).toInt()
return BinaryExpression(expr2.left, "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position) return BinaryExpression(expr2.left, "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position)
} }
} }
in negativePowersOfTwo -> { in negativePowersOfTwo -> {
if (leftValue.inferType(program).typeOrElse(DataType.STRUCT) in IntegerDatatypes) { if (leftValue.inferType(program).typeOrElse(DataType.UNDEFINED) in IntegerDatatypes) {
// times a negative power of two => negate, then shift left // times a negative power of two => negate, then shift left
val numshifts = log2(-cv).toInt() val numshifts = log2(-cv).toInt()
return BinaryExpression(PrefixExpression("-", expr2.left, expr.position), "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position) return BinaryExpression(PrefixExpression("-", expr2.left, expr.position), "<<", NumericLiteralValue.optimalInteger(numshifts, expr.position), expr.position)
@ -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.STRUCT)) { when (val targetDt = targetIDt.typeOrElse(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.STRUCT)) { when (idt.typeOrElse(DataType.UNDEFINED)) {
DataType.UBYTE -> { DataType.UBYTE -> {
if (amount >= 8) { if (amount >= 8) {
return NumericLiteralValue.optimalInteger(0, expr.position) return NumericLiteralValue.optimalInteger(0, expr.position)

View File

@ -333,7 +333,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.STRUCT) val targetDt = targetIDt.typeOrElse(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()

View File

@ -86,7 +86,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
DataType.ARRAY_UW -> "uword[" DataType.ARRAY_UW -> "uword["
DataType.ARRAY_W -> "word[" DataType.ARRAY_W -> "word["
DataType.ARRAY_F -> "float[" DataType.ARRAY_F -> "float["
DataType.STRUCT -> "" // TODO STRUCT DOESN'T EXIST ANYMORE
else -> "?????" else -> "?????"
} }
} }

View File

@ -62,7 +62,7 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
val vd = it.vardecl() val vd = it.vardecl()
return VarDecl( return VarDecl(
VarDeclType.VAR, VarDeclType.VAR,
vd.datatype()?.toAst() ?: DataType.STRUCT, vd.datatype()?.toAst() ?: DataType.UNDEFINED,
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE, if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
vd.arrayindex()?.toAst(encoding), vd.arrayindex()?.toAst(encoding),
vd.varname.text, vd.varname.text,
@ -78,7 +78,7 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
val vd = cvarinit.vardecl() val vd = cvarinit.vardecl()
return VarDecl( return VarDecl(
VarDeclType.CONST, VarDeclType.CONST,
vd.datatype()?.toAst() ?: DataType.STRUCT, vd.datatype()?.toAst() ?: DataType.UNDEFINED,
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE, if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
vd.arrayindex()?.toAst(encoding), vd.arrayindex()?.toAst(encoding),
vd.varname.text, vd.varname.text,
@ -94,7 +94,7 @@ private fun prog8Parser.VariabledeclarationContext.toAst(encoding: IStringEncodi
val vd = mvarinit.vardecl() val vd = mvarinit.vardecl()
return VarDecl( return VarDecl(
VarDeclType.MEMORY, VarDeclType.MEMORY,
vd.datatype()?.toAst() ?: DataType.STRUCT, vd.datatype()?.toAst() ?: DataType.UNDEFINED,
if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE, if (vd.ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
vd.arrayindex()?.toAst(encoding), vd.arrayindex()?.toAst(encoding),
vd.varname.text, vd.varname.text,
@ -255,7 +255,7 @@ private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn>
private fun prog8Parser.Asmsub_paramsContext.toAst(): List<AsmSubroutineParameter> private fun prog8Parser.Asmsub_paramsContext.toAst(): List<AsmSubroutineParameter>
= asmsub_param().map { = asmsub_param().map {
val vardecl = it.vardecl() val vardecl = it.vardecl()
val datatype = vardecl.datatype()?.toAst() ?: DataType.STRUCT val datatype = vardecl.datatype()?.toAst() ?: DataType.UNDEFINED
val register = it.register().text val register = it.register().text
var registerorpair: RegisterOrPair? = null var registerorpair: RegisterOrPair? = null
var statusregister: Statusflag? = null var statusregister: Statusflag? = null
@ -321,7 +321,7 @@ private fun prog8Parser.Sub_return_partContext.toAst(): List<DataType> {
private fun prog8Parser.Sub_paramsContext.toAst(): List<SubroutineParameter> = private fun prog8Parser.Sub_paramsContext.toAst(): List<SubroutineParameter> =
vardecl().map { vardecl().map {
val datatype = it.datatype()?.toAst() ?: DataType.STRUCT val datatype = it.datatype()?.toAst() ?: DataType.UNDEFINED
SubroutineParameter(it.varname.text, datatype, it.toPosition()) SubroutineParameter(it.varname.text, datatype, it.toPosition())
} }
@ -594,7 +594,7 @@ private fun prog8Parser.When_choiceContext.toAst(encoding: IStringEncoding): Whe
private fun prog8Parser.VardeclContext.toAst(encoding: IStringEncoding): VarDecl { private fun prog8Parser.VardeclContext.toAst(encoding: IStringEncoding): VarDecl {
return VarDecl( return VarDecl(
VarDeclType.VAR, VarDeclType.VAR,
datatype()?.toAst() ?: DataType.STRUCT, datatype()?.toAst() ?: DataType.UNDEFINED,
if(ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE, if(ZEROPAGE() != null) ZeropageWish.PREFER_ZEROPAGE else ZeropageWish.DONTCARE,
arrayindex()?.toAst(encoding), arrayindex()?.toAst(encoding),
varname.text, varname.text,

View File

@ -17,7 +17,7 @@ enum class DataType {
ARRAY_UW, // pass by reference ARRAY_UW, // pass by reference
ARRAY_W, // pass by reference ARRAY_W, // pass by reference
ARRAY_F, // pass by reference ARRAY_F, // pass by reference
STRUCT; // pass by reference UNDEFINED;
/** /**
* is the type assignable to the given other type (perhaps via a typecast) without loss of precision? * is the type assignable to the given other type (perhaps via a typecast) without loss of precision?
@ -140,7 +140,7 @@ val IterableDatatypes = setOf(
DataType.ARRAY_F DataType.ARRAY_F
) )
val PassByValueDatatypes = NumericDatatypes val PassByValueDatatypes = NumericDatatypes
val PassByReferenceDatatypes = IterableDatatypes.plus(DataType.STRUCT) val PassByReferenceDatatypes = IterableDatatypes
val ArrayElementTypes = mapOf( val ArrayElementTypes = mapOf(
DataType.STR to DataType.UBYTE, DataType.STR to DataType.UBYTE,
DataType.ARRAY_B to DataType.BYTE, DataType.ARRAY_B to DataType.BYTE,

View File

@ -89,14 +89,14 @@ class PrefixExpression(val operator: String, var expression: Expression, overrid
return when(operator) { return when(operator) {
"+" -> inferred "+" -> inferred
"~", "not" -> { "~", "not" -> {
when(inferred.typeOrElse(DataType.STRUCT)) { when(inferred.typeOrElse(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.STRUCT)) { when(inferred.typeOrElse(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
@ -567,7 +567,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 = ArrayElementTypes.getValue(type.typeOrElse(DataType.STRUCT)) val eltType = ArrayElementTypes.getValue(type.typeOrElse(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")
@ -580,17 +580,17 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
if(forloop != null) { if(forloop != null) {
val loopvarDt = forloop.loopVarDt(program) val loopvarDt = forloop.loopVarDt(program)
if(loopvarDt.isKnown) { if(loopvarDt.isKnown) {
return if(loopvarDt.typeOrElse(DataType.STRUCT) !in ElementArrayTypes) return if(loopvarDt.typeOrElse(DataType.UNDEFINED) !in ElementArrayTypes)
InferredTypes.InferredType.unknown() InferredTypes.InferredType.unknown()
else else
InferredTypes.InferredType.known(ElementArrayTypes.getValue(loopvarDt.typeOrElse(DataType.STRUCT))) InferredTypes.InferredType.known(ElementArrayTypes.getValue(loopvarDt.typeOrElse(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.STRUCT) } val dts = datatypesInArray.map { it.typeOrElse(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)
@ -602,8 +602,7 @@ class ArrayLiteralValue(val type: InferredTypes.InferredType, // inferred be
DataType.ARRAY_W in dts || DataType.ARRAY_W in dts ||
DataType.ARRAY_UB in dts || DataType.ARRAY_UB in dts ||
DataType.ARRAY_B in dts || DataType.ARRAY_B in dts ||
DataType.ARRAY_F in dts || DataType.ARRAY_F in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
DataType.STRUCT in dts -> InferredTypes.InferredType.known(DataType.ARRAY_UW)
else -> InferredTypes.InferredType.unknown() else -> InferredTypes.InferredType.unknown()
} }
} }
@ -677,8 +676,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.STRUCT) val fdt = fromDt.typeOrElse(DataType.UNDEFINED)
val tdt = toDt.typeOrElse(DataType.STRUCT) val tdt = toDt.typeOrElse(DataType.UNDEFINED)
if(fdt largerThan tdt) if(fdt largerThan tdt)
InferredTypes.knownFor(ElementArrayTypes.getValue(fdt)) InferredTypes.knownFor(ElementArrayTypes.getValue(fdt))
else else

View File

@ -57,8 +57,7 @@ object InferredTypes {
DataType.ARRAY_B to InferredType.known(DataType.ARRAY_B), DataType.ARRAY_B to InferredType.known(DataType.ARRAY_B),
DataType.ARRAY_UW to InferredType.known(DataType.ARRAY_UW), DataType.ARRAY_UW to InferredType.known(DataType.ARRAY_UW),
DataType.ARRAY_W to InferredType.known(DataType.ARRAY_W), DataType.ARRAY_W to InferredType.known(DataType.ARRAY_W),
DataType.ARRAY_F to InferredType.known(DataType.ARRAY_F), DataType.ARRAY_F to InferredType.known(DataType.ARRAY_F)
DataType.STRUCT to InferredType.known(DataType.STRUCT)
) )
fun void() = voidInstance fun void() = voidInstance

View File

@ -179,7 +179,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.STRUCT) array.type.typeOrElse(DataType.UNDEFINED)
val declaredType = ArrayElementTypes.getValue(arrayDt) val declaredType = ArrayElementTypes.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,

View File

@ -2,11 +2,9 @@
TODO TODO
==== ====
- get rid of Datatype.STRUCT
- fix problem that unused vars are no longer properly removed - fix problem that unused vars are no longer properly removed
- BeforeAsmGenerationAstChanger no longer needs to move vardecls?? - BeforeAsmGenerationAstChanger no longer needs to move vardecls??
- 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
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking) - c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- get rid of all other TODO's in the code ;-) - get rid of all other TODO's in the code ;-)
@ -14,6 +12,7 @@ TODO
Low prio Low prio
^^^^^^^^ ^^^^^^^^
- see if we can improve the ".typeOrElse(DataType.UNDEFINED)" to not depend on the DEFINED anymore or at least less
- optimize several inner loops in gfx2 even further? - optimize several inner loops in gfx2 even further?
- add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)? - add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)?
- add a flood fill routine to gfx2? - add a flood fill routine to gfx2?