mirror of
				https://github.com/irmen/prog8.git
				synced 2025-10-31 00:16:08 +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,7 +868,7 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| class FunctionCall(override var target: IdentifierReference, | class FunctionCallExpr(override var target: IdentifierReference, | ||||||
|                        override var args: MutableList<Expression>, |                        override var args: MutableList<Expression>, | ||||||
|                        override val position: Position) : Expression(), IFunctionCall { |                        override val position: Position) : Expression(), IFunctionCall { | ||||||
|     override lateinit var parent: Node |     override lateinit var parent: Node | ||||||
| @@ -879,7 +879,7 @@ class FunctionCall(override var target: IdentifierReference, | |||||||
|         args.forEach { it.linkParents(this) } |         args.forEach { it.linkParents(this) } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun copy() = FunctionCall(target.copy(), args.map { it.copy() }.toMutableList(), position) |     override fun copy() = FunctionCallExpr(target.copy(), args.map { it.copy() }.toMutableList(), position) | ||||||
|     override val isSimple = target.nameInSource.size==1 && (target.nameInSource[0] in arrayOf("msb", "lsb", "peek", "peekw")) |     override val isSimple = target.nameInSource.size==1 && (target.nameInSource[0] in arrayOf("msb", "lsb", "peek", "peekw")) | ||||||
|  |  | ||||||
|     override fun replaceChildNode(node: Node, replacement: Node) { |     override fun replaceChildNode(node: Node, replacement: Node) { | ||||||
| @@ -925,7 +925,7 @@ class FunctionCall(override var target: IdentifierReference, | |||||||
|             return InferredTypes.knownFor(constVal.type) |             return InferredTypes.knownFor(constVal.type) | ||||||
|         val stmt = target.targetStatement(program) ?: return InferredTypes.unknown() |         val stmt = target.targetStatement(program) ?: return InferredTypes.unknown() | ||||||
|         when (stmt) { |         when (stmt) { | ||||||
|             is BuiltinFunctionStatementPlaceholder -> { |             is BuiltinFunctionPlaceholder -> { | ||||||
|                 if(target.nameInSource[0] == "set_carry" || target.nameInSource[0]=="set_irqd" || |                 if(target.nameInSource[0] == "set_carry" || target.nameInSource[0]=="set_irqd" || | ||||||
|                         target.nameInSource[0] == "clear_carry" || target.nameInSource[0]=="clear_irqd") { |                         target.nameInSource[0] == "clear_carry" || target.nameInSource[0]=="clear_irqd") { | ||||||
|                     return InferredTypes.void() // these have no return value |                     return InferredTypes.void() // these have no return value | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ sealed class Statement : Node { | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| class BuiltinFunctionStatementPlaceholder(val name: String, override val position: Position, override var parent: Node) : Statement() { | class BuiltinFunctionPlaceholder(val name: String, override val position: Position, override var parent: Node) : Statement() { | ||||||
|     override fun linkParents(parent: Node) {} |     override fun linkParents(parent: Node) {} | ||||||
|     override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node") |     override fun accept(visitor: IAstVisitor) = throw FatalAstException("should not iterate over this node") | ||||||
|     override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node") |     override fun accept(visitor: AstWalker, parent: Node) = throw FatalAstException("should not iterate over this node") | ||||||
| @@ -605,7 +605,7 @@ class AnonymousScope(override var statements: MutableList<Statement>, | |||||||
|     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) |     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) | ||||||
| } | } | ||||||
|  |  | ||||||
| class NopStatement(override val position: Position): Statement() { | class Nop(override val position: Position): Statement() { | ||||||
|     override lateinit var parent: Node |     override lateinit var parent: Node | ||||||
|  |  | ||||||
|     override fun linkParents(parent: Node) { |     override fun linkParents(parent: Node) { | ||||||
| @@ -613,7 +613,7 @@ class NopStatement(override val position: Position): Statement() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here") |     override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here") | ||||||
|     override fun copy() = NopStatement(position) |     override fun copy() = Nop(position) | ||||||
|     override fun accept(visitor: IAstVisitor) = visitor.visit(this) |     override fun accept(visitor: IAstVisitor) = visitor.visit(this) | ||||||
|     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) |     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) | ||||||
| } | } | ||||||
| @@ -754,7 +754,7 @@ open class SubroutineParameter(val name: String, | |||||||
|     override fun toString() = "Param($type:$name)" |     override fun toString() = "Param($type:$name)" | ||||||
| } | } | ||||||
|  |  | ||||||
| class IfStatement(var condition: Expression, | class IfElse(var condition: Expression, | ||||||
|              var truepart: AnonymousScope, |              var truepart: AnonymousScope, | ||||||
|              var elsepart: AnonymousScope, |              var elsepart: AnonymousScope, | ||||||
|              override val position: Position) : Statement() { |              override val position: Position) : Statement() { | ||||||
| @@ -784,7 +784,7 @@ class IfStatement(var condition: Expression, | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| class BranchStatement(var condition: BranchCondition, | class Branch(var condition: BranchCondition, | ||||||
|              var truepart: AnonymousScope, |              var truepart: AnonymousScope, | ||||||
|              var elsepart: AnonymousScope, |              var elsepart: AnonymousScope, | ||||||
|              override val position: Position) : Statement() { |              override val position: Position) : Statement() { | ||||||
| @@ -919,7 +919,7 @@ class UntilLoop(var body: AnonymousScope, | |||||||
|     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) |     override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent) | ||||||
| } | } | ||||||
|  |  | ||||||
| class WhenStatement(var condition: Expression, | class When(var condition: Expression, | ||||||
|            var choices: MutableList<WhenChoice>, |            var choices: MutableList<WhenChoice>, | ||||||
|            override val position: Position): Statement() { |            override val position: Position): Statement() { | ||||||
|     override lateinit var parent: Node |     override lateinit var parent: Node | ||||||
|   | |||||||
| @@ -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) { | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								examples/test.p8
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								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("\nthe end\n") | ||||||
|     } |     } | ||||||
|         txt.print_ub(xx) |  | ||||||
|         txt.nl() |  | ||||||
|  |  | ||||||
|         do { |     sub foobar() { | ||||||
|             xx++ |         txt.print("foobar\n") | ||||||
|             if xx==80 |     } | ||||||
|                 break |  | ||||||
|         } until xx>100 |  | ||||||
|         txt.print_ub(xx) |  | ||||||
|         txt.nl() |  | ||||||
|  |  | ||||||
|         for xx in 0 to 25 { |  | ||||||
|             if xx==20 |  | ||||||
|                 break |  | ||||||
|         } |  | ||||||
|         txt.print_ub(xx) |  | ||||||
|         txt.nl() |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  | ; | ||||||
|  | ; | ||||||
|  | ;main { | ||||||
|  | ;    ubyte @shared foo=99 | ||||||
|  | ;      sub thing(uword rr) { | ||||||
|  | ;        ubyte @shared xx = rr[1]    ; should still work as var initializer that will be rewritten | ||||||
|  | ;        ubyte @shared yy | ||||||
|  | ;        yy = rr[2] | ||||||
|  | ;        uword @shared other | ||||||
|  | ;        ubyte @shared zz = other[3] | ||||||
|  | ;      } | ||||||
|  | ;    sub start() { | ||||||
|  | ; | ||||||
|  | ;        txt.print("should print:  10  40  80  20\n") | ||||||
|  | ; | ||||||
|  | ;        ubyte @shared xx | ||||||
|  | ; | ||||||
|  | ;        if xx >0 | ||||||
|  | ;            goto $c000 | ||||||
|  | ;        else | ||||||
|  | ;           xx++ | ||||||
|  | ;labeltje: | ||||||
|  | ; | ||||||
|  | ;        repeat { | ||||||
|  | ;            xx++ | ||||||
|  | ;            if xx==10 | ||||||
|  | ;                break | ||||||
|  | ;        } | ||||||
|  | ;        txt.print_ub(xx) | ||||||
|  | ;        txt.nl() | ||||||
|  | ; | ||||||
|  | ;        while xx<50 { | ||||||
|  | ;            xx++ | ||||||
|  | ;            if xx==40 | ||||||
|  | ;                break | ||||||
|  | ;        } | ||||||
|  | ;        txt.print_ub(xx) | ||||||
|  | ;        txt.nl() | ||||||
|  | ; | ||||||
|  | ;        do { | ||||||
|  | ;            xx++ | ||||||
|  | ;            if xx==80 | ||||||
|  | ;                break | ||||||
|  | ;        } until xx>100 | ||||||
|  | ;        txt.print_ub(xx) | ||||||
|  | ;        txt.nl() | ||||||
|  | ; | ||||||
|  | ;        for xx in 0 to 25 { | ||||||
|  | ;            if xx==20 | ||||||
|  | ;                break | ||||||
|  | ;        } | ||||||
|  | ;        txt.print_ub(xx) | ||||||
|  | ;        txt.nl() | ||||||
|  | ;    } | ||||||
|  | ;} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user