mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
now explicit separation between byte and word literal integers
This commit is contained in:
parent
949e468543
commit
ea94063689
@ -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)?**
|
||||||
|
@ -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' ;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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 {
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}")
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user