matrix decl parsing and fixes

This commit is contained in:
Irmen de Jong 2018-09-12 00:51:48 +02:00
parent e71fef709a
commit efd3b1f5c6
13 changed files with 304 additions and 168 deletions

View File

@ -164,18 +164,20 @@ Values will usually be part of an expression or assignment statement::
byte counter = 42 ; variable of size 8 bits, with initial value 42 byte counter = 42 ; variable of size 8 bits, with initial value 42
Array and Matrix (2-dimensional array) types are also supported in a limited way::
byte[4] array = [1, 2, 3, 4] ; initialize the array byte[4] array = [1, 2, 3, 4] ; initialize the array
byte[99] array = 255 ; initialize array with all 255's [255, 255, 255, 255, ...] byte[99] array = 255 ; initialize array with all 255's [255, 255, 255, 255, ...]
byte[100] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199] byte[100] array = 100 to 199 ; initialize array with [100, 101, ..., 198, 199]
byte[2,3] matrix = 1 ; a matrix of 2*3=6 bytes all with value 1
byte[2,3] matrix = [1,2,3,4,5,6] ; a 2*3 matrix with value |(1,2) (3,4) (5,6)|
Note that the various keywords for the data type and variable type (``byte``, ``word``, ``const``, etc.) Note that the various keywords for the data type and variable type (``byte``, ``word``, ``const``, etc.)
cannot be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte`` cannot be used as *identifiers* elsewhere. You can't make a variable, block or subroutine with the name ``byte``
for instance. for instance.
.. todo::
matrix datatype
.. todo:: .. todo::
There must be a way to tell the compiler which variables you require to be in Zeropage: There must be a way to tell the compiler which variables you require to be in Zeropage:
``zeropage`` modifier keyword on vardecl perhaps? ``zeropage`` modifier keyword on vardecl perhaps?

View File

@ -197,22 +197,23 @@ Variable declarations
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
Variables should be declared with their exact type and size so the compiler can allocate storage Variables should be declared with their exact type and size so the compiler can allocate storage
for them. You can give them an initial value as well. That value can be a simple literal value, for them. You must give them an initial value as well. That value can be a simple literal value,
but you can put a (constant) expression there as well. The syntax is:: or a (constant) expression. The syntax is::
<datatype> <variable name> [ = <initial value> ] <datatype> <variable name> [ = <initial value> ]
Various examples:: Various examples::
word thing word thing = 0
byte counter = 0 byte counter = len([1, 2, 3]) * 20
byte age = 2018 - 1974 byte age = 2018 - 1974
float wallet = 55.25 float wallet = 55.25
str name = "my name is Irmen" str name = "my name is Irmen"
word address = #counter word address = #counter
byte[5] values = [11, 22, 33, 44, 55] byte[5] values = [11, 22, 33, 44, 55]
byte[5] values = 255 ; initialize with five 255 bytes byte[5] values = 255 ; initialize with five 255 bytes
byte[5][6] empty_matrix byte[5][6] empty_matrix = 0 ; initialize with 30 zero bytes
byte[2][3] other_matrix = [1,2,3,4,5,6] ; 2*3 matrix with value | (1,2) (3,4) (5,6) |
@ -348,7 +349,8 @@ range creation: ``to``
} }
array indexing: ``[`` *index* ``]`` .. todo::
array indexing: ``[`` *index* ``]``
When put after a sequence type (array, string or matrix) it means to point to the given element in that sequence:: When put after a sequence type (array, string or matrix) it means to point to the given element in that sequence::
array[2] ; the third byte in the array (index is 0-based) array[2] ; the third byte in the array (index is 0-based)

View File

@ -20,10 +20,10 @@ input.result word 0
nop nop
syscall WRITE_MEMSTR w:1000 syscall WRITE_MEMSTR w:1000
loop: loop:
inc_var "main.textcolor" inc_var main.textcolor
syscall RANDOM syscall RANDOM
syscall RANDOM syscall RANDOM
push_var "main.textcolor" push_var main.textcolor
syscall GFX_PIXEL syscall GFX_PIXEL
; syscall WRITE_VAR "input.prompt" ; syscall WRITE_VAR "input.prompt"
; syscall INPUT_VAR "input.result" ; syscall INPUT_VAR "input.result"

View File

@ -4,10 +4,20 @@
%import c64lib %import c64lib
~ not_main $d000 { ~ not_main $d000 {
const float len1 = 111 ;len([1,2,3]) byte [100] array1 = 0
const float round1 = 111 ;len([1,2,3]) word [100] array2 = 1
const float sin1 = 111 ;len([1,2,3]) byte [2,3] matrix1 = 2
float cos1 = 111 ;len([1,2,3]) byte [2,3] matrix2 = [1,2,3,4,5,6]
const byte [100] carray1 = 0
const word [100] carray2 = 1
const byte [2,3] cmatrix1 = [1,2,3,4,5,255]
const float len1 = len([1,2,3])
const float round1 = len([1,2,3])
const float sin1 = len([1,2,3])
float cos1 = len([1,2,3])
} }
~ main $c003 { ~ main $c003 {

View File

@ -62,6 +62,7 @@ fun main(args: Array<String>) {
val compiler = Compiler(compilerOptions) val compiler = Compiler(compilerOptions)
val intermediate = compiler.compile(moduleAst) val intermediate = compiler.compile(moduleAst)
intermediate.optimize() intermediate.optimize()
intermediate.toTextLines().forEach { println(it) }
// val assembly = stackvmProg.compileToAssembly() // val assembly = stackvmProg.compileToAssembly()
// //

View File

@ -68,15 +68,15 @@ class NameError(override var message: String, val position: Position?) : AstExce
} }
} }
open class ExpressionException(message: String, val position: Position?) : AstException(message) { open class ExpressionError(message: String, val position: Position?) : AstException(message) {
override fun toString(): String { override fun toString(): String {
val location = position?.toString() ?: "" val location = position?.toString() ?: ""
return "$location Error: $message" return "$location Error: $message"
} }
} }
class UndefinedSymbolException(symbol: IdentifierReference) class UndefinedSymbolError(symbol: IdentifierReference)
: ExpressionException("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position) : ExpressionError("undefined symbol: ${symbol.nameInSource.joinToString(".")}", symbol.position)
data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) { data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) {
@ -514,26 +514,17 @@ enum class VarDeclType {
} }
class VarDecl(val type: VarDeclType, class VarDecl(val type: VarDeclType,
declaredDatatype: DataType, private val declaredDatatype: DataType,
val arrayspec: ArraySpec?, val arrayspec: ArraySpec?,
val name: String, val name: String,
var value: IExpression?) : IStatement { var value: IExpression?) : IStatement {
override var position: Position? = null override var position: Position? = null
override lateinit var parent: Node override lateinit var parent: Node
val datatype: DataType
init { // note: the actual datatype will be determined somewhat later (in the ast checker phase)
datatype = when { // (we don't do it at init time, because we have to have a way to create a proper syntax error instead of a crash)
arrayspec!=null -> // it's not a scalar, adjust the datatype lateinit var datatype: DataType
when(declaredDatatype) {
DataType.BYTE -> DataType.ARRAY
DataType.WORD -> DataType.ARRAY_W
DataType.MATRIX -> TODO()
else -> throw FatalAstException("invalid vardecl array datatype $declaredDatatype at $position")
}
else -> declaredDatatype
}
}
override fun linkParents(parent: Node) { override fun linkParents(parent: Node) {
this.parent = parent this.parent = parent
arrayspec?.linkParents(this) arrayspec?.linkParents(this)
@ -543,10 +534,52 @@ class VarDecl(val type: VarDeclType,
override fun process(processor: IAstProcessor) = processor.process(this) override fun process(processor: IAstProcessor) = processor.process(this)
val scopedname: String by lazy { makeScopedName(name).joinToString(".") } val scopedname: String by lazy { makeScopedName(name).joinToString(".") }
val memorySize: Int
get() = when(datatype) {
DataType.BYTE -> 1
DataType.WORD -> 2
DataType.FLOAT -> 5 // MFLPT5
DataType.STR,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> {
val lv = value as? LiteralValue ?: throw ExpressionError("need constant initializer value expression", position)
lv.strvalue!!.length + 1
}
DataType.ARRAY -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
aX.intvalue!!
}
DataType.ARRAY_W -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
2*aX.intvalue!!
}
DataType.MATRIX -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
val aY = arrayspec.y as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
aX.intvalue!! * aY.intvalue!!
}
}
override fun toString(): String { override fun toString(): String {
return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)" return "VarDecl(name=$name, vartype=$type, datatype=$datatype, value=$value, pos=$position)"
} }
fun setDatatype() {
datatype =
when {
arrayspec == null -> declaredDatatype
arrayspec.y!=null -> when (declaredDatatype) {
DataType.BYTE -> DataType.MATRIX
else -> throw SyntaxError("matrix can only contain bytes", position)
}
else -> when (declaredDatatype) {
DataType.BYTE -> DataType.ARRAY
DataType.WORD -> DataType.ARRAY_W
else -> throw SyntaxError("array can only contain bytes or words", position)
}
}
}
} }
@ -719,10 +752,10 @@ data class IdentifierReference(val nameInSource: List<String>) : IExpression {
override fun constValue(namespace: INameScope): LiteralValue? { override fun constValue(namespace: INameScope): LiteralValue? {
val node = namespace.lookup(nameInSource, this) val node = namespace.lookup(nameInSource, this)
?: throw UndefinedSymbolException(this) ?: throw UndefinedSymbolError(this)
val vardecl = node as? VarDecl val vardecl = node as? VarDecl
if(vardecl==null) { if(vardecl==null) {
throw ExpressionException("name should be a constant, instead of: ${node::class.simpleName}", position) throw ExpressionError("name should be a constant, instead of: ${node::class.simpleName}", position)
} else if(vardecl.type!=VarDeclType.CONST) { } else if(vardecl.type!=VarDeclType.CONST) {
return null return null
} }
@ -813,12 +846,12 @@ class FunctionCall(override var target: IdentifierReference, override var arglis
"ceil" -> builtinCeil(arglist, position, namespace) "ceil" -> builtinCeil(arglist, position, namespace)
"lsl" -> builtinLsl(arglist, position, namespace) "lsl" -> builtinLsl(arglist, position, namespace)
"lsr" -> builtinLsr(arglist, position, namespace) "lsr" -> builtinLsr(arglist, position, namespace)
"rol" -> throw ExpressionException("builtin function rol can't be used in expressions because it doesn't return a value", position) "rol" -> throw ExpressionError("builtin function rol can't be used in expressions because it doesn't return a value", position)
"rol2" -> throw ExpressionException("builtin function rol2 can't be used in expressions because it doesn't return a value", position) "rol2" -> throw ExpressionError("builtin function rol2 can't be used in expressions because it doesn't return a value", position)
"ror" -> throw ExpressionException("builtin function ror can't be used in expressions because it doesn't return a value", position) "ror" -> throw ExpressionError("builtin function ror can't be used in expressions because it doesn't return a value", position)
"ror2" -> throw ExpressionException("builtin function ror2 can't be used in expressions because it doesn't return a value", position) "ror2" -> throw ExpressionError("builtin function ror2 can't be used in expressions because it doesn't return a value", position)
"P_carry" -> throw ExpressionException("builtin function P_carry can't be used in expressions because it doesn't return a value", position) "P_carry" -> throw ExpressionError("builtin function P_carry can't be used in expressions because it doesn't return a value", position)
"P_irqd" -> throw ExpressionException("builtin function P_irqd can't be used in expressions because it doesn't return a value", position) "P_irqd" -> throw ExpressionError("builtin function P_irqd can't be used in expressions because it doesn't return a value", position)
else -> null else -> null
} }
} }

View File

@ -26,9 +26,9 @@ fun Module.checkValid(globalNamespace: INameScope, compilerOptions: CompilationO
*/ */
class AstChecker(private val namespace: INameScope, private val compilerOptions: CompilationOptions) : IAstProcessor { class AstChecker(private val namespace: INameScope, private val compilerOptions: CompilationOptions) : IAstProcessor {
private val checkResult: MutableList<SyntaxError> = mutableListOf() private val checkResult: MutableList<AstException> = mutableListOf()
fun result(): List<SyntaxError> { fun result(): List<AstException> {
return checkResult return checkResult
} }
@ -122,15 +122,23 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
*/ */
override fun process(assignment: Assignment): IStatement { override fun process(assignment: Assignment): IStatement {
if(assignment.target.identifier!=null) { if(assignment.target.identifier!=null) {
val targetSymbol = namespace.lookup(assignment.target.identifier!!.nameInSource, assignment) val targetName = assignment.target.identifier!!.nameInSource
if(targetSymbol !is VarDecl) { val targetSymbol = namespace.lookup(targetName, assignment)
when {
targetSymbol == null -> {
checkResult.add(ExpressionError("undefined symbol: ${targetName.joinToString(".")}", assignment.position))
return super.process(assignment)
}
targetSymbol !is VarDecl -> {
checkResult.add(SyntaxError("assignment LHS must be register or variable", assignment.position)) checkResult.add(SyntaxError("assignment LHS must be register or variable", assignment.position))
return super.process(assignment) return super.process(assignment)
} else if(targetSymbol.type==VarDeclType.CONST) { }
checkResult.add(SyntaxError("cannot assign new value to a constant", assignment.position)) targetSymbol.type == VarDeclType.CONST -> {
checkResult.add(ExpressionError("cannot assign new value to a constant", assignment.position))
return super.process(assignment) return super.process(assignment)
} }
} }
}
if(assignment.value is LiteralValue) { if(assignment.value is LiteralValue) {
val targetDatatype = assignment.target.determineDatatype(namespace, assignment) val targetDatatype = assignment.target.determineDatatype(namespace, assignment)
@ -361,7 +369,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
private fun checkValueTypeAndRange(datatype: DataType, arrayspec: ArraySpec?, value: LiteralValue, position: Position?) : Boolean { private fun checkValueTypeAndRange(datatype: DataType, arrayspec: ArraySpec?, value: LiteralValue, position: Position?) : Boolean {
fun err(msg: String) : Boolean { fun err(msg: String) : Boolean {
checkResult.add(SyntaxError(msg, position)) checkResult.add(ExpressionError(msg, position))
return false return false
} }
when (datatype) { when (datatype) {
@ -417,7 +425,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
val number = (av as LiteralValue).intvalue val number = (av as LiteralValue).intvalue
?: return err("array must be all words") ?: return err("array must be all words")
val expectedSize = arrayspec?.x?.constValue(namespace)?.intvalue val expectedSize = arrayspec!!.x.constValue(namespace)?.intvalue!!
if (value.arrayvalue.size != expectedSize) if (value.arrayvalue.size != expectedSize)
return err("initializer array size mismatch (expecting $expectedSize, got ${value.arrayvalue.size})") return err("initializer array size mismatch (expecting $expectedSize, got ${value.arrayvalue.size})")
@ -431,7 +439,29 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("value '$number' out of range for unsigned word") return err("value '$number' out of range for unsigned word")
} }
} }
DataType.MATRIX -> TODO() DataType.MATRIX -> {
// value can only be a single byte, or a byte array (which represents the matrix)
if(value.isArray) {
for (av in value.arrayvalue!!) {
val number = (av as LiteralValue).intvalue
?: return err("array must be all bytes")
val expectedSizeX = arrayspec!!.x.constValue(namespace)?.intvalue!!
val expectedSizeY = arrayspec.y!!.constValue(namespace)?.intvalue!!
val expectedSize = expectedSizeX * expectedSizeY
if (value.arrayvalue.size != expectedSize)
return err("initializer array size mismatch (expecting $expectedSize, got ${value.arrayvalue.size})")
if (number < 0 || number > 255)
return err("value '$number' in byte array is out of range for unsigned byte")
}
} else {
val number = value.intvalue
?: return err("byte integer value expected")
if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte")
}
}
} }
return true return true
} }

View File

@ -6,6 +6,7 @@ import il65.parser.ParsingFailedError
/** /**
* Checks the validity of all identifiers (no conflicts) * Checks the validity of all identifiers (no conflicts)
* Also builds a list of all (scoped) symbol definitions * Also builds a list of all (scoped) symbol definitions
* Finally, it also makes sure the datatype of all Var decls is set correctly.
*/ */
fun Module.checkIdentifiers(): MutableMap<String, IStatement> { fun Module.checkIdentifiers(): MutableMap<String, IStatement> {
@ -47,6 +48,14 @@ class AstIdentifiersChecker : IAstProcessor {
} }
override fun process(decl: VarDecl): IStatement { override fun process(decl: VarDecl): IStatement {
// first, set the datatype
try {
decl.setDatatype()
} catch(ax: AstException) {
checkResult.add(ax)
}
// now check the identifier
if(BuiltinFunctionNames.contains(decl.name)) if(BuiltinFunctionNames.contains(decl.name))
// the builtin functions can't be redefined // the builtin functions can't be redefined
checkResult.add(NameError("builtin function cannot be redefined", decl.position)) checkResult.add(NameError("builtin function cannot be redefined", decl.position))

View File

@ -85,39 +85,6 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va
} }
} }
/*
; source code for a stackvm program
; init memory bytes/words/strings
%memory
0400 01 02 03 04 05 06 07 08 09 22 33 44 55 66
0500 1111 2222 3333 4444
1000 "Hello world!\n"
%end_memory
; init global var table with bytes/words/floats/strings
%variables
main.var1 str "This is main.var1"
main.var2 byte aa
main.var3 word ea44
main.var4 float 3.1415927
input.prompt str "Enter a number: "
input.result word 0
%end_variables
; instructions and labels
%instructions
nop
syscall WRITE_MEMSTR word:1000
loop:
syscall WRITE_VAR str:"input.prompt"
syscall INPUT_VAR str:"input.result"
syscall WRITE_VAR str:"input.result"
push byte:8d
syscall WRITE_CHAR
jump loop
%end_instructions
*/
class Compiler(private val options: CompilationOptions) { class Compiler(private val options: CompilationOptions) {
fun compile(module: Module) : StackVmProgram { fun compile(module: Module) : StackVmProgram {
@ -125,19 +92,19 @@ class Compiler(private val options: CompilationOptions) {
val namespace = module.definingScope() val namespace = module.definingScope()
// todo
val intermediate = StackVmProgram(module.name) val intermediate = StackVmProgram(module.name)
namespace.debugPrint() namespace.debugPrint()
// create the pool of all variables used in all blocks and scopes // create the pool of all variables used in all blocks and scopes
val varGather = VarGatherer(intermediate) val varGather = VarGatherer(intermediate)
varGather.process(module) varGather.process(module)
println("Number of allocated variables and constants: ${intermediate.variables.size} (${intermediate.variablesMemSize} bytes)")
val stmtGatherer = StatementGatherer(intermediate, namespace) val translator = StatementTranslator(intermediate, namespace)
stmtGatherer.process(module) translator.process(module)
println("Number of source statements: ${translator.stmtUniqueSequenceNr}")
println("Number of vm instructions: ${intermediate.instructions.size}")
intermediate.toTextLines().forEach { System.out.println(it) }
return intermediate return intermediate
} }
@ -151,7 +118,10 @@ class Compiler(private val options: CompilationOptions) {
} }
} }
class StatementGatherer(val stackvmProg: StackVmProgram, val namespace: INameScope): IAstProcessor { class StatementTranslator(val stackvmProg: StackVmProgram, val namespace: INameScope): IAstProcessor {
var stmtUniqueSequenceNr = 0
private set
override fun process(subroutine: Subroutine): IStatement { override fun process(subroutine: Subroutine): IStatement {
translate(subroutine.statements) translate(subroutine.statements)
return super.process(subroutine) return super.process(subroutine)
@ -164,6 +134,7 @@ class Compiler(private val options: CompilationOptions) {
private fun translate(statements: List<IStatement>) { private fun translate(statements: List<IStatement>) {
for (stmt: IStatement in statements) { for (stmt: IStatement in statements) {
stmtUniqueSequenceNr++
when (stmt) { when (stmt) {
is AnonymousStatementList -> translate(stmt.statements) is AnonymousStatementList -> translate(stmt.statements)
is BuiltinFunctionStatementPlaceholder -> translate(stmt) is BuiltinFunctionStatementPlaceholder -> translate(stmt)
@ -176,30 +147,90 @@ class Compiler(private val options: CompilationOptions) {
is InlineAssembly -> translate(stmt) is InlineAssembly -> translate(stmt)
is IfStatement -> translate(stmt) is IfStatement -> translate(stmt)
is BranchStatement -> translate(stmt) is BranchStatement -> translate(stmt)
is Directive, is VarDecl, is Subroutine -> {} is Directive, is VarDecl, is Subroutine -> {} // skip this, already processed these.
else -> TODO("translate statement $stmt") else -> TODO("translate statement $stmt")
} }
} }
} }
private fun translate(stmt: BranchStatement) { private fun translate(branch: BranchStatement) {
println("translate: $stmt") /*
// todo * A branch: IF_CC { stuff } else { other_stuff }
* Which is desugared into:
* BCS _stmt_999_else
* stuff
* JUMP _stmt_999_continue
* _stmt_999_else:
* other_stuff ;; optional
* _stmt_999_continue:
* ...
*/
val labelElse = makeLabel("else")
val labelContinue = makeLabel("continue")
val opcode = when(branch.condition) {
BranchCondition.CS -> "bcc"
BranchCondition.CC -> "bcs"
BranchCondition.EQ -> "bne"
BranchCondition.NE -> "beq"
BranchCondition.VS -> "bvc"
BranchCondition.VC -> "bvs"
BranchCondition.MI -> "bpl"
BranchCondition.PL -> "bmi"
}
if(branch.elsepart.isEmpty()) {
stackvmProg.instruction("$opcode $labelContinue")
translate(branch.statements)
stackvmProg.label(labelContinue)
} else {
stackvmProg.instruction("$opcode $labelElse")
translate(branch.statements)
stackvmProg.instruction("jump $labelContinue")
stackvmProg.label(labelElse)
translate(branch.elsepart)
stackvmProg.label(labelContinue)
}
} }
private fun makeLabel(postfix: String): String = "_il65stmt_${stmtUniqueSequenceNr}_$postfix"
private fun translate(stmt: IfStatement) { private fun translate(stmt: IfStatement) {
println("translate: $stmt") println("@todo translate: #$stmtUniqueSequenceNr : $stmt")
// todo stackvmProg.instruction("nop") // todo translate if statement
} }
private fun translate(stmt: InlineAssembly) { private fun translate(stmt: InlineAssembly) {
println("translate: $stmt") println("@todo translate: #$stmtUniqueSequenceNr : $stmt")
TODO("inline assembly not supported yet by stackvm") TODO("inline assembly not supported yet by stackvm")
} }
private fun translate(stmt: FunctionCallStatement) { private fun translate(stmt: FunctionCallStatement) {
println("translate: $stmt") val targetStmt = stmt.target.targetStatement(namespace)!!
// todo if(targetStmt is BuiltinFunctionStatementPlaceholder) {
// call to a builtin function
TODO("BUILTIN_${stmt.target.nameInSource[0]}") // TODO
return
}
val targetname = when(targetStmt) {
is Label -> targetStmt.scopedname
is Subroutine -> targetStmt.scopedname
else -> throw AstException("invalid call target node type: ${targetStmt::class}")
}
for (arg in stmt.arglist) {
val lv = arg.constValue(namespace)
if(lv==null) TODO("argument must be constant for now") // TODO non-const args
stackvmProg.instruction("push ${makeValue(lv)}")
}
stackvmProg.instruction("call $targetname")
}
private fun makeValue(value: LiteralValue): String {
return when {
value.isString -> "\"${value.strvalue}\""
value.isNumeric -> value.asNumericValue.toString()
else -> TODO("stackvm value for $value")
}
} }
private fun translate(stmt: Jump) { private fun translate(stmt: Jump) {
@ -230,8 +261,8 @@ class Compiler(private val options: CompilationOptions) {
} }
private fun translate(stmt: Assignment) { private fun translate(stmt: Assignment) {
println("translate: $stmt") println("@todo translate: #$stmtUniqueSequenceNr : $stmt")
// todo stackvmProg.instruction("nop") // todo translate assignment
} }
private fun translate(stmt: Return) { private fun translate(stmt: Return) {
@ -246,8 +277,8 @@ class Compiler(private val options: CompilationOptions) {
} }
private fun translate(stmt: BuiltinFunctionStatementPlaceholder) { private fun translate(stmt: BuiltinFunctionStatementPlaceholder) {
println("translate: $stmt") println("@todo translate: #$stmtUniqueSequenceNr : $stmt")
// todo stackvmProg.instruction("nop") // todo translate builtinfunction placeholder
} }
} }
} }
@ -258,20 +289,23 @@ class StackVmProgram(val name: String) {
val variables = mutableMapOf<String, VarDecl>() val variables = mutableMapOf<String, VarDecl>()
val instructions = mutableListOf<String>() val instructions = mutableListOf<String>()
val variablesMemSize: Int
get() {
return variables.values.fold(0) { acc, vardecl -> acc+vardecl.memorySize}
}
fun optimize() { fun optimize() {
println("\nOptimizing stackvmProg code...") println("\nOptimizing stackvmProg code...")
// todo // todo optimize stackvm code
} }
fun compileToAssembly(): AssemblyResult { fun compileToAssembly(): AssemblyResult {
println("\nGenerating assembly code from stackvmProg code... ") println("\nGenerating assembly code from stackvmProg code... ")
// todo // todo generate 6502 assembly
return AssemblyResult(name) return AssemblyResult(name)
} }
fun blockvar(scopedname: String, decl: VarDecl) { fun blockvar(scopedname: String, decl: VarDecl) {
println("$scopedname $decl")
variables[scopedname] = decl variables[scopedname] = decl
} }
@ -295,7 +329,7 @@ class StackVmProgram(val name: String) {
result.add("%end_variables") result.add("%end_variables")
result.add("%instructions") result.add("%instructions")
result.addAll(instructions) result.addAll(instructions)
result.add("%end_nstructions") result.add("%end_instructions")
return result return result
} }

View File

@ -69,7 +69,7 @@ class Zeropage(private val options: CompilationOptions) {
// 2 dimensional matrix (only bytes for now) // 2 dimensional matrix (only bytes for now)
when(vardecl.datatype) { when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * y DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * y
else -> throw CompilerException("matrix can only be of byte") else -> throw CompilerException("matrix can only contain bytes")
} }
} }
} else { } else {

View File

@ -71,7 +71,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
if(decl.value?.referencesIdentifier(decl.name) == true|| if(decl.value?.referencesIdentifier(decl.name) == true||
decl.arrayspec?.x?.referencesIdentifier(decl.name) == true || decl.arrayspec?.x?.referencesIdentifier(decl.name) == true ||
decl.arrayspec?.y?.referencesIdentifier(decl.name) == true) { decl.arrayspec?.y?.referencesIdentifier(decl.name) == true) {
errors.add(ExpressionException("recursive var declaration", decl.position)) errors.add(ExpressionError("recursive var declaration", decl.position))
return decl return decl
} }
@ -148,14 +148,14 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
optimizationsDone++ optimizationsDone++
LiteralValue(floatvalue = -subexpr.floatvalue) LiteralValue(floatvalue = -subexpr.floatvalue)
} }
else -> throw ExpressionException("can only take negative of int or float", subexpr.position) else -> throw ExpressionError("can only take negative of int or float", subexpr.position)
} }
expr.operator == "~" -> when { expr.operator == "~" -> when {
subexpr.intvalue != null -> { subexpr.intvalue != null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = subexpr.intvalue.inv()) LiteralValue(intvalue = subexpr.intvalue.inv())
} }
else -> throw ExpressionException("can only take bitwise inversion of int", subexpr.position) else -> throw ExpressionError("can only take bitwise inversion of int", subexpr.position)
} }
expr.operator == "not" -> when { expr.operator == "not" -> when {
subexpr.intvalue != null -> { subexpr.intvalue != null -> {
@ -166,9 +166,9 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0) LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0)
} }
else -> throw ExpressionException("can not take logical not of $subexpr", subexpr.position) else -> throw ExpressionError("can not take logical not of $subexpr", subexpr.position)
} }
else -> throw ExpressionException(expr.operator, subexpr.position) else -> throw ExpressionError(expr.operator, subexpr.position)
} }
result.position = subexpr.position result.position = subexpr.position
return result return result
@ -216,7 +216,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
// int range // int range
val rangevalue = from.intvalue.rangeTo(to.intvalue) val rangevalue = from.intvalue.rangeTo(to.intvalue)
if (rangevalue.last - rangevalue.first > 65535) { if (rangevalue.last - rangevalue.first > 65535) {
throw ExpressionException("amount of values in range exceeds 65535", range.position) throw ExpressionError("amount of values in range exceeds 65535", range.position)
} }
return LiteralValue(arrayvalue = rangevalue.map { return LiteralValue(arrayvalue = rangevalue.map {
val v = LiteralValue(intvalue = it) val v = LiteralValue(intvalue = it)
@ -229,7 +229,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
// char range // char range
val rangevalue = from.strvalue[0].rangeTo(to.strvalue[0]) val rangevalue = from.strvalue[0].rangeTo(to.strvalue[0])
if (rangevalue.last - rangevalue.first > 65535) { if (rangevalue.last - rangevalue.first > 65535) {
throw ExpressionException("amount of characters in range exceeds 65535", range.position) throw ExpressionError("amount of characters in range exceeds 65535", range.position)
} }
val newval = LiteralValue(strvalue = rangevalue.toList().joinToString("")) val newval = LiteralValue(strvalue = rangevalue.toList().joinToString(""))
newval.position = range.position newval.position = range.position
@ -316,16 +316,16 @@ class ConstExprEvaluator {
intvalue = if (left.intvalue >= right.intvalue) 1 else 0) intvalue = if (left.intvalue >= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0) intvalue = if (left.intvalue >= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0) intvalue = if (left.floatvalue >= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0) intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -339,16 +339,16 @@ class ConstExprEvaluator {
intvalue = if (left.intvalue <= right.intvalue) 1 else 0) intvalue = if (left.intvalue <= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0) intvalue = if (left.intvalue <= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0) intvalue = if (left.floatvalue <= right.intvalue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0) intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -376,16 +376,16 @@ class ConstExprEvaluator {
intvalue = if ((left.intvalue != 0).xor(right.intvalue != 0)) 1 else 0) intvalue = if ((left.intvalue != 0).xor(right.intvalue != 0)) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if ((left.intvalue != 0).xor(right.floatvalue != 0.0)) 1 else 0) intvalue = if ((left.intvalue != 0).xor(right.floatvalue != 0.0)) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.intvalue!=null -> LiteralValue(
intvalue = if ((left.floatvalue != 0.0).xor(right.intvalue != 0)) 1 else 0) intvalue = if ((left.floatvalue != 0.0).xor(right.intvalue != 0)) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if ((left.floatvalue != 0.0).xor(right.floatvalue != 0.0)) 1 else 0) intvalue = if ((left.floatvalue != 0.0).xor(right.floatvalue != 0.0)) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -399,16 +399,16 @@ class ConstExprEvaluator {
intvalue = if (left.intvalue != 0 || right.intvalue != 0) 1 else 0) intvalue = if (left.intvalue != 0 || right.intvalue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 || right.floatvalue != 0.0) 1 else 0) intvalue = if (left.intvalue != 0 || right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 || right.intvalue != 0) 1 else 0) intvalue = if (left.floatvalue != 0.0 || right.intvalue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 || right.floatvalue != 0.0) 1 else 0) intvalue = if (left.floatvalue != 0.0 || right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -422,16 +422,16 @@ class ConstExprEvaluator {
intvalue = if (left.intvalue != 0 && right.intvalue != 0) 1 else 0) intvalue = if (left.intvalue != 0 && right.intvalue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 && right.floatvalue != 0.0) 1 else 0) intvalue = if (left.intvalue != 0 && right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.intvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 && right.intvalue != 0) 1 else 0) intvalue = if (left.floatvalue != 0.0 && right.intvalue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 && right.floatvalue != 0.0) 1 else 0) intvalue = if (left.floatvalue != 0.0 && right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -443,7 +443,7 @@ class ConstExprEvaluator {
litval.position = left.position litval.position = left.position
return litval return litval
} }
throw ExpressionException("cannot calculate $left ^ $right", left.position) throw ExpressionError("cannot calculate $left ^ $right", left.position)
} }
private fun bitwiseor(left: LiteralValue, right: LiteralValue): LiteralValue { private fun bitwiseor(left: LiteralValue, right: LiteralValue): LiteralValue {
@ -452,7 +452,7 @@ class ConstExprEvaluator {
litval.position = left.position litval.position = left.position
return litval return litval
} }
throw ExpressionException("cannot calculate $left | $right", left.position) throw ExpressionError("cannot calculate $left | $right", left.position)
} }
private fun bitwiseand(left: LiteralValue, right: LiteralValue): LiteralValue { private fun bitwiseand(left: LiteralValue, right: LiteralValue): LiteralValue {
@ -461,7 +461,7 @@ class ConstExprEvaluator {
litval.position = left.position litval.position = left.position
return litval return litval
} }
throw ExpressionException("cannot calculate $left & $right", left.position) throw ExpressionError("cannot calculate $left & $right", left.position)
} }
private fun power(left: LiteralValue, right: LiteralValue): LiteralValue { private fun power(left: LiteralValue, right: LiteralValue): LiteralValue {
@ -470,14 +470,14 @@ class ConstExprEvaluator {
left.intvalue!=null -> when { left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt()) right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt())
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue)) right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue))
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue)) right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue))
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue)) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue))
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -489,14 +489,14 @@ class ConstExprEvaluator {
left.intvalue!=null -> when { left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue) right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue) right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -508,14 +508,14 @@ class ConstExprEvaluator {
left.intvalue!=null -> when { left.intvalue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue) right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue) right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -528,24 +528,24 @@ class ConstExprEvaluator {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue) right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue)
right.strvalue!=null -> { right.strvalue!=null -> {
if(right.strvalue.length * left.intvalue > 65535) throw ExpressionException("string too large", left.position) if(right.strvalue.length * left.intvalue > 65535) throw ExpressionError("string too large", left.position)
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue)) LiteralValue(strvalue = right.strvalue.repeat(left.intvalue))
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue) right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue)
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.strvalue!=null -> when { left.strvalue!=null -> when {
right.intvalue!=null -> { right.intvalue!=null -> {
if(left.strvalue.length * right.intvalue > 65535) throw ExpressionException("string too large", left.position) if(left.strvalue.length * right.intvalue > 65535) throw ExpressionError("string too large", left.position)
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue)) LiteralValue(strvalue = left.strvalue.repeat(right.intvalue))
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval
@ -556,27 +556,27 @@ class ConstExprEvaluator {
val litval = when { val litval = when {
left.intvalue!=null -> when { left.intvalue!=null -> when {
right.intvalue!=null -> { right.intvalue!=null -> {
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero", left.position) if(right.intvalue==0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(intvalue = left.intvalue / right.intvalue) LiteralValue(intvalue = left.intvalue / right.intvalue)
} }
right.floatvalue!=null -> { right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero", left.position) if(right.floatvalue==0.0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(floatvalue = left.intvalue / right.floatvalue) LiteralValue(floatvalue = left.intvalue / right.floatvalue)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> { right.intvalue!=null -> {
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero", left.position) if(right.intvalue==0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(floatvalue = left.floatvalue / right.intvalue) LiteralValue(floatvalue = left.floatvalue / right.intvalue)
} }
right.floatvalue!=null -> { right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero", left.position) if(right.floatvalue==0.0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(floatvalue = left.floatvalue / right.floatvalue) LiteralValue(floatvalue = left.floatvalue / right.floatvalue)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionException(error, left.position) else -> throw ExpressionError(error, left.position)
} }
litval.position = left.position litval.position = left.position
return litval return litval

View File

@ -495,6 +495,14 @@ class Program (prog: MutableList<Instruction>,
Opcode.JUMP -> { Opcode.JUMP -> {
Instruction(opcode, callLabel = args) Instruction(opcode, callLabel = args)
} }
Opcode.INC_VAR, Opcode.DEC_VAR,
Opcode.SHR_VAR, Opcode.SHL_VAR, Opcode.ROL_VAR, Opcode.ROR_VAR,
Opcode.ROL2_VAR, Opcode.ROR2_VAR, Opcode.POP_VAR, Opcode.PUSH_VAR -> {
val withoutQuotes =
if(args!!.startsWith('"') && args.endsWith('"'))
args.substring(1, args.length-1) else args
Instruction(opcode, Value(DataType.STR, null, withoutQuotes))
}
Opcode.SYSCALL -> { Opcode.SYSCALL -> {
val syscallparts = args!!.split(' ') val syscallparts = args!!.split(' ')
val call = Syscall.valueOf(syscallparts[0]) val call = Syscall.valueOf(syscallparts[0])

7
il65/stackvm.sh Executable file
View File

@ -0,0 +1,7 @@
#/bin/env sh
IL65_LIBDIR=../lib65
IL65CLASSPATH=out/production/il65
LIBJARS=/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-stdlib.jar:/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
java -cp ${IL65CLASSPATH}:${LIBJARS} il65.stackvm.StackVmKt $*