mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
no more Gosub node in new Ast, back to Functioncalls there.
This commit is contained in:
parent
7b27d270a2
commit
dbc7ad2ec4
@ -86,13 +86,6 @@ class PtForLoop(position: Position) : PtNode(position) {
|
||||
}
|
||||
|
||||
|
||||
class PtGosub(val identifier: PtIdentifier, position: Position) : PtNode(position) {
|
||||
override fun printProperties() {
|
||||
identifier.printProperties()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PtIfElse(position: Position) : PtNode(position) {
|
||||
val condition: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
|
@ -164,7 +164,6 @@ class AstToXmlConverter(internal val program: PtProgram,
|
||||
is PtContainmentCheck -> write(it)
|
||||
is PtForLoop -> write(it)
|
||||
is PtFunctionCall -> write(it)
|
||||
is PtGosub -> write(it)
|
||||
is PtIdentifier -> write(it)
|
||||
is PtIfElse -> write(it)
|
||||
is PtInlineAssembly -> write(it)
|
||||
@ -554,12 +553,6 @@ class AstToXmlConverter(internal val program: PtProgram,
|
||||
xml.endElt()
|
||||
}
|
||||
|
||||
private fun write(gosub: PtGosub) {
|
||||
xml.elt("gosub")
|
||||
xml.attr("symbol", strTargetName(gosub.identifier))
|
||||
xml.endElt()
|
||||
}
|
||||
|
||||
private fun write(sub: PtSub) {
|
||||
xml.elt("sub")
|
||||
xml.attr("name", sub.scopedName.joinToString("."))
|
||||
|
@ -1,43 +0,0 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
import prog8.code.ast.PtBuiltinFunctionCall
|
||||
import prog8.code.ast.PtNumber
|
||||
import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
|
||||
internal class BuiltinFunctionsGen(val codegen: CodeGen) {
|
||||
fun translate(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val chunk = VmCodeChunk()
|
||||
when(call.name) {
|
||||
"syscall" -> {
|
||||
val vExpr = call.args.single() as PtNumber
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall1" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
val vExpr1 = call.args[1] as PtNumber
|
||||
// TODO assign regs
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall2" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
val vExpr1 = call.args[1] as PtNumber
|
||||
val vExpr2 = call.args[2] as PtNumber
|
||||
// TODO assign regs
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall3" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
val vExpr1 = call.args[1] as PtNumber
|
||||
val vExpr2 = call.args[2] as PtNumber
|
||||
val vExpr3 = call.args[3] as PtNumber
|
||||
// TODO assign regs
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
else -> {
|
||||
TODO("builtinfunc ${call.name}")
|
||||
}
|
||||
}
|
||||
return chunk
|
||||
}
|
||||
}
|
@ -15,8 +15,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
): IAssemblyGenerator {
|
||||
|
||||
internal val allocations = VariableAllocator(symbolTable, program, errors)
|
||||
private val builtinFunctions = BuiltinFunctionsGen(this)
|
||||
private val expressionEval = ExpressionGen(this, builtinFunctions)
|
||||
private val expressionEval = ExpressionGen(this)
|
||||
private val instructions = mutableListOf<String>()
|
||||
|
||||
init {
|
||||
@ -93,7 +92,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtArrayIndexer -> TODO()
|
||||
is PtArrayLiteral -> TODO()
|
||||
is PtBinaryExpression -> TODO()
|
||||
is PtBuiltinFunctionCall -> builtinFunctions.translate(node)
|
||||
is PtBuiltinFunctionCall -> expressionEval.translate(node)
|
||||
is PtContainmentCheck -> TODO()
|
||||
is PtFunctionCall -> translate(node)
|
||||
is PtIdentifier -> TODO()
|
||||
@ -105,7 +104,6 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtString -> TODO()
|
||||
is PtTypeCast -> TODO()
|
||||
is PtForLoop -> TODO()
|
||||
is PtGosub -> translate(node)
|
||||
is PtIfElse -> TODO()
|
||||
is PtJump -> TODO()
|
||||
is PtNodeGroup -> TODO()
|
||||
@ -128,17 +126,17 @@ class CodeGen(internal val program: PtProgram,
|
||||
|
||||
private fun translate(fcall: PtFunctionCall): VmCodeChunk {
|
||||
val chunk = VmCodeChunk()
|
||||
// TODO evaluate function call arguments
|
||||
for ((index, arg) in fcall.args.withIndex()) {
|
||||
// TODO make sure the expressions code doesn't clobber the previous registers, and doesn't use the r0, r1, r2... which are needed to pass the args
|
||||
val (expressionChunk, resultRegister) = expressionEval.translateExpression(arg)
|
||||
chunk += expressionChunk
|
||||
if(resultRegister!=index)
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.LOADR, vmType(arg.type), reg1=0, reg2=resultRegister))
|
||||
}
|
||||
chunk += VmCodeOpcodeWithStringArg(Opcode.GOSUB, gosubArg(fcall.functionName))
|
||||
return chunk
|
||||
}
|
||||
|
||||
private fun translate(gosub: PtGosub): VmCodeChunk {
|
||||
val chunk = VmCodeChunk()
|
||||
chunk += VmCodeOpcodeWithStringArg(Opcode.GOSUB, gosubArg(gosub.identifier.targetName))
|
||||
return chunk
|
||||
}
|
||||
|
||||
private fun translate(ret: PtReturn): VmCodeChunk {
|
||||
val chunk = VmCodeChunk()
|
||||
val value = ret.value
|
||||
|
@ -5,7 +5,7 @@ import prog8.code.core.AssemblyError
|
||||
import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
|
||||
internal class ExpressionGen(val codeGen: CodeGen, val builtinFunctions: BuiltinFunctionsGen) {
|
||||
internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
fun translateExpression(expr: PtExpression): Pair<VmCodeChunk, Int> {
|
||||
// TODO("Not yet implemented")
|
||||
val chunk = VmCodeChunk()
|
||||
@ -80,4 +80,50 @@ internal class ExpressionGen(val codeGen: CodeGen, val builtinFunctions: Builtin
|
||||
return Pair(chunk, 0) // TODO function result always in r0?
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun translate(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val chunk = VmCodeChunk()
|
||||
when(call.name) {
|
||||
"syscall" -> {
|
||||
val vExpr = call.args.single() as PtNumber
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall1" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
// TODO make sure it evaluates into r0
|
||||
val (expressionChunk0, resultRegister0) = translateExpression(call.args[1])
|
||||
chunk += expressionChunk0
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall2" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
// TODO make sure it evaluates into r0
|
||||
val (expressionChunk0, resultRegister0) = translateExpression(call.args[1])
|
||||
chunk += expressionChunk0
|
||||
// TODO make sure it evaluates into r1
|
||||
val (expressionChunk1, resultRegister1) = translateExpression(call.args[2])
|
||||
chunk += expressionChunk1
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
"syscall3" -> {
|
||||
val vExpr = call.args[0] as PtNumber
|
||||
// TODO make sure it evaluates into r0
|
||||
val (expressionChunk0, resultRegister0) = translateExpression(call.args[1])
|
||||
chunk += expressionChunk0
|
||||
// TODO make sure it evaluates into r1
|
||||
val (expressionChunk1, resultRegister1) = translateExpression(call.args[2])
|
||||
chunk += expressionChunk1
|
||||
// TODO make sure it evaluates into r2
|
||||
val (expressionChunk2, resultRegister2) = translateExpression(call.args[3])
|
||||
chunk += expressionChunk2
|
||||
chunk += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
|
||||
}
|
||||
else -> {
|
||||
TODO("builtinfunc ${call.name}")
|
||||
}
|
||||
}
|
||||
return chunk
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.getOrElse
|
||||
import com.github.michaelbull.result.mapError
|
||||
import prog8.ast.IStatementContainer
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.*
|
||||
@ -87,7 +88,13 @@ class IntermediateAstMaker(val program: Program) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun transform(srcAssign: Assignment): PtAssignment {
|
||||
private fun transform(srcAssign: Assignment): PtNode {
|
||||
if(srcAssign.origin==AssignmentOrigin.PARAMETERASSIGN) {
|
||||
// assignments that are setting the parameters for a function call,
|
||||
// will be gathered at the GoSub itself later.
|
||||
return PtNop(srcAssign.position)
|
||||
}
|
||||
|
||||
val assign = PtAssignment(srcAssign.isAugmentable, srcAssign.position)
|
||||
assign.add(transform(srcAssign.target))
|
||||
assign.add(transformExpression(srcAssign.value))
|
||||
@ -222,7 +229,35 @@ class IntermediateAstMaker(val program: Program) {
|
||||
return call
|
||||
}
|
||||
|
||||
private fun transform(gosub: GoSub): PtGosub = PtGosub(transform(gosub.identifier), gosub.position)
|
||||
private fun transform(gosub: GoSub): PtFunctionCall {
|
||||
// Gather the Goto and any preceding parameter assignments back into a single Function call node.
|
||||
// (the reason it was split up in the first place, is because the Compiler Ast optimizers
|
||||
// can then work on any complex expressions that are used as arguments.)
|
||||
val parent = gosub.parent as IStatementContainer
|
||||
val gosubIdx = parent.statements.indexOf(gosub)
|
||||
val previousNodes = parent.statements.subList(0, gosubIdx).reversed()
|
||||
val paramAssigns = mutableListOf<Assignment>()
|
||||
for (node in previousNodes) {
|
||||
if(node !is Assignment || node.origin!=AssignmentOrigin.PARAMETERASSIGN)
|
||||
break
|
||||
paramAssigns += node
|
||||
}
|
||||
val parameters = gosub.identifier.targetSubroutine(program)!!.parameters
|
||||
if(paramAssigns.size != parameters.size)
|
||||
throw FatalAstException("mismatched number of parameter assignments for function call")
|
||||
|
||||
val target = transform(gosub.identifier)
|
||||
val call = PtFunctionCall(target.targetName, true, DataType.UNDEFINED, gosub.position)
|
||||
|
||||
// put arguments in correct order for the parameters
|
||||
val namedAssigns = paramAssigns.associate { it.target.identifier!!.targetVarDecl(program)!!.name to it.value }
|
||||
parameters.forEach {
|
||||
val argument = namedAssigns.getValue(it.name)
|
||||
call.add(transformExpression(argument))
|
||||
}
|
||||
|
||||
return call
|
||||
}
|
||||
|
||||
private fun transform(srcIf: IfElse): PtIfElse {
|
||||
val ifelse = PtIfElse(srcIf.position)
|
||||
|
@ -3,7 +3,6 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- in new AST: combine param assignments + GoSub, back into PtFunctionCall node. PtGosub node should not exist.
|
||||
|
||||
...
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user