mirror of
https://github.com/irmen/prog8.git
synced 2025-10-31 15:16:13 +00:00
more consistent naming of the statement classes
This commit is contained in:
@@ -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")
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")) {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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("}")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,9 +868,9 @@ 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
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(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
|
||||||
|
|||||||
@@ -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,10 +754,10 @@ 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() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
@@ -784,10 +784,10 @@ 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() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
@@ -919,9 +919,9 @@ 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
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
103
examples/test.p8
103
examples/test.p8
@@ -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_ub(xx)
|
txt.print("\nthe end\n")
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub foobar() {
|
||||||
|
txt.print("foobar\n")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
;
|
||||||
|
;
|
||||||
|
;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()
|
||||||
|
; }
|
||||||
|
;}
|
||||||
|
|||||||
Reference in New Issue
Block a user