mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +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) {
|
class PtIfElse(position: Position) : PtNode(position) {
|
||||||
val condition: PtExpression
|
val condition: PtExpression
|
||||||
get() = children[0] as PtExpression
|
get() = children[0] as PtExpression
|
||||||
|
@ -164,7 +164,6 @@ class AstToXmlConverter(internal val program: PtProgram,
|
|||||||
is PtContainmentCheck -> write(it)
|
is PtContainmentCheck -> write(it)
|
||||||
is PtForLoop -> write(it)
|
is PtForLoop -> write(it)
|
||||||
is PtFunctionCall -> write(it)
|
is PtFunctionCall -> write(it)
|
||||||
is PtGosub -> write(it)
|
|
||||||
is PtIdentifier -> write(it)
|
is PtIdentifier -> write(it)
|
||||||
is PtIfElse -> write(it)
|
is PtIfElse -> write(it)
|
||||||
is PtInlineAssembly -> write(it)
|
is PtInlineAssembly -> write(it)
|
||||||
@ -554,12 +553,6 @@ class AstToXmlConverter(internal val program: PtProgram,
|
|||||||
xml.endElt()
|
xml.endElt()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun write(gosub: PtGosub) {
|
|
||||||
xml.elt("gosub")
|
|
||||||
xml.attr("symbol", strTargetName(gosub.identifier))
|
|
||||||
xml.endElt()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun write(sub: PtSub) {
|
private fun write(sub: PtSub) {
|
||||||
xml.elt("sub")
|
xml.elt("sub")
|
||||||
xml.attr("name", sub.scopedName.joinToString("."))
|
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 {
|
): IAssemblyGenerator {
|
||||||
|
|
||||||
internal val allocations = VariableAllocator(symbolTable, program, errors)
|
internal val allocations = VariableAllocator(symbolTable, program, errors)
|
||||||
private val builtinFunctions = BuiltinFunctionsGen(this)
|
private val expressionEval = ExpressionGen(this)
|
||||||
private val expressionEval = ExpressionGen(this, builtinFunctions)
|
|
||||||
private val instructions = mutableListOf<String>()
|
private val instructions = mutableListOf<String>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -93,7 +92,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
is PtArrayIndexer -> TODO()
|
is PtArrayIndexer -> TODO()
|
||||||
is PtArrayLiteral -> TODO()
|
is PtArrayLiteral -> TODO()
|
||||||
is PtBinaryExpression -> TODO()
|
is PtBinaryExpression -> TODO()
|
||||||
is PtBuiltinFunctionCall -> builtinFunctions.translate(node)
|
is PtBuiltinFunctionCall -> expressionEval.translate(node)
|
||||||
is PtContainmentCheck -> TODO()
|
is PtContainmentCheck -> TODO()
|
||||||
is PtFunctionCall -> translate(node)
|
is PtFunctionCall -> translate(node)
|
||||||
is PtIdentifier -> TODO()
|
is PtIdentifier -> TODO()
|
||||||
@ -105,7 +104,6 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
is PtString -> TODO()
|
is PtString -> TODO()
|
||||||
is PtTypeCast -> TODO()
|
is PtTypeCast -> TODO()
|
||||||
is PtForLoop -> TODO()
|
is PtForLoop -> TODO()
|
||||||
is PtGosub -> translate(node)
|
|
||||||
is PtIfElse -> TODO()
|
is PtIfElse -> TODO()
|
||||||
is PtJump -> TODO()
|
is PtJump -> TODO()
|
||||||
is PtNodeGroup -> TODO()
|
is PtNodeGroup -> TODO()
|
||||||
@ -128,17 +126,17 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
|
|
||||||
private fun translate(fcall: PtFunctionCall): VmCodeChunk {
|
private fun translate(fcall: PtFunctionCall): VmCodeChunk {
|
||||||
val chunk = 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))
|
chunk += VmCodeOpcodeWithStringArg(Opcode.GOSUB, gosubArg(fcall.functionName))
|
||||||
return chunk
|
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 {
|
private fun translate(ret: PtReturn): VmCodeChunk {
|
||||||
val chunk = VmCodeChunk()
|
val chunk = VmCodeChunk()
|
||||||
val value = ret.value
|
val value = ret.value
|
||||||
|
@ -5,7 +5,7 @@ import prog8.code.core.AssemblyError
|
|||||||
import prog8.vm.Instruction
|
import prog8.vm.Instruction
|
||||||
import prog8.vm.Opcode
|
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> {
|
fun translateExpression(expr: PtExpression): Pair<VmCodeChunk, Int> {
|
||||||
// TODO("Not yet implemented")
|
// TODO("Not yet implemented")
|
||||||
val chunk = VmCodeChunk()
|
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?
|
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.Result
|
||||||
import com.github.michaelbull.result.getOrElse
|
import com.github.michaelbull.result.getOrElse
|
||||||
import com.github.michaelbull.result.mapError
|
import com.github.michaelbull.result.mapError
|
||||||
|
import prog8.ast.IStatementContainer
|
||||||
import prog8.ast.Program
|
import prog8.ast.Program
|
||||||
import prog8.ast.base.FatalAstException
|
import prog8.ast.base.FatalAstException
|
||||||
import prog8.ast.expressions.*
|
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)
|
val assign = PtAssignment(srcAssign.isAugmentable, srcAssign.position)
|
||||||
assign.add(transform(srcAssign.target))
|
assign.add(transform(srcAssign.target))
|
||||||
assign.add(transformExpression(srcAssign.value))
|
assign.add(transformExpression(srcAssign.value))
|
||||||
@ -222,7 +229,35 @@ class IntermediateAstMaker(val program: Program) {
|
|||||||
return call
|
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 {
|
private fun transform(srcIf: IfElse): PtIfElse {
|
||||||
val ifelse = PtIfElse(srcIf.position)
|
val ifelse = PtIfElse(srcIf.position)
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
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