more consistent naming of the statement classes

This commit is contained in:
Irmen de Jong
2021-12-28 13:56:47 +01:00
parent 6e11b8ada1
commit 7b54aa0c7d
30 changed files with 340 additions and 317 deletions

View File

@@ -760,7 +760,7 @@ class AsmGen(private val program: Program,
outputSourceLine(stmt) outputSourceLine(stmt)
when(stmt) { when(stmt) {
is VarDecl -> translate(stmt) is VarDecl -> translate(stmt)
is NopStatement -> {} is Nop -> {}
is Directive -> translate(stmt) is Directive -> translate(stmt)
is Return -> translate(stmt) is Return -> translate(stmt)
is Subroutine -> translateSubroutine(stmt) is Subroutine -> translateSubroutine(stmt)
@@ -779,13 +779,13 @@ class AsmGen(private val program: Program,
is GoSub -> translate(stmt) is GoSub -> translate(stmt)
is PostIncrDecr -> postincrdecrAsmGen.translate(stmt) is PostIncrDecr -> postincrdecrAsmGen.translate(stmt)
is Label -> translate(stmt) is Label -> translate(stmt)
is BranchStatement -> translate(stmt) is Branch -> translate(stmt)
is IfStatement -> translate(stmt) is IfElse -> translate(stmt)
is ForLoop -> forloopsAsmGen.translate(stmt) is ForLoop -> forloopsAsmGen.translate(stmt)
is RepeatLoop -> translate(stmt) is RepeatLoop -> translate(stmt)
is WhenStatement -> translate(stmt) is When -> translate(stmt)
is AnonymousScope -> translate(stmt) is AnonymousScope -> translate(stmt)
is BuiltinFunctionStatementPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore") is BuiltinFunctionPlaceholder -> throw AssemblyError("builtin function should not have placeholder anymore")
is UntilLoop -> throw AssemblyError("do..until should have been desugared to jumps") is UntilLoop -> throw AssemblyError("do..until should have been desugared to jumps")
is WhileLoop -> throw AssemblyError("while should have been desugared to jumps") is WhileLoop -> throw AssemblyError("while should have been desugared to jumps")
is Block -> throw AssemblyError("block should have been handled elsewhere") is Block -> throw AssemblyError("block should have been handled elsewhere")
@@ -890,11 +890,11 @@ class AsmGen(private val program: Program,
internal fun translateExpression(expression: Expression) = internal fun translateExpression(expression: Expression) =
expressionsAsmGen.translateExpression(expression) expressionsAsmGen.translateExpression(expression)
internal fun translateBuiltinFunctionCallExpression(functionCall: FunctionCall, signature: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) = internal fun translateBuiltinFunctionCallExpression(functionCallExpr: FunctionCallExpr, signature: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) =
builtinFunctionsAsmGen.translateFunctioncallExpression(functionCall, signature, resultToStack, resultRegister) builtinFunctionsAsmGen.translateFunctioncallExpression(functionCallExpr, signature, resultToStack, resultRegister)
internal fun translateFunctionCall(functionCall: FunctionCall, isExpression: Boolean) = internal fun translateFunctionCall(functionCallExpr: FunctionCallExpr, isExpression: Boolean) =
functioncallAsmGen.translateFunctionCall(functionCall, isExpression) functioncallAsmGen.translateFunctionCall(functionCallExpr, isExpression)
internal fun saveXbeforeCall(functionCall: IFunctionCall) = internal fun saveXbeforeCall(functionCall: IFunctionCall) =
functioncallAsmGen.saveXbeforeCall(functionCall) functioncallAsmGen.saveXbeforeCall(functionCall)
@@ -1094,7 +1094,7 @@ class AsmGen(private val program: Program,
} }
} }
private fun translate(stmt: IfStatement) { private fun translate(stmt: IfElse) {
requireComparisonExpression(stmt.condition) // IfStatement: condition must be of form 'x <comparison> <value>' requireComparisonExpression(stmt.condition) // IfStatement: condition must be of form 'x <comparison> <value>'
val booleanCondition = stmt.condition as BinaryExpression val booleanCondition = stmt.condition as BinaryExpression
@@ -1274,7 +1274,7 @@ $repeatLabel lda $counterVar
return counterVar return counterVar
} }
private fun translate(stmt: WhenStatement) { private fun translate(stmt: When) {
val endLabel = makeLabel("choice_end") val endLabel = makeLabel("choice_end")
val choiceBlocks = mutableListOf<Pair<String, AnonymousScope>>() val choiceBlocks = mutableListOf<Pair<String, AnonymousScope>>()
val conditionDt = stmt.condition.inferType(program) val conditionDt = stmt.condition.inferType(program)
@@ -1328,7 +1328,7 @@ $repeatLabel lda $counterVar
scope.statements.forEach{ translate(it) } scope.statements.forEach{ translate(it) }
} }
private fun translate(stmt: BranchStatement) { private fun translate(stmt: Branch) {
if(stmt.truepart.isEmpty() && stmt.elsepart.isNotEmpty()) if(stmt.truepart.isEmpty() && stmt.elsepart.isNotEmpty())
throw AssemblyError("only else part contains code, shoud have been switched already") throw AssemblyError("only else part contains code, shoud have been switched already")
@@ -1674,7 +1674,7 @@ $label nop""")
} }
if(dt==DataType.UBYTE) { if(dt==DataType.UBYTE) {
assignExpressionToRegister(left, RegisterOrPair.A, false) assignExpressionToRegister(left, RegisterOrPair.A, false)
if (left is FunctionCall && !left.isSimple) if (left is FunctionCallExpr && !left.isSimple)
out(" cmp #0") out(" cmp #0")
} else { } else {
assignExpressionToRegister(left, RegisterOrPair.AY, false) assignExpressionToRegister(left, RegisterOrPair.AY, false)
@@ -1690,7 +1690,7 @@ $label nop""")
} }
DataType.BYTE -> { DataType.BYTE -> {
assignExpressionToRegister(left, RegisterOrPair.A, true) assignExpressionToRegister(left, RegisterOrPair.A, true)
if (left is FunctionCall && !left.isSimple) if (left is FunctionCallExpr && !left.isSimple)
out(" cmp #0") out(" cmp #0")
when (operator) { when (operator) {
"==" -> out(" bne $jumpIfFalseLabel") "==" -> out(" bne $jumpIfFalseLabel")

View File

@@ -44,7 +44,7 @@ internal fun asmsub6502ArgsHaveRegisterClobberRisk(args: List<Expression>,
it.registerOrPair in listOf(RegisterOrPair.Y, RegisterOrPair.AY, RegisterOrPair.XY) it.registerOrPair in listOf(RegisterOrPair.Y, RegisterOrPair.AY, RegisterOrPair.XY)
} }
} }
is FunctionCall -> { is FunctionCallExpr -> {
if (expr.target.nameInSource == listOf("lsb") || expr.target.nameInSource == listOf("msb")) if (expr.target.nameInSource == listOf("lsb") || expr.target.nameInSource == listOf("msb"))
return isClobberRisk(expr.args[0]) return isClobberRisk(expr.args[0])
if (expr.target.nameInSource == listOf("mkword")) if (expr.target.nameInSource == listOf("mkword"))

View File

@@ -19,7 +19,7 @@ import prog8.compilerinterface.subroutineFloatEvalResultVar2
internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) { internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) {
internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) { internal fun translateFunctioncallExpression(fcall: FunctionCallExpr, func: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister) translateFunctioncall(fcall, func, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)
} }
@@ -414,7 +414,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
} }
private fun funcMemory(fcall: IFunctionCall, discardResult: Boolean, resultToStack: Boolean, resultRegister: RegisterOrPair?) { private fun funcMemory(fcall: IFunctionCall, discardResult: Boolean, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
if(discardResult || fcall !is FunctionCall) if(discardResult || fcall !is FunctionCallExpr)
throw AssemblyError("should not discard result of memory allocation at $fcall") throw AssemblyError("should not discard result of memory allocation at $fcall")
val nameRef = fcall.args[0] as IdentifierReference val nameRef = fcall.args[0] as IdentifierReference
val name = (nameRef.targetVarDecl(program)!!.value as StringLiteralValue).value val name = (nameRef.targetVarDecl(program)!!.value as StringLiteralValue).value

View File

@@ -3,7 +3,7 @@ package prog8.compiler.target.cpu6502.codegen
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.* import prog8.ast.base.*
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.BuiltinFunctionStatementPlaceholder import prog8.ast.statements.BuiltinFunctionPlaceholder
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.toHex import prog8.ast.toHex
import prog8.compiler.target.AssemblyError import prog8.compiler.target.AssemblyError
@@ -36,18 +36,18 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
is DirectMemoryRead -> asmgen.translateDirectMemReadExpressionToRegAorStack(expression, true) is DirectMemoryRead -> asmgen.translateDirectMemReadExpressionToRegAorStack(expression, true)
is NumericLiteralValue -> translateExpression(expression) is NumericLiteralValue -> translateExpression(expression)
is IdentifierReference -> translateExpression(expression) is IdentifierReference -> translateExpression(expression)
is FunctionCall -> translateFunctionCallResultOntoStack(expression) is FunctionCallExpr -> translateFunctionCallResultOntoStack(expression)
is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array literal value assignment - should have been replaced by a variable") is ArrayLiteralValue, is StringLiteralValue -> throw AssemblyError("no asm gen for string/array literal value assignment - should have been replaced by a variable")
is RangeExpr -> throw AssemblyError("range expression should have been changed into array values") is RangeExpr -> throw AssemblyError("range expression should have been changed into array values")
is CharLiteral -> throw AssemblyError("charliteral should have been replaced by ubyte using certain encoding") is CharLiteral -> throw AssemblyError("charliteral should have been replaced by ubyte using certain encoding")
} }
} }
private fun translateFunctionCallResultOntoStack(call: FunctionCall) { private fun translateFunctionCallResultOntoStack(call: FunctionCallExpr) {
// only for use in nested expression evaluation // only for use in nested expression evaluation
val sub = call.target.targetStatement(program) val sub = call.target.targetStatement(program)
if(sub is BuiltinFunctionStatementPlaceholder) { if(sub is BuiltinFunctionPlaceholder) {
val builtinFunc = BuiltinFunctions.getValue(sub.name) val builtinFunc = BuiltinFunctions.getValue(sub.name)
asmgen.translateBuiltinFunctionCallExpression(call, builtinFunc, true, null) asmgen.translateBuiltinFunctionCallExpression(call, builtinFunc, true, null)
} else { } else {

View File

@@ -167,7 +167,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
val dt = value.inferType(program).getOrElse { throw AssemblyError("unknown dt") } val dt = value.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value) AsmAssignSource(SourceStorageKind.ARRAY, program, asmgen, dt, array = value)
} }
is FunctionCall -> { is FunctionCallExpr -> {
when (val sub = value.target.targetStatement(program)) { when (val sub = value.target.targetStatement(program)) {
is Subroutine -> { is Subroutine -> {
val returnType = sub.returntypes.zip(sub.asmReturnvaluesRegisters).firstOrNull { rr -> rr.second.registerOrPair != null || rr.second.statusflag!=null }?.first val returnType = sub.returntypes.zip(sub.asmReturnvaluesRegisters).firstOrNull { rr -> rr.second.registerOrPair != null || rr.second.statusflag!=null }?.first
@@ -175,7 +175,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType, expression = value) AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType, expression = value)
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
val returnType = value.inferType(program) val returnType = value.inferType(program)
AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.getOrElse { throw AssemblyError("unknown dt") }, expression = value) AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, returnType.getOrElse { throw AssemblyError("unknown dt") }, expression = value)
} }

View File

@@ -159,7 +159,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
is ArrayIndexedExpression -> throw AssemblyError("source kind should have been array") is ArrayIndexedExpression -> throw AssemblyError("source kind should have been array")
is DirectMemoryRead -> throw AssemblyError("source kind should have been memory") is DirectMemoryRead -> throw AssemblyError("source kind should have been memory")
is TypecastExpression -> assignTypeCastedValue(assign.target, value.type, value.expression, value) is TypecastExpression -> assignTypeCastedValue(assign.target, value.type, value.expression, value)
is FunctionCall -> { is FunctionCallExpr -> {
when (val sub = value.target.targetStatement(program)) { when (val sub = value.target.targetStatement(program)) {
is Subroutine -> { is Subroutine -> {
asmgen.saveXbeforeCall(value) asmgen.saveXbeforeCall(value)
@@ -215,7 +215,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
} }
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
val signature = BuiltinFunctions.getValue(sub.name) val signature = BuiltinFunctions.getValue(sub.name)
asmgen.translateBuiltinFunctionCallExpression(value, signature, false, assign.target.register) asmgen.translateBuiltinFunctionCallExpression(value, signature, false, assign.target.register)
if(assign.target.register==null) { if(assign.target.register==null) {
@@ -474,7 +474,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
private fun assignCastViaLsbFunc(value: Expression, target: AsmAssignTarget) { private fun assignCastViaLsbFunc(value: Expression, target: AsmAssignTarget) {
val lsb = FunctionCall(IdentifierReference(listOf("lsb"), value.position), mutableListOf(value), value.position) val lsb = FunctionCallExpr(IdentifierReference(listOf("lsb"), value.position), mutableListOf(value), value.position)
lsb.linkParents(value.parent) lsb.linkParents(value.parent)
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UBYTE, expression = lsb) val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UBYTE, expression = lsb)
val assign = AsmAssignment(src, target, false, program.memsizer, value.position) val assign = AsmAssignment(src, target, false, program.memsizer, value.position)

View File

@@ -303,11 +303,11 @@ class ConstantFoldingOptimizer(private val program: Program) : AstWalker() {
return noModifications return noModifications
} }
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> { override fun after(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> {
// the args of a fuction are constfolded via recursion already. // the args of a fuction are constfolded via recursion already.
val constvalue = functionCall.constValue(program) val constvalue = functionCallExpr.constValue(program)
return if(constvalue!=null) return if(constvalue!=null)
listOf(IAstModification.ReplaceNode(functionCall, constvalue, parent)) listOf(IAstModification.ReplaceNode(functionCallExpr, constvalue, parent))
else else
noModifications noModifications
} }

View File

@@ -10,7 +10,7 @@ import prog8.ast.base.NumericDatatypes
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.AnonymousScope import prog8.ast.statements.AnonymousScope
import prog8.ast.statements.Assignment import prog8.ast.statements.Assignment
import prog8.ast.statements.IfStatement import prog8.ast.statements.IfElse
import prog8.ast.statements.Jump import prog8.ast.statements.Jump
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification import prog8.ast.walk.IAstModification
@@ -58,24 +58,24 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
return mods return mods
} }
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> { override fun after(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
val truepart = ifStatement.truepart val truepart = ifElse.truepart
val elsepart = ifStatement.elsepart val elsepart = ifElse.elsepart
if(truepart.isNotEmpty() && elsepart.isNotEmpty()) { if(truepart.isNotEmpty() && elsepart.isNotEmpty()) {
if(truepart.statements.singleOrNull() is Jump) { if(truepart.statements.singleOrNull() is Jump) {
return listOf( return listOf(
IAstModification.InsertAfter(ifStatement, elsepart, parent as IStatementContainer), IAstModification.InsertAfter(ifElse, elsepart, parent as IStatementContainer),
IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifStatement) IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifElse)
) )
} }
if(elsepart.statements.singleOrNull() is Jump) { if(elsepart.statements.singleOrNull() is Jump) {
val invertedCondition = invertCondition(ifStatement.condition) val invertedCondition = invertCondition(ifElse.condition)
if(invertedCondition!=null) { if(invertedCondition!=null) {
return listOf( return listOf(
IAstModification.ReplaceNode(ifStatement.condition, invertedCondition, ifStatement), IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse),
IAstModification.InsertAfter(ifStatement, truepart, parent as IStatementContainer), IAstModification.InsertAfter(ifElse, truepart, parent as IStatementContainer),
IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifStatement), IAstModification.ReplaceNode(elsepart, AnonymousScope(mutableListOf(), elsepart.position), ifElse),
IAstModification.ReplaceNode(truepart, elsepart, ifStatement) IAstModification.ReplaceNode(truepart, elsepart, ifElse)
) )
} }
} }
@@ -211,7 +211,7 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
// signedw < 0 --> msb(signedw) & $80 // signedw < 0 --> msb(signedw) & $80
return listOf(IAstModification.ReplaceNode( return listOf(IAstModification.ReplaceNode(
expr, expr,
BinaryExpression(FunctionCall(IdentifierReference(listOf("msb"), expr.position), BinaryExpression(FunctionCallExpr(IdentifierReference(listOf("msb"), expr.position),
mutableListOf(expr.left), mutableListOf(expr.left),
expr.position expr.position
), "&", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position), ), "&", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position),
@@ -301,31 +301,31 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
return noModifications return noModifications
} }
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> { override fun after(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> {
if(functionCall.target.nameInSource == listOf("lsb")) { if(functionCallExpr.target.nameInSource == listOf("lsb")) {
val arg = functionCall.args[0] val arg = functionCallExpr.args[0]
if(arg is TypecastExpression) { if(arg is TypecastExpression) {
val valueDt = arg.expression.inferType(program) val valueDt = arg.expression.inferType(program)
if (valueDt istype DataType.BYTE || valueDt istype DataType.UBYTE) { if (valueDt istype DataType.BYTE || valueDt istype DataType.UBYTE) {
// useless lsb() of byte value that was typecasted to word // useless lsb() of byte value that was typecasted to word
return listOf(IAstModification.ReplaceNode(functionCall, arg.expression, parent)) return listOf(IAstModification.ReplaceNode(functionCallExpr, arg.expression, parent))
} }
} else { } else {
val argDt = arg.inferType(program) val argDt = arg.inferType(program)
if (argDt istype DataType.BYTE || argDt istype DataType.UBYTE) { if (argDt istype DataType.BYTE || argDt istype DataType.UBYTE) {
// useless lsb() of byte value // useless lsb() of byte value
return listOf(IAstModification.ReplaceNode(functionCall, arg, parent)) return listOf(IAstModification.ReplaceNode(functionCallExpr, arg, parent))
} }
} }
} }
else if(functionCall.target.nameInSource == listOf("msb")) { else if(functionCallExpr.target.nameInSource == listOf("msb")) {
val arg = functionCall.args[0] val arg = functionCallExpr.args[0]
if(arg is TypecastExpression) { if(arg is TypecastExpression) {
val valueDt = arg.expression.inferType(program) val valueDt = arg.expression.inferType(program)
if (valueDt istype DataType.BYTE || valueDt istype DataType.UBYTE) { if (valueDt istype DataType.BYTE || valueDt istype DataType.UBYTE) {
// 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, functionCallExpr,
NumericLiteralValue(valueDt.getOr(DataType.UBYTE), 0.0, arg.expression.position), NumericLiteralValue(valueDt.getOr(DataType.UBYTE), 0.0, arg.expression.position),
parent)) parent))
} }
@@ -334,7 +334,7 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
if (argDt istype DataType.BYTE || argDt istype DataType.UBYTE) { if (argDt istype DataType.BYTE || argDt istype DataType.UBYTE) {
// 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, functionCallExpr,
NumericLiteralValue(argDt.getOr(DataType.UBYTE), 0.0, arg.position), NumericLiteralValue(argDt.getOr(DataType.UBYTE), 0.0, arg.position),
parent)) parent))
} }
@@ -455,7 +455,7 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
} }
0.5 -> { 0.5 -> {
// sqrt(left) // sqrt(left)
return FunctionCall(IdentifierReference(listOf("sqrt"), expr.position), mutableListOf(expr.left), expr.position) return FunctionCallExpr(IdentifierReference(listOf("sqrt"), expr.position), mutableListOf(expr.left), expr.position)
} }
1.0 -> { 1.0 -> {
// left // left
@@ -648,12 +648,12 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
if (amount >= 16) { if (amount >= 16) {
return NumericLiteralValue(targetDt, 0.0, expr.position) return NumericLiteralValue(targetDt, 0.0, expr.position)
} else if (amount >= 8) { } else if (amount >= 8) {
val lsb = FunctionCall(IdentifierReference(listOf("lsb"), expr.position), mutableListOf(expr.left), expr.position) val lsb = FunctionCallExpr(IdentifierReference(listOf("lsb"), expr.position), mutableListOf(expr.left), expr.position)
if (amount == 8) { if (amount == 8) {
return FunctionCall(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(lsb, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position) return FunctionCallExpr(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(lsb, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position)
} }
val shifted = BinaryExpression(lsb, "<<", NumericLiteralValue.optimalInteger(amount - 8, expr.position), expr.position) val shifted = BinaryExpression(lsb, "<<", NumericLiteralValue.optimalInteger(amount - 8, expr.position), expr.position)
return FunctionCall(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(shifted, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position) return FunctionCallExpr(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(shifted, NumericLiteralValue.optimalInteger(0, expr.position)), expr.position)
} }
} }
else -> { else -> {
@@ -690,11 +690,11 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
return NumericLiteralValue.optimalInteger(0, expr.position) return NumericLiteralValue.optimalInteger(0, expr.position)
} }
else if (amount >= 8) { else if (amount >= 8) {
val msb = FunctionCall(IdentifierReference(listOf("msb"), expr.position), mutableListOf(expr.left), expr.position) val msb = FunctionCallExpr(IdentifierReference(listOf("msb"), expr.position), mutableListOf(expr.left), expr.position)
if (amount == 8) { if (amount == 8) {
// mkword(0, msb(v)) // mkword(0, msb(v))
val zero = NumericLiteralValue(DataType.UBYTE, 0.0, expr.position) val zero = NumericLiteralValue(DataType.UBYTE, 0.0, expr.position)
return FunctionCall(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(zero, msb), expr.position) return FunctionCallExpr(IdentifierReference(listOf("mkword"), expr.position), mutableListOf(zero, msb), expr.position)
} }
return TypecastExpression(BinaryExpression(msb, ">>", NumericLiteralValue.optimalInteger(amount - 8, expr.position), expr.position), DataType.UWORD, true, expr.position) return TypecastExpression(BinaryExpression(msb, ">>", NumericLiteralValue.optimalInteger(amount - 8, expr.position), expr.position), DataType.UWORD, true, expr.position)
} }

View File

@@ -18,7 +18,7 @@ class StatementOptimizer(private val program: Program,
private val compTarget: ICompilationTarget private val compTarget: ICompilationTarget
) : AstWalker() { ) : AstWalker() {
override fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> { override fun before(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> {
// if the first instruction in the called subroutine is a return statement with a simple value, // if the first instruction in the called subroutine is a return statement with a simple value,
// remove the jump altogeter and inline the returnvalue directly. // remove the jump altogeter and inline the returnvalue directly.
@@ -27,7 +27,7 @@ class StatementOptimizer(private val program: Program,
return IdentifierReference(target.scopedName, variable.position) return IdentifierReference(target.scopedName, variable.position)
} }
val subroutine = functionCall.target.targetSubroutine(program) val subroutine = functionCallExpr.target.targetSubroutine(program)
if(subroutine!=null) { if(subroutine!=null) {
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull() val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
if(first is Return && first.value?.isSimple==true) { if(first is Return && first.value?.isSimple==true) {
@@ -47,7 +47,7 @@ class StatementOptimizer(private val program: Program,
is StringLiteralValue -> orig.copy() is StringLiteralValue -> orig.copy()
else -> return noModifications else -> return noModifications
} }
return listOf(IAstModification.ReplaceNode(functionCall, copy, parent)) return listOf(IAstModification.ReplaceNode(functionCallExpr, copy, parent))
} }
} }
return noModifications return noModifications
@@ -56,7 +56,7 @@ class StatementOptimizer(private val program: Program,
override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> { override fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> {
if(functionCallStatement.target.targetStatement(program) is BuiltinFunctionStatementPlaceholder) { if(functionCallStatement.target.targetStatement(program) is BuiltinFunctionPlaceholder) {
val functionName = functionCallStatement.target.nameInSource[0] val functionName = functionCallStatement.target.nameInSource[0]
if (functionName in functions.purefunctionNames) { if (functionName in functions.purefunctionNames) {
errors.warn("statement has no effect (function return value is discarded)", functionCallStatement.position) errors.warn("statement has no effect (function return value is discarded)", functionCallStatement.position)
@@ -133,33 +133,33 @@ class StatementOptimizer(private val program: Program,
return noModifications return noModifications
} }
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> { override fun after(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
// remove empty if statements // remove empty if statements
if(ifStatement.truepart.isEmpty() && ifStatement.elsepart.isEmpty()) if(ifElse.truepart.isEmpty() && ifElse.elsepart.isEmpty())
return listOf(IAstModification.Remove(ifStatement, parent as IStatementContainer)) return listOf(IAstModification.Remove(ifElse, parent as IStatementContainer))
// empty true part? switch with the else part // empty true part? switch with the else part
if(ifStatement.truepart.isEmpty() && ifStatement.elsepart.isNotEmpty()) { if(ifElse.truepart.isEmpty() && ifElse.elsepart.isNotEmpty()) {
val invertedCondition = PrefixExpression("not", ifStatement.condition, ifStatement.condition.position) val invertedCondition = PrefixExpression("not", ifElse.condition, ifElse.condition.position)
val emptyscope = AnonymousScope(mutableListOf(), ifStatement.elsepart.position) val emptyscope = AnonymousScope(mutableListOf(), ifElse.elsepart.position)
val truepart = AnonymousScope(ifStatement.elsepart.statements, ifStatement.truepart.position) val truepart = AnonymousScope(ifElse.elsepart.statements, ifElse.truepart.position)
return listOf( return listOf(
IAstModification.ReplaceNode(ifStatement.condition, invertedCondition, ifStatement), IAstModification.ReplaceNode(ifElse.condition, invertedCondition, ifElse),
IAstModification.ReplaceNode(ifStatement.truepart, truepart, ifStatement), IAstModification.ReplaceNode(ifElse.truepart, truepart, ifElse),
IAstModification.ReplaceNode(ifStatement.elsepart, emptyscope, ifStatement) IAstModification.ReplaceNode(ifElse.elsepart, emptyscope, ifElse)
) )
} }
val constvalue = ifStatement.condition.constValue(program) val constvalue = ifElse.condition.constValue(program)
if(constvalue!=null) { if(constvalue!=null) {
return if(constvalue.asBooleanValue){ return if(constvalue.asBooleanValue){
// always true -> keep only if-part // always true -> keep only if-part
errors.warn("condition is always true", ifStatement.position) errors.warn("condition is always true", ifElse.position)
listOf(IAstModification.ReplaceNode(ifStatement, ifStatement.truepart, parent)) listOf(IAstModification.ReplaceNode(ifElse, ifElse.truepart, parent))
} else { } else {
// always false -> keep only else-part // always false -> keep only else-part
errors.warn("condition is always false", ifStatement.position) errors.warn("condition is always false", ifElse.position)
listOf(IAstModification.ReplaceNode(ifStatement, ifStatement.elsepart, parent)) listOf(IAstModification.ReplaceNode(ifElse, ifElse.elsepart, parent))
} }
} }

View File

@@ -234,7 +234,7 @@ class UnusedCodeRemover(private val program: Program,
is PrefixExpression, is PrefixExpression,
is BinaryExpression, is BinaryExpression,
is TypecastExpression, is TypecastExpression,
is FunctionCall -> { /* don't remove */ } is FunctionCallExpr -> { /* don't remove */ }
else -> linesToRemove.add(assign1) else -> linesToRemove.add(assign1)
} }
} }

View File

@@ -193,19 +193,19 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
return noModifications return noModifications
} }
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> { override fun after(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
val prefixExpr = ifStatement.condition as? PrefixExpression val prefixExpr = ifElse.condition as? PrefixExpression
if(prefixExpr!=null && prefixExpr.operator=="not") { if(prefixExpr!=null && prefixExpr.operator=="not") {
// if not x -> if x==0 // if not x -> if x==0
val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, ifStatement.condition.position), ifStatement.condition.position) val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, ifElse.condition.position), ifElse.condition.position)
return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) return listOf(IAstModification.ReplaceNode(ifElse.condition, booleanExpr, ifElse))
} }
val binExpr = ifStatement.condition as? BinaryExpression val binExpr = ifElse.condition as? BinaryExpression
if(binExpr==null || binExpr.operator !in ComparisonOperators) { if(binExpr==null || binExpr.operator !in ComparisonOperators) {
// if x -> if x!=0, if x+5 -> if x+5 != 0 // if x -> if x!=0, if x+5 -> if x+5 != 0
val booleanExpr = BinaryExpression(ifStatement.condition, "!=", NumericLiteralValue.optimalInteger(0, ifStatement.condition.position), ifStatement.condition.position) val booleanExpr = BinaryExpression(ifElse.condition, "!=", NumericLiteralValue.optimalInteger(0, ifElse.condition.position), ifElse.condition.position)
return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) return listOf(IAstModification.ReplaceNode(ifElse.condition, booleanExpr, ifElse))
} }
if((binExpr.left as? NumericLiteralValue)?.number==0.0 && if((binExpr.left as? NumericLiteralValue)?.number==0.0 &&
@@ -219,11 +219,11 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
val modifications = mutableListOf<IAstModification>() val modifications = mutableListOf<IAstModification>()
if(simplify.rightVarAssignment!=null) { if(simplify.rightVarAssignment!=null) {
modifications += IAstModification.ReplaceNode(binExpr.right, simplify.rightOperandReplacement!!, binExpr) modifications += IAstModification.ReplaceNode(binExpr.right, simplify.rightOperandReplacement!!, binExpr)
modifications += IAstModification.InsertBefore(ifStatement, simplify.rightVarAssignment, parent as IStatementContainer) modifications += IAstModification.InsertBefore(ifElse, simplify.rightVarAssignment, parent as IStatementContainer)
} }
if(simplify.leftVarAssignment!=null) { if(simplify.leftVarAssignment!=null) {
modifications += IAstModification.ReplaceNode(binExpr.left, simplify.leftOperandReplacement!!, binExpr) modifications += IAstModification.ReplaceNode(binExpr.left, simplify.leftOperandReplacement!!, binExpr)
modifications += IAstModification.InsertBefore(ifStatement, simplify.leftVarAssignment, parent as IStatementContainer) modifications += IAstModification.InsertBefore(ifElse, simplify.leftVarAssignment, parent as IStatementContainer)
} }
return modifications return modifications
@@ -341,12 +341,12 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o
complexArrayIndexedExpressions.add(arrayIndexedExpression) complexArrayIndexedExpressions.add(arrayIndexedExpression)
} }
override fun visit(branchStatement: BranchStatement) {} override fun visit(branch: Branch) {}
override fun visit(forLoop: ForLoop) {} override fun visit(forLoop: ForLoop) {}
override fun visit(ifStatement: IfStatement) { override fun visit(ifElse: IfElse) {
ifStatement.condition.accept(this) ifElse.condition.accept(this)
} }
override fun visit(untilLoop: UntilLoop) { override fun visit(untilLoop: UntilLoop) {

View File

@@ -80,10 +80,10 @@ internal class AstChecker(private val program: Program,
super.visit(returnStmt) super.visit(returnStmt)
} }
override fun visit(ifStatement: IfStatement) { override fun visit(ifElse: IfElse) {
if(!ifStatement.condition.inferType(program).isInteger) if(!ifElse.condition.inferType(program).isInteger)
errors.err("condition value should be an integer type", ifStatement.condition.position) errors.err("condition value should be an integer type", ifElse.condition.position)
super.visit(ifStatement) super.visit(ifElse)
} }
override fun visit(forLoop: ForLoop) { override fun visit(forLoop: ForLoop) {
@@ -165,7 +165,7 @@ internal class AstChecker(private val program: Program,
if(ident!=null) { if(ident!=null) {
val targetStatement = checkFunctionOrLabelExists(ident, jump) val targetStatement = checkFunctionOrLabelExists(ident, jump)
if(targetStatement!=null) { if(targetStatement!=null) {
if(targetStatement is BuiltinFunctionStatementPlaceholder) if(targetStatement is BuiltinFunctionPlaceholder)
errors.err("can't jump to a builtin function", jump.position) errors.err("can't jump to a builtin function", jump.position)
} }
if(targetStatement is Subroutine && targetStatement.parameters.any()) { if(targetStatement is Subroutine && targetStatement.parameters.any()) {
@@ -184,7 +184,7 @@ internal class AstChecker(private val program: Program,
if(ident!=null) { if(ident!=null) {
val targetStatement = checkFunctionOrLabelExists(ident, gosub) val targetStatement = checkFunctionOrLabelExists(ident, gosub)
if(targetStatement!=null) { if(targetStatement!=null) {
if(targetStatement is BuiltinFunctionStatementPlaceholder) if(targetStatement is BuiltinFunctionPlaceholder)
errors.err("can't gosub to a builtin function", gosub.position) errors.err("can't gosub to a builtin function", gosub.position)
} }
} }
@@ -209,7 +209,7 @@ internal class AstChecker(private val program: Program,
is VarDecl, is VarDecl,
is InlineAssembly, is InlineAssembly,
is IStatementContainer, is IStatementContainer,
is NopStatement -> true is Nop -> true
is Assignment -> { is Assignment -> {
val target = statement.target.identifier!!.targetStatement(program) val target = statement.target.identifier!!.targetStatement(program)
target === statement.previousSibling() // an initializer assignment is okay target === statement.previousSibling() // an initializer assignment is okay
@@ -503,7 +503,7 @@ internal class AstChecker(private val program: Program,
} 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 FunctionCallExpr)
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.getOr(DataType.BYTE), checkAssignmentCompatible(targetDatatype.getOr(DataType.BYTE),
@@ -935,28 +935,28 @@ internal class AstChecker(private val program: Program,
} }
} }
override fun visit(functionCall: FunctionCall) { override fun visit(functionCallExpr: FunctionCallExpr) {
// this function call is (part of) an expression, which should be in a statement somewhere. // this function call is (part of) an expression, which should be in a statement somewhere.
val stmtOfExpression = findParentNode<Statement>(functionCall) val stmtOfExpression = findParentNode<Statement>(functionCallExpr)
?: throw FatalAstException("cannot determine statement scope of function call expression at ${functionCall.position}") ?: throw FatalAstException("cannot determine statement scope of function call expression at ${functionCallExpr.position}")
val targetStatement = checkFunctionOrLabelExists(functionCall.target, stmtOfExpression) val targetStatement = checkFunctionOrLabelExists(functionCallExpr.target, stmtOfExpression)
if(targetStatement!=null) if(targetStatement!=null)
checkFunctionCall(targetStatement, functionCall.args, functionCall.position) checkFunctionCall(targetStatement, functionCallExpr.args, functionCallExpr.position)
// warn about sgn(unsigned) this is likely a mistake // warn about sgn(unsigned) this is likely a mistake
if(functionCall.target.nameInSource.last()=="sgn") { if(functionCallExpr.target.nameInSource.last()=="sgn") {
val sgnArgType = functionCall.args.first().inferType(program) val sgnArgType = functionCallExpr.args.first().inferType(program)
if(sgnArgType istype DataType.UBYTE || sgnArgType istype DataType.UWORD) if(sgnArgType istype DataType.UBYTE || sgnArgType istype DataType.UWORD)
errors.warn("sgn() of unsigned type is always 0 or 1, this is perhaps not what was intended", functionCall.args.first().position) errors.warn("sgn() of unsigned type is always 0 or 1, this is perhaps not what was intended", functionCallExpr.args.first().position)
} }
val error = VerifyFunctionArgTypes.checkTypes(functionCall, program) val error = VerifyFunctionArgTypes.checkTypes(functionCallExpr, program)
if(error!=null) if(error!=null)
errors.err(error, functionCall.position) errors.err(error, functionCallExpr.position)
// check the functions that return multiple returnvalues. // check the functions that return multiple returnvalues.
val stmt = functionCall.target.targetStatement(program) val stmt = functionCallExpr.target.targetStatement(program)
if (stmt is Subroutine) { if (stmt is Subroutine) {
if (stmt.returntypes.size > 1) { if (stmt.returntypes.size > 1) {
// Currently, it's only possible to handle ONE (or zero) return values from a subroutine. // Currently, it's only possible to handle ONE (or zero) return values from a subroutine.
@@ -969,7 +969,7 @@ internal class AstChecker(private val program: Program,
// dealing with the status bit as just being that, the status bit after the call. // dealing with the status bit as just being that, the status bit after the call.
val (returnRegisters, _) = stmt.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null } val (returnRegisters, _) = stmt.asmReturnvaluesRegisters.partition { rr -> rr.registerOrPair != null }
if (returnRegisters.size>1) { if (returnRegisters.size>1) {
errors.err("It's not possible to store the multiple result values of this asmsub call; you should use a small block of custom inline assembly for this.", functionCall.position) errors.err("It's not possible to store the multiple result values of this asmsub call; you should use a small block of custom inline assembly for this.", functionCallExpr.position)
} }
} }
} }
@@ -977,18 +977,18 @@ internal class AstChecker(private val program: Program,
// functions that don't return a value, can't be used in an expression or assignment // functions that don't return a value, can't be used in an expression or assignment
if(targetStatement is Subroutine) { if(targetStatement is Subroutine) {
if(targetStatement.returntypes.isEmpty()) { if(targetStatement.returntypes.isEmpty()) {
if(functionCall.parent is Expression || functionCall.parent is Assignment) if(functionCallExpr.parent is Expression || functionCallExpr.parent is Assignment)
errors.err("subroutine doesn't return a value", functionCall.position) errors.err("subroutine doesn't return a value", functionCallExpr.position)
} }
} }
else if(targetStatement is BuiltinFunctionStatementPlaceholder) { else if(targetStatement is BuiltinFunctionPlaceholder) {
if(builtinFunctionReturnType(targetStatement.name, functionCall.args, program).isUnknown) { if(builtinFunctionReturnType(targetStatement.name, functionCallExpr.args, program).isUnknown) {
if(functionCall.parent is Expression || functionCall.parent is Assignment) if(functionCallExpr.parent is Expression || functionCallExpr.parent is Assignment)
errors.err("function doesn't return a value", functionCall.position) errors.err("function doesn't return a value", functionCallExpr.position)
} }
} }
super.visit(functionCall) super.visit(functionCallExpr)
} }
override fun visit(functionCallStatement: FunctionCallStatement) { override fun visit(functionCallStatement: FunctionCallStatement) {
@@ -1044,7 +1044,7 @@ internal class AstChecker(private val program: Program,
if(target is Label && args.isNotEmpty()) if(target is Label && args.isNotEmpty())
errors.err("cannot use arguments when calling a label", position) errors.err("cannot use arguments when calling a label", position)
if(target is BuiltinFunctionStatementPlaceholder) { if(target is BuiltinFunctionPlaceholder) {
if(target.name=="swap") { if(target.name=="swap") {
// swap() is a bit weird because this one is translated into an operations directly, instead of being a function call // swap() is a bit weird because this one is translated into an operations directly, instead of being a function call
val dt1 = args[0].inferType(program) val dt1 = args[0].inferType(program)
@@ -1080,8 +1080,8 @@ internal class AstChecker(private val program: Program,
var ident: IdentifierReference? = null var ident: IdentifierReference? = null
if(arg.value is IdentifierReference) if(arg.value is IdentifierReference)
ident = arg.value as IdentifierReference ident = arg.value as IdentifierReference
else if(arg.value is FunctionCall) { else if(arg.value is FunctionCallExpr) {
val fcall = arg.value as FunctionCall val fcall = arg.value as FunctionCallExpr
if(fcall.target.nameInSource == listOf("lsb") || fcall.target.nameInSource == listOf("msb")) if(fcall.target.nameInSource == listOf("lsb") || fcall.target.nameInSource == listOf("msb"))
ident = fcall.args[0] as? IdentifierReference ident = fcall.args[0] as? IdentifierReference
} }
@@ -1164,11 +1164,11 @@ internal class AstChecker(private val program: Program,
super.visit(arrayIndexedExpression) super.visit(arrayIndexedExpression)
} }
override fun visit(whenStatement: WhenStatement) { override fun visit(whenStmt: When) {
if(!whenStatement.condition.inferType(program).isInteger) if(!whenStmt.condition.inferType(program).isInteger)
errors.err("when condition must be an integer value", whenStatement.position) errors.err("when condition must be an integer value", whenStmt.position)
val tally = mutableSetOf<Int>() val tally = mutableSetOf<Int>()
for((choices, choiceNode) in whenStatement.choiceValues(program)) { for((choices, choiceNode) in whenStmt.choiceValues(program)) {
if(choices!=null) { if(choices!=null) {
for (c in choices) { for (c in choices) {
if(c in tally) if(c in tally)
@@ -1179,14 +1179,14 @@ internal class AstChecker(private val program: Program,
} }
} }
if(whenStatement.choices.isEmpty()) if(whenStmt.choices.isEmpty())
errors.err("empty when statement", whenStatement.position) errors.err("empty when statement", whenStmt.position)
super.visit(whenStatement) super.visit(whenStmt)
} }
override fun visit(whenChoice: WhenChoice) { override fun visit(whenChoice: WhenChoice) {
val whenStmt = whenChoice.parent as WhenStatement val whenStmt = whenChoice.parent as When
if(whenChoice.values!=null) { if(whenChoice.values!=null) {
val conditionType = whenStmt.condition.inferType(program) val conditionType = whenStmt.condition.inferType(program)
if(!conditionType.isKnown) if(!conditionType.isKnown)
@@ -1208,7 +1208,7 @@ internal class AstChecker(private val program: Program,
private fun checkFunctionOrLabelExists(target: IdentifierReference, statement: Statement): Statement? { private fun checkFunctionOrLabelExists(target: IdentifierReference, statement: Statement): Statement? {
when (val targetStatement = target.targetStatement(program)) { when (val targetStatement = target.targetStatement(program)) {
is Label, is Subroutine, is BuiltinFunctionStatementPlaceholder -> return targetStatement is Label, is Subroutine, is BuiltinFunctionPlaceholder -> return targetStatement
null -> errors.err("undefined function or subroutine: ${target.nameInSource.joinToString(".")}", statement.position) null -> errors.err("undefined function or subroutine: ${target.nameInSource.joinToString(".")}", statement.position)
else -> errors.err("cannot call that: ${target.nameInSource.joinToString(".")}", statement.position) else -> errors.err("cannot call that: ${target.nameInSource.joinToString(".")}", statement.position)
} }
@@ -1432,7 +1432,7 @@ internal fun checkUnusedReturnValues(call: FunctionCallStatement, target: Statem
errors.warn("result value of subroutine call is discarded (use void?)", call.position) errors.warn("result value of subroutine call is discarded (use void?)", call.position)
else else
errors.warn("result values of subroutine call are discarded (use void?)", call.position) errors.warn("result values of subroutine call are discarded (use void?)", call.position)
} else if (target is BuiltinFunctionStatementPlaceholder) { } else if (target is BuiltinFunctionPlaceholder) {
val rt = builtinFunctionReturnType(target.name, call.args, program) val rt = builtinFunctionReturnType(target.name, call.args, program)
if (rt.isKnown) if (rt.isKnown)
errors.warn("result value of a function call is discarded (use void?)", call.position) errors.warn("result value of a function call is discarded (use void?)", call.position)

View File

@@ -3,9 +3,8 @@ package prog8.compiler.astprocessing
import prog8.ast.IFunctionCall import prog8.ast.IFunctionCall
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.FatalAstException
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.FunctionCallExpr
import prog8.ast.expressions.StringLiteralValue import prog8.ast.expressions.StringLiteralValue
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
@@ -129,7 +128,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
super.visit(string) super.visit(string)
} }
override fun visit(functionCall: FunctionCall) = visitFunctionCall(functionCall) override fun visit(functionCallExpr: FunctionCallExpr) = visitFunctionCall(functionCallExpr)
override fun visit(functionCallStatement: FunctionCallStatement) = visitFunctionCall(functionCallStatement) override fun visit(functionCallStatement: FunctionCallStatement) = visitFunctionCall(functionCallStatement)
private fun visitFunctionCall(call: IFunctionCall) { private fun visitFunctionCall(call: IFunctionCall) {
@@ -140,7 +139,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
errors.err("invalid number of arguments", pos) errors.err("invalid number of arguments", pos)
} }
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
val func = BuiltinFunctions.getValue(target.name) val func = BuiltinFunctions.getValue(target.name)
if(call.args.size != func.parameters.size) { if(call.args.size != func.parameters.size) {
val pos = (if(call.args.any()) call.args[0] else (call as Node)).position val pos = (if(call.args.any()) call.args[0] else (call as Node)).position

View File

@@ -7,7 +7,7 @@ import prog8.ast.Program
import prog8.ast.base.ParentSentinel import prog8.ast.base.ParentSentinel
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.expressions.DirectMemoryRead import prog8.ast.expressions.DirectMemoryRead
import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.FunctionCallExpr
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.expressions.PrefixExpression import prog8.ast.expressions.PrefixExpression
import prog8.ast.statements.* import prog8.ast.statements.*
@@ -80,7 +80,7 @@ if not CONDITION
val replacement = AnonymousScope(mutableListOf( val replacement = AnonymousScope(mutableListOf(
loopLabel, loopLabel,
untilLoop.body, untilLoop.body,
IfStatement(notCondition, IfElse(notCondition,
AnonymousScope(mutableListOf(jumpLabel(loopLabel)), pos), AnonymousScope(mutableListOf(jumpLabel(loopLabel)), pos),
AnonymousScope(mutableListOf(), pos), AnonymousScope(mutableListOf(), pos),
pos) pos)
@@ -104,7 +104,7 @@ _after:
val notCondition = PrefixExpression("not", whileLoop.condition, pos) val notCondition = PrefixExpression("not", whileLoop.condition, pos)
val replacement = AnonymousScope(mutableListOf( val replacement = AnonymousScope(mutableListOf(
loopLabel, loopLabel,
IfStatement(notCondition, IfElse(notCondition,
AnonymousScope(mutableListOf(jumpLabel(afterLabel)), pos), AnonymousScope(mutableListOf(jumpLabel(afterLabel)), pos),
AnonymousScope(mutableListOf(), pos), AnonymousScope(mutableListOf(), pos),
pos), pos),
@@ -118,8 +118,8 @@ _after:
override fun before(functionCallStatement: FunctionCallStatement, parent: Node) = override fun before(functionCallStatement: FunctionCallStatement, parent: Node) =
before(functionCallStatement as IFunctionCall, parent, functionCallStatement.position) before(functionCallStatement as IFunctionCall, parent, functionCallStatement.position)
override fun before(functionCall: FunctionCall, parent: Node) = override fun before(functionCallExpr: FunctionCallExpr, parent: Node) =
before(functionCall as IFunctionCall, parent, functionCall.position) before(functionCallExpr as IFunctionCall, parent, functionCallExpr.position)
private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable<IAstModification> { private fun before(functionCall: IFunctionCall, parent: Node, position: Position): Iterable<IAstModification> {
if(functionCall.target.nameInSource==listOf("peek")) { if(functionCall.target.nameInSource==listOf("peek")) {

View File

@@ -47,9 +47,9 @@ internal class ParentNodeChecker: AstWalker() {
return noModifications return noModifications
} }
override fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> { override fun before(branch: Branch, parent: Node): Iterable<IAstModification> {
if(branchStatement.parent!==parent) if(branch.parent!==parent)
throw FatalAstException("parent node mismatch at $branchStatement") throw FatalAstException("parent node mismatch at $branch")
return noModifications return noModifications
} }
@@ -101,9 +101,9 @@ internal class ParentNodeChecker: AstWalker() {
return noModifications return noModifications
} }
override fun before(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> { override fun before(ifElse: IfElse, parent: Node): Iterable<IAstModification> {
if(ifStatement.parent!==parent) if(ifElse.parent!==parent)
throw FatalAstException("parent node mismatch at $ifStatement") throw FatalAstException("parent node mismatch at $ifElse")
return noModifications return noModifications
} }
@@ -209,9 +209,9 @@ internal class ParentNodeChecker: AstWalker() {
return noModifications return noModifications
} }
override fun before(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> { override fun before(`when`: When, parent: Node): Iterable<IAstModification> {
if(whenStatement.parent!==parent) if(`when`.parent!==parent)
throw FatalAstException("parent node mismatch at $whenStatement") throw FatalAstException("parent node mismatch at $`when`")
return noModifications return noModifications
} }
@@ -221,9 +221,9 @@ internal class ParentNodeChecker: AstWalker() {
return noModifications return noModifications
} }
override fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> { override fun before(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> {
if(functionCall.parent!==parent) if(functionCallExpr.parent!==parent)
throw FatalAstException("parent node mismatch at $functionCall") throw FatalAstException("parent node mismatch at $functionCallExpr")
return noModifications return noModifications
} }
@@ -233,9 +233,9 @@ internal class ParentNodeChecker: AstWalker() {
return noModifications return noModifications
} }
override fun before(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> { override fun before(nop: Nop, parent: Node): Iterable<IAstModification> {
if(nopStatement.parent!==parent) if(nop.parent!==parent)
throw FatalAstException("parent node mismatch at $nopStatement") throw FatalAstException("parent node mismatch at $nop")
return noModifications return noModifications
} }

View File

@@ -210,7 +210,7 @@ internal class StatementReorderer(val program: Program,
return listOf(IAstModification.ReplaceNode(expr.left, cast, expr)) return listOf(IAstModification.ReplaceNode(expr.left, cast, expr))
} }
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
val func = BuiltinFunctions.getValue(callee.name) val func = BuiltinFunctions.getValue(callee.name)
val paramTypes = func.parameters[argnum].possibleDatatypes val paramTypes = func.parameters[argnum].possibleDatatypes
for(type in paramTypes) { for(type in paramTypes) {
@@ -262,19 +262,19 @@ internal class StatementReorderer(val program: Program,
return noModifications return noModifications
} }
override fun after(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> { override fun after(`when`: When, parent: Node): Iterable<IAstModification> {
val lastChoiceValues = whenStatement.choices.lastOrNull()?.values val lastChoiceValues = `when`.choices.lastOrNull()?.values
if(lastChoiceValues?.isNotEmpty()==true) { if(lastChoiceValues?.isNotEmpty()==true) {
val elseChoice = whenStatement.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true } val elseChoice = `when`.choices.indexOfFirst { it.values==null || it.values?.isEmpty()==true }
if(elseChoice>=0) if(elseChoice>=0)
errors.err("else choice must be the last one", whenStatement.choices[elseChoice].position) errors.err("else choice must be the last one", `when`.choices[elseChoice].position)
} }
val choices = whenStatement.choiceValues(program).sortedBy { val choices = `when`.choiceValues(program).sortedBy {
it.first?.first() ?: Int.MAX_VALUE it.first?.first() ?: Int.MAX_VALUE
} }
whenStatement.choices.clear() `when`.choices.clear()
choices.mapTo(whenStatement.choices) { it.second } choices.mapTo(`when`.choices) { it.second }
return noModifications return noModifications
} }

View File

@@ -135,8 +135,8 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
return afterFunctionCallArgs(functionCallStatement) return afterFunctionCallArgs(functionCallStatement)
} }
override fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> { override fun after(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> {
return afterFunctionCallArgs(functionCall) return afterFunctionCallArgs(functionCallExpr)
} }
private fun afterFunctionCallArgs(call: IFunctionCall): Iterable<IAstModification> { private fun afterFunctionCallArgs(call: IFunctionCall): Iterable<IAstModification> {
@@ -180,7 +180,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
} }
} }
} }
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
val func = BuiltinFunctions.getValue(sub.name) val func = BuiltinFunctions.getValue(sub.name)
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)

View File

@@ -13,8 +13,8 @@ import prog8.compilerinterface.IErrorReporter
internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() { internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() {
override fun before(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> { override fun before(nop: Nop, parent: Node): Iterable<IAstModification> {
return listOf(IAstModification.Remove(nopStatement, parent as IStatementContainer)) return listOf(IAstModification.Remove(nop, parent as IStatementContainer))
} }
override fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> { override fun after(scope: AnonymousScope, parent: Node): Iterable<IAstModification> {

View File

@@ -4,7 +4,7 @@ import prog8.ast.IFunctionCall
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.DataType import prog8.ast.base.DataType
import prog8.ast.expressions.Expression import prog8.ast.expressions.Expression
import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.FunctionCallExpr
import prog8.ast.expressions.TypecastExpression import prog8.ast.expressions.TypecastExpression
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
@@ -13,8 +13,8 @@ import prog8.compilerinterface.InternalCompilerException
internal class VerifyFunctionArgTypes(val program: Program) : IAstVisitor { internal class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
override fun visit(functionCall: FunctionCall) { override fun visit(functionCallExpr: FunctionCallExpr) {
val error = checkTypes(functionCall as IFunctionCall, program) val error = checkTypes(functionCallExpr as IFunctionCall, program)
if(error!=null) if(error!=null)
throw InternalCompilerException(error) throw InternalCompilerException(error)
} }
@@ -76,7 +76,7 @@ internal class VerifyFunctionArgTypes(val program: Program) : IAstVisitor {
} }
} }
} }
else if (target is BuiltinFunctionStatementPlaceholder) { else if (target is BuiltinFunctionPlaceholder) {
val func = BuiltinFunctions.getValue(target.name) val func = BuiltinFunctions.getValue(target.name)
if(call.args.size != func.parameters.size) if(call.args.size != func.parameters.size)
return "invalid number of arguments" return "invalid number of arguments"

View File

@@ -444,7 +444,7 @@ class TestOptimization: FunSpec({
}""" }"""
val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess() val result = compileText(C64Target, optimize=true, src, writeAssembly=false).assertSuccess()
result.program.entrypoint.statements.size shouldBe 3 result.program.entrypoint.statements.size shouldBe 3
val ifstmt = result.program.entrypoint.statements[0] as IfStatement val ifstmt = result.program.entrypoint.statements[0] as IfElse
ifstmt.truepart.statements.size shouldBe 1 ifstmt.truepart.statements.size shouldBe 1
(ifstmt.truepart.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0") (ifstmt.truepart.statements[0] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "r0")
val func2 = result.program.entrypoint.statements[2] as Subroutine val func2 = result.program.entrypoint.statements[2] as Subroutine

View File

@@ -19,7 +19,6 @@ import prog8.ast.base.DataType
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.compiler.printProgram
import prog8.compiler.target.C64Target import prog8.compiler.target.C64Target
import prog8.compiler.target.cbm.Petscii import prog8.compiler.target.cbm.Petscii
import prog8.parser.ParseError import prog8.parser.ParseError
@@ -334,7 +333,7 @@ class TestProg8Parser: FunSpec( {
assertPositionOf(rhsFoo, mpf, 4, 21, 22) assertPositionOf(rhsFoo, mpf, 4, 21, 22)
val declBar = startSub.statements.filterIsInstance<VarDecl>()[1] val declBar = startSub.statements.filterIsInstance<VarDecl>()[1]
assertPositionOf(declBar, mpf, 5, 9, 13) assertPositionOf(declBar, mpf, 5, 9, 13)
val whenStmt = startSub.statements.filterIsInstance<WhenStatement>()[0] val whenStmt = startSub.statements.filterIsInstance<When>()[0]
assertPositionOf(whenStmt, mpf, 6, 9, 12) assertPositionOf(whenStmt, mpf, 6, 9, 12)
assertPositionOf(whenStmt.choices[0], mpf, 7, 13, 14) assertPositionOf(whenStmt.choices[0], mpf, 7, 13, 14)
assertPositionOf(whenStmt.choices[1], mpf, 8, 13, 14) assertPositionOf(whenStmt.choices[1], mpf, 8, 13, 14)

View File

@@ -195,8 +195,8 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
} }
} }
override fun visit(functionCall: FunctionCall) { override fun visit(functionCallExpr: FunctionCallExpr) {
printout(functionCall as IFunctionCall) printout(functionCallExpr as IFunctionCall)
} }
override fun visit(functionCallStatement: FunctionCallStatement) { override fun visit(functionCallStatement: FunctionCallStatement) {
@@ -236,23 +236,23 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
} }
} }
override fun visit(ifStatement: IfStatement) { override fun visit(ifElse: IfElse) {
output("if ") output("if ")
ifStatement.condition.accept(this) ifElse.condition.accept(this)
output(" ") output(" ")
ifStatement.truepart.accept(this) ifElse.truepart.accept(this)
if(ifStatement.elsepart.statements.isNotEmpty()) { if(ifElse.elsepart.statements.isNotEmpty()) {
output(" else ") output(" else ")
ifStatement.elsepart.accept(this) ifElse.elsepart.accept(this)
} }
} }
override fun visit(branchStatement: BranchStatement) { override fun visit(branch: Branch) {
output("if_${branchStatement.condition.toString().lowercase()} ") output("if_${branch.condition.toString().lowercase()} ")
branchStatement.truepart.accept(this) branch.truepart.accept(this)
if(branchStatement.elsepart.statements.isNotEmpty()) { if(branch.elsepart.statements.isNotEmpty()) {
output(" else ") output(" else ")
branchStatement.elsepart.accept(this) branch.elsepart.accept(this)
} }
} }
@@ -422,12 +422,12 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
outputlni("}}") outputlni("}}")
} }
override fun visit(whenStatement: WhenStatement) { override fun visit(`when`: When) {
output("when ") output("when ")
whenStatement.condition.accept(this) `when`.condition.accept(this)
outputln(" {") outputln(" {")
scopelevel++ scopelevel++
whenStatement.choices.forEach { it.accept(this) } `when`.choices.forEach { it.accept(this) }
scopelevel-- scopelevel--
outputlni("}") outputlni("}")
} }

View File

@@ -39,14 +39,14 @@ interface IStatementContainer {
when(it) { when(it) {
is Label -> result.add(it) is Label -> result.add(it)
is IStatementContainer -> find(it) is IStatementContainer -> find(it)
is IfStatement -> { is IfElse -> {
find(it.truepart) find(it.truepart)
find(it.elsepart) find(it.elsepart)
} }
is UntilLoop -> find(it.body) is UntilLoop -> find(it.body)
is RepeatLoop -> find(it.body) is RepeatLoop -> find(it.body)
is WhileLoop -> find(it.body) is WhileLoop -> find(it.body)
is WhenStatement -> it.choices.forEach { choice->find(choice.statements) } is When -> it.choices.forEach { choice->find(choice.statements) }
else -> { /* do nothing */ } else -> { /* do nothing */ }
} }
} }
@@ -87,12 +87,12 @@ interface IStatementContainer {
if(found!=null) if(found!=null)
return found return found
} }
is IfStatement -> { is IfElse -> {
val found = stmt.truepart.searchSymbol(name) ?: stmt.elsepart.searchSymbol(name) val found = stmt.truepart.searchSymbol(name) ?: stmt.elsepart.searchSymbol(name)
if(found!=null) if(found!=null)
return found return found
} }
is BranchStatement -> { is Branch -> {
val found = stmt.truepart.searchSymbol(name) ?: stmt.elsepart.searchSymbol(name) val found = stmt.truepart.searchSymbol(name) ?: stmt.elsepart.searchSymbol(name)
if(found!=null) if(found!=null)
return found return found
@@ -117,7 +117,7 @@ interface IStatementContainer {
if(found!=null) if(found!=null)
return found return found
} }
is WhenStatement -> { is When -> {
stmt.choices.forEach { stmt.choices.forEach {
val found = it.statements.searchSymbol(name) val found = it.statements.searchSymbol(name)
if(found!=null) if(found!=null)

View File

@@ -280,12 +280,12 @@ private fun Prog8ANTLRParser.Functioncall_stmtContext.toAst(): Statement {
FunctionCallStatement(location, expression_list().toAst().toMutableList(), void, toPosition()) FunctionCallStatement(location, expression_list().toAst().toMutableList(), void, toPosition())
} }
private fun Prog8ANTLRParser.FunctioncallContext.toAst(): FunctionCall { private fun Prog8ANTLRParser.FunctioncallContext.toAst(): FunctionCallExpr {
val location = scoped_identifier().toAst() val location = scoped_identifier().toAst()
return if(expression_list() == null) return if(expression_list() == null)
FunctionCall(location, mutableListOf(), toPosition()) FunctionCallExpr(location, mutableListOf(), toPosition())
else else
FunctionCall(location, expression_list().toAst().toMutableList(), toPosition()) FunctionCallExpr(location, expression_list().toAst().toMutableList(), toPosition())
} }
private fun Prog8ANTLRParser.InlineasmContext.toAst(): InlineAssembly { private fun Prog8ANTLRParser.InlineasmContext.toAst(): InlineAssembly {
@@ -516,28 +516,28 @@ private fun Prog8ANTLRParser.BooleanliteralContext.toAst() = when(text) {
private fun Prog8ANTLRParser.ArrayliteralContext.toAst() : Array<Expression> = private fun Prog8ANTLRParser.ArrayliteralContext.toAst() : Array<Expression> =
expression().map { it.toAst() }.toTypedArray() expression().map { it.toAst() }.toTypedArray()
private fun Prog8ANTLRParser.If_stmtContext.toAst(): IfStatement { private fun Prog8ANTLRParser.If_stmtContext.toAst(): IfElse {
val condition = expression().toAst() val condition = expression().toAst()
val trueStatements = statement_block()?.toAst() ?: mutableListOf(statement().toAst()) val trueStatements = statement_block()?.toAst() ?: mutableListOf(statement().toAst())
val elseStatements = else_part()?.toAst() ?: mutableListOf() val elseStatements = else_part()?.toAst() ?: mutableListOf()
val trueScope = AnonymousScope(trueStatements, statement_block()?.toPosition() val trueScope = AnonymousScope(trueStatements, statement_block()?.toPosition()
?: statement().toPosition()) ?: statement().toPosition())
val elseScope = AnonymousScope(elseStatements, else_part()?.toPosition() ?: toPosition()) val elseScope = AnonymousScope(elseStatements, else_part()?.toPosition() ?: toPosition())
return IfStatement(condition, trueScope, elseScope, toPosition()) return IfElse(condition, trueScope, elseScope, toPosition())
} }
private fun Prog8ANTLRParser.Else_partContext.toAst(): MutableList<Statement> { private fun Prog8ANTLRParser.Else_partContext.toAst(): MutableList<Statement> {
return statement_block()?.toAst() ?: mutableListOf(statement().toAst()) return statement_block()?.toAst() ?: mutableListOf(statement().toAst())
} }
private fun Prog8ANTLRParser.Branch_stmtContext.toAst(): BranchStatement { private fun Prog8ANTLRParser.Branch_stmtContext.toAst(): Branch {
val branchcondition = branchcondition().toAst() val branchcondition = branchcondition().toAst()
val trueStatements = statement_block()?.toAst() ?: mutableListOf(statement().toAst()) val trueStatements = statement_block()?.toAst() ?: mutableListOf(statement().toAst())
val elseStatements = else_part()?.toAst() ?: mutableListOf() val elseStatements = else_part()?.toAst() ?: mutableListOf()
val trueScope = AnonymousScope(trueStatements, statement_block()?.toPosition() val trueScope = AnonymousScope(trueStatements, statement_block()?.toPosition()
?: statement().toPosition()) ?: statement().toPosition())
val elseScope = AnonymousScope(elseStatements, else_part()?.toPosition() ?: toPosition()) val elseScope = AnonymousScope(elseStatements, else_part()?.toPosition() ?: toPosition())
return BranchStatement(branchcondition, trueScope, elseScope, toPosition()) return Branch(branchcondition, trueScope, elseScope, toPosition())
} }
private fun Prog8ANTLRParser.BranchconditionContext.toAst() = BranchCondition.valueOf( private fun Prog8ANTLRParser.BranchconditionContext.toAst() = BranchCondition.valueOf(
@@ -581,10 +581,10 @@ private fun Prog8ANTLRParser.UntilloopContext.toAst(): UntilLoop {
return UntilLoop(scope, untilCondition, toPosition()) return UntilLoop(scope, untilCondition, toPosition())
} }
private fun Prog8ANTLRParser.WhenstmtContext.toAst(): WhenStatement { private fun Prog8ANTLRParser.WhenstmtContext.toAst(): When {
val condition = expression().toAst() val condition = expression().toAst()
val choices = this.when_choice()?.map { it.toAst() }?.toMutableList() ?: mutableListOf() val choices = this.when_choice()?.map { it.toAst() }?.toMutableList() ?: mutableListOf()
return WhenStatement(condition, choices, toPosition()) return When(condition, choices, toPosition())
} }
private fun Prog8ANTLRParser.When_choiceContext.toAst(): WhenChoice { private fun Prog8ANTLRParser.When_choiceContext.toAst(): WhenChoice {

View File

@@ -66,8 +66,8 @@ sealed class Expression: Node {
is RangeExpr -> { is RangeExpr -> {
(other is RangeExpr && other.from==from && other.to==to && other.step==step) (other is RangeExpr && other.from==from && other.to==to && other.step==step)
} }
is FunctionCall -> { is FunctionCallExpr -> {
(other is FunctionCall && other.target.nameInSource == target.nameInSource (other is FunctionCallExpr && other.target.nameInSource == target.nameInSource
&& other.args.size == args.size && other.args.size == args.size
&& other.args.zip(args).all { it.first isSameAs it.second } ) && other.args.zip(args).all { it.first isSameAs it.second } )
} }
@@ -811,7 +811,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
fun targetStatement(program: Program) = fun targetStatement(program: Program) =
if(nameInSource.size==1 && nameInSource[0] in program.builtinFunctions.names) if(nameInSource.size==1 && nameInSource[0] in program.builtinFunctions.names)
BuiltinFunctionStatementPlaceholder(nameInSource[0], position, parent) BuiltinFunctionPlaceholder(nameInSource[0], position, parent)
else else
definingScope.lookup(nameInSource) definingScope.lookup(nameInSource)
@@ -868,7 +868,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
} }
} }
class FunctionCall(override var target: IdentifierReference, class FunctionCallExpr(override var target: IdentifierReference,
override var args: MutableList<Expression>, override var args: MutableList<Expression>,
override val position: Position) : Expression(), IFunctionCall { override val position: Position) : Expression(), IFunctionCall {
override lateinit var parent: Node override lateinit var parent: Node
@@ -879,7 +879,7 @@ class FunctionCall(override var target: IdentifierReference,
args.forEach { it.linkParents(this) } args.forEach { it.linkParents(this) }
} }
override fun copy() = FunctionCall(target.copy(), args.map { it.copy() }.toMutableList(), position) override fun copy() = FunctionCallExpr(target.copy(), args.map { it.copy() }.toMutableList(), position)
override val isSimple = target.nameInSource.size==1 && (target.nameInSource[0] in arrayOf("msb", "lsb", "peek", "peekw")) override val isSimple = target.nameInSource.size==1 && (target.nameInSource[0] in arrayOf("msb", "lsb", "peek", "peekw"))
override fun replaceChildNode(node: Node, replacement: Node) { override fun replaceChildNode(node: Node, replacement: Node) {
@@ -925,7 +925,7 @@ class FunctionCall(override var target: IdentifierReference,
return InferredTypes.knownFor(constVal.type) return InferredTypes.knownFor(constVal.type)
val stmt = target.targetStatement(program) ?: return InferredTypes.unknown() val stmt = target.targetStatement(program) ?: return InferredTypes.unknown()
when (stmt) { when (stmt) {
is BuiltinFunctionStatementPlaceholder -> { is BuiltinFunctionPlaceholder -> {
if(target.nameInSource[0] == "set_carry" || target.nameInSource[0]=="set_irqd" || if(target.nameInSource[0] == "set_carry" || target.nameInSource[0]=="set_irqd" ||
target.nameInSource[0] == "clear_carry" || target.nameInSource[0]=="clear_irqd") { target.nameInSource[0] == "clear_carry" || target.nameInSource[0]=="clear_irqd") {
return InferredTypes.void() // these have no return value return InferredTypes.void() // these have no return value

View File

@@ -49,7 +49,7 @@ sealed class Statement : Node {
} }
class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position, override var parent: Node) : Statement() { class BuiltinFunctionPlaceholder(val name: String, override val position: Position, override var parent: Node) : Statement() {
override fun linkParents(parent: Node) {} override fun linkParents(parent: Node) {}
override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node") override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node")
override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node") override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node")
@@ -605,7 +605,7 @@ class AnonymousScope(override var statements: MutableList<Statement>,
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
} }
class NopStatement(override val position: Position): Statement() { class Nop(override val position: Position): Statement() {
override lateinit var parent: Node override lateinit var parent: Node
override fun linkParents(parent: Node) { override fun linkParents(parent: Node) {
@@ -613,7 +613,7 @@ class NopStatement(override val position: Position): Statement() {
} }
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here") override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun copy() = NopStatement(position) override fun copy() = Nop(position)
override fun accept(visitor: IAstVisitor) = visitor.visit(this) override fun accept(visitor: IAstVisitor) = visitor.visit(this)
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
} }
@@ -754,7 +754,7 @@ open class SubroutineParameter(val name: String,
override fun toString() = "Param($type:$name)" override fun toString() = "Param($type:$name)"
} }
class IfStatement(var condition: Expression, class IfElse(var condition: Expression,
var truepart: AnonymousScope, var truepart: AnonymousScope,
var elsepart: AnonymousScope, var elsepart: AnonymousScope,
override val position: Position) : Statement() { override val position: Position) : Statement() {
@@ -784,7 +784,7 @@ class IfStatement(var condition: Expression,
} }
class BranchStatement(var condition: BranchCondition, class Branch(var condition: BranchCondition,
var truepart: AnonymousScope, var truepart: AnonymousScope,
var elsepart: AnonymousScope, var elsepart: AnonymousScope,
override val position: Position) : Statement() { override val position: Position) : Statement() {
@@ -919,7 +919,7 @@ class UntilLoop(var body: AnonymousScope,
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
} }
class WhenStatement(var condition: Expression, class When(var condition: Expression,
var choices: MutableList<WhenChoice>, var choices: MutableList<WhenChoice>,
override val position: Position): Statement() { override val position: Position): Statement() {
override lateinit var parent: Node override lateinit var parent: Node

View File

@@ -85,7 +85,7 @@ abstract class AstWalker {
open fun before(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications open fun before(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
open fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> = noModifications open fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> = noModifications
open fun before(block: Block, parent: Node): Iterable<IAstModification> = noModifications open fun before(block: Block, parent: Node): Iterable<IAstModification> = noModifications
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = noModifications open fun before(branch: Branch, parent: Node): Iterable<IAstModification> = noModifications
open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = noModifications open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = noModifications
open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = noModifications open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = noModifications
open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = noModifications open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = noModifications
@@ -93,10 +93,10 @@ abstract class AstWalker {
open fun before(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications open fun before(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun before(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications open fun before(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun before(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications open fun before(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> = noModifications open fun before(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> = noModifications
open fun before(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> = noModifications open fun before(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> = noModifications
open fun before(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> = noModifications open fun before(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> = noModifications
open fun before(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> = noModifications open fun before(ifElse: IfElse, parent: Node): Iterable<IAstModification> = noModifications
open fun before(inlineAssembly: InlineAssembly, parent: Node): Iterable<IAstModification> = noModifications open fun before(inlineAssembly: InlineAssembly, parent: Node): Iterable<IAstModification> = noModifications
open fun before(jump: Jump, parent: Node): Iterable<IAstModification> = noModifications open fun before(jump: Jump, parent: Node): Iterable<IAstModification> = noModifications
open fun before(gosub: GoSub, parent: Node): Iterable<IAstModification> = noModifications open fun before(gosub: GoSub, parent: Node): Iterable<IAstModification> = noModifications
@@ -104,7 +104,7 @@ abstract class AstWalker {
open fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> = noModifications open fun before(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> = noModifications
open fun before(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications open fun before(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications
open fun before(module: Module, parent: Node): Iterable<IAstModification> = noModifications open fun before(module: Module, parent: Node): Iterable<IAstModification> = noModifications
open fun before(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> = noModifications open fun before(nop: Nop, parent: Node): Iterable<IAstModification> = noModifications
open fun before(numLiteral: NumericLiteralValue, parent: Node): Iterable<IAstModification> = noModifications open fun before(numLiteral: NumericLiteralValue, parent: Node): Iterable<IAstModification> = noModifications
open fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications open fun before(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications
open fun before(program: Program): Iterable<IAstModification> = noModifications open fun before(program: Program): Iterable<IAstModification> = noModifications
@@ -117,7 +117,7 @@ abstract class AstWalker {
open fun before(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications open fun before(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications
open fun before(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications open fun before(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun before(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications open fun before(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications
open fun before(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> = noModifications open fun before(whenStmt: When, parent: Node): Iterable<IAstModification> = noModifications
open fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications open fun before(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications open fun after(addressOf: AddressOf, parent: Node): Iterable<IAstModification> = noModifications
@@ -126,19 +126,19 @@ abstract class AstWalker {
open fun after(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications open fun after(assignTarget: AssignTarget, parent: Node): Iterable<IAstModification> = noModifications
open fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> = noModifications open fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> = noModifications
open fun after(block: Block, parent: Node): Iterable<IAstModification> = noModifications open fun after(block: Block, parent: Node): Iterable<IAstModification> = noModifications
open fun after(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = noModifications open fun after(branch: Branch, parent: Node): Iterable<IAstModification> = noModifications
open fun after(breakStmt: Break, parent: Node): Iterable<IAstModification> = noModifications open fun after(breakStmt: Break, parent: Node): Iterable<IAstModification> = noModifications
open fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = noModifications open fun after(builtinFunctionPlaceholder: BuiltinFunctionPlaceholder, parent: Node): Iterable<IAstModification> = noModifications
open fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> = noModifications open fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> = noModifications
open fun after(directive: Directive, parent: Node): Iterable<IAstModification> = noModifications open fun after(directive: Directive, parent: Node): Iterable<IAstModification> = noModifications
open fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = noModifications open fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications open fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun after(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications open fun after(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun after(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications open fun after(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications
open fun after(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> = noModifications open fun after(functionCallExpr: FunctionCallExpr, parent: Node): Iterable<IAstModification> = noModifications
open fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> = noModifications open fun after(functionCallStatement: FunctionCallStatement, parent: Node): Iterable<IAstModification> = noModifications
open fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> = noModifications open fun after(identifier: IdentifierReference, parent: Node): Iterable<IAstModification> = noModifications
open fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> = noModifications open fun after(ifElse: IfElse, parent: Node): Iterable<IAstModification> = noModifications
open fun after(inlineAssembly: InlineAssembly, parent: Node): Iterable<IAstModification> = noModifications open fun after(inlineAssembly: InlineAssembly, parent: Node): Iterable<IAstModification> = noModifications
open fun after(jump: Jump, parent: Node): Iterable<IAstModification> = noModifications open fun after(jump: Jump, parent: Node): Iterable<IAstModification> = noModifications
open fun after(gosub: GoSub, parent: Node): Iterable<IAstModification> = noModifications open fun after(gosub: GoSub, parent: Node): Iterable<IAstModification> = noModifications
@@ -146,7 +146,7 @@ abstract class AstWalker {
open fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> = noModifications open fun after(memread: DirectMemoryRead, parent: Node): Iterable<IAstModification> = noModifications
open fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications open fun after(memwrite: DirectMemoryWrite, parent: Node): Iterable<IAstModification> = noModifications
open fun after(module: Module, parent: Node): Iterable<IAstModification> = noModifications open fun after(module: Module, parent: Node): Iterable<IAstModification> = noModifications
open fun after(nopStatement: NopStatement, parent: Node): Iterable<IAstModification> = noModifications open fun after(nop: Nop, parent: Node): Iterable<IAstModification> = noModifications
open fun after(numLiteral: NumericLiteralValue, parent: Node): Iterable<IAstModification> = noModifications open fun after(numLiteral: NumericLiteralValue, parent: Node): Iterable<IAstModification> = noModifications
open fun after(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications open fun after(postIncrDecr: PostIncrDecr, parent: Node): Iterable<IAstModification> = noModifications
open fun after(program: Program): Iterable<IAstModification> = noModifications open fun after(program: Program): Iterable<IAstModification> = noModifications
@@ -159,7 +159,7 @@ abstract class AstWalker {
open fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications open fun after(subroutine: Subroutine, parent: Node): Iterable<IAstModification> = noModifications
open fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications open fun after(typecast: TypecastExpression, parent: Node): Iterable<IAstModification> = noModifications
open fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications open fun after(whenChoice: WhenChoice, parent: Node): Iterable<IAstModification> = noModifications
open fun after(whenStatement: WhenStatement, parent: Node): Iterable<IAstModification> = noModifications open fun after(whenStmt: When, parent: Node): Iterable<IAstModification> = noModifications
open fun after(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications open fun after(whileLoop: WhileLoop, parent: Node): Iterable<IAstModification> = noModifications
protected val modifications = mutableListOf<Triple<IAstModification, Node, Node>>() protected val modifications = mutableListOf<Triple<IAstModification, Node, Node>>()
@@ -247,11 +247,11 @@ abstract class AstWalker {
track(after(subroutine, parent), subroutine, parent) track(after(subroutine, parent), subroutine, parent)
} }
fun visit(functionCall: FunctionCall, parent: Node) { fun visit(functionCallExpr: FunctionCallExpr, parent: Node) {
track(before(functionCall, parent), functionCall, parent) track(before(functionCallExpr, parent), functionCallExpr, parent)
functionCall.target.accept(this, functionCall) functionCallExpr.target.accept(this, functionCallExpr)
functionCall.args.forEach { it.accept(this, functionCall) } functionCallExpr.args.forEach { it.accept(this, functionCallExpr) }
track(after(functionCall, parent), functionCall, parent) track(after(functionCallExpr, parent), functionCallExpr, parent)
} }
fun visit(functionCallStatement: FunctionCallStatement, parent: Node) { fun visit(functionCallStatement: FunctionCallStatement, parent: Node) {
@@ -278,19 +278,19 @@ abstract class AstWalker {
track(after(gosub, parent), gosub, parent) track(after(gosub, parent), gosub, parent)
} }
fun visit(ifStatement: IfStatement, parent: Node) { fun visit(ifElse: IfElse, parent: Node) {
track(before(ifStatement, parent), ifStatement, parent) track(before(ifElse, parent), ifElse, parent)
ifStatement.condition.accept(this, ifStatement) ifElse.condition.accept(this, ifElse)
ifStatement.truepart.accept(this, ifStatement) ifElse.truepart.accept(this, ifElse)
ifStatement.elsepart.accept(this, ifStatement) ifElse.elsepart.accept(this, ifElse)
track(after(ifStatement, parent), ifStatement, parent) track(after(ifElse, parent), ifElse, parent)
} }
fun visit(branchStatement: BranchStatement, parent: Node) { fun visit(branch: Branch, parent: Node) {
track(before(branchStatement, parent), branchStatement, parent) track(before(branch, parent), branch, parent)
branchStatement.truepart.accept(this, branchStatement) branch.truepart.accept(this, branch)
branchStatement.elsepart.accept(this, branchStatement) branch.elsepart.accept(this, branch)
track(after(branchStatement, parent), branchStatement, parent) track(after(branch, parent), branch, parent)
} }
fun visit(range: RangeExpr, parent: Node) { fun visit(range: RangeExpr, parent: Node) {
@@ -430,16 +430,16 @@ abstract class AstWalker {
track(after(inlineAssembly, parent), inlineAssembly, parent) track(after(inlineAssembly, parent), inlineAssembly, parent)
} }
fun visit(nopStatement: NopStatement, parent: Node) { fun visit(nop: Nop, parent: Node) {
track(before(nopStatement, parent), nopStatement, parent) track(before(nop, parent), nop, parent)
track(after(nopStatement, parent), nopStatement, parent) track(after(nop, parent), nop, parent)
} }
fun visit(whenStatement: WhenStatement, parent: Node) { fun visit(whenStmt: When, parent: Node) {
track(before(whenStatement, parent), whenStatement, parent) track(before(whenStmt, parent), whenStmt, parent)
whenStatement.condition.accept(this, whenStatement) whenStmt.condition.accept(this, whenStmt)
whenStatement.choices.forEach { it.accept(this, whenStatement) } whenStmt.choices.forEach { it.accept(this, whenStmt) }
track(after(whenStatement, parent), whenStatement, parent) track(after(whenStmt, parent), whenStmt, parent)
} }
fun visit(whenChoice: WhenChoice, parent: Node) { fun visit(whenChoice: WhenChoice, parent: Node) {

View File

@@ -39,9 +39,9 @@ interface IAstVisitor {
subroutine.statements.forEach { it.accept(this) } subroutine.statements.forEach { it.accept(this) }
} }
fun visit(functionCall: FunctionCall) { fun visit(functionCallExpr: FunctionCallExpr) {
functionCall.target.accept(this) functionCallExpr.target.accept(this)
functionCall.args.forEach { it.accept(this) } functionCallExpr.args.forEach { it.accept(this) }
} }
fun visit(functionCallStatement: FunctionCallStatement) { fun visit(functionCallStatement: FunctionCallStatement) {
@@ -60,15 +60,15 @@ interface IAstVisitor {
gosub.identifier?.accept(this) gosub.identifier?.accept(this)
} }
fun visit(ifStatement: IfStatement) { fun visit(ifElse: IfElse) {
ifStatement.condition.accept(this) ifElse.condition.accept(this)
ifStatement.truepart.accept(this) ifElse.truepart.accept(this)
ifStatement.elsepart.accept(this) ifElse.elsepart.accept(this)
} }
fun visit(branchStatement: BranchStatement) { fun visit(branch: Branch) {
branchStatement.truepart.accept(this) branch.truepart.accept(this)
branchStatement.elsepart.accept(this) branch.elsepart.accept(this)
} }
fun visit(range: RangeExpr) { fun visit(range: RangeExpr) {
@@ -164,12 +164,12 @@ interface IAstVisitor {
fun visit(inlineAssembly: InlineAssembly) { fun visit(inlineAssembly: InlineAssembly) {
} }
fun visit(nopStatement: NopStatement) { fun visit(nop: Nop) {
} }
fun visit(whenStatement: WhenStatement) { fun visit(`when`: When) {
whenStatement.condition.accept(this) `when`.condition.accept(this)
whenStatement.choices.forEach { it.accept(this) } `when`.choices.forEach { it.accept(this) }
} }
fun visit(whenChoice: WhenChoice) { fun visit(whenChoice: WhenChoice) {

View File

@@ -6,7 +6,7 @@ import prog8.ast.Program
import prog8.ast.base.Position import prog8.ast.base.Position
import prog8.ast.base.VarDeclType import prog8.ast.base.VarDeclType
import prog8.ast.expressions.AddressOf import prog8.ast.expressions.AddressOf
import prog8.ast.expressions.FunctionCall import prog8.ast.expressions.FunctionCallExpr
import prog8.ast.expressions.IdentifierReference import prog8.ast.expressions.IdentifierReference
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor import prog8.ast.walk.IAstVisitor
@@ -59,15 +59,15 @@ class CallGraph(private val program: Program) : IAstVisitor {
super.visit(directive) super.visit(directive)
} }
override fun visit(functionCall: FunctionCall) { override fun visit(functionCallExpr: FunctionCallExpr) {
val otherSub = functionCall.target.targetSubroutine(program) val otherSub = functionCallExpr.target.targetSubroutine(program)
if (otherSub != null) { if (otherSub != null) {
functionCall.definingSubroutine?.let { thisSub -> functionCallExpr.definingSubroutine?.let { thisSub ->
calls[thisSub] = calls.getValue(thisSub) + otherSub calls[thisSub] = calls.getValue(thisSub) + otherSub
calledBy[otherSub] = calledBy.getValue(otherSub) + functionCall calledBy[otherSub] = calledBy.getValue(otherSub) + functionCallExpr
} }
} }
super.visit(functionCall) super.visit(functionCallExpr)
} }
override fun visit(functionCallStatement: FunctionCallStatement) { override fun visit(functionCallStatement: FunctionCallStatement) {

View File

@@ -1,49 +1,74 @@
%import textio %import textio
%zeropage basicsafe %zeropage basicsafe
main { main {
ubyte @shared foo=99
sub thing(uword rr) {
ubyte @shared xx = rr[1] ; should still work as var initializer that will be rewritten
ubyte @shared yy
yy = rr[2]
uword @shared other
ubyte @shared zz = other[3]
}
sub start() { sub start() {
txt.print("should print: 10 40 80 20\n")
ubyte @shared xx ubyte @shared xx
repeat {
xx++
if xx==10
break
}
txt.print_ub(xx)
txt.nl()
while xx<50 { if xx<100 {
xx++ foobar()
if xx==40 }
break txt.print("\nthe end\n")
} }
txt.print_ub(xx)
txt.nl()
do { sub foobar() {
xx++ txt.print("foobar\n")
if xx==80 }
break
} until xx>100
txt.print_ub(xx)
txt.nl()
for xx in 0 to 25 {
if xx==20
break
}
txt.print_ub(xx)
txt.nl()
}
} }
;
;
;main {
; ubyte @shared foo=99
; sub thing(uword rr) {
; ubyte @shared xx = rr[1] ; should still work as var initializer that will be rewritten
; ubyte @shared yy
; yy = rr[2]
; uword @shared other
; ubyte @shared zz = other[3]
; }
; sub start() {
;
; txt.print("should print: 10 40 80 20\n")
;
; ubyte @shared xx
;
; if xx >0
; goto $c000
; else
; xx++
;labeltje:
;
; repeat {
; xx++
; if xx==10
; break
; }
; txt.print_ub(xx)
; txt.nl()
;
; while xx<50 {
; xx++
; if xx==40
; break
; }
; txt.print_ub(xx)
; txt.nl()
;
; do {
; xx++
; if xx==80
; break
; } until xx>100
; txt.print_ub(xx)
; txt.nl()
;
; for xx in 0 to 25 {
; if xx==20
; break
; }
; txt.print_ub(xx)
; txt.nl()
; }
;}