mirror of
https://github.com/irmen/prog8.git
synced 2026-04-19 20:16:51 +00:00
working on vm and new ast
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.mapError
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.vm.Instruction
|
||||
import java.io.File
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.isRegularFile
|
||||
import prog8.vm.Opcode
|
||||
|
||||
class CodeGen(internal val program: PtProgram,
|
||||
internal val symbolTable: SymbolTable,
|
||||
@@ -19,11 +14,30 @@ class CodeGen(internal val program: PtProgram,
|
||||
|
||||
private val instructions = mutableListOf<String>()
|
||||
|
||||
init {
|
||||
if(options.dontReinitGlobals)
|
||||
TODO("support no globals re-init in vm")
|
||||
}
|
||||
|
||||
override fun compileToAssembly(): IAssemblyProgram? {
|
||||
instructions.clear()
|
||||
val allocations = VariableAllocator(symbolTable, program, errors)
|
||||
for (block in program.allBlocks())
|
||||
|
||||
outComment("GLOBAL VARS INITS")
|
||||
program.allBlocks().forEach {
|
||||
it.children
|
||||
.singleOrNull { node->node is PtScopeVarsInit }
|
||||
?.let { inits->
|
||||
translateNode(inits)
|
||||
it.children.remove(inits)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
outComment("PROGRAM CODE")
|
||||
for (block in program.allBlocks()) {
|
||||
translateNode(block)
|
||||
}
|
||||
return AssemblyProgram(program.name, allocations, instructions)
|
||||
}
|
||||
|
||||
@@ -31,21 +45,22 @@ class CodeGen(internal val program: PtProgram,
|
||||
instructions.add(ins.toString())
|
||||
}
|
||||
|
||||
private fun out(ins: String) {
|
||||
instructions.add(ins)
|
||||
private fun outComment(ins: String) {
|
||||
instructions.add("; $ins")
|
||||
}
|
||||
|
||||
private fun translateNode(node: PtNode) {
|
||||
when(node) {
|
||||
is PtBlock -> translate(node)
|
||||
is PtSub -> translate(node)
|
||||
is PtScopeVarsDecls -> { /* vars should be looked up via symbol table */ }
|
||||
is PtVariable -> { /* var should be looked up via symbol table */ }
|
||||
is PtMemMapped -> { /* memmapped var should be looked up via symbol table */ }
|
||||
is PtConstant -> { /* constants have all been folded into the code */ }
|
||||
is PtAsmSub -> translate(node)
|
||||
is PtAssignTarget -> TODO()
|
||||
is PtAssignment -> translate(node)
|
||||
is PtBreakpoint -> TODO()
|
||||
is PtScopeVarsInit -> translate(node)
|
||||
is PtBreakpoint -> translate(node)
|
||||
is PtConditionalBranch -> TODO()
|
||||
is PtAddressOf -> TODO()
|
||||
is PtArrayIndexer -> TODO()
|
||||
@@ -76,28 +91,42 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtSubroutineParameter -> TODO()
|
||||
is PtWhen -> TODO()
|
||||
is PtWhenChoice -> TODO()
|
||||
is PtAsmSub -> throw AssemblyError("asmsub not supported on virtual machine target")
|
||||
is PtInlineAssembly -> throw AssemblyError("inline assembly not supported on virtual machine target")
|
||||
else -> TODO("missing codegen for $node")
|
||||
}
|
||||
}
|
||||
|
||||
private fun translate(sub: PtSub) {
|
||||
out("; SUB: ${sub.scopedName} -> ${sub.returntype}")
|
||||
private fun translate(breakpoint: PtBreakpoint) {
|
||||
out(Instruction(Opcode.BREAKPOINT))
|
||||
}
|
||||
|
||||
private fun translate(asmsub: PtAsmSub) {
|
||||
out("; ASMSUB: ${asmsub.scopedName} = ${asmsub.address} -> ${asmsub.retvalRegisters}")
|
||||
private fun translate(init: PtScopeVarsInit) {
|
||||
init.children.forEach { translateNode(it) }
|
||||
}
|
||||
|
||||
private fun translate(sub: PtSub) {
|
||||
outComment("SUB: ${sub.scopedName} -> ${sub.returntype}")
|
||||
sub.children
|
||||
.singleOrNull { it is PtScopeVarsInit }
|
||||
?.let { inits ->
|
||||
sub.children.remove(inits)
|
||||
translateNode(inits)
|
||||
}
|
||||
|
||||
// TODO rest
|
||||
outComment("SUB-END ${sub.scopedName}\n")
|
||||
}
|
||||
|
||||
private fun translate(assign: PtAssignment) {
|
||||
out("; ASSIGN: ${assign.target.identifier?.targetName} = ${assign.value}")
|
||||
outComment("ASSIGN: ${assign.target.identifier?.targetName} = ${assign.value}")
|
||||
}
|
||||
|
||||
private fun translate(block: PtBlock) {
|
||||
out("\n; BLOCK '${block.name}' addr=${block.address} lib=${block.library}")
|
||||
outComment("BLOCK '${block.name}' addr=${block.address} lib=${block.library}")
|
||||
for (child in block.children) {
|
||||
translateNode(child)
|
||||
}
|
||||
out("; BLOCK-END '${block.name}'\n")
|
||||
outComment("BLOCK-END '${block.name}'\n")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user