mirror of
https://github.com/irmen/prog8.git
synced 2024-08-10 14:29:06 +00:00
working on new Ast and XML export to test it
This commit is contained in:
parent
e227cc92ff
commit
40e9fba312
@ -3,6 +3,7 @@ package prog8.code.ast
|
|||||||
import prog8.code.core.IMemSizer
|
import prog8.code.core.IMemSizer
|
||||||
import prog8.code.core.IStringEncoding
|
import prog8.code.core.IStringEncoding
|
||||||
import prog8.code.core.Position
|
import prog8.code.core.Position
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
// New (work-in-progress) simplified AST for the code generator.
|
// New (work-in-progress) simplified AST for the code generator.
|
||||||
|
|
||||||
@ -62,6 +63,9 @@ class PtProgram(
|
|||||||
print("'$name'")
|
print("'$name'")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun allModuleDirectives(): Sequence<PtDirective> =
|
||||||
|
children.asSequence().flatMap { it.children }.filterIsInstance<PtDirective>().distinct()
|
||||||
|
|
||||||
fun allBlocks(): Sequence<PtBlock> =
|
fun allBlocks(): Sequence<PtBlock> =
|
||||||
children.asSequence().flatMap { it.children }.filterIsInstance<PtBlock>()
|
children.asSequence().flatMap { it.children }.filterIsInstance<PtBlock>()
|
||||||
|
|
||||||
@ -72,7 +76,7 @@ class PtProgram(
|
|||||||
|
|
||||||
class PtModule(
|
class PtModule(
|
||||||
name: String,
|
name: String,
|
||||||
val loadAddress: UInt,
|
val loadAddress: UInt?,
|
||||||
val library: Boolean,
|
val library: Boolean,
|
||||||
position: Position
|
position: Position
|
||||||
) : PtNamedNode(name, position) {
|
) : PtNamedNode(name, position) {
|
||||||
@ -100,6 +104,18 @@ class PtDirective(var name: String, position: Position) : PtNode(position) {
|
|||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print(name)
|
print(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(name, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if(other !is PtDirective)
|
||||||
|
return false
|
||||||
|
if(other===this)
|
||||||
|
return true
|
||||||
|
return(name==other.name && args.zip(other.args).all { it.first==it.second })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,6 +127,18 @@ class PtDirectiveArg(val str: String?,
|
|||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print("str=$str name=$name int=$int")
|
print("str=$str name=$name int=$int")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return Objects.hash(str, name, int)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if(other !is PtDirectiveArg)
|
||||||
|
return false
|
||||||
|
if(other===this)
|
||||||
|
return true
|
||||||
|
return str==other.str || name==other.name || int==other.int
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,76 +5,115 @@ import prog8.code.core.Encoding
|
|||||||
import prog8.code.core.Position
|
import prog8.code.core.Position
|
||||||
|
|
||||||
|
|
||||||
class PtAddressOf(position: Position) : PtNode(position) {
|
sealed class PtExpression(val type: DataType, position: Position) : PtNode(position) {
|
||||||
val identifier: PtIdentifier
|
|
||||||
get() = children.single() as PtIdentifier
|
|
||||||
|
|
||||||
override fun printProperties() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtArrayIndexer(position: Position): PtNode(position) {
|
|
||||||
val variable: PtIdentifier
|
|
||||||
get() = children[0] as PtIdentifier
|
|
||||||
val index: PtNode
|
|
||||||
get() = children[1]
|
|
||||||
|
|
||||||
override fun printProperties() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtArrayLiteral(val type: DataType, position: Position): PtNode(position) {
|
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print(type)
|
print(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtBinaryExpression(val operator: String, position: Position): PtNode(position) {
|
class PtAddressOf(position: Position) : PtExpression(DataType.UWORD, position) {
|
||||||
val left: PtNode
|
val identifier: PtIdentifier
|
||||||
get() = children[0]
|
get() = children.single() as PtIdentifier
|
||||||
val right: PtNode
|
}
|
||||||
get() = children[1]
|
|
||||||
|
|
||||||
|
|
||||||
|
class PtArrayIndexer(type: DataType, position: Position): PtExpression(type, position) {
|
||||||
|
val variable: PtIdentifier
|
||||||
|
get() = children[0] as PtIdentifier
|
||||||
|
val index: PtExpression
|
||||||
|
get() = children[1] as PtExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PtArrayLiteral(type: DataType, position: Position): PtExpression(type, position)
|
||||||
|
|
||||||
|
|
||||||
|
class PtBuiltinFunctionCall(val name: String, val void: Boolean, type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
|
init {
|
||||||
|
if(!void)
|
||||||
|
require(type!=DataType.UNDEFINED)
|
||||||
|
}
|
||||||
|
|
||||||
|
val args: List<PtExpression>
|
||||||
|
get() = children.map { it as PtExpression }
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print(operator)
|
print("$name void=$void")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtContainmentCheck(position: Position): PtNode(position) {
|
class PtBinaryExpression(val operator: String, type: DataType, position: Position): PtExpression(type, position) {
|
||||||
val element: PtNode
|
val left: PtExpression
|
||||||
get() = children[0]
|
get() = children[0] as PtExpression
|
||||||
val iterable: PtNode
|
val right: PtExpression
|
||||||
get() = children[0]
|
get() = children[1] as PtExpression
|
||||||
override fun printProperties() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtIdentifier(val ref: List<String>, val targetName: List<String>, position: Position) : PtNode(position) {
|
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print("$ref --> $targetName")
|
print("$operator -> $type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtMemoryByte(position: Position) : PtNode(position) {
|
class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, position) {
|
||||||
val address: PtNode
|
val element: PtExpression
|
||||||
get() = children.single()
|
get() = children[0] as PtExpression
|
||||||
|
val iterable: PtExpression
|
||||||
|
get() = children[0] as PtExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PtFunctionCall(val functionName: List<String>,
|
||||||
|
val void: Boolean,
|
||||||
|
type: DataType,
|
||||||
|
position: Position) : PtExpression(type, position) {
|
||||||
|
init {
|
||||||
|
if(!void)
|
||||||
|
require(type!=DataType.UNDEFINED)
|
||||||
|
}
|
||||||
|
|
||||||
|
val args: List<PtExpression>
|
||||||
|
get() = children.map { it as PtExpression }
|
||||||
|
override fun printProperties() {
|
||||||
|
print("${functionName.joinToString(".")} void=$void")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PtIdentifier(val ref: List<String>, val targetName: List<String>, type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
|
override fun printProperties() {
|
||||||
|
print("$ref --> $targetName $type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PtMemoryByte(position: Position) : PtExpression(DataType.UBYTE, position) {
|
||||||
|
val address: PtExpression
|
||||||
|
get() = children.single() as PtExpression
|
||||||
override fun printProperties() {}
|
override fun printProperties() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtNumber(val type: DataType, val number: Double, position: Position) : PtNode(position) {
|
class PtNumber(type: DataType, val number: Double, position: Position) : PtExpression(type, position) {
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print("$number ($type)")
|
print("$number ($type)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtPrefix(val operator: String, position: Position): PtNode(position) {
|
class PtPipe(type: DataType, val void: Boolean, position: Position) : PtExpression(type, position) {
|
||||||
val value: PtNode
|
init {
|
||||||
get() = children.single()
|
if(!void)
|
||||||
|
require(type!=DataType.UNDEFINED)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printProperties() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PtPrefix(val operator: String, type: DataType, position: Position): PtExpression(type, position) {
|
||||||
|
val value: PtExpression
|
||||||
|
get() = children.single() as PtExpression
|
||||||
|
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print(operator)
|
print(operator)
|
||||||
@ -82,27 +121,26 @@ class PtPrefix(val operator: String, position: Position): PtNode(position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtRange(position: Position) : PtNode(position) {
|
class PtRange(type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
val from: PtNode
|
val from: PtExpression
|
||||||
get() = children[0]
|
get() = children[0] as PtExpression
|
||||||
val to: PtNode
|
val to: PtExpression
|
||||||
get() = children[1]
|
get() = children[1] as PtExpression
|
||||||
val step: PtNode
|
val step: PtExpression
|
||||||
get() = children[2]
|
get() = children[2] as PtExpression
|
||||||
|
|
||||||
override fun printProperties() {}
|
override fun printProperties() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtString(val value: String, val encoding: Encoding, position: Position) : PtNode(position) {
|
class PtString(val value: String, val encoding: Encoding, position: Position) : PtExpression(DataType.STR, position) {
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print("$encoding:\"$value\"")
|
print("$encoding:\"$value\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtTypeCast(val type: DataType, position: Position) : PtNode(position) {
|
class PtTypeCast(type: DataType, position: Position) : PtExpression(type, position) {
|
||||||
override fun printProperties() {
|
val value: PtExpression
|
||||||
print(type)
|
get() = children.single() as PtExpression
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package prog8.code.ast
|
package prog8.code.ast
|
||||||
|
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
|
import javax.xml.crypto.Data
|
||||||
|
|
||||||
|
|
||||||
class PtAsmSub(
|
class PtAsmSub(
|
||||||
name: String,
|
name: String,
|
||||||
val address: UInt?,
|
val address: UInt?,
|
||||||
val clobbers: Set<CpuRegister>,
|
val clobbers: Set<CpuRegister>,
|
||||||
val paramRegisters: List<RegisterOrStatusflag>,
|
val parameters: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>,
|
||||||
val retvalRegisters: List<RegisterOrStatusflag>,
|
val retvalRegisters: List<RegisterOrStatusflag>,
|
||||||
val inline: Boolean,
|
val inline: Boolean,
|
||||||
position: Position
|
position: Position
|
||||||
@ -41,8 +42,8 @@ class PtSubroutineParameter(val name: String, val type: DataType, position: Posi
|
|||||||
class PtAssignment(val augmentable: Boolean, position: Position) : PtNode(position) {
|
class PtAssignment(val augmentable: Boolean, position: Position) : PtNode(position) {
|
||||||
val target: PtAssignTarget
|
val target: PtAssignTarget
|
||||||
get() = children[0] as PtAssignTarget
|
get() = children[0] as PtAssignTarget
|
||||||
val value: PtNode
|
val value: PtExpression
|
||||||
get() = children[1]
|
get() = children[1] as PtExpression
|
||||||
|
|
||||||
override fun printProperties() {
|
override fun printProperties() {
|
||||||
print("aug=$augmentable")
|
print("aug=$augmentable")
|
||||||
@ -62,13 +63,6 @@ class PtAssignTarget(position: Position) : PtNode(position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtBuiltinFunctionCall(val name: String, position: Position) : PtNode(position) {
|
|
||||||
override fun printProperties() {
|
|
||||||
print(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtConditionalBranch(val condition: BranchCondition, position: Position) : PtNode(position) {
|
class PtConditionalBranch(val condition: BranchCondition, position: Position) : PtNode(position) {
|
||||||
val trueScope: PtNodeGroup
|
val trueScope: PtNodeGroup
|
||||||
get() = children[0] as PtNodeGroup
|
get() = children[0] as PtNodeGroup
|
||||||
@ -84,8 +78,8 @@ class PtConditionalBranch(val condition: BranchCondition, position: Position) :
|
|||||||
class PtForLoop(position: Position) : PtNode(position) {
|
class PtForLoop(position: Position) : PtNode(position) {
|
||||||
val variable: PtIdentifier
|
val variable: PtIdentifier
|
||||||
get() = children[0] as PtIdentifier
|
get() = children[0] as PtIdentifier
|
||||||
val iterable: PtNode
|
val iterable: PtExpression
|
||||||
get() = children[1]
|
get() = children[1] as PtExpression
|
||||||
val statements: PtNodeGroup
|
val statements: PtNodeGroup
|
||||||
get() = children[2] as PtNodeGroup
|
get() = children[2] as PtNodeGroup
|
||||||
|
|
||||||
@ -93,18 +87,6 @@ class PtForLoop(position: Position) : PtNode(position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtFunctionCall(val void: Boolean, position: Position) : PtNode(position) {
|
|
||||||
val target: PtIdentifier
|
|
||||||
get() = children[0] as PtIdentifier
|
|
||||||
val args: PtNodeGroup
|
|
||||||
get() = children[1] as PtNodeGroup
|
|
||||||
|
|
||||||
override fun printProperties() {
|
|
||||||
print("void=$void")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtGosub(val identifier: PtIdentifier?,
|
class PtGosub(val identifier: PtIdentifier?,
|
||||||
val address: UInt?,
|
val address: UInt?,
|
||||||
val generatedLabel: String?,
|
val generatedLabel: String?,
|
||||||
@ -118,8 +100,8 @@ class PtGosub(val identifier: PtIdentifier?,
|
|||||||
|
|
||||||
|
|
||||||
class PtIfElse(position: Position) : PtNode(position) {
|
class PtIfElse(position: Position) : PtNode(position) {
|
||||||
val condition: PtNode
|
val condition: PtExpression
|
||||||
get() = children[0]
|
get() = children[0] as PtExpression
|
||||||
val ifScope: PtNodeGroup
|
val ifScope: PtNodeGroup
|
||||||
get() = children[1] as PtNodeGroup
|
get() = children[1] as PtNodeGroup
|
||||||
val elseScope: PtNodeGroup
|
val elseScope: PtNodeGroup
|
||||||
@ -141,11 +123,6 @@ class PtJump(val identifier: PtIdentifier?,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PtPipe(position: Position) : PtNode(position) {
|
|
||||||
override fun printProperties() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class PtPostIncrDecr(val operator: String, position: Position) : PtNode(position) {
|
class PtPostIncrDecr(val operator: String, position: Position) : PtNode(position) {
|
||||||
val target: PtAssignTarget
|
val target: PtAssignTarget
|
||||||
get() = children.single() as PtAssignTarget
|
get() = children.single() as PtAssignTarget
|
||||||
@ -157,8 +134,10 @@ class PtPostIncrDecr(val operator: String, position: Position) : PtNode(position
|
|||||||
|
|
||||||
|
|
||||||
class PtRepeatLoop(position: Position) : PtNode(position) {
|
class PtRepeatLoop(position: Position) : PtNode(position) {
|
||||||
val count: PtNode
|
val count: PtExpression
|
||||||
get() = children.single()
|
get() = children[0] as PtExpression
|
||||||
|
val statements: PtNodeGroup
|
||||||
|
get() = children[1] as PtNodeGroup
|
||||||
|
|
||||||
override fun printProperties() {}
|
override fun printProperties() {}
|
||||||
}
|
}
|
||||||
@ -166,10 +145,10 @@ class PtRepeatLoop(position: Position) : PtNode(position) {
|
|||||||
|
|
||||||
class PtReturn(position: Position) : PtNode(position) {
|
class PtReturn(position: Position) : PtNode(position) {
|
||||||
val hasValue = children.any()
|
val hasValue = children.any()
|
||||||
val value: PtNode?
|
val value: PtExpression?
|
||||||
get() {
|
get() {
|
||||||
return if(children.any())
|
return if(children.any())
|
||||||
children.single()
|
children.single() as PtExpression
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@ -200,8 +179,8 @@ class PtMemMapped(name: String, val type: DataType, val address: UInt, position:
|
|||||||
|
|
||||||
|
|
||||||
class PtWhen(position: Position) : PtNode(position) {
|
class PtWhen(position: Position) : PtNode(position) {
|
||||||
val value: PtNode
|
val value: PtExpression
|
||||||
get() = children[0]
|
get() = children[0] as PtExpression
|
||||||
val choices: PtNodeGroup
|
val choices: PtNodeGroup
|
||||||
get() = children[1] as PtNodeGroup
|
get() = children[1] as PtNodeGroup
|
||||||
|
|
||||||
@ -210,5 +189,9 @@ class PtWhen(position: Position) : PtNode(position) {
|
|||||||
|
|
||||||
|
|
||||||
class PtWhenChoice(val isElse: Boolean, position: Position) : PtNode(position) {
|
class PtWhenChoice(val isElse: Boolean, position: Position) : PtNode(position) {
|
||||||
|
val values: PtNodeGroup
|
||||||
|
get() = children[0] as PtNodeGroup
|
||||||
|
val statements: PtNodeGroup
|
||||||
|
get() = children[1] as PtNodeGroup
|
||||||
override fun printProperties() {}
|
override fun printProperties() {}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ internal class ProgramAndVarsGen(
|
|||||||
asmgen.out("")
|
asmgen.out("")
|
||||||
asmgen.out(".cpu '$cpu'\n.enc 'none'\n")
|
asmgen.out(".cpu '$cpu'\n.enc 'none'\n")
|
||||||
|
|
||||||
program.actualLoadAddress = program.definedLoadAddress
|
program.actualLoadAddress = program.definedLoadAddress ?: 0u
|
||||||
if (program.actualLoadAddress == 0u) {
|
if (program.actualLoadAddress == 0u) {
|
||||||
when(options.output) {
|
when(options.output) {
|
||||||
OutputType.RAW -> {
|
OutputType.RAW -> {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package prog8.codegen.experimental
|
package prog8.codegen.experimental
|
||||||
|
|
||||||
import prog8.code.SymbolTable
|
import prog8.code.SymbolTable
|
||||||
import prog8.code.ast.PtProgram
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.CompilationOptions
|
import prog8.code.core.*
|
||||||
import prog8.code.core.IAssemblyGenerator
|
import javax.xml.stream.XMLOutputFactory
|
||||||
import prog8.code.core.IAssemblyProgram
|
import kotlin.io.path.Path
|
||||||
import prog8.code.core.IErrorReporter
|
import kotlin.io.path.div
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -17,21 +17,578 @@ import prog8.code.core.IErrorReporter
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
class AsmGen(internal val program: PtProgram,
|
class AsmGen(internal val program: PtProgram,
|
||||||
internal val errors: IErrorReporter,
|
internal val errors: IErrorReporter,
|
||||||
internal val symbolTable: SymbolTable,
|
internal val symbolTable: SymbolTable,
|
||||||
internal val options: CompilationOptions
|
internal val options: CompilationOptions
|
||||||
): IAssemblyGenerator {
|
): IAssemblyGenerator {
|
||||||
|
|
||||||
|
private lateinit var xml: IndentingXmlWriter
|
||||||
|
|
||||||
override fun compileToAssembly(): IAssemblyProgram? {
|
override fun compileToAssembly(): IAssemblyProgram? {
|
||||||
|
|
||||||
println("\n** experimental code generator **\n")
|
println("\n** experimental code generator **\n")
|
||||||
|
|
||||||
symbolTable.print()
|
val writer = (options.outputDir / Path(program.name+"-ast.xml")).toFile().printWriter()
|
||||||
symbolTable.flat.forEach { println(it) }
|
xml = IndentingXmlWriter(XMLOutputFactory.newFactory().createXMLStreamWriter(writer))
|
||||||
program.print()
|
xml.doc()
|
||||||
|
xml.elt("program")
|
||||||
|
xml.attr("name", program.name)
|
||||||
|
xml.startChildren()
|
||||||
|
program.allModuleDirectives().forEach { writeNode(it) }
|
||||||
|
program.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
xml.endDoc()
|
||||||
|
xml.close()
|
||||||
println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
|
println("..todo: create assembly code into ${options.outputDir.toAbsolutePath()}..")
|
||||||
return AssemblyProgram("dummy")
|
return AssemblyProgram("dummy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun writeNode(it: PtNode) {
|
||||||
|
when(it) {
|
||||||
|
is PtModule -> write(it)
|
||||||
|
is PtBlock -> write(it)
|
||||||
|
is PtDirective -> write(it)
|
||||||
|
is PtSub -> write(it)
|
||||||
|
is PtVariable -> write(it)
|
||||||
|
is PtAssignment -> write(it)
|
||||||
|
is PtConstant -> write(it)
|
||||||
|
is PtAsmSub -> write(it)
|
||||||
|
is PtAddressOf -> write(it)
|
||||||
|
is PtArrayIndexer -> write(it)
|
||||||
|
is PtArrayLiteral -> write(it)
|
||||||
|
is PtBinaryExpression -> write(it)
|
||||||
|
is PtBuiltinFunctionCall -> write(it)
|
||||||
|
is PtConditionalBranch -> write(it)
|
||||||
|
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)
|
||||||
|
is PtJump -> write(it)
|
||||||
|
is PtMemoryByte -> write(it)
|
||||||
|
is PtMemMapped -> write(it)
|
||||||
|
is PtNumber -> write(it)
|
||||||
|
is PtPipe -> write(it)
|
||||||
|
is PtPostIncrDecr -> write(it)
|
||||||
|
is PtPrefix -> write(it)
|
||||||
|
is PtRange -> write(it)
|
||||||
|
is PtRepeatLoop -> write(it)
|
||||||
|
is PtReturn -> write(it)
|
||||||
|
is PtString -> write(it)
|
||||||
|
is PtTypeCast -> write(it)
|
||||||
|
is PtWhen -> write(it)
|
||||||
|
is PtWhenChoice -> write(it)
|
||||||
|
is PtLabel -> write(it)
|
||||||
|
is PtNodeGroup -> it.children.forEach { writeNode(it) }
|
||||||
|
else -> TODO("$it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(pipe: PtPipe) {
|
||||||
|
xml.elt("pipe")
|
||||||
|
xml.attr("type", pipe.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
pipe.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(array: PtArrayLiteral) {
|
||||||
|
xml.elt("array")
|
||||||
|
xml.attr("type", array.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
array.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(prefix: PtPrefix) {
|
||||||
|
xml.elt("prefix")
|
||||||
|
xml.attr("op", prefix.operator)
|
||||||
|
xml.attr("type", prefix.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.elt("value")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(prefix.value)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(string: PtString) {
|
||||||
|
xml.elt("string")
|
||||||
|
xml.attr("encoding", string.encoding.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.text(string.value)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(rept: PtRepeatLoop) {
|
||||||
|
xml.elt("repeat")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(rept.position)
|
||||||
|
xml.elt("count")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(rept.count)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("statements")
|
||||||
|
writeNode(rept.statements)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(branch: PtConditionalBranch) {
|
||||||
|
xml.elt("conditionalbranch")
|
||||||
|
xml.attr("condition", branch.condition.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(branch.position)
|
||||||
|
xml.elt("true")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(branch.trueScope)
|
||||||
|
xml.endElt()
|
||||||
|
if(branch.falseScope.children.isNotEmpty()) {
|
||||||
|
xml.elt("false")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(branch.falseScope)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(check: PtContainmentCheck) {
|
||||||
|
xml.elt("containment")
|
||||||
|
xml.attr("type", check.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.elt("element")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(check.element)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("iterable")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(check.iterable)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(range: PtRange) {
|
||||||
|
xml.elt("range")
|
||||||
|
xml.attr("type", range.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.elt("from")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(range.from)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("to")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(range.to)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("step")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(range.step)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(forLoop: PtForLoop) {
|
||||||
|
xml.elt("for")
|
||||||
|
xml.attr("var", strTargetName(forLoop.variable))
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(forLoop.position)
|
||||||
|
xml.elt("iterable")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(forLoop.iterable)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("statements")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(forLoop.statements)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(membyte: PtMemoryByte) {
|
||||||
|
xml.elt("membyte")
|
||||||
|
xml.attr("type", membyte.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.elt("address")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(membyte.address)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(whenStmt: PtWhen) {
|
||||||
|
xml.elt("when")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(whenStmt.position)
|
||||||
|
xml.elt("value")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(whenStmt.value)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("choices")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(whenStmt.choices)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(choice: PtWhenChoice) {
|
||||||
|
xml.elt("choice")
|
||||||
|
if(choice.isElse) {
|
||||||
|
xml.attr("else", "true")
|
||||||
|
xml.startChildren()
|
||||||
|
} else {
|
||||||
|
xml.startChildren()
|
||||||
|
xml.elt("values")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(choice.values)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
xml.elt("statements")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(choice.statements)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(inlineAsm: PtInlineAssembly) {
|
||||||
|
xml.elt("assembly")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(inlineAsm.position)
|
||||||
|
xml.elt("code")
|
||||||
|
xml.text(inlineAsm.assembly)
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(fcall: PtBuiltinFunctionCall) {
|
||||||
|
xml.elt("builtinfcall")
|
||||||
|
xml.attr("name", fcall.name)
|
||||||
|
if(fcall.void)
|
||||||
|
xml.attr("type", "VOID")
|
||||||
|
else
|
||||||
|
xml.attr("type", fcall.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
fcall.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(cast: PtTypeCast) {
|
||||||
|
xml.elt("cast")
|
||||||
|
xml.attr("type", cast.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(cast.value)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(aix: PtArrayIndexer) {
|
||||||
|
xml.elt("arrayindexed")
|
||||||
|
xml.attr("type", aix.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
write(aix.variable)
|
||||||
|
writeNode(aix.index)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(binexpr: PtBinaryExpression) {
|
||||||
|
xml.elt("binexpr")
|
||||||
|
xml.attr("op", binexpr.operator)
|
||||||
|
xml.attr("type", binexpr.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(binexpr.left)
|
||||||
|
writeNode(binexpr.right)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(addrof: PtAddressOf) {
|
||||||
|
xml.elt("addrof")
|
||||||
|
xml.startChildren()
|
||||||
|
write(addrof.identifier)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(fcall: PtFunctionCall) {
|
||||||
|
xml.elt("fcall")
|
||||||
|
xml.attr("name", strTargetName(fcall))
|
||||||
|
if(fcall.void)
|
||||||
|
xml.attr("type", "VOID")
|
||||||
|
else
|
||||||
|
xml.attr("type", fcall.type.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(fcall.position)
|
||||||
|
fcall.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(number: PtNumber) {
|
||||||
|
xml.elt("number")
|
||||||
|
xml.attr("type", number.type.name)
|
||||||
|
xml.attr("value", intOrDouble(number.type, number.number).toString())
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(symbol: PtIdentifier) {
|
||||||
|
xml.elt("symbol")
|
||||||
|
xml.attr("name", strTargetName(symbol))
|
||||||
|
xml.attr("type", symbol.type.name)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(assign: PtAssignment) {
|
||||||
|
xml.elt("assign")
|
||||||
|
xml.attr("aug", assign.augmentable.toString())
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(assign.position)
|
||||||
|
write(assign.target)
|
||||||
|
writeNode(assign.value)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(ifElse: PtIfElse) {
|
||||||
|
xml.elt("ifelse")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(ifElse.position)
|
||||||
|
xml.elt("condition")
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(ifElse.condition)
|
||||||
|
xml.endElt()
|
||||||
|
xml.elt("true")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(ifElse.ifScope.position)
|
||||||
|
writeNode(ifElse.ifScope)
|
||||||
|
xml.endElt()
|
||||||
|
if(ifElse.elseScope.children.isNotEmpty()) {
|
||||||
|
xml.elt("false")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(ifElse.elseScope.position)
|
||||||
|
writeNode(ifElse.elseScope)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(ret: PtReturn) {
|
||||||
|
xml.elt("return")
|
||||||
|
if(ret.hasValue) {
|
||||||
|
xml.startChildren()
|
||||||
|
writeNode(ret.value!!)
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(incdec: PtPostIncrDecr) {
|
||||||
|
if(incdec.operator=="++") xml.elt("inc") else xml.elt("dec")
|
||||||
|
xml.startChildren()
|
||||||
|
write(incdec.target)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(label: PtLabel) {
|
||||||
|
xml.elt("label")
|
||||||
|
xml.attr("name", label.name)
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(label.position)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(module: PtModule) {
|
||||||
|
xml.elt("module")
|
||||||
|
xml.attr("name", module.name)
|
||||||
|
xml.attr("library", module.library.toString())
|
||||||
|
if(module.loadAddress!=null)
|
||||||
|
xml.attr("loadaddress", module.loadAddress.toString())
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(module.position)
|
||||||
|
module.children.asSequence().filter { it !is PtDirective }.forEach { write(it as PtBlock) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(block: PtBlock) {
|
||||||
|
xml.elt("block")
|
||||||
|
xml.attr("name", block.name)
|
||||||
|
if(block.address!=null)
|
||||||
|
xml.attr("address", block.address!!.toString())
|
||||||
|
xml.attr("library", block.library.toString())
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(block.position)
|
||||||
|
block.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(memMapped: PtMemMapped) {
|
||||||
|
xml.elt("memvar")
|
||||||
|
xml.attr("type", memMapped.type.name)
|
||||||
|
xml.attr("name", memMapped.name)
|
||||||
|
xml.attr("address", memMapped.address.toString())
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(target: PtAssignTarget) {
|
||||||
|
xml.elt("target")
|
||||||
|
xml.startChildren()
|
||||||
|
if(target.identifier!=null) {
|
||||||
|
writeNode(target.identifier!!)
|
||||||
|
} else if(target.memory!=null) {
|
||||||
|
writeNode(target.memory!!)
|
||||||
|
} else if(target.array!=null) {
|
||||||
|
writeNode(target.array!!)
|
||||||
|
} else
|
||||||
|
throw InternalCompilerException("weird assign target")
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(jump: PtJump) {
|
||||||
|
xml.elt("jump")
|
||||||
|
if(jump.identifier!=null) xml.attr("symbol", strTargetName(jump.identifier!!))
|
||||||
|
else if(jump.address!=null) xml.attr("address", jump.address!!.toString())
|
||||||
|
else if(jump.generatedLabel!=null) xml.attr("label", jump.generatedLabel!!)
|
||||||
|
else
|
||||||
|
throw InternalCompilerException("weird jump target")
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(gosub: PtGosub) {
|
||||||
|
xml.elt("gosub")
|
||||||
|
if(gosub.identifier!=null) xml.attr("symbol", strTargetName(gosub.identifier!!))
|
||||||
|
else if(gosub.address!=null) xml.attr("address", gosub.address!!.toString())
|
||||||
|
else if(gosub.generatedLabel!=null) xml.attr("label", gosub.generatedLabel!!)
|
||||||
|
else
|
||||||
|
throw InternalCompilerException("weird jump target")
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(sub: PtSub) {
|
||||||
|
xml.elt("sub")
|
||||||
|
xml.attr("name", sub.name)
|
||||||
|
if(sub.inline)
|
||||||
|
xml.attr("inline", "true")
|
||||||
|
xml.attr("returntype", sub.returntype?.toString() ?: "VOID")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(sub.position)
|
||||||
|
if(sub.parameters.isNotEmpty()) {
|
||||||
|
xml.elt("parameters")
|
||||||
|
xml.startChildren()
|
||||||
|
sub.parameters.forEach { write(it) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
xml.elt("statements")
|
||||||
|
xml.startChildren()
|
||||||
|
sub.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(parameter: PtSubroutineParameter, registerOrStatusflag: RegisterOrStatusflag? = null) {
|
||||||
|
xml.elt("param")
|
||||||
|
xml.attr("name", parameter.name)
|
||||||
|
xml.attr("type", parameter.type.name)
|
||||||
|
if(registerOrStatusflag?.statusflag!=null) {
|
||||||
|
xml.attr("statusflag", registerOrStatusflag.statusflag!!.toString())
|
||||||
|
}
|
||||||
|
if(registerOrStatusflag?.registerOrPair!=null){
|
||||||
|
xml.attr("registers", registerOrStatusflag.registerOrPair!!.name)
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(asmSub: PtAsmSub) {
|
||||||
|
if(asmSub.address!=null) {
|
||||||
|
xml.elt("romsub")
|
||||||
|
xml.attr("name", asmSub.name)
|
||||||
|
xml.attr("address", asmSub.address!!.toString())
|
||||||
|
if(asmSub.inline)
|
||||||
|
xml.attr("inline", "true")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(asmSub.position)
|
||||||
|
paramsEtcetera(asmSub)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xml.elt("asmsub")
|
||||||
|
xml.attr("name", asmSub.name)
|
||||||
|
if(asmSub.inline)
|
||||||
|
xml.attr("inline", "true")
|
||||||
|
xml.startChildren()
|
||||||
|
xml.pos(asmSub.position)
|
||||||
|
paramsEtcetera(asmSub)
|
||||||
|
xml.elt("code")
|
||||||
|
xml.startChildren()
|
||||||
|
asmSub.children.forEach { writeNode(it) }
|
||||||
|
xml.endElt()
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun paramsEtcetera(asmSub: PtAsmSub) {
|
||||||
|
if(asmSub.parameters.isNotEmpty()) {
|
||||||
|
xml.elt("parameters")
|
||||||
|
xml.startChildren()
|
||||||
|
asmSub.parameters.forEach { (param, reg) -> write(param, reg) }
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
if(asmSub.clobbers.isNotEmpty()) {
|
||||||
|
xml.elt("clobbers")
|
||||||
|
xml.attr("registers", asmSub.clobbers.map {it.name}.joinToString(","))
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
if(asmSub.retvalRegisters.isNotEmpty()) {
|
||||||
|
xml.elt("returns")
|
||||||
|
xml.startChildren()
|
||||||
|
asmSub.retvalRegisters.forEach {
|
||||||
|
xml.elt("register")
|
||||||
|
if(it.statusflag!=null)
|
||||||
|
xml.attr("statusflag", it.statusflag!!.toString())
|
||||||
|
if(it.registerOrPair!=null)
|
||||||
|
xml.attr("registers", it.registerOrPair!!.toString())
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(constant: PtConstant) {
|
||||||
|
xml.elt("const")
|
||||||
|
xml.attr("name", constant.name)
|
||||||
|
xml.attr("type", constant.type.name)
|
||||||
|
xml.attr("value", intOrDouble(constant.type, constant.value).toString())
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(variable: PtVariable) {
|
||||||
|
// TODO get this from the AST only?
|
||||||
|
xml.elt("var")
|
||||||
|
xml.attr("name", variable.name)
|
||||||
|
xml.attr("type", variable.type.name)
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun write(directive: PtDirective) {
|
||||||
|
if(directive.name=="%import")
|
||||||
|
return
|
||||||
|
xml.elt("directive")
|
||||||
|
xml.attr("name", directive.name.substring(1))
|
||||||
|
if(directive.args.isNotEmpty()) {
|
||||||
|
xml.startChildren()
|
||||||
|
directive.args.forEach {
|
||||||
|
xml.elt("arg")
|
||||||
|
if(it.name!=null)
|
||||||
|
xml.attr("name", it.name!!)
|
||||||
|
if(it.str!=null)
|
||||||
|
xml.attr("string", it.str!!)
|
||||||
|
if(it.int!=null)
|
||||||
|
xml.attr("number", it.int!!.toString())
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xml.endElt()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private fun strTargetName(ident: PtIdentifier): String = ident.targetName.joinToString(".")
|
||||||
|
|
||||||
|
private fun strTargetName(call: PtFunctionCall): String = call.functionName.joinToString(".")
|
||||||
|
|
||||||
|
private fun intOrDouble(type: DataType, value: Double): Number =
|
||||||
|
if(type in IntegerDatatypes) value.toInt() else value
|
||||||
}
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package prog8.codegen.experimental
|
||||||
|
|
||||||
|
import prog8.code.core.Position
|
||||||
|
import java.util.*
|
||||||
|
import javax.xml.stream.XMLStreamWriter
|
||||||
|
|
||||||
|
class IndentingXmlWriter(val xml: XMLStreamWriter): XMLStreamWriter by xml {
|
||||||
|
private var indent = 0
|
||||||
|
private var content = Stack<Boolean>()
|
||||||
|
|
||||||
|
fun doc(version: String? = null) = if(version==null) writeStartDocument() else writeStartDocument(version)
|
||||||
|
fun endDoc() = writeEndDocument()
|
||||||
|
fun elt(name: String) = writeStartElement(name)
|
||||||
|
fun attr(name: String, value: String) = writeAttribute(name, value)
|
||||||
|
fun attrs(attributes: List<Pair<String, String>>) = attributes.forEach { writeAttribute(it.first, it.second) }
|
||||||
|
fun text(text: String) = writeCData(text)
|
||||||
|
fun startChildren() {
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
content.pop()
|
||||||
|
content.push(true)
|
||||||
|
}
|
||||||
|
fun endElt() = this.writeEndElement()
|
||||||
|
fun pos(pos: Position) {
|
||||||
|
elt("src")
|
||||||
|
attr("pos", pos.toString())
|
||||||
|
endElt()
|
||||||
|
}
|
||||||
|
fun comment(text: String) {
|
||||||
|
writeComment(text)
|
||||||
|
writeCharacters("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeStartDocument() {
|
||||||
|
xml.writeStartDocument()
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
content.push(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeStartDocument(version: String) {
|
||||||
|
xml.writeStartDocument(version)
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
content.push(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeEndDocument() {
|
||||||
|
xml.writeEndDocument()
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
require(indent==0)
|
||||||
|
require(content.size==1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeStartElement(name: String) {
|
||||||
|
xml.writeCharacters(" ".repeat(indent))
|
||||||
|
xml.writeStartElement(name)
|
||||||
|
indent++
|
||||||
|
content.push(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeStartElement(name: String, ns: String) {
|
||||||
|
xml.writeCharacters(" ".repeat(indent))
|
||||||
|
xml.writeStartElement(name, ns)
|
||||||
|
indent++
|
||||||
|
content.push(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeEndElement() {
|
||||||
|
indent--
|
||||||
|
if(content.pop())
|
||||||
|
xml.writeCharacters(" ".repeat(indent))
|
||||||
|
xml.writeEndElement()
|
||||||
|
xml.writeCharacters("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeStartElement(name: String, ns: String, p2: String) {
|
||||||
|
xml.writeCharacters(" ".repeat(indent))
|
||||||
|
xml.writeStartElement(name, ns, p2)
|
||||||
|
indent++
|
||||||
|
content.push(false)
|
||||||
|
}
|
||||||
|
}
|
@ -6,21 +6,22 @@ import prog8.ast.base.FatalAstException
|
|||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
|
import prog8.code.core.DataType
|
||||||
|
|
||||||
|
|
||||||
class IntermediateAstMaker(val srcProgram: Program) {
|
class IntermediateAstMaker(val program: Program) {
|
||||||
fun transform(): PtProgram {
|
fun transform(): PtProgram {
|
||||||
val program = PtProgram(
|
val ptProgram = PtProgram(
|
||||||
srcProgram.name,
|
program.name,
|
||||||
srcProgram.memsizer,
|
program.memsizer,
|
||||||
srcProgram.encoding
|
program.encoding
|
||||||
)
|
)
|
||||||
|
|
||||||
for (module in srcProgram.modules) {
|
for (module in program.modules) {
|
||||||
program.add(transform(module))
|
ptProgram.add(transform(module))
|
||||||
}
|
}
|
||||||
|
|
||||||
return program
|
return ptProgram
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcModule: Module): PtModule {
|
private fun transform(srcModule: Module): PtModule {
|
||||||
@ -71,7 +72,7 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformExpression(expr: Expression): PtNode {
|
private fun transformExpression(expr: Expression): PtExpression {
|
||||||
return when(expr) {
|
return when(expr) {
|
||||||
is AddressOf -> transform(expr)
|
is AddressOf -> transform(expr)
|
||||||
is ArrayIndexedExpression -> transform(expr)
|
is ArrayIndexedExpression -> transform(expr)
|
||||||
@ -112,13 +113,19 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(identifier: IdentifierReference): PtIdentifier {
|
private fun targetOf(identifier: IdentifierReference): Pair<List<String>, DataType> {
|
||||||
val target=identifier.targetStatement(srcProgram)!! as INamedStatement
|
val target=identifier.targetStatement(program)!! as INamedStatement
|
||||||
val targetname = if(target.name in srcProgram.builtinFunctions.names)
|
val targetname = if(target.name in program.builtinFunctions.names)
|
||||||
listOf("<builtin>", target.name)
|
listOf("<builtin>", target.name)
|
||||||
else
|
else
|
||||||
target.scopedName
|
target.scopedName
|
||||||
return PtIdentifier(identifier.nameInSource, targetname, identifier.position)
|
val type = identifier.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
|
return Pair(targetname, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun transform(identifier: IdentifierReference): PtIdentifier {
|
||||||
|
val (target, type) = targetOf(identifier)
|
||||||
|
return PtIdentifier(identifier.nameInSource, target, type, identifier.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcBlock: Block): PtBlock {
|
private fun transform(srcBlock: Block): PtBlock {
|
||||||
@ -131,7 +138,8 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcNode: BuiltinFunctionCallStatement): PtBuiltinFunctionCall {
|
private fun transform(srcNode: BuiltinFunctionCallStatement): PtBuiltinFunctionCall {
|
||||||
val call = PtBuiltinFunctionCall(srcNode.name, srcNode.position)
|
val type = builtinFunctionReturnType(srcNode.name, srcNode.args, program).getOr(DataType.UNDEFINED)
|
||||||
|
val call = PtBuiltinFunctionCall(srcNode.name, true, type, srcNode.position)
|
||||||
for (arg in srcNode.args)
|
for (arg in srcNode.args)
|
||||||
call.add(transformExpression(arg))
|
call.add(transformExpression(arg))
|
||||||
return call
|
return call
|
||||||
@ -173,22 +181,19 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcCall: FunctionCallStatement): PtFunctionCall {
|
private fun transform(srcCall: FunctionCallStatement): PtFunctionCall {
|
||||||
val call = PtFunctionCall(true, srcCall.position)
|
val (target, type) = targetOf(srcCall.target)
|
||||||
call.add(transform(srcCall.target))
|
val call = PtFunctionCall(target,true, type, srcCall.position)
|
||||||
val args = PtNodeGroup()
|
|
||||||
for (arg in srcCall.args)
|
for (arg in srcCall.args)
|
||||||
args.add(transformExpression(arg))
|
call.add(transformExpression(arg))
|
||||||
call.add(args)
|
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcCall: FunctionCallExpression): PtFunctionCall {
|
private fun transform(srcCall: FunctionCallExpression): PtFunctionCall {
|
||||||
val call = PtFunctionCall(false, srcCall.position)
|
val (target, _) = targetOf(srcCall.target)
|
||||||
call.add(transform(srcCall.target))
|
val type = srcCall.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
val args = PtNodeGroup()
|
val call = PtFunctionCall(target, false, type, srcCall.position)
|
||||||
for (arg in srcCall.args)
|
for (arg in srcCall.args)
|
||||||
args.add(transformExpression(arg))
|
call.add(transformExpression(arg))
|
||||||
call.add(args)
|
|
||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +234,8 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
PtLabel(label.name, label.position)
|
PtLabel(label.name, label.position)
|
||||||
|
|
||||||
private fun transform(srcPipe: Pipe): PtPipe {
|
private fun transform(srcPipe: Pipe): PtPipe {
|
||||||
val pipe = PtPipe(srcPipe.position)
|
val type = srcPipe.segments.last().inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val pipe = PtPipe(type, true, srcPipe.position)
|
||||||
pipe.add(transformExpression(srcPipe.source))
|
pipe.add(transformExpression(srcPipe.source))
|
||||||
for (segment in srcPipe.segments)
|
for (segment in srcPipe.segments)
|
||||||
pipe.add(transformExpression(segment))
|
pipe.add(transformExpression(segment))
|
||||||
@ -247,9 +253,11 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
throw FatalAstException("repeat-forever loop should have been replaced with label+jump")
|
throw FatalAstException("repeat-forever loop should have been replaced with label+jump")
|
||||||
val repeat = PtRepeatLoop(srcRepeat.position)
|
val repeat = PtRepeatLoop(srcRepeat.position)
|
||||||
repeat.add(transformExpression(srcRepeat.iterations!!))
|
repeat.add(transformExpression(srcRepeat.iterations!!))
|
||||||
|
val scope = PtNodeGroup()
|
||||||
for (statement in srcRepeat.body.statements) {
|
for (statement in srcRepeat.body.statements) {
|
||||||
repeat.add(transformStatement(statement))
|
scope.add(transformStatement(statement))
|
||||||
}
|
}
|
||||||
|
repeat.add(scope)
|
||||||
return repeat
|
return repeat
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,10 +269,13 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transformAsmSub(srcSub: Subroutine): PtAsmSub {
|
private fun transformAsmSub(srcSub: Subroutine): PtAsmSub {
|
||||||
|
val params = srcSub.parameters
|
||||||
|
.map { PtSubroutineParameter(it.name, it.type, it.position) }
|
||||||
|
.zip(srcSub.asmParameterRegisters)
|
||||||
val sub = PtAsmSub(srcSub.name,
|
val sub = PtAsmSub(srcSub.name,
|
||||||
srcSub.asmAddress,
|
srcSub.asmAddress,
|
||||||
srcSub.asmClobbers,
|
srcSub.asmClobbers,
|
||||||
srcSub.asmParameterRegisters,
|
params,
|
||||||
srcSub.asmReturnvaluesRegisters,
|
srcSub.asmReturnvaluesRegisters,
|
||||||
srcSub.inline,
|
srcSub.inline,
|
||||||
srcSub.position)
|
srcSub.position)
|
||||||
@ -334,7 +345,8 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
||||||
val array = PtArrayIndexer(srcArr.position)
|
val type = srcArr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val array = PtArrayIndexer(type, srcArr.position)
|
||||||
array.add(transform(srcArr.arrayvar))
|
array.add(transform(srcArr.arrayvar))
|
||||||
array.add(transformExpression(srcArr.indexer.indexExpr))
|
array.add(transformExpression(srcArr.indexer.indexExpr))
|
||||||
return array
|
return array
|
||||||
@ -348,14 +360,16 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcExpr: BinaryExpression): PtBinaryExpression {
|
private fun transform(srcExpr: BinaryExpression): PtBinaryExpression {
|
||||||
val expr = PtBinaryExpression(srcExpr.operator, srcExpr.position)
|
val type = srcExpr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val expr = PtBinaryExpression(srcExpr.operator, type, srcExpr.position)
|
||||||
expr.add(transformExpression(srcExpr.left))
|
expr.add(transformExpression(srcExpr.left))
|
||||||
expr.add(transformExpression(srcExpr.right))
|
expr.add(transformExpression(srcExpr.right))
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcCall: BuiltinFunctionCall): PtBuiltinFunctionCall {
|
private fun transform(srcCall: BuiltinFunctionCall): PtBuiltinFunctionCall {
|
||||||
val call = PtBuiltinFunctionCall(srcCall.name, srcCall.position)
|
val type = srcCall.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val call = PtBuiltinFunctionCall(srcCall.name, false, type, srcCall.position)
|
||||||
for (arg in srcCall.args)
|
for (arg in srcCall.args)
|
||||||
call.add(transformExpression(arg))
|
call.add(transformExpression(arg))
|
||||||
return call
|
return call
|
||||||
@ -384,7 +398,8 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
PtNumber(number.type, number.number, number.position)
|
PtNumber(number.type, number.number, number.position)
|
||||||
|
|
||||||
private fun transform(srcPipe: PipeExpression): PtPipe {
|
private fun transform(srcPipe: PipeExpression): PtPipe {
|
||||||
val pipe = PtPipe(srcPipe.position)
|
val type = srcPipe.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val pipe = PtPipe(type, false, srcPipe.position)
|
||||||
pipe.add(transformExpression(srcPipe.source))
|
pipe.add(transformExpression(srcPipe.source))
|
||||||
for (segment in srcPipe.segments)
|
for (segment in srcPipe.segments)
|
||||||
pipe.add(transformExpression(segment))
|
pipe.add(transformExpression(segment))
|
||||||
@ -392,13 +407,15 @@ class IntermediateAstMaker(val srcProgram: Program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcPrefix: PrefixExpression): PtPrefix {
|
private fun transform(srcPrefix: PrefixExpression): PtPrefix {
|
||||||
val prefix = PtPrefix(srcPrefix.operator, srcPrefix.position)
|
val type = srcPrefix.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val prefix = PtPrefix(srcPrefix.operator, type, srcPrefix.position)
|
||||||
prefix.add(transformExpression(srcPrefix.expression))
|
prefix.add(transformExpression(srcPrefix.expression))
|
||||||
return prefix
|
return prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(srcRange: RangeExpression): PtRange {
|
private fun transform(srcRange: RangeExpression): PtRange {
|
||||||
val range=PtRange(srcRange.position)
|
val type = srcRange.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
|
val range=PtRange(type, srcRange.position)
|
||||||
range.add(transformExpression(srcRange.from))
|
range.add(transformExpression(srcRange.from))
|
||||||
range.add(transformExpression(srcRange.to))
|
range.add(transformExpression(srcRange.to))
|
||||||
range.add(transformExpression(srcRange.step))
|
range.add(transformExpression(srcRange.step))
|
||||||
|
@ -285,9 +285,8 @@ open class Module(final override var statements: MutableList<Statement>,
|
|||||||
.substringAfterLast("/")
|
.substringAfterLast("/")
|
||||||
.substringAfterLast("\\")
|
.substringAfterLast("\\")
|
||||||
|
|
||||||
val loadAddress: UInt by lazy {
|
val loadAddress: UInt? by lazy {
|
||||||
val address = (statements.singleOrNull { it is Directive && it.directive == "%address" } as? Directive)?.args?.single()?.int ?: 0u
|
(statements.singleOrNull { it is Directive && it.directive == "%address" } as? Directive)?.args?.single()?.int
|
||||||
address
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
|
@ -67,7 +67,7 @@ class Program(val name: String,
|
|||||||
val toplevelModule: Module
|
val toplevelModule: Module
|
||||||
get() = modules.first { it.name!= internedStringsModuleName }
|
get() = modules.first { it.name!= internedStringsModuleName }
|
||||||
|
|
||||||
val definedLoadAddress: UInt
|
val definedLoadAddress: UInt?
|
||||||
get() = toplevelModule.loadAddress
|
get() = toplevelModule.loadAddress
|
||||||
|
|
||||||
var actualLoadAddress = 0u
|
var actualLoadAddress = 0u
|
||||||
|
@ -3,6 +3,8 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- unit test for PtProgram AST: should also test new things such as the Datatype in nodes.
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ main {
|
|||||||
txt.print_ub(amount)
|
txt.print_ub(amount)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
; test_stack.test()
|
uword[] @shared array = [111,222,333,444,555]
|
||||||
}
|
|
||||||
|
|
||||||
sub derp() -> ubyte, ubyte {
|
amount = amount |> sin8u() |> cos8u() |> sin8u()
|
||||||
return 0, 1
|
|
||||||
|
; test_stack.test()
|
||||||
}
|
}
|
||||||
|
|
||||||
sub find_next_prime() -> ubyte {
|
sub find_next_prime() -> ubyte {
|
||||||
|
Loading…
Reference in New Issue
Block a user