mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 04:31:20 +00:00
reducing ast dependencies - separate Ast compilation module
This commit is contained in:
parent
c97d76dbf2
commit
d9244f22c2
@ -3,6 +3,7 @@
|
|||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" />
|
<module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/compilerAst/compilerAst.iml" filepath="$PROJECT_DIR$/compilerAst/compilerAst.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" filepath="$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" />
|
<module fileurl="file://$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" filepath="$PROJECT_DIR$/dbusCompilerService/dbusCompilerService.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" />
|
<module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
|
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'application'
|
id 'application'
|
||||||
id "org.jetbrains.kotlin.jvm" version "1.4.21"
|
id "org.jetbrains.kotlin.jvm" version "1.4.30"
|
||||||
id 'org.jetbrains.dokka' version "0.9.18"
|
id 'org.jetbrains.dokka' version "0.9.18"
|
||||||
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
||||||
}
|
}
|
||||||
@ -18,14 +18,12 @@ repositories {
|
|||||||
def prog8version = rootProject.file('compiler/res/version.txt').text.trim()
|
def prog8version = rootProject.file('compiler/res/version.txt').text.trim()
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':parser')
|
implementation project(':compilerAst')
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||||
// implementation "org.jetbrains.kotlin:kotlin-reflect"
|
// implementation "org.jetbrains.kotlin:kotlin-reflect"
|
||||||
implementation 'org.antlr:antlr4-runtime:4.8'
|
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-cli:0.3.1'
|
implementation 'org.jetbrains.kotlinx:kotlinx-cli:0.3.1'
|
||||||
// implementation 'net.razorvine:ksim65:1.8'
|
// implementation 'net.razorvine:ksim65:1.8'
|
||||||
// implementation "com.github.hypfvieh:dbus-java:3.2.4"
|
// implementation "com.github.hypfvieh:dbus-java:3.2.4"
|
||||||
implementation project(':parser')
|
|
||||||
|
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
|
testImplementation "org.jetbrains.kotlin:kotlin-test-junit5"
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2'
|
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2'
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
<orderEntry type="jdk" jdkName="11" jdkType="JavaSDK" />
|
<orderEntry type="jdk" jdkName="11" jdkType="JavaSDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||||
<orderEntry type="module" module-name="parser" />
|
|
||||||
<orderEntry type="library" name="unittest-libs" level="project" />
|
<orderEntry type="library" name="unittest-libs" level="project" />
|
||||||
<orderEntry type="library" name="kotlinx-cli-jvm" level="project" />
|
<orderEntry type="library" name="kotlinx-cli-jvm" level="project" />
|
||||||
<orderEntry type="library" name="antlr-runtime-4.9" level="project" />
|
<orderEntry type="module" module-name="compilerAst" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
@ -151,21 +151,24 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(jump: Jump) {
|
override fun visit(jump: Jump) {
|
||||||
if(jump.identifier!=null) {
|
val ident = jump.identifier
|
||||||
val targetStatement = checkFunctionOrLabelExists(jump.identifier, jump)
|
if(ident!=null) {
|
||||||
|
val targetStatement = checkFunctionOrLabelExists(ident, jump)
|
||||||
if(targetStatement!=null) {
|
if(targetStatement!=null) {
|
||||||
if(targetStatement is BuiltinFunctionStatementPlaceholder)
|
if(targetStatement is BuiltinFunctionStatementPlaceholder)
|
||||||
errors.err("can't jump to a builtin function", jump.position)
|
errors.err("can't jump to a builtin function", jump.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(jump.address!=null && (jump.address < 0 || jump.address > 65535))
|
val addr = jump.address
|
||||||
|
if(addr!=null && (addr < 0 || addr > 65535))
|
||||||
errors.err("jump address must be valid integer 0..\$ffff", jump.position)
|
errors.err("jump address must be valid integer 0..\$ffff", jump.position)
|
||||||
super.visit(jump)
|
super.visit(jump)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(block: Block) {
|
override fun visit(block: Block) {
|
||||||
if(block.address!=null && (block.address<0 || block.address>65535)) {
|
val addr = block.address
|
||||||
|
if(addr!=null && (addr<0 || addr>65535)) {
|
||||||
errors.err("block memory address must be valid integer 0..\$ffff", block.position)
|
errors.err("block memory address must be valid integer 0..\$ffff", block.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,9 +319,11 @@ internal class AstChecker(private val program: Program,
|
|||||||
RegisterOrPair.R13,
|
RegisterOrPair.R13,
|
||||||
RegisterOrPair.R14,
|
RegisterOrPair.R14,
|
||||||
RegisterOrPair.R15 -> { /* no sensible way to count this */ }
|
RegisterOrPair.R15 -> { /* no sensible way to count this */ }
|
||||||
null ->
|
null -> {
|
||||||
if(p.statusflag!=null)
|
val statusf = p.statusflag
|
||||||
statusflagCounts[p.statusflag] = statusflagCounts.getValue(p.statusflag) + 1
|
if (statusf != null)
|
||||||
|
statusflagCounts[statusf] = statusflagCounts.getValue(statusf) + 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,17 @@ internal interface CompilationTarget: IStringEncoding {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isInRegularRAM(target: AssignTarget, program: Program): Boolean {
|
fun isInRegularRAM(target: AssignTarget, program: Program): Boolean {
|
||||||
|
val memAddr = target.memoryAddress
|
||||||
|
val arrayIdx = target.arrayindexed
|
||||||
|
val ident = target.identifier
|
||||||
when {
|
when {
|
||||||
target.memoryAddress != null -> {
|
memAddr != null -> {
|
||||||
return when (target.memoryAddress.addressExpression) {
|
return when (memAddr.addressExpression) {
|
||||||
is NumericLiteralValue -> {
|
is NumericLiteralValue -> {
|
||||||
machine.isRegularRAMaddress((target.memoryAddress.addressExpression as NumericLiteralValue).number.toInt())
|
machine.isRegularRAMaddress((memAddr.addressExpression as NumericLiteralValue).number.toInt())
|
||||||
}
|
}
|
||||||
is IdentifierReference -> {
|
is IdentifierReference -> {
|
||||||
val decl = (target.memoryAddress.addressExpression as IdentifierReference).targetVarDecl(program)
|
val decl = (memAddr.addressExpression as IdentifierReference).targetVarDecl(program)
|
||||||
if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
|
if ((decl?.type == VarDeclType.VAR || decl?.type == VarDeclType.CONST) && decl.value is NumericLiteralValue)
|
||||||
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
||||||
else
|
else
|
||||||
@ -44,8 +47,8 @@ internal interface CompilationTarget: IStringEncoding {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target.arrayindexed != null -> {
|
arrayIdx != null -> {
|
||||||
val targetStmt = target.arrayindexed!!.arrayvar.targetVarDecl(program)
|
val targetStmt = arrayIdx.arrayvar.targetVarDecl(program)
|
||||||
return if (targetStmt?.type == VarDeclType.MEMORY) {
|
return if (targetStmt?.type == VarDeclType.MEMORY) {
|
||||||
val addr = targetStmt.value as? NumericLiteralValue
|
val addr = targetStmt.value as? NumericLiteralValue
|
||||||
if (addr != null)
|
if (addr != null)
|
||||||
@ -54,8 +57,8 @@ internal interface CompilationTarget: IStringEncoding {
|
|||||||
false
|
false
|
||||||
} else true
|
} else true
|
||||||
}
|
}
|
||||||
target.identifier != null -> {
|
ident != null -> {
|
||||||
val decl = target.identifier!!.targetVarDecl(program)!!
|
val decl = ident.targetVarDecl(program)!!
|
||||||
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue)
|
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteralValue)
|
||||||
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
machine.isRegularRAMaddress((decl.value as NumericLiteralValue).number.toInt())
|
||||||
else
|
else
|
||||||
|
@ -177,9 +177,10 @@ internal class AsmGen(private val program: Program,
|
|||||||
out("\n\n; ---- block: '${block.name}' ----")
|
out("\n\n; ---- block: '${block.name}' ----")
|
||||||
out("${block.name}\t" + (if("force_output" in block.options()) ".block\n" else ".proc\n"))
|
out("${block.name}\t" + (if("force_output" in block.options()) ".block\n" else ".proc\n"))
|
||||||
|
|
||||||
if(block.address!=null) {
|
val addr = block.address
|
||||||
out(".cerror * > ${block.address.toHex()}, 'block address overlaps by ', *-${block.address.toHex()},' bytes'")
|
if(addr!=null) {
|
||||||
out("* = ${block.address.toHex()}")
|
out(".cerror * > ${addr.toHex()}, 'block address overlaps by ', *-${addr.toHex()},' bytes'")
|
||||||
|
out("* = ${addr.toHex()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
outputSourceLine(block)
|
outputSourceLine(block)
|
||||||
@ -356,10 +357,11 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
val asmSubs = statements.filterIsInstance<Subroutine>().filter { it.isAsmSubroutine }
|
val asmSubs = statements.filterIsInstance<Subroutine>().filter { it.isAsmSubroutine }
|
||||||
for(sub in asmSubs) {
|
for(sub in asmSubs) {
|
||||||
if(sub.asmAddress!=null) {
|
val addr = sub.asmAddress
|
||||||
|
if(addr!=null) {
|
||||||
if(sub.statements.isNotEmpty())
|
if(sub.statements.isNotEmpty())
|
||||||
throw AssemblyError("kernel subroutine cannot have statements")
|
throw AssemblyError("kernel subroutine cannot have statements")
|
||||||
out(" ${sub.name} = ${sub.asmAddress.toHex()}")
|
out(" ${sub.name} = ${addr.toHex()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1268,17 +1270,20 @@ $label nop""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getJumpTarget(jmp: Jump): String {
|
private fun getJumpTarget(jmp: Jump): String {
|
||||||
|
val ident = jmp.identifier
|
||||||
|
val label = jmp.generatedLabel
|
||||||
|
val addr = jmp.address
|
||||||
return when {
|
return when {
|
||||||
jmp.identifier!=null -> {
|
ident!=null -> {
|
||||||
val target = jmp.identifier.targetStatement(program)
|
val target = ident.targetStatement(program)
|
||||||
val asmName = asmSymbolName(jmp.identifier)
|
val asmName = asmSymbolName(ident)
|
||||||
if(target is Label)
|
if(target is Label)
|
||||||
"_$asmName" // prefix with underscore to jump to local label
|
"_$asmName" // prefix with underscore to jump to local label
|
||||||
else
|
else
|
||||||
asmName
|
asmName
|
||||||
}
|
}
|
||||||
jmp.generatedLabel!=null -> jmp.generatedLabel
|
label!=null -> label
|
||||||
jmp.address!=null -> jmp.address.toHex()
|
addr!=null -> addr.toHex()
|
||||||
else -> "????"
|
else -> "????"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1293,12 +1298,12 @@ $label nop""")
|
|||||||
|
|
||||||
when (returnType) {
|
when (returnType) {
|
||||||
in NumericDatatypes -> {
|
in NumericDatatypes -> {
|
||||||
assignExpressionToRegister(returnvalue, returnReg.registerOrPair)
|
assignExpressionToRegister(returnvalue, returnReg.registerOrPair!!)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// all else take its address and assign that also to AY register pair
|
// all else take its address and assign that also to AY register pair
|
||||||
val addrofValue = AddressOf(returnvalue as IdentifierReference, returnvalue.position)
|
val addrofValue = AddressOf(returnvalue as IdentifierReference, returnvalue.position)
|
||||||
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnReg.registerOrPair)
|
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnReg.registerOrPair!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
compilerAst/build.gradle
Normal file
65
compilerAst/build.gradle
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
plugins {
|
||||||
|
id 'antlr'
|
||||||
|
id 'java'
|
||||||
|
id "org.jetbrains.kotlin.jvm" version "1.4.30"
|
||||||
|
}
|
||||||
|
|
||||||
|
targetCompatibility = 11
|
||||||
|
sourceCompatibility = 11
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
// strange antlr plugin issue, see https://github.com/gradle/gradle/issues/820
|
||||||
|
// this avoids linking in the complete antlr binary jar
|
||||||
|
compile {
|
||||||
|
extendsFrom = extendsFrom.findAll { it != configurations.antlr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
antlr 'org.antlr:antlr4:4.9'
|
||||||
|
implementation 'org.antlr:antlr4-runtime:4.9'
|
||||||
|
implementation project(':parser')
|
||||||
|
|
||||||
|
// antlr('org.antlr:antlr4:4.9') {
|
||||||
|
// exclude group: 'com.ibm.icu', module: 'icu4j'
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
// verbose = true
|
||||||
|
// freeCompilerArgs += "-XXLanguage:+NewInference"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileTestKotlin {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
srcDirs = ["${project.projectDir}/src"]
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
srcDirs = ["${project.projectDir}/res"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test {
|
||||||
|
java {
|
||||||
|
srcDirs = ["${project.projectDir}/test"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task wrapper(type: Wrapper) {
|
||||||
|
gradleVersion = '6.7'
|
||||||
|
}
|
14
compilerAst/compilerAst.iml
Normal file
14
compilerAst/compilerAst.iml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="jdk" jdkName="openjdk-11" jdkType="JavaSDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||||
|
<orderEntry type="module" module-name="parser" />
|
||||||
|
<orderEntry type="library" name="antlr-runtime-4.9" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -392,7 +392,7 @@ object BuiltinFunctionScopePlaceholder : INameScope {
|
|||||||
|
|
||||||
|
|
||||||
// prefix for struct member variables
|
// prefix for struct member variables
|
||||||
internal fun mangledStructMemberName(varName: String, memberName: String) = "prog8struct_${varName}_$memberName"
|
fun mangledStructMemberName(varName: String, memberName: String) = "prog8struct_${varName}_$memberName"
|
||||||
|
|
||||||
|
|
||||||
fun Number.toHex(): String {
|
fun Number.toHex(): String {
|
@ -644,48 +644,3 @@ private fun prog8Parser.VardeclContext.toAst(encoding: IStringEncoding): VarDecl
|
|||||||
toPosition()
|
toPosition()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun escape(str: String): String {
|
|
||||||
val es = str.map {
|
|
||||||
when(it) {
|
|
||||||
'\t' -> "\\t"
|
|
||||||
'\n' -> "\\n"
|
|
||||||
'\r' -> "\\r"
|
|
||||||
'"' -> "\\\""
|
|
||||||
in '\u8000'..'\u80ff' -> "\\x" + (it.toInt() - 0x8000).toString(16).padStart(2, '0')
|
|
||||||
in '\u0000'..'\u00ff' -> it.toString()
|
|
||||||
else -> "\\u" + it.toInt().toString(16).padStart(4, '0')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return es.joinToString("")
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun unescape(str: String, position: Position): String {
|
|
||||||
val result = mutableListOf<Char>()
|
|
||||||
val iter = str.iterator()
|
|
||||||
while(iter.hasNext()) {
|
|
||||||
val c = iter.nextChar()
|
|
||||||
if(c=='\\') {
|
|
||||||
val ec = iter.nextChar()
|
|
||||||
result.add(when(ec) {
|
|
||||||
'\\' -> '\\'
|
|
||||||
'n' -> '\n'
|
|
||||||
'r' -> '\r'
|
|
||||||
'"' -> '"'
|
|
||||||
'\'' -> '\''
|
|
||||||
'u' -> {
|
|
||||||
"${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar()
|
|
||||||
}
|
|
||||||
'x' -> {
|
|
||||||
// special hack 0x8000..0x80ff will be outputted verbatim without encoding
|
|
||||||
val hex = ("" + iter.nextChar() + iter.nextChar()).toInt(16)
|
|
||||||
(0x8000 + hex).toChar()
|
|
||||||
}
|
|
||||||
else -> throw SyntaxError("invalid escape char in string: \\$ec", position)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
result.add(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.joinToString("")
|
|
||||||
}
|
|
49
compilerAst/src/prog8/ast/antlr/EscapeChars.kt
Normal file
49
compilerAst/src/prog8/ast/antlr/EscapeChars.kt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package prog8.ast.antlr
|
||||||
|
|
||||||
|
import prog8.ast.base.Position
|
||||||
|
import prog8.ast.base.SyntaxError
|
||||||
|
|
||||||
|
fun escape(str: String): String {
|
||||||
|
val es = str.map {
|
||||||
|
when(it) {
|
||||||
|
'\t' -> "\\t"
|
||||||
|
'\n' -> "\\n"
|
||||||
|
'\r' -> "\\r"
|
||||||
|
'"' -> "\\\""
|
||||||
|
in '\u8000'..'\u80ff' -> "\\x" + (it.toInt() - 0x8000).toString(16).padStart(2, '0')
|
||||||
|
in '\u0000'..'\u00ff' -> it.toString()
|
||||||
|
else -> "\\u" + it.toInt().toString(16).padStart(4, '0')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return es.joinToString("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unescape(str: String, position: Position): String {
|
||||||
|
val result = mutableListOf<Char>()
|
||||||
|
val iter = str.iterator()
|
||||||
|
while(iter.hasNext()) {
|
||||||
|
val c = iter.nextChar()
|
||||||
|
if(c=='\\') {
|
||||||
|
val ec = iter.nextChar()
|
||||||
|
result.add(when(ec) {
|
||||||
|
'\\' -> '\\'
|
||||||
|
'n' -> '\n'
|
||||||
|
'r' -> '\r'
|
||||||
|
'"' -> '"'
|
||||||
|
'\'' -> '\''
|
||||||
|
'u' -> {
|
||||||
|
"${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar()
|
||||||
|
}
|
||||||
|
'x' -> {
|
||||||
|
// special hack 0x8000..0x80ff will be outputted verbatim without encoding
|
||||||
|
val hex = ("" + iter.nextChar() + iter.nextChar()).toInt(16)
|
||||||
|
(0x8000 + hex).toChar()
|
||||||
|
}
|
||||||
|
else -> throw SyntaxError("invalid escape char in string: \\$ec", position)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
result.add(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.joinToString("")
|
||||||
|
}
|
@ -43,7 +43,7 @@ enum class DataType {
|
|||||||
this == other -> false
|
this == other -> false
|
||||||
this in ByteDatatypes -> false
|
this in ByteDatatypes -> false
|
||||||
this in WordDatatypes -> other in ByteDatatypes
|
this in WordDatatypes -> other in ByteDatatypes
|
||||||
this==STR && other==UWORD || this==UWORD && other==STR -> false
|
this== STR && other== UWORD || this== UWORD && other== STR -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ enum class DataType {
|
|||||||
this == other -> true
|
this == other -> true
|
||||||
this in ByteDatatypes -> other in ByteDatatypes
|
this in ByteDatatypes -> other in ByteDatatypes
|
||||||
this in WordDatatypes -> other in WordDatatypes
|
this in WordDatatypes -> other in WordDatatypes
|
||||||
this==STR && other==UWORD || this==UWORD && other==STR -> true
|
this== STR && other== UWORD || this== UWORD && other== STR -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,10 +128,11 @@ val NumericDatatypes = setOf(DataType.UBYTE, DataType.BYTE, DataType.UWORD, Data
|
|||||||
val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F)
|
val ArrayDatatypes = setOf(DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F)
|
||||||
val StringlyDatatypes = setOf(DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, DataType.UWORD)
|
val StringlyDatatypes = setOf(DataType.STR, DataType.ARRAY_UB, DataType.ARRAY_B, DataType.UWORD)
|
||||||
val IterableDatatypes = setOf(
|
val IterableDatatypes = setOf(
|
||||||
DataType.STR,
|
DataType.STR,
|
||||||
DataType.ARRAY_UB, DataType.ARRAY_B,
|
DataType.ARRAY_UB, DataType.ARRAY_B,
|
||||||
DataType.ARRAY_UW, DataType.ARRAY_W,
|
DataType.ARRAY_UW, DataType.ARRAY_W,
|
||||||
DataType.ARRAY_F)
|
DataType.ARRAY_F
|
||||||
|
)
|
||||||
val PassByValueDatatypes = NumericDatatypes
|
val PassByValueDatatypes = NumericDatatypes
|
||||||
val PassByReferenceDatatypes = IterableDatatypes.plus(DataType.STRUCT)
|
val PassByReferenceDatatypes = IterableDatatypes.plus(DataType.STRUCT)
|
||||||
val ArrayElementTypes = mapOf(
|
val ArrayElementTypes = mapOf(
|
||||||
@ -140,7 +141,8 @@ val ArrayElementTypes = mapOf(
|
|||||||
DataType.ARRAY_UB to DataType.UBYTE,
|
DataType.ARRAY_UB to DataType.UBYTE,
|
||||||
DataType.ARRAY_W to DataType.WORD,
|
DataType.ARRAY_W to DataType.WORD,
|
||||||
DataType.ARRAY_UW to DataType.UWORD,
|
DataType.ARRAY_UW to DataType.UWORD,
|
||||||
DataType.ARRAY_F to DataType.FLOAT)
|
DataType.ARRAY_F to DataType.FLOAT
|
||||||
|
)
|
||||||
val ElementArrayTypes = mapOf(
|
val ElementArrayTypes = mapOf(
|
||||||
DataType.BYTE to DataType.ARRAY_B,
|
DataType.BYTE to DataType.ARRAY_B,
|
||||||
DataType.UBYTE to DataType.ARRAY_UB,
|
DataType.UBYTE to DataType.ARRAY_UB,
|
||||||
@ -148,10 +150,12 @@ val ElementArrayTypes = mapOf(
|
|||||||
DataType.UWORD to DataType.ARRAY_UW,
|
DataType.UWORD to DataType.ARRAY_UW,
|
||||||
DataType.FLOAT to DataType.ARRAY_F
|
DataType.FLOAT to DataType.ARRAY_F
|
||||||
)
|
)
|
||||||
val Cx16VirtualRegisters = listOf(RegisterOrPair.R0, RegisterOrPair.R1, RegisterOrPair.R2, RegisterOrPair.R3,
|
val Cx16VirtualRegisters = listOf(
|
||||||
|
RegisterOrPair.R0, RegisterOrPair.R1, RegisterOrPair.R2, RegisterOrPair.R3,
|
||||||
RegisterOrPair.R4, RegisterOrPair.R5, RegisterOrPair.R6, RegisterOrPair.R7,
|
RegisterOrPair.R4, RegisterOrPair.R5, RegisterOrPair.R6, RegisterOrPair.R7,
|
||||||
RegisterOrPair.R8, RegisterOrPair.R9, RegisterOrPair.R10, RegisterOrPair.R11,
|
RegisterOrPair.R8, RegisterOrPair.R9, RegisterOrPair.R10, RegisterOrPair.R11,
|
||||||
RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15)
|
RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
// find the parent node of a specific type or interface
|
// find the parent node of a specific type or interface
|
@ -2,7 +2,7 @@ package prog8.ast.base
|
|||||||
|
|
||||||
import prog8.parser.ParsingFailedError
|
import prog8.parser.ParsingFailedError
|
||||||
|
|
||||||
|
// TODO can move to compiler?????? **************
|
||||||
class ErrorReporter {
|
class ErrorReporter {
|
||||||
private enum class MessageSeverity {
|
private enum class MessageSeverity {
|
||||||
WARNING,
|
WARNING,
|
@ -147,10 +147,13 @@ class BinaryExpression(var left: Expression, var operator: String, var right: Ex
|
|||||||
InferredTypes.unknown()
|
InferredTypes.unknown()
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
InferredTypes.knownFor(commonDatatype(
|
InferredTypes.knownFor(
|
||||||
|
commonDatatype(
|
||||||
leftDt.typeOrElse(DataType.BYTE),
|
leftDt.typeOrElse(DataType.BYTE),
|
||||||
rightDt.typeOrElse(DataType.BYTE),
|
rightDt.typeOrElse(DataType.BYTE),
|
||||||
null, null).first)
|
null, null
|
||||||
|
).first
|
||||||
|
)
|
||||||
} catch (x: FatalAstException) {
|
} catch (x: FatalAstException) {
|
||||||
InferredTypes.unknown()
|
InferredTypes.unknown()
|
||||||
}
|
}
|
||||||
@ -704,7 +707,8 @@ internal fun makeRange(fromVal: Int, toVal: Int, stepVal: Int): IntProgression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class IdentifierReference(val nameInSource: List<String>, override val position: Position) : Expression(), IAssignable {
|
data class IdentifierReference(val nameInSource: List<String>, override val position: Position) : Expression(),
|
||||||
|
IAssignable {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
fun targetStatement(program: Program) =
|
fun targetStatement(program: Program) =
|
@ -155,15 +155,15 @@ enum class ZeropageWish {
|
|||||||
|
|
||||||
|
|
||||||
open class VarDecl(val type: VarDeclType,
|
open class VarDecl(val type: VarDeclType,
|
||||||
private val declaredDatatype: DataType,
|
private val declaredDatatype: DataType,
|
||||||
val zeropage: ZeropageWish,
|
val zeropage: ZeropageWish,
|
||||||
var arraysize: ArrayIndex?,
|
var arraysize: ArrayIndex?,
|
||||||
val name: String,
|
val name: String,
|
||||||
private val structName: String?,
|
private val structName: String?,
|
||||||
var value: Expression?,
|
var value: Expression?,
|
||||||
val isArray: Boolean,
|
val isArray: Boolean,
|
||||||
val autogeneratedDontRemove: Boolean,
|
val autogeneratedDontRemove: Boolean,
|
||||||
override val position: Position) : Statement() {
|
override val position: Position) : Statement() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
var struct: StructDecl? = null // set later (because at parse time, we only know the name)
|
var struct: StructDecl? = null // set later (because at parse time, we only know the name)
|
||||||
private set
|
private set
|
@ -16,7 +16,8 @@ interface IAstModification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetExpression(private val setter: (newExpr: Expression) -> Unit, private val newExpr: Expression, private val parent: Node) : IAstModification {
|
class SetExpression(private val setter: (newExpr: Expression) -> Unit, private val newExpr: Expression, private val parent: Node) :
|
||||||
|
IAstModification {
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
setter(newExpr)
|
setter(newExpr)
|
||||||
newExpr.linkParents(parent)
|
newExpr.linkParents(parent)
|
||||||
@ -37,7 +38,8 @@ interface IAstModification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsertAfter(private val after: Statement, private val stmt: Statement, private val parent: INameScope) : IAstModification {
|
class InsertAfter(private val after: Statement, private val stmt: Statement, private val parent: INameScope) :
|
||||||
|
IAstModification {
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
val idx = parent.statements.indexOfFirst { it===after } + 1
|
val idx = parent.statements.indexOfFirst { it===after } + 1
|
||||||
parent.statements.add(idx, stmt)
|
parent.statements.add(idx, stmt)
|
||||||
@ -45,7 +47,8 @@ interface IAstModification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsertBefore(private val before: Statement, private val stmt: Statement, private val parent: INameScope) : IAstModification {
|
class InsertBefore(private val before: Statement, private val stmt: Statement, private val parent: INameScope) :
|
||||||
|
IAstModification {
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
val idx = parent.statements.indexOfFirst { it===before }
|
val idx = parent.statements.indexOfFirst { it===before }
|
||||||
parent.statements.add(idx, stmt)
|
parent.statements.add(idx, stmt)
|
||||||
@ -53,7 +56,8 @@ interface IAstModification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReplaceNode(private val node: Node, private val replacement: Node, private val parent: Node) : IAstModification {
|
class ReplaceNode(private val node: Node, private val replacement: Node, private val parent: Node) :
|
||||||
|
IAstModification {
|
||||||
override fun perform() {
|
override fun perform() {
|
||||||
parent.replaceChildNode(node, replacement)
|
parent.replaceChildNode(node, replacement)
|
||||||
replacement.linkParents(parent)
|
replacement.linkParents(parent)
|
@ -9,25 +9,25 @@ import prog8.ast.base.Position
|
|||||||
import prog8.ast.base.SyntaxError
|
import prog8.ast.base.SyntaxError
|
||||||
import prog8.ast.statements.Directive
|
import prog8.ast.statements.Directive
|
||||||
import prog8.ast.statements.DirectiveArg
|
import prog8.ast.statements.DirectiveArg
|
||||||
import prog8.pathFrom
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
import java.nio.file.FileSystems
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
|
||||||
internal class ParsingFailedError(override var message: String) : Exception(message)
|
class ParsingFailedError(override var message: String) : Exception(message)
|
||||||
|
|
||||||
|
|
||||||
internal class CustomLexer(val modulePath: Path, input: CharStream?) : prog8Lexer(input)
|
internal class CustomLexer(val modulePath: Path, input: CharStream?) : prog8Lexer(input)
|
||||||
|
|
||||||
|
fun moduleName(fileName: Path) = fileName.toString().substringBeforeLast('.')
|
||||||
|
|
||||||
internal fun moduleName(fileName: Path) = fileName.toString().substringBeforeLast('.')
|
internal fun pathFrom(stringPath: String, vararg rest: String): Path = FileSystems.getDefault().getPath(stringPath, *rest)
|
||||||
|
|
||||||
|
|
||||||
internal class ModuleImporter {
|
class ModuleImporter {
|
||||||
|
|
||||||
internal fun importModule(program: Program, filePath: Path, encoder: IStringEncoding, compilationTargetName: String): Module {
|
fun importModule(program: Program, filePath: Path, encoder: IStringEncoding, compilationTargetName: String): Module {
|
||||||
print("importing '${moduleName(filePath.fileName)}'")
|
print("importing '${moduleName(filePath.fileName)}'")
|
||||||
if(filePath.parent!=null) {
|
if(filePath.parent!=null) {
|
||||||
var importloc = filePath.toString()
|
var importloc = filePath.toString()
|
||||||
@ -45,7 +45,7 @@ internal class ModuleImporter {
|
|||||||
return importModule(program, input, filePath, false, encoder, compilationTargetName)
|
return importModule(program, input, filePath, false, encoder, compilationTargetName)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun importLibraryModule(program: Program, name: String,
|
fun importLibraryModule(program: Program, name: String,
|
||||||
encoder: IStringEncoding, compilationTargetName: String): Module? {
|
encoder: IStringEncoding, compilationTargetName: String): Module? {
|
||||||
val import = Directive("%import", listOf(
|
val import = Directive("%import", listOf(
|
||||||
DirectiveArg("", name, 42, position = Position("<<<implicit-import>>>", 0, 0, 0))
|
DirectiveArg("", name, 42, position = Position("<<<implicit-import>>>", 0, 0, 0))
|
@ -2,7 +2,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'application'
|
id 'application'
|
||||||
id "org.jetbrains.kotlin.jvm" version "1.4.21"
|
id "org.jetbrains.kotlin.jvm" version "1.4.30"
|
||||||
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'application'
|
id 'application'
|
||||||
id "org.jetbrains.kotlin.jvm" version "1.4.21"
|
id "org.jetbrains.kotlin.jvm" version "1.4.30"
|
||||||
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
id 'com.github.johnrengelman.shadow' version '6.1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
|
|
||||||
rm -f *.jar *.asm *.prg *.vm.txt *.vice-mon-list a.out
|
rm -f *.jar *.asm *.prg *.vm.txt *.vice-mon-list a.out
|
||||||
rm -rf build out
|
rm -rf build out
|
||||||
|
rm -rf compiler/build compilerAst/build dbusCompilerService/build httpCompilerService/build parser/build
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
include ':parser'
|
include ':parser'
|
||||||
|
include ':compilerAst'
|
||||||
include ':compiler'
|
include ':compiler'
|
||||||
include ':dbusCompilerService'
|
include ':dbusCompilerService'
|
||||||
include ':httpCompilerService'
|
include ':httpCompilerService'
|
||||||
|
Loading…
Reference in New Issue
Block a user