now explicit separation between byte and word literal integers

This commit is contained in:
Irmen de Jong 2018-09-13 22:31:59 +02:00
parent 949e468543
commit ea94063689
20 changed files with 1269 additions and 1078 deletions

View File

@ -248,6 +248,18 @@ type identifier type storage size example var declara
=============== ======================= ================= ========================================= =============== ======================= ================= =========================================
**hexadecimal numbers:** you can use a dollar prefix to write hexadecimal numbers: ``$20ac``
**binary numbers:** you can use a percent prefix to write binary numbers: ``%10010011``
**``byte`` versus ``word`` values:**
- When an integer value ranges from 0..255 the compiler sees it as a ``byte``.
- When an integer value ranges from 256..65535 the compiler sees it as a ``word``.
- When a hex number has 3 or 4 digits, for example ``$0004``, it is seen as a ``word`` otherwise as a ``byte``.
- When a binary number has 9 to 16 digits, for example ``%1100110011``, it is seen as a ``word`` otherwise as a ``byte``.
- You can force a byte value into a word value by adding the ``.w`` datatype suffix to the number: ``$2a.w`` is equivalent to ``$002a``.
**@todo pointers/addresses? (as opposed to normal WORDs)** **@todo pointers/addresses? (as opposed to normal WORDs)**
**@todo signed integers (byte and word)?** **@todo signed integers (byte and word)?**

View File

@ -1,10 +1,10 @@
/* /*
IL65 combined lexer bitand parser grammar IL65 combined lexer and parser grammar
NOTES: NOTES:
- whitespace is ignored. (tabs/spaces) - whitespace is ignored. (tabs/spaces)
- every position can be empty, be a comment, bitor contain ONE statement. - every position can be empty, be a comment, or contain ONE statement.
*/ */
@ -155,7 +155,9 @@ register : 'A' | 'X' | 'Y' | 'AX' | 'AY' | 'XY' ;
statusflag : 'Pc' | 'Pz' | 'Pn' | 'Pv' ; statusflag : 'Pc' | 'Pz' | 'Pn' | 'Pv' ;
integerliteral : DEC_INTEGER | HEX_INTEGER | BIN_INTEGER ; integerliteral : intpart=(DEC_INTEGER | HEX_INTEGER | BIN_INTEGER) wordsuffix? ;
wordsuffix : '.w' ;
booleanliteral : 'true' | 'false' ; booleanliteral : 'true' | 'false' ;

View File

@ -9,8 +9,8 @@
byte [2,3] matrix1 = 2 byte [2,3] matrix1 = 2
byte [2,3] matrix2 = [1,2,3,4,5,6] byte [2,3] matrix2 = [1,2,3,4,5,6]
const byte [100] carray1 = 0 const byte [100] carray1 = 2
const word [100] carray2 = 1 const word [100] carray2 = 1.w
const byte [2,3] cmatrix1 = [1,2,3,4,5,255] const byte [2,3] cmatrix1 = [1,2,3,4,5,255]
@ -30,7 +30,13 @@
const word len1 = len([1,2,3,wa1, wa2, ws1, all1]) const word len1 = len([1,2,3,wa1, wa2, ws1, all1])
const word wa1 = ceil(abs(-999.22)) const word wa1 = ceil(abs(-999.22))
const byte wa1b = abs(99)
const byte wa1c = -(1-99)
const byte wa1d = -0
const byte wa2 = abs(-99) const byte wa2 = abs(-99)
const byte wa2b= abs(-99.w)
const byte wa2c = abs(-99)
const word wa2d = abs(-999)
const float wa3 = abs(-1.23456) const float wa3 = abs(-1.23456)
const float wa4 = abs(-133) const float wa4 = abs(-133)
const float avg1 = avg([-1.23456, 99999]) const float avg1 = avg([-1.23456, 99999])
@ -44,7 +50,7 @@
const word all2 = all([0.0]) const word all2 = all([0.0])
const word all3 = all([wa1, wa2, ws1, all1]) const word all3 = all([wa1, wa2, ws1, all1])
const word max1 = max([-1,-2,3,99+22]) const word max1 = max([-1,-2,3.33,99+22])
const word min1 = min([1,2,3,99+22]) const word min1 = min([1,2,3,99+22])
word dinges = round(not_main.len1) word dinges = round(not_main.len1)
@ -154,12 +160,21 @@
sub start () -> () { sub start () -> () {
word dinges = 0 word dinges = 0
word blerp1 =99 word blerp1 =999
word blerp3 = 1
byte blerp2 =99 byte blerp2 =99
dinges=blerp1 dinges=blerp1
A=blerp1 ; @todo error can't assign word to byte A=blerp1 ; @todo error can't assign word to byte
A=blerp3 ; @todo error can't assign word to byte
blerp2=blerp3; @todo error can't assign word to byte
blerp3 = blerp2
A=blerp2 A=blerp2
A=9999 A=$02
A=$002
A=$00ff
A=%11001100
A=%0010011001
A=99.w
XY=blerp1 XY=blerp1
X=blerp1 ; @todo error can't assign word to byte X=blerp1 ; @todo error can't assign word to byte
X=blerp2 X=blerp2

View File

@ -15,7 +15,7 @@ fun main(args: Array<String>) {
println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)") println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)")
println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n") println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
// import main module bitand process additional imports // import main module and process additional imports
if(args.size != 1) { if(args.size != 1) {
System.err.println("module filename argument missing") System.err.println("module filename argument missing")
@ -46,7 +46,7 @@ fun main(args: Array<String>) {
) )
// perform syntax checks bitand optimizations // perform syntax checks and optimizations
moduleAst.checkIdentifiers() moduleAst.checkIdentifiers()
moduleAst.optimizeExpressions(globalNameSpaceBeforeOptimization) moduleAst.optimizeExpressions(globalNameSpaceBeforeOptimization)
moduleAst.checkValid(globalNameSpaceBeforeOptimization, compilerOptions) // check if tree is valid moduleAst.checkValid(globalNameSpaceBeforeOptimization, compilerOptions) // check if tree is valid
@ -59,7 +59,7 @@ fun main(args: Array<String>) {
// globalNamespaceAfterOptimize.debugPrint() // globalNamespaceAfterOptimize.debugPrint()
// compile the syntax tree into stackvmProg form, bitand optimize that // compile the syntax tree into stackvmProg form, and optimize that
val compiler = Compiler(compilerOptions) val compiler = Compiler(compilerOptions)
val intermediate = compiler.compile(moduleAst) val intermediate = compiler.compile(moduleAst)
intermediate.optimize() intermediate.optimize()

View File

@ -5,6 +5,7 @@ import il65.parser.il65Parser
import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.TerminalNode import org.antlr.v4.runtime.tree.TerminalNode
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.math.floor
/**************************** AST Data classes ****************************/ /**************************** AST Data classes ****************************/
@ -86,7 +87,7 @@ data class Position(val file: String, val line: Int, val startCol: Int, val endC
interface IAstProcessor { interface IAstProcessor {
fun process(module: Module) { fun process(module: Module) {
module.statements = module.statements.map { it.process(this) }.toMutableList() module.statements = module.statements.asSequence().map { it.process(this) }.toMutableList()
} }
fun process(expr: PrefixExpression): IExpression { fun process(expr: PrefixExpression): IExpression {
@ -105,7 +106,7 @@ interface IAstProcessor {
} }
fun process(block: Block): IStatement { fun process(block: Block): IStatement {
block.statements = block.statements.map { it.process(this) }.toMutableList() block.statements = block.statements.asSequence().map { it.process(this) }.toMutableList()
return block return block
} }
@ -116,7 +117,7 @@ interface IAstProcessor {
} }
fun process(subroutine: Subroutine): IStatement { fun process(subroutine: Subroutine): IStatement {
subroutine.statements = subroutine.statements.map { it.process(this) }.toMutableList() subroutine.statements = subroutine.statements.asSequence().map { it.process(this) }.toMutableList()
return subroutine return subroutine
} }
@ -197,7 +198,7 @@ interface Node {
} }
// find the parent node of a specific type bitor interface // find the parent node of a specific type or interface
// (useful to figure out in what namespace/block something is defined, etc) // (useful to figure out in what namespace/block something is defined, etc)
inline fun <reified T> findParentNode(node: Node): T? { inline fun <reified T> findParentNode(node: Node): T? {
var candidate = node.parent var candidate = node.parent
@ -243,9 +244,9 @@ interface INameScope {
fun registerUsedName(name: String) fun registerUsedName(name: String)
fun subScopes() = statements.filter { it is INameScope } .map { it as INameScope }.associate { it.name to it } fun subScopes() = statements.asSequence().filter { it is INameScope }.map { it as INameScope }.associate { it.name to it }
fun labelsAndVariables() = statements.filter { it is Label || it is VarDecl } fun labelsAndVariables() = statements.asSequence().filter { it is Label || it is VarDecl }
.associate {((it as? Label)?.name ?: (it as? VarDecl)?.name) to it } .associate {((it as? Label)?.name ?: (it as? VarDecl)?.name) to it }
fun lookup(scopedName: List<String>, statement: Node) : IStatement? { fun lookup(scopedName: List<String>, statement: Node) : IStatement? {
@ -302,7 +303,7 @@ interface INameScope {
/** /**
* Inserted into the Ast in place of modified nodes (not inserted directly as a parser result) * Inserted into the Ast in place of modified nodes (not inserted directly as a parser result)
* It can hold zero bitor more replacement statements that have to be inserted at that point. * It can hold zero or more replacement statements that have to be inserted at that point.
*/ */
class AnonymousStatementList(override var parent: Node, var statements: List<IStatement>) : IStatement { class AnonymousStatementList(override var parent: Node, var statements: List<IStatement>) : IStatement {
override var position: Position? = null override var position: Position? = null
@ -371,7 +372,7 @@ private class GlobalNamespace(override val name: String,
override var statements: MutableList<IStatement>, override var statements: MutableList<IStatement>,
override val position: Position?) : INameScope { override val position: Position?) : INameScope {
private val scopedNamesUsed: MutableSet<String> = mutableSetOf("main", "main.start") // main bitand main.start are always used private val scopedNamesUsed: MutableSet<String> = mutableSetOf("main", "main.start") // main and main.start are always used
override fun usedNames(): Set<String> = scopedNamesUsed override fun usedNames(): Set<String> = scopedNamesUsed
@ -548,16 +549,16 @@ class VarDecl(val type: VarDeclType,
} }
DataType.ARRAY -> { DataType.ARRAY -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position) val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
aX.intvalue!! aX.asIntegerValue!!
} }
DataType.ARRAY_W -> { DataType.ARRAY_W -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position) val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
2*aX.intvalue!! 2*aX.asIntegerValue!!
} }
DataType.MATRIX -> { DataType.MATRIX -> {
val aX = arrayspec?.x as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position) 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) val aY = arrayspec.y as? LiteralValue ?: throw ExpressionError("need constant value expression for arrayspec", position)
aX.intvalue!! * aY.intvalue!! aX.asIntegerValue!! * aY.asIntegerValue!!
} }
} }
@ -576,7 +577,7 @@ class VarDecl(val type: VarDeclType,
else -> when (declaredDatatype) { else -> when (declaredDatatype) {
DataType.BYTE -> DataType.ARRAY DataType.BYTE -> DataType.ARRAY
DataType.WORD -> DataType.ARRAY_W DataType.WORD -> DataType.ARRAY_W
else -> throw SyntaxError("array can only contain bytes bitor words", position) else -> throw SyntaxError("array can only contain bytes or words", position)
} }
} }
} }
@ -666,7 +667,13 @@ class BinaryExpression(var left: IExpression, val operator: String, var right: I
override fun referencesIdentifier(name: String) = left.referencesIdentifier(name) || right.referencesIdentifier(name) override fun referencesIdentifier(name: String) = left.referencesIdentifier(name) || right.referencesIdentifier(name)
} }
data class LiteralValue(val intvalue: Int? = null, private data class ByteOrWordLiteral(val intvalue: Int, val datatype: DataType) {
fun asWord() = ByteOrWordLiteral(intvalue, DataType.WORD)
fun asByte() = ByteOrWordLiteral(intvalue, DataType.BYTE)
}
data class LiteralValue(val bytevalue: Short? = null,
val wordvalue: Int? = null,
val floatvalue: Double? = null, val floatvalue: Double? = null,
val strvalue: String? = null, val strvalue: String? = null,
val arrayvalue: MutableList<IExpression>? = null) : IExpression { val arrayvalue: MutableList<IExpression>? = null) : IExpression {
@ -674,21 +681,52 @@ data class LiteralValue(val intvalue: Int? = null,
override lateinit var parent: Node override lateinit var parent: Node
override fun referencesIdentifier(name: String) = arrayvalue?.any { it.referencesIdentifier(name) } ?: false override fun referencesIdentifier(name: String) = arrayvalue?.any { it.referencesIdentifier(name) } ?: false
val isInteger = intvalue!=null companion object {
fun optimalNumeric(value: Number): LiteralValue {
val floatval = value.toDouble()
return if(floatval == floor(floatval) && floatval in -32768..65535) {
// the floating point value is actually an integer.
when (floatval) {
// note: we cheat a little here and allow negative integers during expression evaluations
in -128..255 -> LiteralValue(bytevalue = floatval.toShort())
in -32768..65535 -> LiteralValue(wordvalue = floatval.toInt())
else -> throw FatalAstException("integer overflow: $floatval")
}
} else {
LiteralValue(floatvalue = floatval)
}
}
}
val isByte = bytevalue!=null
val isWord = wordvalue!=null
val isInteger = isByte or isWord
val isFloat = floatvalue!=null val isFloat = floatvalue!=null
val isNumeric = intvalue!=null || floatvalue!=null val isArray = arrayvalue!=null // @todo: array / word-array / matrix ?
val isArray = arrayvalue!=null
val isString = strvalue!=null val isString = strvalue!=null
init {
if(bytevalue==null && wordvalue==null && floatvalue==null && arrayvalue==null && strvalue==null)
throw FatalAstException("literal value without actual value")
}
val asNumericValue: Number? = when { val asNumericValue: Number? = when {
intvalue!=null -> intvalue bytevalue!=null -> bytevalue
wordvalue!=null -> wordvalue
floatvalue!=null -> floatvalue floatvalue!=null -> floatvalue
else -> null else -> null
} }
val asIntegerValue: Int? = when {
bytevalue!=null -> bytevalue.toInt()
wordvalue!=null -> wordvalue
else -> null
}
val asBooleanValue: Boolean = val asBooleanValue: Boolean =
(floatvalue!=null && floatvalue != 0.0) || (floatvalue!=null && floatvalue != 0.0) ||
(intvalue!=null && intvalue != 0) || (bytevalue!=null && bytevalue != 0.toShort()) ||
(wordvalue!=null && wordvalue != 0) ||
(strvalue!=null && strvalue.isNotEmpty()) || (strvalue!=null && strvalue.isNotEmpty()) ||
(arrayvalue != null && arrayvalue.isNotEmpty()) (arrayvalue != null && arrayvalue.isNotEmpty())
@ -701,7 +739,7 @@ data class LiteralValue(val intvalue: Int? = null,
override fun process(processor: IAstProcessor) = processor.process(this) override fun process(processor: IAstProcessor) = processor.process(this)
override fun toString(): String { override fun toString(): String {
return "LiteralValue(int=$intvalue, float=$floatvalue, str=$strvalue, array=$arrayvalue pos=$position)" return "LiteralValue(byte=$bytevalue, word=$wordvalue, float=$floatvalue, str=$strvalue, array=$arrayvalue pos=$position)"
} }
} }
@ -816,7 +854,7 @@ class FunctionCall(override var target: IdentifierReference, override var arglis
} }
override fun constValue(namespace: INameScope): LiteralValue? { override fun constValue(namespace: INameScope): LiteralValue? {
// if the function is a built-in function bitand the args are consts, should try to const-evaluate! // if the function is a built-in function and the args are consts, should try to const-evaluate!
if(target.nameInSource.size>1) return null if(target.nameInSource.size>1) return null
try { try {
return when (target.nameInSource[0]) { return when (target.nameInSource[0]) {
@ -988,7 +1026,7 @@ class BranchStatement(var condition: BranchCondition,
/***************** Antlr Extension methods to create AST ****************/ /***************** Antlr Extension methods to create AST ****************/
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module { fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module {
val module = Module(name, modulestatement().map { it.toAst(withPosition) }.toMutableList()) val module = Module(name, modulestatement().asSequence().map { it.toAst(withPosition) }.toMutableList())
module.position = toPosition(withPosition) module.position = toPosition(withPosition)
return module return module
} }
@ -1019,7 +1057,7 @@ private fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : ISt
private fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement { private fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
val block= Block(identifier().text, val block= Block(identifier().text,
integerliteral()?.toAst(), integerliteral()?.toAst()?.intvalue,
statement_block().toAst(withPosition)) statement_block().toAst(withPosition))
block.position = toPosition(withPosition) block.position = toPosition(withPosition)
return block return block
@ -1027,7 +1065,7 @@ private fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
private fun il65Parser.Statement_blockContext.toAst(withPosition: Boolean): MutableList<IStatement> private fun il65Parser.Statement_blockContext.toAst(withPosition: Boolean): MutableList<IStatement>
= statement().map { it.toAst(withPosition) }.toMutableList() = statement().asSequence().map { it.toAst(withPosition) }.toMutableList()
private fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement { private fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
@ -1164,7 +1202,7 @@ private fun il65Parser.ReturnstmtContext.toAst(withPosition: Boolean) : IStateme
private fun il65Parser.UnconditionaljumpContext.toAst(withPosition: Boolean): IStatement { private fun il65Parser.UnconditionaljumpContext.toAst(withPosition: Boolean): IStatement {
val address = integerliteral()?.toAst() val address = integerliteral()?.toAst()?.intvalue
val identifier = val identifier =
if(identifier()!=null) identifier()?.toAst(withPosition) if(identifier()!=null) identifier()?.toAst(withPosition)
else scoped_identifier()?.toAst(withPosition) else scoped_identifier()?.toAst(withPosition)
@ -1186,7 +1224,7 @@ private fun il65Parser.SubroutineContext.toAst(withPosition: Boolean) : Subrouti
val sub = Subroutine(identifier().text, val sub = Subroutine(identifier().text,
if(sub_params()==null) emptyList() else sub_params().toAst(), if(sub_params()==null) emptyList() else sub_params().toAst(),
if(sub_returns()==null) emptyList() else sub_returns().toAst(), if(sub_returns()==null) emptyList() else sub_returns().toAst(),
sub_address()?.integerliteral()?.toAst(), sub_address()?.integerliteral()?.toAst()?.intvalue,
if(statement_block()==null) mutableListOf() else statement_block().toAst(withPosition)) if(statement_block()==null) mutableListOf() else statement_block().toAst(withPosition))
sub.position = toPosition(withPosition) sub.position = toPosition(withPosition)
return sub return sub
@ -1244,18 +1282,39 @@ private fun il65Parser.DirectiveContext.toAst(withPosition: Boolean) : Directive
private fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) : DirectiveArg { private fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) : DirectiveArg {
val darg = DirectiveArg(stringliteral()?.text, val darg = DirectiveArg(stringliteral()?.text,
identifier()?.text, identifier()?.text,
integerliteral()?.toAst()) integerliteral()?.toAst()?.intvalue)
darg.position = toPosition(withPosition) darg.position = toPosition(withPosition)
return darg return darg
} }
private fun il65Parser.IntegerliteralContext.toAst(): Int { private fun il65Parser.IntegerliteralContext.toAst(): ByteOrWordLiteral {
fun makeLiteral(text: String, radix: Int, forceWord: Boolean): ByteOrWordLiteral {
val integer: Int
var datatype = DataType.BYTE
if(radix==10) {
integer = text.toInt()
if(integer in 256..65535)
datatype = DataType.WORD
} else if(radix==2) {
if(text.length>8)
datatype = DataType.WORD
integer = text.toInt(2)
} else if(radix==16) {
if(text.length>2)
datatype = DataType.WORD
integer = text.toInt(16)
} else {
throw FatalAstException("invalid radix")
}
return ByteOrWordLiteral(integer, if(forceWord) DataType.WORD else datatype)
}
val terminal: TerminalNode = children[0] as TerminalNode val terminal: TerminalNode = children[0] as TerminalNode
val integerPart = this.intpart.text
return when (terminal.symbol.type) { return when (terminal.symbol.type) {
il65Parser.DEC_INTEGER -> text.toInt() il65Parser.DEC_INTEGER -> makeLiteral(integerPart, 10, wordsuffix()!=null)
il65Parser.HEX_INTEGER -> text.substring(1).toInt(16) il65Parser.HEX_INTEGER -> makeLiteral(integerPart.substring(1), 16, wordsuffix()!=null)
il65Parser.BIN_INTEGER -> text.substring(1).toInt(2) il65Parser.BIN_INTEGER -> makeLiteral(integerPart.substring(1), 2, wordsuffix()!=null)
else -> throw FatalAstException(terminal.text) else -> throw FatalAstException(terminal.text)
} }
} }
@ -1268,12 +1327,22 @@ private fun il65Parser.ExpressionContext.toAst(withPosition: Boolean) : IExpress
val booleanlit = litval.booleanliteral()?.toAst() val booleanlit = litval.booleanliteral()?.toAst()
val value = val value =
if(booleanlit!=null) if(booleanlit!=null)
LiteralValue(intvalue = if(booleanlit) 1 else 0) LiteralValue(bytevalue = if(booleanlit) 1 else 0)
else else {
LiteralValue(litval.integerliteral()?.toAst(), val intLit = litval.integerliteral()?.toAst()
litval.floatliteral()?.toAst(), if(intLit!=null) {
litval.stringliteral()?.text, when(intLit.datatype) {
litval.arrayliteral()?.toAst(withPosition)) DataType.BYTE -> LiteralValue(bytevalue = intLit.intvalue.toShort())
DataType.WORD -> LiteralValue(wordvalue = intLit.intvalue)
else -> throw FatalAstException("invalid datatype for integer literal")
}
} else {
LiteralValue(null, null,
litval.floatliteral()?.toAst(),
litval.stringliteral()?.text,
litval.arrayliteral()?.toAst(withPosition))
}
}
value.position = litval.toPosition(withPosition) value.position = litval.toPosition(withPosition)
return value return value
} }
@ -1349,7 +1418,7 @@ private fun il65Parser.BooleanliteralContext.toAst() = when(text) {
private fun il65Parser.ArrayliteralContext.toAst(withPosition: Boolean) = private fun il65Parser.ArrayliteralContext.toAst(withPosition: Boolean) =
expression().map { it.toAst(withPosition) }.toMutableList() expression().asSequence().map { it.toAst(withPosition) }.toMutableList()
private fun il65Parser.If_stmtContext.toAst(withPosition: Boolean): IfStatement { private fun il65Parser.If_stmtContext.toAst(withPosition: Boolean): IfStatement {

View File

@ -34,7 +34,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
override fun process(module: Module) { override fun process(module: Module) {
super.process(module) super.process(module)
val directives = module.statements.filter { it is Directive }.groupBy { (it as Directive).directive } val directives = module.statements.asSequence().filter { it is Directive }.groupBy { (it as Directive).directive }
directives.filter { it.value.size > 1 }.forEach{ entry -> directives.filter { it.value.size > 1 }.forEach{ entry ->
when(entry.key) { when(entry.key) {
"%output", "%launcher", "%zeropage", "%address" -> "%output", "%launcher", "%zeropage", "%address" ->
@ -88,31 +88,32 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if(BuiltinFunctionNames.contains(subroutine.name)) if(BuiltinFunctionNames.contains(subroutine.name))
err("cannot redefine a built-in function") err("cannot redefine a built-in function")
val uniqueNames = subroutine.parameters.map { it.name }.toSet() val uniqueNames = subroutine.parameters.asSequence().map { it.name }.toSet()
if(uniqueNames.size!=subroutine.parameters.size) if(uniqueNames.size!=subroutine.parameters.size)
err("parameter names should be unique") err("parameter names should be unique")
val uniqueParamRegs = subroutine.parameters.map {it.register}.toSet() val uniqueParamRegs = subroutine.parameters.asSequence().map {it.register}.toSet()
if(uniqueParamRegs.size!=subroutine.parameters.size) if(uniqueParamRegs.size!=subroutine.parameters.size)
err("parameter registers should be unique") err("parameter registers should be unique")
val uniqueResultRegisters = subroutine.returnvalues.filter{it.register!=null}.map {it.register.toString()}.toMutableSet() val uniqueResultRegisters = subroutine.returnvalues.asSequence().filter{it.register!=null}.map {it.register.toString()}.toMutableSet()
uniqueResultRegisters.addAll(subroutine.returnvalues.filter{it.statusflag!=null}.map{it.statusflag.toString()}) uniqueResultRegisters.addAll(subroutine.returnvalues.asSequence().filter{it.statusflag!=null}.map{it.statusflag.toString()}.toList())
if(uniqueResultRegisters.size!=subroutine.returnvalues.size) if(uniqueResultRegisters.size!=subroutine.returnvalues.size)
err("return registers should be unique") err("return registers should be unique")
super.process(subroutine) super.process(subroutine)
checkSubroutinesPrecededByReturnOrJump(subroutine.statements) checkSubroutinesPrecededByReturnOrJump(subroutine.statements)
// subroutine must contain at least one 'return' bitor 'goto' // subroutine must contain at least one 'return' or 'goto'
// (bitor if it has an asm block, that must contain a 'rts' bitor 'jmp') // (or if it has an asm block, that must contain a 'rts' or 'jmp')
if(subroutine.statements.count { it is Return || it is Jump } == 0) { if(subroutine.statements.count { it is Return || it is Jump } == 0) {
if(subroutine.address==null) { if(subroutine.address==null) {
val amount = subroutine.statements val amount = subroutine.statements
.asSequence()
.filter { it is InlineAssembly } .filter { it is InlineAssembly }
.map {(it as InlineAssembly).assembly} .map {(it as InlineAssembly).assembly}
.count { it.contains(" rts") || it.contains("\trts") || .count { it.contains(" rts") || it.contains("\trts") ||
it.contains(" jmp") || it.contains("\tjmp")} it.contains(" jmp") || it.contains("\tjmp")}
if(amount==0 ) if(amount==0 )
err("subroutine must have at least one 'return' bitor 'goto' in it (bitor 'rts' / 'jmp' in case of %asm)") err("subroutine must have at least one 'return' or 'goto' in it (or 'rts' / 'jmp' in case of %asm)")
} }
} }
@ -128,7 +129,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
&& preceding !is Subroutine && preceding !is Subroutine
&& preceding !is VarDecl && preceding !is VarDecl
&& preceding !is BuiltinFunctionStatementPlaceholder) { && preceding !is BuiltinFunctionStatementPlaceholder) {
checkResult.add(SyntaxError("subroutine definition should be preceded by a return, jump, vardecl, bitor another subroutine statement", stmt.position)) checkResult.add(SyntaxError("subroutine definition should be preceded by a return, jump, vardecl, or another subroutine statement", stmt.position))
} }
} }
preceding = stmt preceding = stmt
@ -136,7 +137,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
} }
/** /**
* Assignment target must be register, bitor a variable name * Assignment target must be register, or a variable name
* for constant-value assignments, check the datatype as well * for constant-value assignments, check the datatype as well
*/ */
override fun process(assignment: Assignment): IStatement { override fun process(assignment: Assignment): IStatement {
@ -149,7 +150,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return super.process(assignment) return super.process(assignment)
} }
targetSymbol !is VarDecl -> { targetSymbol !is VarDecl -> {
checkResult.add(SyntaxError("assignment LHS must be register bitor variable", assignment.position)) checkResult.add(SyntaxError("assignment LHS must be register or variable", assignment.position))
return super.process(assignment) return super.process(assignment)
} }
targetSymbol.type == VarDeclType.CONST -> { targetSymbol.type == VarDeclType.CONST -> {
@ -204,7 +205,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
err("value of memory var decl is not a literal (it is a ${decl.value!!::class.simpleName}).", decl.value?.position) err("value of memory var decl is not a literal (it is a ${decl.value!!::class.simpleName}).", decl.value?.position)
} else { } else {
val value = decl.value as LiteralValue val value = decl.value as LiteralValue
if (value.intvalue == null || value.intvalue < 0 || value.intvalue > 65535) { if (value.asIntegerValue == null || value.asIntegerValue< 0 || value.asIntegerValue > 65535) {
err("memory address must be valid integer 0..\$ffff") err("memory address must be valid integer 0..\$ffff")
} }
} }
@ -238,12 +239,12 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
"%output" -> { "%output" -> {
if(directive.parent !is Module) err("this directive may only occur at module level") if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name != "raw" && directive.args[0].name != "prg") if(directive.args.size!=1 || directive.args[0].name != "raw" && directive.args[0].name != "prg")
err("invalid output directive type, expected raw bitor prg") err("invalid output directive type, expected raw or prg")
} }
"%launcher" -> { "%launcher" -> {
if(directive.parent !is Module) err("this directive may only occur at module level") if(directive.parent !is Module) err("this directive may only occur at module level")
if(directive.args.size!=1 || directive.args[0].name != "basic" && directive.args[0].name != "none") if(directive.args.size!=1 || directive.args[0].name != "basic" && directive.args[0].name != "none")
err("invalid launcher directive type, expected basic bitor none") err("invalid launcher directive type, expected basic or none")
} }
"%zeropage" -> { "%zeropage" -> {
if(directive.parent !is Module) err("this directive may only occur at module level") if(directive.parent !is Module) err("this directive may only occur at module level")
@ -251,7 +252,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
directive.args[0].name != "basicsafe" && directive.args[0].name != "basicsafe" &&
directive.args[0].name != "kernalsafe" && directive.args[0].name != "kernalsafe" &&
directive.args[0].name != "full") directive.args[0].name != "full")
err("invalid zp directive style, expected basicsafe, kernalsafe, bitor full") err("invalid zp directive style, expected basicsafe, kernalsafe, or full")
} }
"%address" -> { "%address" -> {
if(directive.parent !is Module) err("this directive may only occur at module level") if(directive.parent !is Module) err("this directive may only occur at module level")
@ -298,6 +299,11 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if(!compilerOptions.floats && literalValue.isFloat) { if(!compilerOptions.floats && literalValue.isFloat) {
checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position)) checkResult.add(SyntaxError("floating point value used, but floating point is not enabled via options", literalValue.position))
} }
when {
literalValue.isByte -> checkValueTypeAndRange(DataType.BYTE, null, literalValue, literalValue.position)
literalValue.isWord -> checkValueTypeAndRange(DataType.WORD, null, literalValue, literalValue.position)
literalValue.isFloat -> checkValueTypeAndRange(DataType.FLOAT, null, literalValue, literalValue.position)
}
return super.process(literalValue) return super.process(literalValue)
} }
@ -310,17 +316,17 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
val to = range.to.constValue(namespace) val to = range.to.constValue(namespace)
if(from!=null && to != null) { if(from!=null && to != null) {
when { when {
from.intvalue!=null && to.intvalue!=null -> { from.asIntegerValue!=null && to.asIntegerValue!=null -> {
if(from.intvalue > to.intvalue) if(from.asIntegerValue > to.asIntegerValue)
err("range from is larger than to value") err("range from is larger than to value")
} }
from.strvalue!=null && to.strvalue!=null -> { from.strvalue!=null && to.strvalue!=null -> {
if(from.strvalue.length!=1 || to.strvalue.length!=1) if(from.strvalue.length!=1 || to.strvalue.length!=1)
err("range from bitand to must be a single character") err("range from and to must be a single character")
if(from.strvalue[0] > to.strvalue[0]) if(from.strvalue[0] > to.strvalue[0])
err("range from is larger than to value") err("range from is larger than to value")
} }
else -> err("range expression must be over integers bitor over characters") else -> err("range expression must be over integers or over characters")
} }
} }
return range return range
@ -352,9 +358,9 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
checkResult.add(SyntaxError("undefined symbol: ${targetName.joinToString(".")}", postIncrDecr.position)) checkResult.add(SyntaxError("undefined symbol: ${targetName.joinToString(".")}", postIncrDecr.position))
} else { } else {
if(target !is VarDecl || target.type==VarDeclType.CONST) { if(target !is VarDecl || target.type==VarDeclType.CONST) {
checkResult.add(SyntaxError("can only increment bitor decrement a variable", postIncrDecr.position)) checkResult.add(SyntaxError("can only increment or decrement a variable", postIncrDecr.position))
} else if(target.datatype!=DataType.FLOAT && target.datatype!=DataType.WORD && target.datatype!=DataType.BYTE) { } else if(target.datatype!=DataType.FLOAT && target.datatype!=DataType.WORD && target.datatype!=DataType.BYTE) {
checkResult.add(SyntaxError("can only increment bitor decrement a byte/float/word variable", postIncrDecr.position)) checkResult.add(SyntaxError("can only increment or decrement a byte/float/word variable", postIncrDecr.position))
} }
} }
} }
@ -365,7 +371,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
val targetStatement = target.targetStatement(namespace) val targetStatement = target.targetStatement(namespace)
if(targetStatement is Label || targetStatement is Subroutine || targetStatement is BuiltinFunctionStatementPlaceholder) if(targetStatement is Label || targetStatement is Subroutine || targetStatement is BuiltinFunctionStatementPlaceholder)
return targetStatement return targetStatement
checkResult.add(SyntaxError("undefined function bitor subroutine: ${target.nameInSource.joinToString(".")}", statement.position)) checkResult.add(SyntaxError("undefined function or subroutine: ${target.nameInSource.joinToString(".")}", statement.position))
return null return null
} }
@ -373,13 +379,13 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
if(call.target.nameInSource.size==1 && BuiltinFunctionNames.contains(call.target.nameInSource[0])) { if(call.target.nameInSource.size==1 && BuiltinFunctionNames.contains(call.target.nameInSource[0])) {
val functionName = call.target.nameInSource[0] val functionName = call.target.nameInSource[0]
if(functionName=="P_carry" || functionName=="P_irqd") { if(functionName=="P_carry" || functionName=="P_irqd") {
// these functions allow only 0 bitor 1 as argument // these functions allow only 0 or 1 as argument
if(call.arglist.size!=1 || call.arglist[0] !is LiteralValue) { if(call.arglist.size!=1 || call.arglist[0] !is LiteralValue) {
checkResult.add(SyntaxError("$functionName requires one argument, 0 bitor 1", position)) checkResult.add(SyntaxError("$functionName requires one argument, 0 or 1", position))
} else { } else {
val value = call.arglist[0] as LiteralValue val value = call.arglist[0] as LiteralValue
if(value.intvalue==null || value.intvalue < 0 || value.intvalue > 1) { if(value.asIntegerValue==null || value.asIntegerValue < 0 || value.asIntegerValue > 1) {
checkResult.add(SyntaxError("$functionName requires one argument, 0 bitor 1", position)) checkResult.add(SyntaxError("$functionName requires one argument, 0 or 1", position))
} }
} }
} }
@ -399,14 +405,18 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("floating point value '$number' out of range for MFLPT format") return err("floating point value '$number' out of range for MFLPT format")
} }
DataType.BYTE -> { DataType.BYTE -> {
val number = value.intvalue val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
?: return err("byte integer value expected") err("unsigned byte integer value expected instead of float; possible loss of precision")
else
err("unsigned byte integer value expected")
if (number < 0 || number > 255) if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte") return err("value '$number' out of range for unsigned byte")
} }
DataType.WORD -> { DataType.WORD -> {
val number = value.intvalue val number = value.asIntegerValue ?: return if (value.floatvalue!=null)
?: return err("word integer value expected") err("unsigned word integer value expected instead of float; possible loss of precision")
else
err("unsigned word integer value expected")
if (number < 0 || number > 65535) if (number < 0 || number > 65535)
return err("value '$number' out of range for unsigned word") return err("value '$number' out of range for unsigned word")
} }
@ -417,13 +427,13 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("string length must be 1..65535") return err("string length must be 1..65535")
} }
DataType.ARRAY -> { DataType.ARRAY -> {
// value may be either a single byte, bitor a byte array // value may be either a single byte, or a byte array
if(value.isArray) { if(value.isArray) {
for (av in value.arrayvalue!!) { for (av in value.arrayvalue!!) {
val number = (av as LiteralValue).intvalue val number = (av as LiteralValue).bytevalue
?: return err("array must be all bytes") ?: return err("array must be all bytes")
val expectedSize = arrayspec?.x?.constValue(namespace)?.intvalue val expectedSize = arrayspec?.x?.constValue(namespace)?.asIntegerValue
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,20 +441,22 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("value '$number' in byte array is out of range for unsigned byte") return err("value '$number' in byte array is out of range for unsigned byte")
} }
} else { } else {
val number = value.intvalue val number = value.bytevalue ?: return if (value.floatvalue!=null)
?: return err("byte integer value expected") err("unsigned byte integer value expected instead of float; possible loss of precision")
else
err("unsigned byte integer value expected")
if (number < 0 || number > 255) if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte") return err("value '$number' out of range for unsigned byte")
} }
} }
DataType.ARRAY_W -> { DataType.ARRAY_W -> {
// value may be either a single word, bitor a word array // value may be either a single word, or a word array
if(value.isArray) { if(value.isArray) {
for (av in value.arrayvalue!!) { for (av in value.arrayvalue!!) {
val number = (av as LiteralValue).intvalue val number = (av as LiteralValue).asIntegerValue // both byte and word are acceptable
?: 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)?.asIntegerValue
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})")
@ -452,21 +464,24 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("value '$number' in word array is out of range for unsigned word") return err("value '$number' in word array is out of range for unsigned word")
} }
} else { } else {
val number = value.intvalue val number = value.asIntegerValue // both byte and word are acceptable
?: return err("word integer value expected") ?: return if (value.floatvalue!=null)
err("unsigned word integer value expected instead of float; possible loss of precision")
else
err("unsigned word integer value expected")
if (number < 0 || number > 65535) if (number < 0 || number > 65535)
return err("value '$number' out of range for unsigned word") return err("value '$number' out of range for unsigned word")
} }
} }
DataType.MATRIX -> { DataType.MATRIX -> {
// value can only be a single byte, bitor a byte array (which represents the matrix) // value can only be a single byte, or a byte array (which represents the matrix)
if(value.isArray) { if(value.isArray) {
for (av in value.arrayvalue!!) { for (av in value.arrayvalue!!) {
val number = (av as LiteralValue).intvalue val number = (av as LiteralValue).bytevalue
?: return err("array must be all bytes") ?: return err("array must be all bytes")
val expectedSizeX = arrayspec!!.x.constValue(namespace)?.intvalue!! val expectedSizeX = arrayspec!!.x.constValue(namespace)?.asIntegerValue!!
val expectedSizeY = arrayspec.y!!.constValue(namespace)?.intvalue!! val expectedSizeY = arrayspec.y!!.constValue(namespace)?.asIntegerValue!!
val expectedSize = expectedSizeX * expectedSizeY val expectedSize = expectedSizeX * expectedSizeY
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})")
@ -475,8 +490,8 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
return err("value '$number' in byte array is out of range for unsigned byte") return err("value '$number' in byte array is out of range for unsigned byte")
} }
} else { } else {
val number = value.intvalue val number = value.bytevalue
?: return err("byte integer value expected") ?: return err("unsigned byte integer value expected")
if (number < 0 || number > 255) if (number < 0 || number > 255)
return err("value '$number' out of range for unsigned byte") return err("value '$number' out of range for unsigned byte")
} }

View File

@ -66,7 +66,7 @@ class DirectedGraph<VT> {
if(recStack[node]==true) return true if(recStack[node]==true) return true
if(visited[node]==true) return false if(visited[node]==true) return false
// mark current node as visited bitand add to recursion stack // mark current node as visited and add to recursion stack
visited[node] = true visited[node] = true
recStack[node] = true recStack[node] = true

View File

@ -4,7 +4,7 @@ class StatementReorderer: IAstProcessor {
// Reorders the statements in a way the compiler needs. // Reorders the statements in a way the compiler needs.
// - 'main' block must be the very first statement. // - 'main' block must be the very first statement.
// - in every scope: // - in every scope:
// -- the directives '%output', '%launcher', '%zeropage', '%address' bitand '%option' will come first. // -- the directives '%output', '%launcher', '%zeropage', '%address' and '%option' will come first.
// -- all vardecls then follow. // -- all vardecls then follow.
// -- the remaining statements then follow in their original order. // -- the remaining statements then follow in their original order.
// - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives. // - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives.

View File

@ -34,8 +34,8 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va
val zero = Mflpt5(0, 0,0,0,0) val zero = Mflpt5(0, 0,0,0,0)
fun fromNumber(num: Number): Mflpt5 { fun fromNumber(num: Number): Mflpt5 {
// see https://en.wikipedia.org/wiki/Microsoft_Binary_Format // see https://en.wikipedia.org/wiki/Microsoft_Binary_Format
// bitand https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a // and https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a
// bitand https://en.wikipedia.org/wiki/IEEE_754-1985 // and https://en.wikipedia.org/wiki/IEEE_754-1985
val flt = num.toDouble() val flt = num.toDouble()
if(flt < FLOAT_MAX_NEGATIVE || flt > FLOAT_MAX_POSITIVE) if(flt < FLOAT_MAX_NEGATIVE || flt > FLOAT_MAX_POSITIVE)
@ -47,12 +47,12 @@ data class Mflpt5(val b0: Short, val b1: Short, val b2: Short, val b3: Short, va
var exponent = 128 + 32 // 128 is cbm's bias, 32 is this algo's bias var exponent = 128 + 32 // 128 is cbm's bias, 32 is this algo's bias
var mantissa = flt.absoluteValue var mantissa = flt.absoluteValue
// if mantissa is too large, shift right bitand adjust exponent // if mantissa is too large, shift right and adjust exponent
while(mantissa >= 0x100000000) { while(mantissa >= 0x100000000) {
mantissa /= 2.0 mantissa /= 2.0
exponent ++ exponent ++
} }
// if mantissa is too small, shift left bitand adjust exponent // if mantissa is too small, shift left and adjust exponent
while(mantissa < 0x80000000) { while(mantissa < 0x80000000) {
mantissa *= 2.0 mantissa *= 2.0
exponent -- exponent --
@ -95,10 +95,10 @@ class Compiler(private val options: CompilationOptions) {
val intermediate = StackVmProgram(module.name) val intermediate = StackVmProgram(module.name)
namespace.debugPrint() namespace.debugPrint()
// create the pool of all variables used in all blocks bitand 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 bitand constants: ${intermediate.variables.size} (${intermediate.variablesMemSize} bytes)") println("Number of allocated variables and constants: ${intermediate.variables.size} (${intermediate.variablesMemSize} bytes)")
val translator = StatementTranslator(intermediate, namespace) val translator = StatementTranslator(intermediate, namespace)
translator.process(module) translator.process(module)
@ -271,14 +271,9 @@ class Compiler(private val options: CompilationOptions) {
val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr") val lv = expr.constValue(namespace) ?: throw CompilerException("constant expression required, not $expr")
when { when {
lv.isString -> stackvmProg.instruction("push \"${lv.strvalue}\"") lv.isString -> stackvmProg.instruction("push \"${lv.strvalue}\"")
lv.isInteger -> { lv.isByte -> stackvmProg.instruction("push b:${lv.bytevalue!!.toString(16)}")
val intval = lv.intvalue!! lv.isWord -> stackvmProg.instruction("push w:${lv.wordvalue!!.toString(16)}")
if(intval<=255) lv.isFloat -> stackvmProg.instruction("push f:${lv.floatvalue}")
stackvmProg.instruction("push b:${intval.toString(16)}")
else if(intval <= 65535)
stackvmProg.instruction("push w:${intval.toString(16)}")
}
lv.isNumeric -> stackvmProg.instruction("push f:${lv.asNumericValue}")
lv.isArray -> { lv.isArray -> {
lv.arrayvalue?.forEach { translate(it) } lv.arrayvalue?.forEach { translate(it) }
stackvmProg.instruction("array w:${lv.arrayvalue!!.size.toString(16)}") stackvmProg.instruction("array w:${lv.arrayvalue!!.size.toString(16)}")
@ -299,9 +294,9 @@ class Compiler(private val options: CompilationOptions) {
"&" -> "bitand" "&" -> "bitand"
"|" -> "bitor" "|" -> "bitor"
"^" -> "bitxor" "^" -> "bitxor"
"bitand" -> "bitand" "and" -> "and"
"bitor" -> "bitor" "or" -> "or"
"bitxor" -> "bitxor" "xor" -> "xor"
"<" -> "less" "<" -> "less"
">" -> "greater" ">" -> "greater"
"<=" -> "lesseq" "<=" -> "lesseq"
@ -450,11 +445,12 @@ class StackVmProgram(val name: String) {
result.add("%variables") result.add("%variables")
for(v in variables) { for(v in variables) {
if (!(v.value.type == VarDeclType.VAR || v.value.type == VarDeclType.CONST)) { if (!(v.value.type == VarDeclType.VAR || v.value.type == VarDeclType.CONST)) {
throw AssertionError("Should be only VAR bitor CONST variables") throw AssertionError("Should be only VAR or CONST variables")
} }
val litval = v.value.value as LiteralValue val litval = v.value.value as LiteralValue
val litvalStr = when { val litvalStr = when {
litval.isInteger -> litval.intvalue!!.toString(16) litval.isByte -> litval.bytevalue!!.toString(16)
litval.isWord -> litval.wordvalue!!.toString(16)
litval.isFloat -> litval.floatvalue.toString() litval.isFloat -> litval.floatvalue.toString()
litval.isString -> "\"${litval.strvalue}\"" litval.isString -> "\"${litval.strvalue}\""
else -> TODO("non-scalar value") else -> TODO("non-scalar value")

View File

@ -56,19 +56,19 @@ class Zeropage(private val options: CompilationOptions) {
if(vardecl.position!=null) if(vardecl.position!=null)
print(vardecl.position) print(vardecl.position)
println(" warning: allocating a large value (array) in zeropage") println(" warning: allocating a large value (array) in zeropage")
val y = (vardecl.arrayspec.y as? LiteralValue)?.intvalue val y = (vardecl.arrayspec.y as? LiteralValue)?.asIntegerValue
if(y==null) { if(y==null) {
// 1 dimensional array // 1 dimensional array
when(vardecl.datatype) { when(vardecl.datatype) {
DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).intvalue!! DataType.BYTE -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!!
DataType.WORD -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * 2 DataType.WORD -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 2
DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).intvalue!! * 5 DataType.FLOAT -> (vardecl.arrayspec.x as LiteralValue).asIntegerValue!! * 5
else -> throw CompilerException("array can only be of byte, word, float") else -> throw CompilerException("array can only be of byte, word, float")
} }
} else { } else {
// 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).asIntegerValue!! * y
else -> throw CompilerException("matrix can only contain bytes") else -> throw CompilerException("matrix can only contain bytes")
} }
} }

View File

@ -23,9 +23,7 @@ private fun oneDoubleArg(args: List<IExpression>, position: Position?, namespace
throw SyntaxError("built-in function requires one floating point argument", position) throw SyntaxError("built-in function requires one floating point argument", position)
val float = constval.asNumericValue?.toDouble()!! val float = constval.asNumericValue?.toDouble()!!
val result = numericLiteral(function(float), args[0].position) return numericLiteral(function(float), args[0].position)
result.position = args[0].position
return result
} }
private fun oneDoubleArgOutputInt(args: List<IExpression>, position: Position?, namespace:INameScope, function: (arg: Double)->Number): LiteralValue { private fun oneDoubleArgOutputInt(args: List<IExpression>, position: Position?, namespace:INameScope, function: (arg: Double)->Number): LiteralValue {
@ -36,9 +34,7 @@ private fun oneDoubleArgOutputInt(args: List<IExpression>, position: Position?,
throw SyntaxError("built-in function requires one floating point argument", position) throw SyntaxError("built-in function requires one floating point argument", position)
val float = constval.asNumericValue?.toDouble()!! val float = constval.asNumericValue?.toDouble()!!
val result = LiteralValue(function(float).toInt()) return numericLiteral(function(float).toInt(), args[0].position)
result.position = args[0].position
return result
} }
private fun oneIntArgOutputInt(args: List<IExpression>, position: Position?, namespace:INameScope, function: (arg: Int)->Number): LiteralValue { private fun oneIntArgOutputInt(args: List<IExpression>, position: Position?, namespace:INameScope, function: (arg: Int)->Number): LiteralValue {
@ -49,9 +45,7 @@ private fun oneIntArgOutputInt(args: List<IExpression>, position: Position?, nam
throw SyntaxError("built-in function requires one integer argument", position) throw SyntaxError("built-in function requires one integer argument", position)
val integer = constval.asNumericValue?.toInt()!! val integer = constval.asNumericValue?.toInt()!!
val result = LiteralValue(function(integer).toInt()) return numericLiteral(function(integer).toInt(), args[0].position)
result.position = args[0].position
return result
} }
private fun collectionArgOutputNumber(args: List<IExpression>, position: Position?, namespace:INameScope, private fun collectionArgOutputNumber(args: List<IExpression>, position: Position?, namespace:INameScope,
@ -65,14 +59,7 @@ private fun collectionArgOutputNumber(args: List<IExpression>, position: Positio
if(constants.contains(null)) if(constants.contains(null))
throw NotConstArgumentException() throw NotConstArgumentException()
val result = function(constants.map { it!!.toDouble() }).toDouble() val result = function(constants.map { it!!.toDouble() }).toDouble()
val value = return numericLiteral(result, args[0].position)
if(result-floor(result) == 0.0) {
LiteralValue(result.toInt())
} else {
LiteralValue(floatvalue = result)
}
value.position = args[0].position
return value
} }
private fun collectionArgOutputBoolean(args: List<IExpression>, position: Position?, namespace:INameScope, private fun collectionArgOutputBoolean(args: List<IExpression>, position: Position?, namespace:INameScope,
@ -86,7 +73,7 @@ private fun collectionArgOutputBoolean(args: List<IExpression>, position: Positi
if(constants.contains(null)) if(constants.contains(null))
throw NotConstArgumentException() throw NotConstArgumentException()
val result = function(constants.map { it?.toDouble()!! }) val result = function(constants.map { it?.toDouble()!! })
return LiteralValue(if(result) 1 else 0) return LiteralValue(bytevalue = if(result) 1 else 0)
} }
fun builtinRound(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue fun builtinRound(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue
@ -132,26 +119,21 @@ fun builtinDeg(args: List<IExpression>, position: Position?, namespace:INameScop
= oneDoubleArg(args, position, namespace, Math::toDegrees) = oneDoubleArg(args, position, namespace, Math::toDegrees)
fun builtinAbs(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue { fun builtinAbs(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue {
// 1 arg, type = float bitor int, result type= same as argument type // 1 arg, type = float or int, result type= same as argument type
if(args.size!=1) if(args.size!=1)
throw SyntaxError("abs requires one numeric argument", position) throw SyntaxError("abs requires one numeric argument", position)
val constval = args[0].constValue(namespace) ?: throw NotConstArgumentException() val constval = args[0].constValue(namespace) ?: throw NotConstArgumentException()
var number = constval.asNumericValue val number = constval.asNumericValue
val result = return when (number) {
if(number is Int || number is Byte || number is Short) { is Int, is Byte, is Short -> numericLiteral(abs(number.toInt()), args[0].position)
number = number.toInt() is Double -> numericLiteral(abs(number.toDouble()), args[0].position)
LiteralValue(intvalue = abs(number)) else -> throw SyntaxError("abs requires one numeric argument", position)
} else if(number is Double) { }
LiteralValue(floatvalue = abs(number.toDouble()))
} else {
throw SyntaxError("abs requires one numeric argument", position)
}
result.position = args[0].position
return result
} }
// todo different functions for byte/word params/results?
fun builtinLsb(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue fun builtinLsb(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue
= oneIntArgOutputInt(args, position, namespace) { x: Int -> x and 255 } = oneIntArgOutputInt(args, position, namespace) { x: Int -> x and 255 }
@ -183,9 +165,7 @@ fun builtinAvg(args: List<IExpression>, position: Position?, namespace:INameScop
if(constants.contains(null)) if(constants.contains(null))
throw NotConstArgumentException() throw NotConstArgumentException()
val result = (constants.map { it!!.toDouble() }).average() val result = (constants.map { it!!.toDouble() }).average()
val value = LiteralValue(floatvalue = result) return numericLiteral(result, args[0].position)
value.position = args[0].position
return value
} }
fun builtinLen(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue { fun builtinLen(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue {
@ -198,9 +178,7 @@ fun builtinLen(args: List<IExpression>, position: Position?, namespace:INameScop
if(constants.contains(null)) if(constants.contains(null))
throw NotConstArgumentException() throw NotConstArgumentException()
val result = (constants.map { it!!.toDouble() }).size val result = (constants.map { it!!.toDouble() }).size
val value = LiteralValue(intvalue = result) return numericLiteral(result, args[0].position)
value.position = args[0].position
return value
} }
fun builtinAny(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue fun builtinAny(args: List<IExpression>, position: Position?, namespace:INameScope): LiteralValue
@ -211,10 +189,17 @@ fun builtinAll(args: List<IExpression>, position: Position?, namespace:INameScop
private fun numericLiteral(value: Number, position: Position?): LiteralValue { private fun numericLiteral(value: Number, position: Position?): LiteralValue {
val result = when(value) { val floatNum=value.toDouble()
is Int -> LiteralValue(intvalue = value.toInt()) val tweakedValue: Number =
is Short -> LiteralValue(intvalue = value.toInt()) if(floatNum==floor(floatNum) && floatNum in -32768..65535)
is Byte -> LiteralValue(intvalue = value.toInt()) floatNum.toInt() // we have an integer disguised as a float.
else
floatNum
val result = when(tweakedValue) {
is Int -> LiteralValue.optimalNumeric(value.toInt())
is Short -> LiteralValue.optimalNumeric(value.toInt())
is Byte -> LiteralValue(bytevalue = value.toShort())
is Double -> LiteralValue(floatvalue = value.toDouble()) is Double -> LiteralValue(floatvalue = value.toDouble())
is Float -> LiteralValue(floatvalue = value.toDouble()) is Float -> LiteralValue(floatvalue = value.toDouble())
else -> throw FatalAstException("invalid number type ${value::class}") else -> throw FatalAstException("invalid number type ${value::class}")

View File

@ -47,7 +47,7 @@ fun Module.optimizeExpressions(globalNamespace: INameScope) {
X ^ 0 -> X X ^ 0 -> X
todo expression optimization: reduce expression nesting / flattening of parenthesis todo expression optimization: reduce expression nesting / flattening of parenthesis
todo expression optimization: simplify logical expression when a term makes it always true bitor false (1 bitor 0) todo expression optimization: simplify logical expression when a term makes it always true or false (1 or 0)
todo expression optimization: optimize some simple multiplications into shifts (A*8 -> A<<3, A/4 -> A>>2) todo expression optimization: optimize some simple multiplications into shifts (A*8 -> A<<3, A/4 -> A>>2)
todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call) todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call)
@ -83,7 +83,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
// vardecl: for float vars, promote constant integer initialization values to floats // vardecl: for float vars, promote constant integer initialization values to floats
val literal = decl.value as? LiteralValue val literal = decl.value as? LiteralValue
if (literal != null && literal.isInteger) { if (literal != null && literal.isInteger) {
val newValue = LiteralValue(floatvalue = literal.intvalue!!.toDouble()) val newValue = LiteralValue(floatvalue = literal.asNumericValue!!.toDouble())
newValue.position = literal.position newValue.position = literal.position
decl.value = newValue decl.value = newValue
} }
@ -93,7 +93,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
val literal = decl.value as? LiteralValue val literal = decl.value as? LiteralValue
if (literal != null && literal.isString && literal.strvalue?.length == 1) { if (literal != null && literal.isString && literal.strvalue?.length == 1) {
val petscii = Petscii.encodePetscii(literal.strvalue)[0] val petscii = Petscii.encodePetscii(literal.strvalue)[0]
val newValue = LiteralValue(petscii.toInt()) val newValue = LiteralValue(bytevalue = petscii)
newValue.position = literal.position newValue.position = literal.position
decl.value = newValue decl.value = newValue
} }
@ -140,31 +140,31 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
val result = when { val result = when {
expr.operator == "+" -> subexpr expr.operator == "+" -> subexpr
expr.operator == "-" -> when { expr.operator == "-" -> when {
subexpr.intvalue != null -> { subexpr.asIntegerValue!= null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = -subexpr.intvalue) LiteralValue.optimalNumeric(-subexpr.asIntegerValue)
} }
subexpr.floatvalue != null -> { subexpr.floatvalue != null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(floatvalue = -subexpr.floatvalue) LiteralValue(floatvalue = -subexpr.floatvalue)
} }
else -> throw ExpressionError("can only take negative of int bitor 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.asIntegerValue != null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = subexpr.intvalue.inv()) LiteralValue.optimalNumeric(subexpr.asIntegerValue.inv())
} }
else -> throw ExpressionError("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.asIntegerValue != null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = if (subexpr.intvalue == 0) 1 else 0) LiteralValue(bytevalue = if (subexpr.asIntegerValue == 0) 1 else 0)
} }
subexpr.floatvalue != null -> { subexpr.floatvalue != null -> {
optimizationsDone++ optimizationsDone++
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0) LiteralValue(bytevalue = if (subexpr.floatvalue == 0.0) 1 else 0)
} }
else -> throw ExpressionError("can not take logical not of $subexpr", subexpr.position) else -> throw ExpressionError("can not take logical not of $subexpr", subexpr.position)
} }
@ -212,14 +212,27 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
val to = range.to.constValue(globalNamespace) val to = range.to.constValue(globalNamespace)
if (from != null && to != null) { if (from != null && to != null) {
when { when {
from.intvalue != null && to.intvalue != null -> { from.isWord || to.isWord -> {
// int range // range on word value boundaries
val rangevalue = from.intvalue.rangeTo(to.intvalue) val rangeValue = from.asIntegerValue!!.rangeTo(to.asIntegerValue!!)
if (rangevalue.last - rangevalue.first > 65535) { if (rangeValue.last - rangeValue.first > 65535) {
throw ExpressionError("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(wordvalue = it)
v.position = range.position
v.parent = range.parent
v
}.toMutableList())
}
from.isByte && to.isByte -> {
// range on byte value boundaries
val rangeValue = from.bytevalue!!.rangeTo(to.bytevalue!!)
if (rangeValue.last - rangeValue.first > 65535) {
throw ExpressionError("amount of values in range exceeds 65535", range.position)
}
return LiteralValue(arrayvalue = rangeValue.map {
val v = LiteralValue(bytevalue = it.toShort())
v.position = range.position v.position = range.position
v.parent = range.parent v.parent = range.parent
v v
@ -236,6 +249,7 @@ class ExpressionOptimizer(private val globalNamespace: INameScope) : IAstProcess
newval.parent = range.parent newval.parent = range.parent
return newval return newval
} }
else -> AstException("range on weird datatype")
} }
} }
return range return range
@ -268,9 +282,9 @@ class ConstExprEvaluator {
"&" -> bitwiseand(left, right) "&" -> bitwiseand(left, right)
"|" -> bitwiseor(left, right) "|" -> bitwiseor(left, right)
"^" -> bitwisexor(left, right) "^" -> bitwisexor(left, right)
"bitand" -> logicaland(left, right) "and" -> logicaland(left, right)
"bitor" -> logicalor(left, right) "or" -> logicalor(left, right)
"bitxor" -> logicalxor(left, right) "xor" -> logicalxor(left, right)
"<" -> compareless(left, right) "<" -> compareless(left, right)
">" -> comparegreater(left, right) ">" -> comparegreater(left, right)
"<=" -> comparelessequal(left, right) "<=" -> comparelessequal(left, right)
@ -283,27 +297,29 @@ class ConstExprEvaluator {
private fun comparenotequal(left: LiteralValue, right: LiteralValue): LiteralValue { private fun comparenotequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = compareequal(left, right) val leq = compareequal(left, right)
val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) val litval = LiteralValue(bytevalue = if (leq.bytevalue == 1.toShort()) 0 else 1)
litval.position = left.position litval.position = left.position
return litval return litval
} }
private fun compareequal(left: LiteralValue, right: LiteralValue): LiteralValue { private fun compareequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val leftvalue: Any = when { val leftvalue: Any = when {
left.intvalue!=null -> left.intvalue left.bytevalue!=null -> left.bytevalue
left.wordvalue!=null -> left.wordvalue
left.floatvalue!=null -> left.floatvalue left.floatvalue!=null -> left.floatvalue
left.strvalue!=null -> left.strvalue left.strvalue!=null -> left.strvalue
left.arrayvalue!=null -> left.arrayvalue left.arrayvalue!=null -> left.arrayvalue
else -> throw FatalAstException("missing literal value") else -> throw FatalAstException("missing literal value")
} }
val rightvalue: Any = when { val rightvalue: Any = when {
right.intvalue!=null -> right.intvalue right.bytevalue!=null -> right.bytevalue
right.wordvalue!=null -> right.wordvalue
right.floatvalue!=null -> right.floatvalue right.floatvalue!=null -> right.floatvalue
right.strvalue!=null -> right.strvalue right.strvalue!=null -> right.strvalue
right.arrayvalue!=null -> right.arrayvalue right.arrayvalue!=null -> right.arrayvalue
else -> throw FatalAstException("missing literal value") else -> throw FatalAstException("missing literal value")
} }
val litval = LiteralValue(intvalue = if (leftvalue == rightvalue) 1 else 0) val litval = LiteralValue(bytevalue = if (leftvalue == rightvalue) 1 else 0)
litval.position = left.position litval.position = left.position
return litval return litval
} }
@ -311,18 +327,18 @@ class ConstExprEvaluator {
private fun comparegreaterequal(left: LiteralValue, right: LiteralValue): LiteralValue { private fun comparegreaterequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left >= $right" val error = "cannot compute $left >= $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.intvalue >= right.intvalue) 1 else 0) bytevalue = if (left.asIntegerValue >= right.asIntegerValue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0) bytevalue = if (left.asIntegerValue >= right.floatvalue) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0) bytevalue = if (left.floatvalue >= right.asIntegerValue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0) bytevalue = if (left.floatvalue >= right.floatvalue) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
@ -334,18 +350,18 @@ class ConstExprEvaluator {
private fun comparelessequal(left: LiteralValue, right: LiteralValue): LiteralValue { private fun comparelessequal(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left >= $right" val error = "cannot compute $left >= $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.intvalue <= right.intvalue) 1 else 0) bytevalue = if (left.asIntegerValue <= right.asIntegerValue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0) bytevalue = if (left.asIntegerValue <= right.floatvalue) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0) bytevalue = if (left.floatvalue <= right.asIntegerValue) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0) bytevalue = if (left.floatvalue <= right.floatvalue) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
@ -356,14 +372,14 @@ class ConstExprEvaluator {
private fun comparegreater(left: LiteralValue, right: LiteralValue): LiteralValue { private fun comparegreater(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = comparelessequal(left, right) val leq = comparelessequal(left, right)
val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) val litval = LiteralValue(bytevalue = if (leq.bytevalue == 1.toShort()) 0 else 1)
litval.position = left.position litval.position = left.position
return litval return litval
} }
private fun compareless(left: LiteralValue, right: LiteralValue): LiteralValue { private fun compareless(left: LiteralValue, right: LiteralValue): LiteralValue {
val leq = comparegreaterequal(left, right) val leq = comparegreaterequal(left, right)
val litval = LiteralValue(intvalue = if (leq.intvalue == 1) 0 else 1) val litval = LiteralValue(bytevalue = if (leq.bytevalue == 1.toShort()) 0 else 1)
litval.position = left.position litval.position = left.position
return litval return litval
} }
@ -371,18 +387,18 @@ class ConstExprEvaluator {
private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue { private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-bitxor $right" val error = "cannot compute $left locical-bitxor $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if ((left.intvalue != 0).xor(right.intvalue != 0)) 1 else 0) bytevalue = if ((left.asIntegerValue != 0).xor(right.asIntegerValue != 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) bytevalue = if ((left.asIntegerValue != 0).xor(right.floatvalue != 0.0)) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if ((left.floatvalue != 0.0).xor(right.intvalue != 0)) 1 else 0) bytevalue = if ((left.floatvalue != 0.0).xor(right.asIntegerValue != 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) bytevalue = if ((left.floatvalue != 0.0).xor(right.floatvalue != 0.0)) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
@ -392,20 +408,20 @@ class ConstExprEvaluator {
} }
private fun logicalor(left: LiteralValue, right: LiteralValue): LiteralValue { private fun logicalor(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-bitor $right" val error = "cannot compute $left locical-or $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 || right.intvalue != 0) 1 else 0) bytevalue = if (left.asIntegerValue != 0 || right.asIntegerValue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 || right.floatvalue != 0.0) 1 else 0) bytevalue = if (left.asIntegerValue != 0 || right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 || right.intvalue != 0) 1 else 0) bytevalue = if (left.floatvalue != 0.0 || right.asIntegerValue != 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) bytevalue = if (left.floatvalue != 0.0 || right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
@ -415,20 +431,20 @@ class ConstExprEvaluator {
} }
private fun logicaland(left: LiteralValue, right: LiteralValue): LiteralValue { private fun logicaland(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot compute $left locical-bitand $right" val error = "cannot compute $left locical-and $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 && right.intvalue != 0) 1 else 0) bytevalue = if (left.asIntegerValue != 0 && right.asIntegerValue != 0) 1 else 0)
right.floatvalue!=null -> LiteralValue( right.floatvalue!=null -> LiteralValue(
intvalue = if (left.intvalue != 0 && right.floatvalue != 0.0) 1 else 0) bytevalue = if (left.asIntegerValue != 0 && right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> LiteralValue( right.asIntegerValue!=null -> LiteralValue(
intvalue = if (left.floatvalue != 0.0 && right.intvalue != 0) 1 else 0) bytevalue = if (left.floatvalue != 0.0 && right.asIntegerValue != 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) bytevalue = if (left.floatvalue != 0.0 && right.floatvalue != 0.0) 1 else 0)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
@ -438,28 +454,52 @@ class ConstExprEvaluator {
} }
private fun bitwisexor(left: LiteralValue, right: LiteralValue): LiteralValue { private fun bitwisexor(left: LiteralValue, right: LiteralValue): LiteralValue {
if(left.intvalue!=null && right.intvalue !=null) { if(left.isByte) {
val litval = LiteralValue(intvalue = left.intvalue.xor(right.intvalue)) if(right.asIntegerValue!=null) {
litval.position = left.position val litval = LiteralValue(bytevalue = (left.bytevalue!!.toInt() xor (right.asIntegerValue and 255)).toShort())
return litval litval.position = left.position
return litval
}
} else if(left.isWord) {
if(right.asIntegerValue!=null) {
val litval = LiteralValue(wordvalue = left.wordvalue!! xor right.asIntegerValue)
litval.position = left.position
return litval
}
} }
throw ExpressionError("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 {
if(left.intvalue!=null && right.intvalue !=null) { if(left.isByte) {
val litval = LiteralValue(intvalue = left.intvalue.or(right.intvalue)) if(right.asIntegerValue!=null) {
litval.position = left.position val litval = LiteralValue(bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort())
return litval litval.position = left.position
return litval
}
} else if(left.isWord) {
if(right.asIntegerValue!=null) {
val litval = LiteralValue(wordvalue = left.wordvalue!! or right.asIntegerValue)
litval.position = left.position
return litval
}
} }
throw ExpressionError("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 {
if(left.intvalue!=null && right.intvalue !=null) { if(left.isByte) {
val litval = LiteralValue(intvalue = left.intvalue.and(right.intvalue)) if(right.asIntegerValue!=null) {
litval.position = left.position val litval = LiteralValue(bytevalue = (left.bytevalue!!.toInt() or (right.asIntegerValue and 255)).toShort())
return litval litval.position = left.position
return litval
}
} else if(left.isWord) {
if(right.asIntegerValue!=null) {
val litval = LiteralValue(wordvalue = left.wordvalue!! or right.asIntegerValue)
litval.position = left.position
return litval
}
} }
throw ExpressionError("cannot calculate $left & $right", left.position) throw ExpressionError("cannot calculate $left & $right", left.position)
} }
@ -467,13 +507,13 @@ class ConstExprEvaluator {
private fun power(left: LiteralValue, right: LiteralValue): LiteralValue { private fun power(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot calculate $left ** $right" val error = "cannot calculate $left ** $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt()) right.asIntegerValue!=null -> LiteralValue(wordvalue = left.asIntegerValue.toDouble().pow(right.asIntegerValue).toInt())
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue)) right.floatvalue!=null -> LiteralValue(floatvalue = left.asIntegerValue.toDouble().pow(right.floatvalue))
else -> throw ExpressionError(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.asIntegerValue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.asIntegerValue))
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue)) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue))
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
@ -484,15 +524,15 @@ class ConstExprEvaluator {
} }
private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue { private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot add $left bitand $right" val error = "cannot add $left and $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue) right.asIntegerValue!=null -> LiteralValue.optimalNumeric(left.asIntegerValue + right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.asIntegerValue + right.floatvalue)
else -> throw ExpressionError(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.asIntegerValue!=null -> LiteralValue(floatvalue = left.floatvalue + right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
@ -503,15 +543,15 @@ class ConstExprEvaluator {
} }
private fun minus(left: LiteralValue, right: LiteralValue): LiteralValue { private fun minus(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot subtract $left bitand $right" val error = "cannot subtract $left and $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue) right.asIntegerValue!=null -> LiteralValue.optimalNumeric(left.asIntegerValue - right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.asIntegerValue - right.floatvalue)
else -> throw ExpressionError(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.asIntegerValue!=null -> LiteralValue(floatvalue = left.floatvalue - right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
@ -522,26 +562,26 @@ class ConstExprEvaluator {
} }
private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue { private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot multiply $left bitand $right" val error = "cannot multiply $left and $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue) right.asIntegerValue!=null -> LiteralValue.optimalNumeric(left.asIntegerValue * right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.asIntegerValue * right.floatvalue)
right.strvalue!=null -> { right.strvalue!=null -> {
if(right.strvalue.length * left.intvalue > 65535) throw ExpressionError("string too large", left.position) if(right.strvalue.length * left.asIntegerValue > 65535) throw ExpressionError("string too large", left.position)
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue)) LiteralValue(strvalue = right.strvalue.repeat(left.asIntegerValue))
} }
else -> throw ExpressionError(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.asIntegerValue!=null -> LiteralValue(floatvalue = left.floatvalue * right.asIntegerValue)
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue) right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue)
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.strvalue!=null -> when { left.strvalue!=null -> when {
right.intvalue!=null -> { right.asIntegerValue!=null -> {
if(left.strvalue.length * right.intvalue > 65535) throw ExpressionError("string too large", left.position) if(left.strvalue.length * right.asIntegerValue > 65535) throw ExpressionError("string too large", left.position)
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue)) LiteralValue(strvalue = left.strvalue.repeat(right.asIntegerValue))
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
@ -554,21 +594,21 @@ class ConstExprEvaluator {
private fun divide(left: LiteralValue, right: LiteralValue): LiteralValue { private fun divide(left: LiteralValue, right: LiteralValue): LiteralValue {
val error = "cannot divide $left by $right" val error = "cannot divide $left by $right"
val litval = when { val litval = when {
left.intvalue!=null -> when { left.asIntegerValue!=null -> when {
right.intvalue!=null -> { right.asIntegerValue!=null -> {
if(right.intvalue==0) throw ExpressionError("attempt to divide by zero", left.position) if(right.asIntegerValue==0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(intvalue = left.intvalue / right.intvalue) LiteralValue.optimalNumeric(left.asIntegerValue / right.asIntegerValue)
} }
right.floatvalue!=null -> { right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionError("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.asIntegerValue / right.floatvalue)
} }
else -> throw ExpressionError(error, left.position) else -> throw ExpressionError(error, left.position)
} }
left.floatvalue!=null -> when { left.floatvalue!=null -> when {
right.intvalue!=null -> { right.asIntegerValue!=null -> {
if(right.intvalue==0) throw ExpressionError("attempt to divide by zero", left.position) if(right.asIntegerValue==0) throw ExpressionError("attempt to divide by zero", left.position)
LiteralValue(floatvalue = left.floatvalue / right.intvalue) LiteralValue(floatvalue = left.floatvalue / right.asIntegerValue)
} }
right.floatvalue!=null -> { right.floatvalue!=null -> {
if(right.floatvalue==0.0) throw ExpressionError("attempt to divide by zero", left.position) if(right.floatvalue==0.0) throw ExpressionError("attempt to divide by zero", left.position)

View File

@ -24,8 +24,8 @@ fun Module.optimizeStatements(globalNamespace: INameScope, allScopedSymbolDefini
todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc todo remove statements that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
todo optimize addition with self into shift 1 (A+=A -> A<<=1) todo optimize addition with self into shift 1 (A+=A -> A<<=1)
todo assignment optimization: optimize some simple multiplications into shifts (A*=8 -> A<<=3) todo assignment optimization: optimize some simple multiplications into shifts (A*=8 -> A<<=3)
todo analyse for unreachable code bitand remove that (f.i. code after goto bitor return that has no label so can never be jumped to) todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
todo merge sequence of assignments into one (as long as the value is a constant bitand the target not a MEMORY type!) todo merge sequence of assignments into one (as long as the value is a constant and the target not a MEMORY type!)
todo report more always true/always false conditions todo report more always true/always false conditions
*/ */

View File

@ -12,11 +12,13 @@ class CommentHandlingTokenStream(lexer: Lexer) : CommonTokenStream(lexer) {
// extract the comments // extract the comments
val commentTokenChannel = il65Lexer.channelNames.indexOf("HIDDEN") val commentTokenChannel = il65Lexer.channelNames.indexOf("HIDDEN")
val theLexer = tokenSource as Lexer val theLexer = tokenSource as Lexer
return get(0, size()) return get(0, size())
.asSequence()
.filter { it.channel == commentTokenChannel } .filter { it.channel == commentTokenChannel }
.map { .map {
Comment(theLexer.vocabulary.getSymbolicName(it.type), Comment(theLexer.vocabulary.getSymbolicName(it.type),
it.line, it.text.substringAfter(';').trim()) it.line, it.text.substringAfter(';').trim())
} }
.toList()
} }
} }

View File

@ -38,9 +38,11 @@ fun importModule(filePath: Path) : Module {
// process imports // process imports
val lines = moduleAst.statements.toMutableList() val lines = moduleAst.statements.toMutableList()
val imports = lines val imports = lines
.asSequence()
.mapIndexed { i, it -> Pair(i, it) } .mapIndexed { i, it -> Pair(i, it) }
.filter { (it.second as? Directive)?.directive == "%import" } .filter { (it.second as? Directive)?.directive == "%import" }
.map { Pair(it.first, executeImportDirective(it.second as Directive, filePath)) } .map { Pair(it.first, executeImportDirective(it.second as Directive, filePath)) }
.toList()
imports.reversed().forEach { imports.reversed().forEach {
if(it.second==null) { if(it.second==null) {

View File

@ -84,17 +84,18 @@ T__82=83
T__83=84 T__83=84
T__84=85 T__84=85
T__85=86 T__85=86
LINECOMMENT=87 T__86=87
COMMENT=88 LINECOMMENT=88
WS=89 COMMENT=89
EOL=90 WS=90
NAME=91 EOL=91
DEC_INTEGER=92 NAME=92
HEX_INTEGER=93 DEC_INTEGER=93
BIN_INTEGER=94 HEX_INTEGER=94
FLOAT_NUMBER=95 BIN_INTEGER=95
STRING=96 FLOAT_NUMBER=96
INLINEASMBLOCK=97 STRING=97
INLINEASMBLOCK=98
'~'=1 '~'=1
':'=2 ':'=2
'goto'=3 'goto'=3
@ -163,21 +164,22 @@ INLINEASMBLOCK=97
'Pz'=66 'Pz'=66
'Pn'=67 'Pn'=67
'Pv'=68 'Pv'=68
'true'=69 '.w'=69
'false'=70 'true'=70
'%asm'=71 'false'=71
'sub'=72 '%asm'=72
'->'=73 'sub'=73
'{'=74 '->'=74
'}'=75 '{'=75
'?'=76 '}'=76
'if'=77 '?'=77
'else'=78 'if'=78
'if_cs'=79 'else'=79
'if_cc'=80 'if_cs'=80
'if_eq'=81 'if_cc'=81
'if_ne'=82 'if_eq'=82
'if_pl'=83 'if_ne'=83
'if_mi'=84 'if_pl'=84
'if_vs'=85 'if_mi'=85
'if_vc'=86 'if_vs'=86
'if_vc'=87

View File

@ -28,9 +28,9 @@ public class il65Lexer extends Lexer {
T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66, T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66,
T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73, T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, T__72=73,
T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80, T__73=74, T__74=75, T__75=76, T__76=77, T__77=78, T__78=79, T__79=80,
T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, LINECOMMENT=87, T__80=81, T__81=82, T__82=83, T__83=84, T__84=85, T__85=86, T__86=87,
COMMENT=88, WS=89, EOL=90, NAME=91, DEC_INTEGER=92, HEX_INTEGER=93, BIN_INTEGER=94, LINECOMMENT=88, COMMENT=89, WS=90, EOL=91, NAME=92, DEC_INTEGER=93, HEX_INTEGER=94,
FLOAT_NUMBER=95, STRING=96, INLINEASMBLOCK=97; BIN_INTEGER=95, FLOAT_NUMBER=96, STRING=97, INLINEASMBLOCK=98;
public static String[] channelNames = { public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN" "DEFAULT_TOKEN_CHANNEL", "HIDDEN"
}; };
@ -50,7 +50,7 @@ public class il65Lexer extends Lexer {
"T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64",
"T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72", "T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "T__72",
"T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80", "T__73", "T__74", "T__75", "T__76", "T__77", "T__78", "T__79", "T__80",
"T__81", "T__82", "T__83", "T__84", "T__85", "LINECOMMENT", "COMMENT", "T__81", "T__82", "T__83", "T__84", "T__85", "T__86", "LINECOMMENT", "COMMENT",
"WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "WS", "EOL", "NAME", "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER",
"FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK" "FNUMBER", "STRING_ESCAPE_SEQ", "STRING", "INLINEASMBLOCK"
}; };
@ -64,7 +64,7 @@ public class il65Lexer extends Lexer {
"'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'", "'<'", "'>'", "'<='", "'('", "')'", "'+'", "'-'", "'**'", "'*'", "'/'", "'<'", "'>'", "'<='",
"'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'and'", "'or'", "'>='", "'=='", "'!='", "'&'", "'^'", "'|'", "'to'", "'and'", "'or'",
"'xor'", "'not'", "'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'", "'xor'", "'not'", "'return'", "'.'", "'A'", "'X'", "'Y'", "'AX'", "'AY'",
"'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'true'", "'false'", "'%asm'", "'XY'", "'Pc'", "'Pz'", "'Pn'", "'Pv'", "'.w'", "'true'", "'false'", "'%asm'",
"'sub'", "'->'", "'{'", "'}'", "'?'", "'if'", "'else'", "'if_cs'", "'if_cc'", "'sub'", "'->'", "'{'", "'}'", "'?'", "'if'", "'else'", "'if_cs'", "'if_cc'",
"'if_eq'", "'if_ne'", "'if_pl'", "'if_mi'", "'if_vs'", "'if_vc'" "'if_eq'", "'if_ne'", "'if_pl'", "'if_mi'", "'if_vs'", "'if_vc'"
}; };
@ -76,8 +76,9 @@ public class il65Lexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME", "DEC_INTEGER", null, null, null, null, "LINECOMMENT", "COMMENT", "WS", "EOL", "NAME",
"HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING", "INLINEASMBLOCK" "DEC_INTEGER", "HEX_INTEGER", "BIN_INTEGER", "FLOAT_NUMBER", "STRING",
"INLINEASMBLOCK"
}; };
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@ -139,10 +140,10 @@ public class il65Lexer extends Lexer {
@Override @Override
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) { public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
switch (ruleIndex) { switch (ruleIndex) {
case 97: case 98:
STRING_action((RuleContext)_localctx, actionIndex); STRING_action((RuleContext)_localctx, actionIndex);
break; break;
case 98: case 99:
INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex); INLINEASMBLOCK_action((RuleContext)_localctx, actionIndex);
break; break;
} }
@ -171,7 +172,7 @@ public class il65Lexer extends Lexer {
} }
public static final String _serializedATN = public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2c\u02a1\b\1\4\2\t"+ "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2d\u02a6\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@ -182,218 +183,220 @@ public class il65Lexer extends Lexer {
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+ "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+ "\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+ "\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\4b\tb\4c\tc\4d\td\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\5\3"+ "`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\3\2\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4"+
"\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\7"+ "\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3\6\3"+
"\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+ "\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+
"\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ "\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3"+
"\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3"+ "\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3\13\3"+
"\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3"+ "\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3"+
"\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21"+ "\r\3\r\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\21"+
"\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23"+ "\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23"+
"\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26"+ "\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26"+
"\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30"+ "\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30"+
"\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35"+ "\3\30\3\30\3\30\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35"+
"\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3\""+ "\3\35\3\35\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3"+
"\3#\3#\3#\3$\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3)\3*\3*\3+\3+\3,\3"+ "\"\3\"\3#\3#\3#\3$\3$\3$\3%\3%\3&\3&\3\'\3\'\3(\3(\3)\3)\3)\3*\3*\3+\3"+
",\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61\3\62\3\62\3\63"+ "+\3,\3,\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61\3\62\3\62"+
"\3\63\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\67\3\67\3\67\38\3"+ "\3\63\3\63\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\67\3\67\3\67"+
"8\38\38\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3;\3;\3<\3<\3=\3=\3>\3>\3?\3"+ "\38\38\38\38\39\39\39\39\3:\3:\3:\3:\3:\3:\3:\3;\3;\3<\3<\3=\3=\3>\3>"+
"?\3?\3@\3@\3@\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F\3F\3"+ "\3?\3?\3?\3@\3@\3@\3A\3A\3A\3B\3B\3B\3C\3C\3C\3D\3D\3D\3E\3E\3E\3F\3F"+
"F\3F\3G\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3I\3I\3I\3I\3J\3J\3J\3K\3K\3L\3"+ "\3F\3G\3G\3G\3G\3G\3H\3H\3H\3H\3H\3H\3I\3I\3I\3I\3I\3J\3J\3J\3J\3K\3K"+
"L\3M\3M\3N\3N\3N\3O\3O\3O\3O\3O\3P\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3"+ "\3K\3L\3L\3M\3M\3N\3N\3O\3O\3O\3P\3P\3P\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3R\3R"+
"R\3R\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3"+ "\3R\3R\3R\3R\3S\3S\3S\3S\3S\3S\3T\3T\3T\3T\3T\3T\3U\3U\3U\3U\3U\3U\3V"+
"U\3V\3V\3V\3V\3V\3V\3W\3W\3W\3W\3W\3W\3X\3X\7X\u0238\nX\fX\16X\u023b\13"+ "\3V\3V\3V\3V\3V\3W\3W\3W\3W\3W\3W\3X\3X\3X\3X\3X\3X\3Y\3Y\7Y\u023d\nY"+
"X\3X\3X\3X\3X\3Y\3Y\7Y\u0243\nY\fY\16Y\u0246\13Y\3Y\3Y\3Z\3Z\3Z\3Z\3["+ "\fY\16Y\u0240\13Y\3Y\3Y\3Y\3Y\3Z\3Z\7Z\u0248\nZ\fZ\16Z\u024b\13Z\3Z\3"+
"\6[\u024f\n[\r[\16[\u0250\3\\\3\\\7\\\u0255\n\\\f\\\16\\\u0258\13\\\3"+ "Z\3[\3[\3[\3[\3\\\6\\\u0254\n\\\r\\\16\\\u0255\3]\3]\7]\u025a\n]\f]\16"+
"]\3]\3]\6]\u025d\n]\r]\16]\u025e\5]\u0261\n]\3^\3^\6^\u0265\n^\r^\16^"+ "]\u025d\13]\3^\3^\3^\6^\u0262\n^\r^\16^\u0263\5^\u0266\n^\3_\3_\6_\u026a"+
"\u0266\3_\3_\6_\u026b\n_\r_\16_\u026c\3`\3`\3`\5`\u0272\n`\3`\5`\u0275"+ "\n_\r_\16_\u026b\3`\3`\6`\u0270\n`\r`\16`\u0271\3a\3a\3a\5a\u0277\na\3"+
"\n`\3a\6a\u0278\na\ra\16a\u0279\3a\3a\6a\u027e\na\ra\16a\u027f\5a\u0282"+ "a\5a\u027a\na\3b\6b\u027d\nb\rb\16b\u027e\3b\3b\6b\u0283\nb\rb\16b\u0284"+
"\na\3b\3b\3b\3b\5b\u0288\nb\3c\3c\3c\7c\u028d\nc\fc\16c\u0290\13c\3c\3"+ "\5b\u0287\nb\3c\3c\3c\3c\5c\u028d\nc\3d\3d\3d\7d\u0292\nd\fd\16d\u0295"+
"c\3c\3d\3d\3d\3d\6d\u0299\nd\rd\16d\u029a\3d\3d\3d\3d\3d\3\u029a\2e\3"+ "\13d\3d\3d\3d\3e\3e\3e\3e\6e\u029e\ne\re\16e\u029f\3e\3e\3e\3e\3e\3\u029f"+
"\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37"+ "\2f\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35"+
"\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37="+ "\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36"+
" ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67m8o9"+ ";\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65i\66k\67"+
"q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008dH\u008f"+ "m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F\u008bG\u008d"+
"I\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1R\u00a3"+ "H\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009bO\u009dP\u009fQ\u00a1"+
"S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5\\\u00b7"+ "R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00afY\u00b1Z\u00b3[\u00b5"+
"]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1\2\u00c3\2\u00c5b\u00c7c\3\2\n\4\2"+ "\\\u00b7]\u00b9^\u00bb_\u00bd`\u00bfa\u00c1b\u00c3\2\u00c5\2\u00c7c\u00c9"+
"\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;CHch\4\2GGg"+ "d\3\2\n\4\2\f\f\17\17\4\2\13\13\"\"\5\2C\\aac|\6\2\62;C\\aac|\5\2\62;"+
"g\4\2--//\6\2\f\f\16\17$$^^\2\u02af\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2"+ "CHch\4\2GGgg\4\2--//\6\2\f\f\16\17$$^^\2\u02b4\2\3\3\2\2\2\2\5\3\2\2\2"+
"\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23"+ "\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3"+
"\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2"+ "\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2"+
"\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2"+ "\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2"+
"\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3"+ "\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2"+
"\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2"+ "\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2"+
"\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2"+ "\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2"+
"\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2["+ "\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y"+
"\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2"+ "\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2"+
"\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2"+ "\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2"+
"\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2"+ "\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177"+
"\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089"+ "\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2"+
"\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2"+ "\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091"+
"\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b"+ "\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2"+
"\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2"+ "\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3"+
"\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad"+ "\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2"+
"\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5\3\2\2"+ "\2\2\u00ad\3\2\2\2\2\u00af\3\2\2\2\2\u00b1\3\2\2\2\2\u00b3\3\2\2\2\2\u00b5"+
"\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf"+ "\3\2\2\2\2\u00b7\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2\2\2\u00bd\3\2\2"+
"\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\3\u00c9\3\2\2\2\5\u00cb\3\2\2"+ "\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\3\u00cb"+
"\2\7\u00cd\3\2\2\2\t\u00d2\3\2\2\2\13\u00da\3\2\2\2\r\u00e4\3\2\2\2\17"+ "\3\2\2\2\5\u00cd\3\2\2\2\7\u00cf\3\2\2\2\t\u00d4\3\2\2\2\13\u00dc\3\2"+
"\u00ee\3\2\2\2\21\u00f7\3\2\2\2\23\u00ff\3\2\2\2\25\u010b\3\2\2\2\27\u0117"+ "\2\2\r\u00e6\3\2\2\2\17\u00f0\3\2\2\2\21\u00f9\3\2\2\2\23\u0101\3\2\2"+
"\3\2\2\2\31\u0122\3\2\2\2\33\u012a\3\2\2\2\35\u012c\3\2\2\2\37\u012e\3"+ "\2\25\u010d\3\2\2\2\27\u0119\3\2\2\2\31\u0124\3\2\2\2\33\u012c\3\2\2\2"+
"\2\2\2!\u0134\3\2\2\2#\u013b\3\2\2\2%\u0140\3\2\2\2\'\u0145\3\2\2\2)\u014b"+ "\35\u012e\3\2\2\2\37\u0130\3\2\2\2!\u0136\3\2\2\2#\u013d\3\2\2\2%\u0142"+
"\3\2\2\2+\u014f\3\2\2\2-\u0155\3\2\2\2/\u015b\3\2\2\2\61\u0162\3\2\2\2"+ "\3\2\2\2\'\u0147\3\2\2\2)\u014d\3\2\2\2+\u0151\3\2\2\2-\u0157\3\2\2\2"+
"\63\u0164\3\2\2\2\65\u0166\3\2\2\2\67\u0169\3\2\2\29\u016c\3\2\2\2;\u016f"+ "/\u015d\3\2\2\2\61\u0164\3\2\2\2\63\u0166\3\2\2\2\65\u0168\3\2\2\2\67"+
"\3\2\2\2=\u0172\3\2\2\2?\u0176\3\2\2\2A\u0179\3\2\2\2C\u017c\3\2\2\2E"+ "\u016b\3\2\2\29\u016e\3\2\2\2;\u0171\3\2\2\2=\u0174\3\2\2\2?\u0178\3\2"+
"\u017f\3\2\2\2G\u0182\3\2\2\2I\u0185\3\2\2\2K\u0187\3\2\2\2M\u0189\3\2"+ "\2\2A\u017b\3\2\2\2C\u017e\3\2\2\2E\u0181\3\2\2\2G\u0184\3\2\2\2I\u0187"+
"\2\2O\u018b\3\2\2\2Q\u018d\3\2\2\2S\u0190\3\2\2\2U\u0192\3\2\2\2W\u0194"+ "\3\2\2\2K\u0189\3\2\2\2M\u018b\3\2\2\2O\u018d\3\2\2\2Q\u018f\3\2\2\2S"+
"\3\2\2\2Y\u0196\3\2\2\2[\u0198\3\2\2\2]\u019b\3\2\2\2_\u019e\3\2\2\2a"+ "\u0192\3\2\2\2U\u0194\3\2\2\2W\u0196\3\2\2\2Y\u0198\3\2\2\2[\u019a\3\2"+
"\u01a1\3\2\2\2c\u01a4\3\2\2\2e\u01a6\3\2\2\2g\u01a8\3\2\2\2i\u01aa\3\2"+ "\2\2]\u019d\3\2\2\2_\u01a0\3\2\2\2a\u01a3\3\2\2\2c\u01a6\3\2\2\2e\u01a8"+
"\2\2k\u01ad\3\2\2\2m\u01b1\3\2\2\2o\u01b4\3\2\2\2q\u01b8\3\2\2\2s\u01bc"+ "\3\2\2\2g\u01aa\3\2\2\2i\u01ac\3\2\2\2k\u01af\3\2\2\2m\u01b3\3\2\2\2o"+
"\3\2\2\2u\u01c3\3\2\2\2w\u01c5\3\2\2\2y\u01c7\3\2\2\2{\u01c9\3\2\2\2}"+ "\u01b6\3\2\2\2q\u01ba\3\2\2\2s\u01be\3\2\2\2u\u01c5\3\2\2\2w\u01c7\3\2"+
"\u01cb\3\2\2\2\177\u01ce\3\2\2\2\u0081\u01d1\3\2\2\2\u0083\u01d4\3\2\2"+ "\2\2y\u01c9\3\2\2\2{\u01cb\3\2\2\2}\u01cd\3\2\2\2\177\u01d0\3\2\2\2\u0081"+
"\2\u0085\u01d7\3\2\2\2\u0087\u01da\3\2\2\2\u0089\u01dd\3\2\2\2\u008b\u01e0"+ "\u01d3\3\2\2\2\u0083\u01d6\3\2\2\2\u0085\u01d9\3\2\2\2\u0087\u01dc\3\2"+
"\3\2\2\2\u008d\u01e5\3\2\2\2\u008f\u01eb\3\2\2\2\u0091\u01f0\3\2\2\2\u0093"+ "\2\2\u0089\u01df\3\2\2\2\u008b\u01e2\3\2\2\2\u008d\u01e5\3\2\2\2\u008f"+
"\u01f4\3\2\2\2\u0095\u01f7\3\2\2\2\u0097\u01f9\3\2\2\2\u0099\u01fb\3\2"+ "\u01ea\3\2\2\2\u0091\u01f0\3\2\2\2\u0093\u01f5\3\2\2\2\u0095\u01f9\3\2"+
"\2\2\u009b\u01fd\3\2\2\2\u009d\u0200\3\2\2\2\u009f\u0205\3\2\2\2\u00a1"+ "\2\2\u0097\u01fc\3\2\2\2\u0099\u01fe\3\2\2\2\u009b\u0200\3\2\2\2\u009d"+
"\u020b\3\2\2\2\u00a3\u0211\3\2\2\2\u00a5\u0217\3\2\2\2\u00a7\u021d\3\2"+ "\u0202\3\2\2\2\u009f\u0205\3\2\2\2\u00a1\u020a\3\2\2\2\u00a3\u0210\3\2"+
"\2\2\u00a9\u0223\3\2\2\2\u00ab\u0229\3\2\2\2\u00ad\u022f\3\2\2\2\u00af"+ "\2\2\u00a5\u0216\3\2\2\2\u00a7\u021c\3\2\2\2\u00a9\u0222\3\2\2\2\u00ab"+
"\u0235\3\2\2\2\u00b1\u0240\3\2\2\2\u00b3\u0249\3\2\2\2\u00b5\u024e\3\2"+ "\u0228\3\2\2\2\u00ad\u022e\3\2\2\2\u00af\u0234\3\2\2\2\u00b1\u023a\3\2"+
"\2\2\u00b7\u0252\3\2\2\2\u00b9\u0260\3\2\2\2\u00bb\u0262\3\2\2\2\u00bd"+ "\2\2\u00b3\u0245\3\2\2\2\u00b5\u024e\3\2\2\2\u00b7\u0253\3\2\2\2\u00b9"+
"\u0268\3\2\2\2\u00bf\u026e\3\2\2\2\u00c1\u0277\3\2\2\2\u00c3\u0287\3\2"+ "\u0257\3\2\2\2\u00bb\u0265\3\2\2\2\u00bd\u0267\3\2\2\2\u00bf\u026d\3\2"+
"\2\2\u00c5\u0289\3\2\2\2\u00c7\u0294\3\2\2\2\u00c9\u00ca\7\u0080\2\2\u00ca"+ "\2\2\u00c1\u0273\3\2\2\2\u00c3\u027c\3\2\2\2\u00c5\u028c\3\2\2\2\u00c7"+
"\4\3\2\2\2\u00cb\u00cc\7<\2\2\u00cc\6\3\2\2\2\u00cd\u00ce\7i\2\2\u00ce"+ "\u028e\3\2\2\2\u00c9\u0299\3\2\2\2\u00cb\u00cc\7\u0080\2\2\u00cc\4\3\2"+
"\u00cf\7q\2\2\u00cf\u00d0\7v\2\2\u00d0\u00d1\7q\2\2\u00d1\b\3\2\2\2\u00d2"+ "\2\2\u00cd\u00ce\7<\2\2\u00ce\6\3\2\2\2\u00cf\u00d0\7i\2\2\u00d0\u00d1"+
"\u00d3\7\'\2\2\u00d3\u00d4\7q\2\2\u00d4\u00d5\7w\2\2\u00d5\u00d6\7v\2"+ "\7q\2\2\u00d1\u00d2\7v\2\2\u00d2\u00d3\7q\2\2\u00d3\b\3\2\2\2\u00d4\u00d5"+
"\2\u00d6\u00d7\7r\2\2\u00d7\u00d8\7w\2\2\u00d8\u00d9\7v\2\2\u00d9\n\3"+ "\7\'\2\2\u00d5\u00d6\7q\2\2\u00d6\u00d7\7w\2\2\u00d7\u00d8\7v\2\2\u00d8"+
"\2\2\2\u00da\u00db\7\'\2\2\u00db\u00dc\7n\2\2\u00dc\u00dd\7c\2\2\u00dd"+ "\u00d9\7r\2\2\u00d9\u00da\7w\2\2\u00da\u00db\7v\2\2\u00db\n\3\2\2\2\u00dc"+
"\u00de\7w\2\2\u00de\u00df\7p\2\2\u00df\u00e0\7e\2\2\u00e0\u00e1\7j\2\2"+ "\u00dd\7\'\2\2\u00dd\u00de\7n\2\2\u00de\u00df\7c\2\2\u00df\u00e0\7w\2"+
"\u00e1\u00e2\7g\2\2\u00e2\u00e3\7t\2\2\u00e3\f\3\2\2\2\u00e4\u00e5\7\'"+ "\2\u00e0\u00e1\7p\2\2\u00e1\u00e2\7e\2\2\u00e2\u00e3\7j\2\2\u00e3\u00e4"+
"\2\2\u00e5\u00e6\7|\2\2\u00e6\u00e7\7g\2\2\u00e7\u00e8\7t\2\2\u00e8\u00e9"+ "\7g\2\2\u00e4\u00e5\7t\2\2\u00e5\f\3\2\2\2\u00e6\u00e7\7\'\2\2\u00e7\u00e8"+
"\7q\2\2\u00e9\u00ea\7r\2\2\u00ea\u00eb\7c\2\2\u00eb\u00ec\7i\2\2\u00ec"+ "\7|\2\2\u00e8\u00e9\7g\2\2\u00e9\u00ea\7t\2\2\u00ea\u00eb\7q\2\2\u00eb"+
"\u00ed\7g\2\2\u00ed\16\3\2\2\2\u00ee\u00ef\7\'\2\2\u00ef\u00f0\7c\2\2"+ "\u00ec\7r\2\2\u00ec\u00ed\7c\2\2\u00ed\u00ee\7i\2\2\u00ee\u00ef\7g\2\2"+
"\u00f0\u00f1\7f\2\2\u00f1\u00f2\7f\2\2\u00f2\u00f3\7t\2\2\u00f3\u00f4"+ "\u00ef\16\3\2\2\2\u00f0\u00f1\7\'\2\2\u00f1\u00f2\7c\2\2\u00f2\u00f3\7"+
"\7g\2\2\u00f4\u00f5\7u\2\2\u00f5\u00f6\7u\2\2\u00f6\20\3\2\2\2\u00f7\u00f8"+ "f\2\2\u00f3\u00f4\7f\2\2\u00f4\u00f5\7t\2\2\u00f5\u00f6\7g\2\2\u00f6\u00f7"+
"\7\'\2\2\u00f8\u00f9\7k\2\2\u00f9\u00fa\7o\2\2\u00fa\u00fb\7r\2\2\u00fb"+ "\7u\2\2\u00f7\u00f8\7u\2\2\u00f8\20\3\2\2\2\u00f9\u00fa\7\'\2\2\u00fa"+
"\u00fc\7q\2\2\u00fc\u00fd\7t\2\2\u00fd\u00fe\7v\2\2\u00fe\22\3\2\2\2\u00ff"+ "\u00fb\7k\2\2\u00fb\u00fc\7o\2\2\u00fc\u00fd\7r\2\2\u00fd\u00fe\7q\2\2"+
"\u0100\7\'\2\2\u0100\u0101\7d\2\2\u0101\u0102\7t\2\2\u0102\u0103\7g\2"+ "\u00fe\u00ff\7t\2\2\u00ff\u0100\7v\2\2\u0100\22\3\2\2\2\u0101\u0102\7"+
"\2\u0103\u0104\7c\2\2\u0104\u0105\7m\2\2\u0105\u0106\7r\2\2\u0106\u0107"+ "\'\2\2\u0102\u0103\7d\2\2\u0103\u0104\7t\2\2\u0104\u0105\7g\2\2\u0105"+
"\7q\2\2\u0107\u0108\7k\2\2\u0108\u0109\7p\2\2\u0109\u010a\7v\2\2\u010a"+ "\u0106\7c\2\2\u0106\u0107\7m\2\2\u0107\u0108\7r\2\2\u0108\u0109\7q\2\2"+
"\24\3\2\2\2\u010b\u010c\7\'\2\2\u010c\u010d\7c\2\2\u010d\u010e\7u\2\2"+ "\u0109\u010a\7k\2\2\u010a\u010b\7p\2\2\u010b\u010c\7v\2\2\u010c\24\3\2"+
"\u010e\u010f\7o\2\2\u010f\u0110\7k\2\2\u0110\u0111\7p\2\2\u0111\u0112"+ "\2\2\u010d\u010e\7\'\2\2\u010e\u010f\7c\2\2\u010f\u0110\7u\2\2\u0110\u0111"+
"\7e\2\2\u0112\u0113\7n\2\2\u0113\u0114\7w\2\2\u0114\u0115\7f\2\2\u0115"+ "\7o\2\2\u0111\u0112\7k\2\2\u0112\u0113\7p\2\2\u0113\u0114\7e\2\2\u0114"+
"\u0116\7g\2\2\u0116\26\3\2\2\2\u0117\u0118\7\'\2\2\u0118\u0119\7c\2\2"+ "\u0115\7n\2\2\u0115\u0116\7w\2\2\u0116\u0117\7f\2\2\u0117\u0118\7g\2\2"+
"\u0119\u011a\7u\2\2\u011a\u011b\7o\2\2\u011b\u011c\7d\2\2\u011c\u011d"+ "\u0118\26\3\2\2\2\u0119\u011a\7\'\2\2\u011a\u011b\7c\2\2\u011b\u011c\7"+
"\7k\2\2\u011d\u011e\7p\2\2\u011e\u011f\7c\2\2\u011f\u0120\7t\2\2\u0120"+ "u\2\2\u011c\u011d\7o\2\2\u011d\u011e\7d\2\2\u011e\u011f\7k\2\2\u011f\u0120"+
"\u0121\7{\2\2\u0121\30\3\2\2\2\u0122\u0123\7\'\2\2\u0123\u0124\7q\2\2"+ "\7p\2\2\u0120\u0121\7c\2\2\u0121\u0122\7t\2\2\u0122\u0123\7{\2\2\u0123"+
"\u0124\u0125\7r\2\2\u0125\u0126\7v\2\2\u0126\u0127\7k\2\2\u0127\u0128"+ "\30\3\2\2\2\u0124\u0125\7\'\2\2\u0125\u0126\7q\2\2\u0126\u0127\7r\2\2"+
"\7q\2\2\u0128\u0129\7p\2\2\u0129\32\3\2\2\2\u012a\u012b\7.\2\2\u012b\34"+ "\u0127\u0128\7v\2\2\u0128\u0129\7k\2\2\u0129\u012a\7q\2\2\u012a\u012b"+
"\3\2\2\2\u012c\u012d\7?\2\2\u012d\36\3\2\2\2\u012e\u012f\7e\2\2\u012f"+ "\7p\2\2\u012b\32\3\2\2\2\u012c\u012d\7.\2\2\u012d\34\3\2\2\2\u012e\u012f"+
"\u0130\7q\2\2\u0130\u0131\7p\2\2\u0131\u0132\7u\2\2\u0132\u0133\7v\2\2"+ "\7?\2\2\u012f\36\3\2\2\2\u0130\u0131\7e\2\2\u0131\u0132\7q\2\2\u0132\u0133"+
"\u0133 \3\2\2\2\u0134\u0135\7o\2\2\u0135\u0136\7g\2\2\u0136\u0137\7o\2"+ "\7p\2\2\u0133\u0134\7u\2\2\u0134\u0135\7v\2\2\u0135 \3\2\2\2\u0136\u0137"+
"\2\u0137\u0138\7q\2\2\u0138\u0139\7t\2\2\u0139\u013a\7{\2\2\u013a\"\3"+ "\7o\2\2\u0137\u0138\7g\2\2\u0138\u0139\7o\2\2\u0139\u013a\7q\2\2\u013a"+
"\2\2\2\u013b\u013c\7d\2\2\u013c\u013d\7{\2\2\u013d\u013e\7v\2\2\u013e"+ "\u013b\7t\2\2\u013b\u013c\7{\2\2\u013c\"\3\2\2\2\u013d\u013e\7d\2\2\u013e"+
"\u013f\7g\2\2\u013f$\3\2\2\2\u0140\u0141\7y\2\2\u0141\u0142\7q\2\2\u0142"+ "\u013f\7{\2\2\u013f\u0140\7v\2\2\u0140\u0141\7g\2\2\u0141$\3\2\2\2\u0142"+
"\u0143\7t\2\2\u0143\u0144\7f\2\2\u0144&\3\2\2\2\u0145\u0146\7h\2\2\u0146"+ "\u0143\7y\2\2\u0143\u0144\7q\2\2\u0144\u0145\7t\2\2\u0145\u0146\7f\2\2"+
"\u0147\7n\2\2\u0147\u0148\7q\2\2\u0148\u0149\7c\2\2\u0149\u014a\7v\2\2"+ "\u0146&\3\2\2\2\u0147\u0148\7h\2\2\u0148\u0149\7n\2\2\u0149\u014a\7q\2"+
"\u014a(\3\2\2\2\u014b\u014c\7u\2\2\u014c\u014d\7v\2\2\u014d\u014e\7t\2"+ "\2\u014a\u014b\7c\2\2\u014b\u014c\7v\2\2\u014c(\3\2\2\2\u014d\u014e\7"+
"\2\u014e*\3\2\2\2\u014f\u0150\7u\2\2\u0150\u0151\7v\2\2\u0151\u0152\7"+ "u\2\2\u014e\u014f\7v\2\2\u014f\u0150\7t\2\2\u0150*\3\2\2\2\u0151\u0152"+
"t\2\2\u0152\u0153\7a\2\2\u0153\u0154\7r\2\2\u0154,\3\2\2\2\u0155\u0156"+ "\7u\2\2\u0152\u0153\7v\2\2\u0153\u0154\7t\2\2\u0154\u0155\7a\2\2\u0155"+
"\7u\2\2\u0156\u0157\7v\2\2\u0157\u0158\7t\2\2\u0158\u0159\7a\2\2\u0159"+ "\u0156\7r\2\2\u0156,\3\2\2\2\u0157\u0158\7u\2\2\u0158\u0159\7v\2\2\u0159"+
"\u015a\7u\2\2\u015a.\3\2\2\2\u015b\u015c\7u\2\2\u015c\u015d\7v\2\2\u015d"+ "\u015a\7t\2\2\u015a\u015b\7a\2\2\u015b\u015c\7u\2\2\u015c.\3\2\2\2\u015d"+
"\u015e\7t\2\2\u015e\u015f\7a\2\2\u015f\u0160\7r\2\2\u0160\u0161\7u\2\2"+ "\u015e\7u\2\2\u015e\u015f\7v\2\2\u015f\u0160\7t\2\2\u0160\u0161\7a\2\2"+
"\u0161\60\3\2\2\2\u0162\u0163\7]\2\2\u0163\62\3\2\2\2\u0164\u0165\7_\2"+ "\u0161\u0162\7r\2\2\u0162\u0163\7u\2\2\u0163\60\3\2\2\2\u0164\u0165\7"+
"\2\u0165\64\3\2\2\2\u0166\u0167\7-\2\2\u0167\u0168\7?\2\2\u0168\66\3\2"+ "]\2\2\u0165\62\3\2\2\2\u0166\u0167\7_\2\2\u0167\64\3\2\2\2\u0168\u0169"+
"\2\2\u0169\u016a\7/\2\2\u016a\u016b\7?\2\2\u016b8\3\2\2\2\u016c\u016d"+ "\7-\2\2\u0169\u016a\7?\2\2\u016a\66\3\2\2\2\u016b\u016c\7/\2\2\u016c\u016d"+
"\7\61\2\2\u016d\u016e\7?\2\2\u016e:\3\2\2\2\u016f\u0170\7,\2\2\u0170\u0171"+ "\7?\2\2\u016d8\3\2\2\2\u016e\u016f\7\61\2\2\u016f\u0170\7?\2\2\u0170:"+
"\7?\2\2\u0171<\3\2\2\2\u0172\u0173\7,\2\2\u0173\u0174\7,\2\2\u0174\u0175"+ "\3\2\2\2\u0171\u0172\7,\2\2\u0172\u0173\7?\2\2\u0173<\3\2\2\2\u0174\u0175"+
"\7?\2\2\u0175>\3\2\2\2\u0176\u0177\7(\2\2\u0177\u0178\7?\2\2\u0178@\3"+ "\7,\2\2\u0175\u0176\7,\2\2\u0176\u0177\7?\2\2\u0177>\3\2\2\2\u0178\u0179"+
"\2\2\2\u0179\u017a\7~\2\2\u017a\u017b\7?\2\2\u017bB\3\2\2\2\u017c\u017d"+ "\7(\2\2\u0179\u017a\7?\2\2\u017a@\3\2\2\2\u017b\u017c\7~\2\2\u017c\u017d"+
"\7`\2\2\u017d\u017e\7?\2\2\u017eD\3\2\2\2\u017f\u0180\7-\2\2\u0180\u0181"+ "\7?\2\2\u017dB\3\2\2\2\u017e\u017f\7`\2\2\u017f\u0180\7?\2\2\u0180D\3"+
"\7-\2\2\u0181F\3\2\2\2\u0182\u0183\7/\2\2\u0183\u0184\7/\2\2\u0184H\3"+ "\2\2\2\u0181\u0182\7-\2\2\u0182\u0183\7-\2\2\u0183F\3\2\2\2\u0184\u0185"+
"\2\2\2\u0185\u0186\7*\2\2\u0186J\3\2\2\2\u0187\u0188\7+\2\2\u0188L\3\2"+ "\7/\2\2\u0185\u0186\7/\2\2\u0186H\3\2\2\2\u0187\u0188\7*\2\2\u0188J\3"+
"\2\2\u0189\u018a\7-\2\2\u018aN\3\2\2\2\u018b\u018c\7/\2\2\u018cP\3\2\2"+ "\2\2\2\u0189\u018a\7+\2\2\u018aL\3\2\2\2\u018b\u018c\7-\2\2\u018cN\3\2"+
"\2\u018d\u018e\7,\2\2\u018e\u018f\7,\2\2\u018fR\3\2\2\2\u0190\u0191\7"+ "\2\2\u018d\u018e\7/\2\2\u018eP\3\2\2\2\u018f\u0190\7,\2\2\u0190\u0191"+
",\2\2\u0191T\3\2\2\2\u0192\u0193\7\61\2\2\u0193V\3\2\2\2\u0194\u0195\7"+ "\7,\2\2\u0191R\3\2\2\2\u0192\u0193\7,\2\2\u0193T\3\2\2\2\u0194\u0195\7"+
">\2\2\u0195X\3\2\2\2\u0196\u0197\7@\2\2\u0197Z\3\2\2\2\u0198\u0199\7>"+ "\61\2\2\u0195V\3\2\2\2\u0196\u0197\7>\2\2\u0197X\3\2\2\2\u0198\u0199\7"+
"\2\2\u0199\u019a\7?\2\2\u019a\\\3\2\2\2\u019b\u019c\7@\2\2\u019c\u019d"+ "@\2\2\u0199Z\3\2\2\2\u019a\u019b\7>\2\2\u019b\u019c\7?\2\2\u019c\\\3\2"+
"\7?\2\2\u019d^\3\2\2\2\u019e\u019f\7?\2\2\u019f\u01a0\7?\2\2\u01a0`\3"+ "\2\2\u019d\u019e\7@\2\2\u019e\u019f\7?\2\2\u019f^\3\2\2\2\u01a0\u01a1"+
"\2\2\2\u01a1\u01a2\7#\2\2\u01a2\u01a3\7?\2\2\u01a3b\3\2\2\2\u01a4\u01a5"+ "\7?\2\2\u01a1\u01a2\7?\2\2\u01a2`\3\2\2\2\u01a3\u01a4\7#\2\2\u01a4\u01a5"+
"\7(\2\2\u01a5d\3\2\2\2\u01a6\u01a7\7`\2\2\u01a7f\3\2\2\2\u01a8\u01a9\7"+ "\7?\2\2\u01a5b\3\2\2\2\u01a6\u01a7\7(\2\2\u01a7d\3\2\2\2\u01a8\u01a9\7"+
"~\2\2\u01a9h\3\2\2\2\u01aa\u01ab\7v\2\2\u01ab\u01ac\7q\2\2\u01acj\3\2"+ "`\2\2\u01a9f\3\2\2\2\u01aa\u01ab\7~\2\2\u01abh\3\2\2\2\u01ac\u01ad\7v"+
"\2\2\u01ad\u01ae\7c\2\2\u01ae\u01af\7p\2\2\u01af\u01b0\7f\2\2\u01b0l\3"+ "\2\2\u01ad\u01ae\7q\2\2\u01aej\3\2\2\2\u01af\u01b0\7c\2\2\u01b0\u01b1"+
"\2\2\2\u01b1\u01b2\7q\2\2\u01b2\u01b3\7t\2\2\u01b3n\3\2\2\2\u01b4\u01b5"+ "\7p\2\2\u01b1\u01b2\7f\2\2\u01b2l\3\2\2\2\u01b3\u01b4\7q\2\2\u01b4\u01b5"+
"\7z\2\2\u01b5\u01b6\7q\2\2\u01b6\u01b7\7t\2\2\u01b7p\3\2\2\2\u01b8\u01b9"+ "\7t\2\2\u01b5n\3\2\2\2\u01b6\u01b7\7z\2\2\u01b7\u01b8\7q\2\2\u01b8\u01b9"+
"\7p\2\2\u01b9\u01ba\7q\2\2\u01ba\u01bb\7v\2\2\u01bbr\3\2\2\2\u01bc\u01bd"+ "\7t\2\2\u01b9p\3\2\2\2\u01ba\u01bb\7p\2\2\u01bb\u01bc\7q\2\2\u01bc\u01bd"+
"\7t\2\2\u01bd\u01be\7g\2\2\u01be\u01bf\7v\2\2\u01bf\u01c0\7w\2\2\u01c0"+ "\7v\2\2\u01bdr\3\2\2\2\u01be\u01bf\7t\2\2\u01bf\u01c0\7g\2\2\u01c0\u01c1"+
"\u01c1\7t\2\2\u01c1\u01c2\7p\2\2\u01c2t\3\2\2\2\u01c3\u01c4\7\60\2\2\u01c4"+ "\7v\2\2\u01c1\u01c2\7w\2\2\u01c2\u01c3\7t\2\2\u01c3\u01c4\7p\2\2\u01c4"+
"v\3\2\2\2\u01c5\u01c6\7C\2\2\u01c6x\3\2\2\2\u01c7\u01c8\7Z\2\2\u01c8z"+ "t\3\2\2\2\u01c5\u01c6\7\60\2\2\u01c6v\3\2\2\2\u01c7\u01c8\7C\2\2\u01c8"+
"\3\2\2\2\u01c9\u01ca\7[\2\2\u01ca|\3\2\2\2\u01cb\u01cc\7C\2\2\u01cc\u01cd"+ "x\3\2\2\2\u01c9\u01ca\7Z\2\2\u01caz\3\2\2\2\u01cb\u01cc\7[\2\2\u01cc|"+
"\7Z\2\2\u01cd~\3\2\2\2\u01ce\u01cf\7C\2\2\u01cf\u01d0\7[\2\2\u01d0\u0080"+ "\3\2\2\2\u01cd\u01ce\7C\2\2\u01ce\u01cf\7Z\2\2\u01cf~\3\2\2\2\u01d0\u01d1"+
"\3\2\2\2\u01d1\u01d2\7Z\2\2\u01d2\u01d3\7[\2\2\u01d3\u0082\3\2\2\2\u01d4"+ "\7C\2\2\u01d1\u01d2\7[\2\2\u01d2\u0080\3\2\2\2\u01d3\u01d4\7Z\2\2\u01d4"+
"\u01d5\7R\2\2\u01d5\u01d6\7e\2\2\u01d6\u0084\3\2\2\2\u01d7\u01d8\7R\2"+ "\u01d5\7[\2\2\u01d5\u0082\3\2\2\2\u01d6\u01d7\7R\2\2\u01d7\u01d8\7e\2"+
"\2\u01d8\u01d9\7|\2\2\u01d9\u0086\3\2\2\2\u01da\u01db\7R\2\2\u01db\u01dc"+ "\2\u01d8\u0084\3\2\2\2\u01d9\u01da\7R\2\2\u01da\u01db\7|\2\2\u01db\u0086"+
"\7p\2\2\u01dc\u0088\3\2\2\2\u01dd\u01de\7R\2\2\u01de\u01df\7x\2\2\u01df"+ "\3\2\2\2\u01dc\u01dd\7R\2\2\u01dd\u01de\7p\2\2\u01de\u0088\3\2\2\2\u01df"+
"\u008a\3\2\2\2\u01e0\u01e1\7v\2\2\u01e1\u01e2\7t\2\2\u01e2\u01e3\7w\2"+ "\u01e0\7R\2\2\u01e0\u01e1\7x\2\2\u01e1\u008a\3\2\2\2\u01e2\u01e3\7\60"+
"\2\u01e3\u01e4\7g\2\2\u01e4\u008c\3\2\2\2\u01e5\u01e6\7h\2\2\u01e6\u01e7"+ "\2\2\u01e3\u01e4\7y\2\2\u01e4\u008c\3\2\2\2\u01e5\u01e6\7v\2\2\u01e6\u01e7"+
"\7c\2\2\u01e7\u01e8\7n\2\2\u01e8\u01e9\7u\2\2\u01e9\u01ea\7g\2\2\u01ea"+ "\7t\2\2\u01e7\u01e8\7w\2\2\u01e8\u01e9\7g\2\2\u01e9\u008e\3\2\2\2\u01ea"+
"\u008e\3\2\2\2\u01eb\u01ec\7\'\2\2\u01ec\u01ed\7c\2\2\u01ed\u01ee\7u\2"+ "\u01eb\7h\2\2\u01eb\u01ec\7c\2\2\u01ec\u01ed\7n\2\2\u01ed\u01ee\7u\2\2"+
"\2\u01ee\u01ef\7o\2\2\u01ef\u0090\3\2\2\2\u01f0\u01f1\7u\2\2\u01f1\u01f2"+ "\u01ee\u01ef\7g\2\2\u01ef\u0090\3\2\2\2\u01f0\u01f1\7\'\2\2\u01f1\u01f2"+
"\7w\2\2\u01f2\u01f3\7d\2\2\u01f3\u0092\3\2\2\2\u01f4\u01f5\7/\2\2\u01f5"+ "\7c\2\2\u01f2\u01f3\7u\2\2\u01f3\u01f4\7o\2\2\u01f4\u0092\3\2\2\2\u01f5"+
"\u01f6\7@\2\2\u01f6\u0094\3\2\2\2\u01f7\u01f8\7}\2\2\u01f8\u0096\3\2\2"+ "\u01f6\7u\2\2\u01f6\u01f7\7w\2\2\u01f7\u01f8\7d\2\2\u01f8\u0094\3\2\2"+
"\2\u01f9\u01fa\7\177\2\2\u01fa\u0098\3\2\2\2\u01fb\u01fc\7A\2\2\u01fc"+ "\2\u01f9\u01fa\7/\2\2\u01fa\u01fb\7@\2\2\u01fb\u0096\3\2\2\2\u01fc\u01fd"+
"\u009a\3\2\2\2\u01fd\u01fe\7k\2\2\u01fe\u01ff\7h\2\2\u01ff\u009c\3\2\2"+ "\7}\2\2\u01fd\u0098\3\2\2\2\u01fe\u01ff\7\177\2\2\u01ff\u009a\3\2\2\2"+
"\2\u0200\u0201\7g\2\2\u0201\u0202\7n\2\2\u0202\u0203\7u\2\2\u0203\u0204"+ "\u0200\u0201\7A\2\2\u0201\u009c\3\2\2\2\u0202\u0203\7k\2\2\u0203\u0204"+
"\7g\2\2\u0204\u009e\3\2\2\2\u0205\u0206\7k\2\2\u0206\u0207\7h\2\2\u0207"+ "\7h\2\2\u0204\u009e\3\2\2\2\u0205\u0206\7g\2\2\u0206\u0207\7n\2\2\u0207"+
"\u0208\7a\2\2\u0208\u0209\7e\2\2\u0209\u020a\7u\2\2\u020a\u00a0\3\2\2"+ "\u0208\7u\2\2\u0208\u0209\7g\2\2\u0209\u00a0\3\2\2\2\u020a\u020b\7k\2"+
"\2\u020b\u020c\7k\2\2\u020c\u020d\7h\2\2\u020d\u020e\7a\2\2\u020e\u020f"+ "\2\u020b\u020c\7h\2\2\u020c\u020d\7a\2\2\u020d\u020e\7e\2\2\u020e\u020f"+
"\7e\2\2\u020f\u0210\7e\2\2\u0210\u00a2\3\2\2\2\u0211\u0212\7k\2\2\u0212"+ "\7u\2\2\u020f\u00a2\3\2\2\2\u0210\u0211\7k\2\2\u0211\u0212\7h\2\2\u0212"+
"\u0213\7h\2\2\u0213\u0214\7a\2\2\u0214\u0215\7g\2\2\u0215\u0216\7s\2\2"+ "\u0213\7a\2\2\u0213\u0214\7e\2\2\u0214\u0215\7e\2\2\u0215\u00a4\3\2\2"+
"\u0216\u00a4\3\2\2\2\u0217\u0218\7k\2\2\u0218\u0219\7h\2\2\u0219\u021a"+ "\2\u0216\u0217\7k\2\2\u0217\u0218\7h\2\2\u0218\u0219\7a\2\2\u0219\u021a"+
"\7a\2\2\u021a\u021b\7p\2\2\u021b\u021c\7g\2\2\u021c\u00a6\3\2\2\2\u021d"+ "\7g\2\2\u021a\u021b\7s\2\2\u021b\u00a6\3\2\2\2\u021c\u021d\7k\2\2\u021d"+
"\u021e\7k\2\2\u021e\u021f\7h\2\2\u021f\u0220\7a\2\2\u0220\u0221\7r\2\2"+ "\u021e\7h\2\2\u021e\u021f\7a\2\2\u021f\u0220\7p\2\2\u0220\u0221\7g\2\2"+
"\u0221\u0222\7n\2\2\u0222\u00a8\3\2\2\2\u0223\u0224\7k\2\2\u0224\u0225"+ "\u0221\u00a8\3\2\2\2\u0222\u0223\7k\2\2\u0223\u0224\7h\2\2\u0224\u0225"+
"\7h\2\2\u0225\u0226\7a\2\2\u0226\u0227\7o\2\2\u0227\u0228\7k\2\2\u0228"+ "\7a\2\2\u0225\u0226\7r\2\2\u0226\u0227\7n\2\2\u0227\u00aa\3\2\2\2\u0228"+
"\u00aa\3\2\2\2\u0229\u022a\7k\2\2\u022a\u022b\7h\2\2\u022b\u022c\7a\2"+ "\u0229\7k\2\2\u0229\u022a\7h\2\2\u022a\u022b\7a\2\2\u022b\u022c\7o\2\2"+
"\2\u022c\u022d\7x\2\2\u022d\u022e\7u\2\2\u022e\u00ac\3\2\2\2\u022f\u0230"+ "\u022c\u022d\7k\2\2\u022d\u00ac\3\2\2\2\u022e\u022f\7k\2\2\u022f\u0230"+
"\7k\2\2\u0230\u0231\7h\2\2\u0231\u0232\7a\2\2\u0232\u0233\7x\2\2\u0233"+ "\7h\2\2\u0230\u0231\7a\2\2\u0231\u0232\7x\2\2\u0232\u0233\7u\2\2\u0233"+
"\u0234\7e\2\2\u0234\u00ae\3\2\2\2\u0235\u0239\t\2\2\2\u0236\u0238\t\3"+ "\u00ae\3\2\2\2\u0234\u0235\7k\2\2\u0235\u0236\7h\2\2\u0236\u0237\7a\2"+
"\2\2\u0237\u0236\3\2\2\2\u0238\u023b\3\2\2\2\u0239\u0237\3\2\2\2\u0239"+ "\2\u0237\u0238\7x\2\2\u0238\u0239\7e\2\2\u0239\u00b0\3\2\2\2\u023a\u023e"+
"\u023a\3\2\2\2\u023a\u023c\3\2\2\2\u023b\u0239\3\2\2\2\u023c\u023d\5\u00b1"+ "\t\2\2\2\u023b\u023d\t\3\2\2\u023c\u023b\3\2\2\2\u023d\u0240\3\2\2\2\u023e"+
"Y\2\u023d\u023e\3\2\2\2\u023e\u023f\bX\2\2\u023f\u00b0\3\2\2\2\u0240\u0244"+ "\u023c\3\2\2\2\u023e\u023f\3\2\2\2\u023f\u0241\3\2\2\2\u0240\u023e\3\2"+
"\7=\2\2\u0241\u0243\n\2\2\2\u0242\u0241\3\2\2\2\u0243\u0246\3\2\2\2\u0244"+ "\2\2\u0241\u0242\5\u00b3Z\2\u0242\u0243\3\2\2\2\u0243\u0244\bY\2\2\u0244"+
"\u0242\3\2\2\2\u0244\u0245\3\2\2\2\u0245\u0247\3\2\2\2\u0246\u0244\3\2"+ "\u00b2\3\2\2\2\u0245\u0249\7=\2\2\u0246\u0248\n\2\2\2\u0247\u0246\3\2"+
"\2\2\u0247\u0248\bY\2\2\u0248\u00b2\3\2\2\2\u0249\u024a\t\3\2\2\u024a"+ "\2\2\u0248\u024b\3\2\2\2\u0249\u0247\3\2\2\2\u0249\u024a\3\2\2\2\u024a"+
"\u024b\3\2\2\2\u024b\u024c\bZ\3\2\u024c\u00b4\3\2\2\2\u024d\u024f\t\2"+ "\u024c\3\2\2\2\u024b\u0249\3\2\2\2\u024c\u024d\bZ\2\2\u024d\u00b4\3\2"+
"\2\2\u024e\u024d\3\2\2\2\u024f\u0250\3\2\2\2\u0250\u024e\3\2\2\2\u0250"+ "\2\2\u024e\u024f\t\3\2\2\u024f\u0250\3\2\2\2\u0250\u0251\b[\3\2\u0251"+
"\u0251\3\2\2\2\u0251\u00b6\3\2\2\2\u0252\u0256\t\4\2\2\u0253\u0255\t\5"+ "\u00b6\3\2\2\2\u0252\u0254\t\2\2\2\u0253\u0252\3\2\2\2\u0254\u0255\3\2"+
"\2\2\u0254\u0253\3\2\2\2\u0255\u0258\3\2\2\2\u0256\u0254\3\2\2\2\u0256"+ "\2\2\u0255\u0253\3\2\2\2\u0255\u0256\3\2\2\2\u0256\u00b8\3\2\2\2\u0257"+
"\u0257\3\2\2\2\u0257\u00b8\3\2\2\2\u0258\u0256\3\2\2\2\u0259\u0261\4\62"+ "\u025b\t\4\2\2\u0258\u025a\t\5\2\2\u0259\u0258\3\2\2\2\u025a\u025d\3\2"+
";\2\u025a\u025c\4\63;\2\u025b\u025d\4\62;\2\u025c\u025b\3\2\2\2\u025d"+ "\2\2\u025b\u0259\3\2\2\2\u025b\u025c\3\2\2\2\u025c\u00ba\3\2\2\2\u025d"+
"\u025e\3\2\2\2\u025e\u025c\3\2\2\2\u025e\u025f\3\2\2\2\u025f\u0261\3\2"+ "\u025b\3\2\2\2\u025e\u0266\4\62;\2\u025f\u0261\4\63;\2\u0260\u0262\4\62"+
"\2\2\u0260\u0259\3\2\2\2\u0260\u025a\3\2\2\2\u0261\u00ba\3\2\2\2\u0262"+ ";\2\u0261\u0260\3\2\2\2\u0262\u0263\3\2\2\2\u0263\u0261\3\2\2\2\u0263"+
"\u0264\7&\2\2\u0263\u0265\t\6\2\2\u0264\u0263\3\2\2\2\u0265\u0266\3\2"+ "\u0264\3\2\2\2\u0264\u0266\3\2\2\2\u0265\u025e\3\2\2\2\u0265\u025f\3\2"+
"\2\2\u0266\u0264\3\2\2\2\u0266\u0267\3\2\2\2\u0267\u00bc\3\2\2\2\u0268"+ "\2\2\u0266\u00bc\3\2\2\2\u0267\u0269\7&\2\2\u0268\u026a\t\6\2\2\u0269"+
"\u026a\7\'\2\2\u0269\u026b\4\62\63\2\u026a\u0269\3\2\2\2\u026b\u026c\3"+ "\u0268\3\2\2\2\u026a\u026b\3\2\2\2\u026b\u0269\3\2\2\2\u026b\u026c\3\2"+
"\2\2\2\u026c\u026a\3\2\2\2\u026c\u026d\3\2\2\2\u026d\u00be\3\2\2\2\u026e"+ "\2\2\u026c\u00be\3\2\2\2\u026d\u026f\7\'\2\2\u026e\u0270\4\62\63\2\u026f"+
"\u0274\5\u00c1a\2\u026f\u0271\t\7\2\2\u0270\u0272\t\b\2\2\u0271\u0270"+ "\u026e\3\2\2\2\u0270\u0271\3\2\2\2\u0271\u026f\3\2\2\2\u0271\u0272\3\2"+
"\3\2\2\2\u0271\u0272\3\2\2\2\u0272\u0273\3\2\2\2\u0273\u0275\5\u00c1a"+ "\2\2\u0272\u00c0\3\2\2\2\u0273\u0279\5\u00c3b\2\u0274\u0276\t\7\2\2\u0275"+
"\2\u0274\u026f\3\2\2\2\u0274\u0275\3\2\2\2\u0275\u00c0\3\2\2\2\u0276\u0278"+ "\u0277\t\b\2\2\u0276\u0275\3\2\2\2\u0276\u0277\3\2\2\2\u0277\u0278\3\2"+
"\4\62;\2\u0277\u0276\3\2\2\2\u0278\u0279\3\2\2\2\u0279\u0277\3\2\2\2\u0279"+ "\2\2\u0278\u027a\5\u00c3b\2\u0279\u0274\3\2\2\2\u0279\u027a\3\2\2\2\u027a"+
"\u027a\3\2\2\2\u027a\u0281\3\2\2\2\u027b\u027d\7\60\2\2\u027c\u027e\4"+ "\u00c2\3\2\2\2\u027b\u027d\4\62;\2\u027c\u027b\3\2\2\2\u027d\u027e\3\2"+
"\62;\2\u027d\u027c\3\2\2\2\u027e\u027f\3\2\2\2\u027f\u027d\3\2\2\2\u027f"+ "\2\2\u027e\u027c\3\2\2\2\u027e\u027f\3\2\2\2\u027f\u0286\3\2\2\2\u0280"+
"\u0280\3\2\2\2\u0280\u0282\3\2\2\2\u0281\u027b\3\2\2\2\u0281\u0282\3\2"+ "\u0282\7\60\2\2\u0281\u0283\4\62;\2\u0282\u0281\3\2\2\2\u0283\u0284\3"+
"\2\2\u0282\u00c2\3\2\2\2\u0283\u0284\7^\2\2\u0284\u0288\13\2\2\2\u0285"+ "\2\2\2\u0284\u0282\3\2\2\2\u0284\u0285\3\2\2\2\u0285\u0287\3\2\2\2\u0286"+
"\u0286\7^\2\2\u0286\u0288\5\u00b5[\2\u0287\u0283\3\2\2\2\u0287\u0285\3"+ "\u0280\3\2\2\2\u0286\u0287\3\2\2\2\u0287\u00c4\3\2\2\2\u0288\u0289\7^"+
"\2\2\2\u0288\u00c4\3\2\2\2\u0289\u028e\7$\2\2\u028a\u028d\5\u00c3b\2\u028b"+ "\2\2\u0289\u028d\13\2\2\2\u028a\u028b\7^\2\2\u028b\u028d\5\u00b7\\\2\u028c"+
"\u028d\n\t\2\2\u028c\u028a\3\2\2\2\u028c\u028b\3\2\2\2\u028d\u0290\3\2"+ "\u0288\3\2\2\2\u028c\u028a\3\2\2\2\u028d\u00c6\3\2\2\2\u028e\u0293\7$"+
"\2\2\u028e\u028c\3\2\2\2\u028e\u028f\3\2\2\2\u028f\u0291\3\2\2\2\u0290"+ "\2\2\u028f\u0292\5\u00c5c\2\u0290\u0292\n\t\2\2\u0291\u028f\3\2\2\2\u0291"+
"\u028e\3\2\2\2\u0291\u0292\7$\2\2\u0292\u0293\bc\4\2\u0293\u00c6\3\2\2"+ "\u0290\3\2\2\2\u0292\u0295\3\2\2\2\u0293\u0291\3\2\2\2\u0293\u0294\3\2"+
"\2\u0294\u0295\7}\2\2\u0295\u0296\7}\2\2\u0296\u0298\3\2\2\2\u0297\u0299"+ "\2\2\u0294\u0296\3\2\2\2\u0295\u0293\3\2\2\2\u0296\u0297\7$\2\2\u0297"+
"\13\2\2\2\u0298\u0297\3\2\2\2\u0299\u029a\3\2\2\2\u029a\u029b\3\2\2\2"+ "\u0298\bd\4\2\u0298\u00c8\3\2\2\2\u0299\u029a\7}\2\2\u029a\u029b\7}\2"+
"\u029a\u0298\3\2\2\2\u029b\u029c\3\2\2\2\u029c\u029d\7\177\2\2\u029d\u029e"+ "\2\u029b\u029d\3\2\2\2\u029c\u029e\13\2\2\2\u029d\u029c\3\2\2\2\u029e"+
"\7\177\2\2\u029e\u029f\3\2\2\2\u029f\u02a0\bd\5\2\u02a0\u00c8\3\2\2\2"+ "\u029f\3\2\2\2\u029f\u02a0\3\2\2\2\u029f\u029d\3\2\2\2\u02a0\u02a1\3\2"+
"\25\2\u0239\u0244\u0250\u0256\u025e\u0260\u0264\u0266\u026c\u0271\u0274"+ "\2\2\u02a1\u02a2\7\177\2\2\u02a2\u02a3\7\177\2\2\u02a3\u02a4\3\2\2\2\u02a4"+
"\u0279\u027f\u0281\u0287\u028c\u028e\u029a\6\2\3\2\b\2\2\3c\2\3d\3"; "\u02a5\be\5\2\u02a5\u00ca\3\2\2\2\25\2\u023e\u0249\u0255\u025b\u0263\u0265"+
"\u0269\u026b\u0271\u0276\u0279\u027e\u0284\u0286\u028c\u0291\u0293\u029f"+
"\6\2\3\2\b\2\2\3d\2\3e\3";
public static final ATN _ATN = public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray()); new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static { static {

View File

@ -84,17 +84,18 @@ T__82=83
T__83=84 T__83=84
T__84=85 T__84=85
T__85=86 T__85=86
LINECOMMENT=87 T__86=87
COMMENT=88 LINECOMMENT=88
WS=89 COMMENT=89
EOL=90 WS=90
NAME=91 EOL=91
DEC_INTEGER=92 NAME=92
HEX_INTEGER=93 DEC_INTEGER=93
BIN_INTEGER=94 HEX_INTEGER=94
FLOAT_NUMBER=95 BIN_INTEGER=95
STRING=96 FLOAT_NUMBER=96
INLINEASMBLOCK=97 STRING=97
INLINEASMBLOCK=98
'~'=1 '~'=1
':'=2 ':'=2
'goto'=3 'goto'=3
@ -163,21 +164,22 @@ INLINEASMBLOCK=97
'Pz'=66 'Pz'=66
'Pn'=67 'Pn'=67
'Pv'=68 'Pv'=68
'true'=69 '.w'=69
'false'=70 'true'=70
'%asm'=71 'false'=71
'sub'=72 '%asm'=72
'->'=73 'sub'=73
'{'=74 '->'=74
'}'=75 '{'=75
'?'=76 '}'=76
'if'=77 '?'=77
'else'=78 'if'=78
'if_cs'=79 'else'=79
'if_cc'=80 'if_cs'=80
'if_eq'=81 'if_cc'=81
'if_ne'=82 'if_eq'=82
'if_pl'=83 'if_ne'=83
'if_mi'=84 'if_pl'=84
'if_vs'=85 'if_mi'=85
'if_vc'=86 'if_vs'=86
'if_vc'=87

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ enum class Opcode {
POP_MEM, // pop value into destination memory address POP_MEM, // pop value into destination memory address
POP_VAR, // pop value into variable POP_VAR, // pop value into variable
// numeric bitand bitwise arithmetic // numeric and bitwise arithmetic
ADD, ADD,
SUB, SUB,
MUL, MUL,
@ -117,9 +117,9 @@ enum class Opcode {
enum class Syscall(val callNr: Short) { enum class Syscall(val callNr: Short) {
WRITE_MEMCHR(10), // print a single char from the memory WRITE_MEMCHR(10), // print a single char from the memory
WRITE_MEMSTR(11), // print a 0-terminated petscii string from the memory WRITE_MEMSTR(11), // print a 0-terminated petscii string from the memory
WRITE_NUM(12), // pop from the evaluation stack bitand print it as a number WRITE_NUM(12), // pop from the evaluation stack and print it as a number
WRITE_CHAR(13), // pop from the evaluation stack bitand print it as a single petscii character WRITE_CHAR(13), // pop from the evaluation stack and print it as a single petscii character
WRITE_VAR(14), // print the number bitor string from the given variable WRITE_VAR(14), // print the number or string from the given variable
INPUT_VAR(15), // user input a string into a variable INPUT_VAR(15), // user input a string into a variable
GFX_PIXEL(16), // plot a pixel at (x,y,color) pushed on stack in that order GFX_PIXEL(16), // plot a pixel at (x,y,color) pushed on stack in that order
GFX_CLEARSCR(17), // clear the screen with color pushed on stack GFX_CLEARSCR(17), // clear the screen with color pushed on stack
@ -164,7 +164,7 @@ enum class Syscall(val callNr: Short) {
} }
class Memory { class Memory {
private val mem = ShortArray(65536) // shorts because byte is signed bitand we store values 0..255 private val mem = ShortArray(65536) // shorts because byte is signed and we store values 0..255
fun getByte(address: Int): Short { fun getByte(address: Int): Short {
return mem[address] return mem[address]
@ -319,7 +319,7 @@ class Value(val type: DataType, private val numericvalue: Number?, val stringval
} }
fun rol(carry: Boolean): Pair<Value, Boolean> { fun rol(carry: Boolean): Pair<Value, Boolean> {
// 9 bitor 17 bit rotate left (with carry)) // 9 or 17 bit rotate left (with carry))
return when(type) { return when(type) {
DataType.BYTE -> { DataType.BYTE -> {
val v = byteval!!.toInt() val v = byteval!!.toInt()
@ -338,7 +338,7 @@ class Value(val type: DataType, private val numericvalue: Number?, val stringval
} }
fun ror(carry: Boolean): Pair<Value, Boolean> { fun ror(carry: Boolean): Pair<Value, Boolean> {
// 9 bitor 17 bit rotate right (with carry) // 9 or 17 bit rotate right (with carry)
return when(type) { return when(type) {
DataType.BYTE -> { DataType.BYTE -> {
val v = byteval!!.toInt() val v = byteval!!.toInt()
@ -357,7 +357,7 @@ class Value(val type: DataType, private val numericvalue: Number?, val stringval
} }
fun rol2(): Value { fun rol2(): Value {
// 8 bitor 16 bit rotate left // 8 or 16 bit rotate left
return when(type) { return when(type) {
DataType.BYTE -> { DataType.BYTE -> {
val v = byteval!!.toInt() val v = byteval!!.toInt()
@ -376,7 +376,7 @@ class Value(val type: DataType, private val numericvalue: Number?, val stringval
} }
fun ror2(): Value { fun ror2(): Value {
// 8 bitor 16 bit rotate right // 8 or 16 bit rotate right
return when(type) { return when(type) {
DataType.BYTE -> { DataType.BYTE -> {
val v = byteval!!.toInt() val v = byteval!!.toInt()