mirror of
https://github.com/irmen/prog8.git
synced 2024-10-26 22:27:40 +00:00
position and parent moved out of data class constructor
This commit is contained in:
parent
30c5550ece
commit
20d5eb79d0
@ -1,8 +1,15 @@
|
|||||||
~ main $c000 {
|
~ main $c003 {
|
||||||
|
memory byte derp = $ffdd1
|
||||||
const byte hopla=55-33
|
const byte hopla=55-33
|
||||||
const byte hopla2=55-hopla
|
; const byte hopla2=55-hopla
|
||||||
|
const float zwop = -1.7014118345e+38
|
||||||
|
const float zwop = -1.7014118346e+38
|
||||||
|
|
||||||
A = "derp" * %000100
|
A = "derp" * %000100
|
||||||
|
|
||||||
|
%import maghierniet
|
||||||
|
%import maghierniet
|
||||||
|
%import maghierniet
|
||||||
%import maghierniet
|
%import maghierniet
|
||||||
|
|
||||||
return 1+999
|
return 1+999
|
||||||
|
@ -11,7 +11,6 @@ fun Module.checkValid() : List<SyntaxError> {
|
|||||||
|
|
||||||
|
|
||||||
class AstChecker : IAstProcessor {
|
class AstChecker : IAstProcessor {
|
||||||
|
|
||||||
private val checkResult: MutableList<SyntaxError> = mutableListOf()
|
private val checkResult: MutableList<SyntaxError> = mutableListOf()
|
||||||
|
|
||||||
fun result(): List<SyntaxError> {
|
fun result(): List<SyntaxError> {
|
||||||
@ -26,6 +25,73 @@ class AstChecker : IAstProcessor {
|
|||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun process(block: Block): IStatement {
|
||||||
|
if(block.address!=null && (block.address<0 || block.address>65535)) {
|
||||||
|
checkResult.add(SyntaxError("block memory address must be valid 0..\$ffff", block))
|
||||||
|
}
|
||||||
|
block.statements.forEach { it.process(this) }
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the variable declarations (values within range etc)
|
||||||
|
*/
|
||||||
|
override fun process(decl: VarDecl): IStatement {
|
||||||
|
fun err(msg: String) {
|
||||||
|
if(decl.value?.position == null)
|
||||||
|
throw AstException("declvalue no pos!")
|
||||||
|
checkResult.add(SyntaxError(msg, decl))
|
||||||
|
}
|
||||||
|
when(decl.type) {
|
||||||
|
VarDeclType.VAR, VarDeclType.CONST -> {
|
||||||
|
val value = decl.value as? LiteralValue
|
||||||
|
if(value==null)
|
||||||
|
err("need a compile-time constant initializer value, found: ${decl.value!!::class.simpleName}")
|
||||||
|
else
|
||||||
|
when(decl.datatype) {
|
||||||
|
DataType.FLOAT -> {
|
||||||
|
val number = value.asFloat()
|
||||||
|
if(number==null)
|
||||||
|
err("need a const float initializer value")
|
||||||
|
else if(number > 1.7014118345e+38 || number < -1.7014118345e+38)
|
||||||
|
err("floating point value out of range for MFLPT format")
|
||||||
|
}
|
||||||
|
DataType.BYTE -> {
|
||||||
|
val number = value.asInt()
|
||||||
|
if(number==null)
|
||||||
|
err("need a const integer initializer value")
|
||||||
|
else if(number < 0 || number > 255)
|
||||||
|
err("value out of range for unsigned byte")
|
||||||
|
}
|
||||||
|
DataType.WORD -> {
|
||||||
|
val number = value.asInt()
|
||||||
|
if(number==null)
|
||||||
|
err("need a const integer initializer value")
|
||||||
|
else if(number < 0 || number > 65535)
|
||||||
|
err("value out of range for unsigned word")
|
||||||
|
}
|
||||||
|
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> {
|
||||||
|
val str = value.strvalue
|
||||||
|
if(str==null)
|
||||||
|
err("need a const string initializer value")
|
||||||
|
else if(str.isEmpty() || str.length>65535)
|
||||||
|
err("string length must be 1..65535")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarDeclType.MEMORY -> {
|
||||||
|
val value = decl.value as LiteralValue
|
||||||
|
if(value.intvalue==null || value.intvalue<0 || value.intvalue>65535) {
|
||||||
|
err("memory address must be valid 0..\$ffff")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decl.arrayspec?.process(this)
|
||||||
|
decl.value?.process(this)
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check the arguments of the directive
|
* check the arguments of the directive
|
||||||
*/
|
*/
|
||||||
@ -35,14 +101,17 @@ class AstChecker : IAstProcessor {
|
|||||||
}
|
}
|
||||||
when(directive.directive) {
|
when(directive.directive) {
|
||||||
"%output" -> {
|
"%output" -> {
|
||||||
|
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 or 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.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 or none")
|
err("invalid launcher directive type, expected basic or none")
|
||||||
}
|
}
|
||||||
"%zp" -> {
|
"%zp" -> {
|
||||||
|
if(directive.parent !is Module) err("this directive may only occur at module level")
|
||||||
if(directive.args.size!=1 ||
|
if(directive.args.size!=1 ||
|
||||||
directive.args[0].name != "compatible" &&
|
directive.args[0].name != "compatible" &&
|
||||||
directive.args[0].name != "full" &&
|
directive.args[0].name != "full" &&
|
||||||
@ -50,10 +119,12 @@ class AstChecker : IAstProcessor {
|
|||||||
err("invalid zp directive style, expected compatible, full or full-restore")
|
err("invalid zp directive style, expected compatible, full or full-restore")
|
||||||
}
|
}
|
||||||
"%address" -> {
|
"%address" -> {
|
||||||
|
if(directive.parent !is Module) err("this directive may only occur at module level")
|
||||||
if(directive.args.size!=1 || directive.args[0].int == null)
|
if(directive.args.size!=1 || directive.args[0].int == null)
|
||||||
err("invalid address directive, expected numeric address argument")
|
err("invalid address directive, expected numeric address argument")
|
||||||
}
|
}
|
||||||
"%import" -> {
|
"%import" -> {
|
||||||
|
if(directive.parent !is Module) err("this directive may only occur at module level")
|
||||||
if(directive.args.size!=1 || directive.args[0].name==null)
|
if(directive.args.size!=1 || directive.args[0].name==null)
|
||||||
err("invalid import directive, expected module name argument")
|
err("invalid import directive, expected module name argument")
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,17 @@ class AstOptimizer : IAstProcessor {
|
|||||||
optimizationsDone = 0
|
optimizationsDone = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun process(block: Block): IStatement {
|
||||||
|
block.statements = block.statements.map { it.process(this) }
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(decl: VarDecl): IStatement {
|
||||||
|
decl.value = decl.value?.process(this)
|
||||||
|
decl.arrayspec?.process(this)
|
||||||
|
return decl
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to process a unary prefix expression.
|
* Try to process a unary prefix expression.
|
||||||
* Compile-time constant sub expressions will be evaluated on the spot.
|
* Compile-time constant sub expressions will be evaluated on the spot.
|
||||||
@ -37,39 +48,41 @@ class AstOptimizer : IAstProcessor {
|
|||||||
val subexpr = expr.expression
|
val subexpr = expr.expression
|
||||||
if (subexpr is LiteralValue) {
|
if (subexpr is LiteralValue) {
|
||||||
// process prefixed literal values (such as -3, not true)
|
// process prefixed literal values (such as -3, not true)
|
||||||
return when {
|
val result = when {
|
||||||
expr.operator == "+" -> subexpr
|
expr.operator == "+" -> subexpr
|
||||||
expr.operator == "-" -> return when {
|
expr.operator == "-" -> when {
|
||||||
subexpr.intvalue != null -> {
|
subexpr.intvalue != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
LiteralValue(intvalue = subexpr.intvalue, position = subexpr.position)
|
LiteralValue(intvalue = subexpr.intvalue)
|
||||||
}
|
}
|
||||||
subexpr.floatvalue != null -> {
|
subexpr.floatvalue != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
LiteralValue(floatvalue = -subexpr.floatvalue, position = subexpr.position)
|
LiteralValue(floatvalue = -subexpr.floatvalue)
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("can only take negative of int or float")
|
else -> throw UnsupportedOperationException("can only take negative of int or float")
|
||||||
}
|
}
|
||||||
expr.operator == "~" -> return when {
|
expr.operator == "~" -> when {
|
||||||
subexpr.intvalue != null -> {
|
subexpr.intvalue != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
LiteralValue(intvalue = subexpr.intvalue.inv(), position = subexpr.position)
|
LiteralValue(intvalue = subexpr.intvalue.inv())
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("can only take bitwise inversion of int")
|
else -> throw UnsupportedOperationException("can only take bitwise inversion of int")
|
||||||
}
|
}
|
||||||
expr.operator == "not" -> return when {
|
expr.operator == "not" -> when {
|
||||||
subexpr.intvalue != null -> {
|
subexpr.intvalue != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
LiteralValue(intvalue = if (subexpr.intvalue == 0) 1 else 0, position = subexpr.position)
|
LiteralValue(intvalue = if (subexpr.intvalue == 0) 1 else 0)
|
||||||
}
|
}
|
||||||
subexpr.floatvalue != null -> {
|
subexpr.floatvalue != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0, position = subexpr.position)
|
LiteralValue(intvalue = if (subexpr.floatvalue == 0.0) 1 else 0)
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException("can not take logical not of $subexpr")
|
else -> throw UnsupportedOperationException("can not take logical not of $subexpr")
|
||||||
}
|
}
|
||||||
else -> throw UnsupportedOperationException(expr.operator)
|
else -> throw UnsupportedOperationException(expr.operator)
|
||||||
}
|
}
|
||||||
|
result.position = subexpr.position
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
@ -98,7 +111,6 @@ class AstOptimizer : IAstProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun process(directive: Directive): IStatement {
|
override fun process(directive: Directive): IStatement {
|
||||||
println("directove OPT $directive")
|
|
||||||
return directive
|
return directive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +147,9 @@ 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)
|
||||||
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
|
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun compareequal(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun compareequal(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
@ -153,159 +167,164 @@ class ConstExprEvaluator {
|
|||||||
right.arrayvalue!=null -> right.arrayvalue
|
right.arrayvalue!=null -> right.arrayvalue
|
||||||
else -> throw AstException("missing literal value")
|
else -> throw AstException("missing literal value")
|
||||||
}
|
}
|
||||||
return LiteralValue(intvalue = if(leftvalue==rightvalue) 1 else 0, position = left.position)
|
val litval = LiteralValue(intvalue = if(leftvalue==rightvalue) 1 else 0)
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue >= right.intvalue) 1 else 0,
|
intvalue = if (left.intvalue >= right.intvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0,
|
intvalue = if (left.intvalue >= right.floatvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0,
|
intvalue = if (left.floatvalue >= right.intvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0,
|
intvalue = if (left.floatvalue >= right.floatvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue <= right.intvalue) 1 else 0,
|
intvalue = if (left.intvalue <= right.intvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0,
|
intvalue = if (left.intvalue <= right.floatvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0,
|
intvalue = if (left.floatvalue <= right.intvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0,
|
intvalue = if (left.floatvalue <= right.floatvalue) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
|
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
|
||||||
|
litval.position = left.position
|
||||||
|
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)
|
||||||
return LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1, position = left.position)
|
val litval = LiteralValue(intvalue = if(leq.intvalue==1) 0 else 1)
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun logicalxor(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot compute $left locical-xor $right"
|
val error = "cannot compute $left locical-xor $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if ((left.intvalue!=0).xor(right.intvalue!=0)) 1 else 0,
|
intvalue = if ((left.intvalue!=0).xor(right.intvalue!=0)) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if ((left.intvalue!=0).xor(right.floatvalue!=0.0)) 1 else 0,
|
intvalue = if ((left.intvalue!=0).xor(right.floatvalue!=0.0)) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if ((left.floatvalue!=0.0).xor(right.intvalue!=0)) 1 else 0,
|
intvalue = if ((left.floatvalue!=0.0).xor(right.intvalue!=0)) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if ((left.floatvalue!=0.0).xor(right.floatvalue!=0.0)) 1 else 0,
|
intvalue = if ((left.floatvalue!=0.0).xor(right.floatvalue!=0.0)) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logicalor(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun logicalor(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot compute $left locical-or $right"
|
val error = "cannot compute $left locical-or $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue!=0 || right.intvalue!=0) 1 else 0,
|
intvalue = if (left.intvalue!=0 || right.intvalue!=0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue!=0 || right.floatvalue!=0.0) 1 else 0,
|
intvalue = if (left.intvalue!=0 || right.floatvalue!=0.0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue!=0.0 || right.intvalue!=0) 1 else 0,
|
intvalue = if (left.floatvalue!=0.0 || right.intvalue!=0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue!=0.0 || right.floatvalue!=0.0) 1 else 0,
|
intvalue = if (left.floatvalue!=0.0 || right.floatvalue!=0.0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logicaland(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun logicaland(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot compute $left locical-and $right"
|
val error = "cannot compute $left locical-and $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue!=0 && right.intvalue!=0) 1 else 0,
|
intvalue = if (left.intvalue!=0 && right.intvalue!=0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.intvalue!=0 && right.floatvalue!=0.0) 1 else 0,
|
intvalue = if (left.intvalue!=0 && right.floatvalue!=0.0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(
|
right.intvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue!=0.0 && right.intvalue!=0) 1 else 0,
|
intvalue = if (left.floatvalue!=0.0 && right.intvalue!=0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
right.floatvalue!=null -> LiteralValue(
|
right.floatvalue!=null -> LiteralValue(
|
||||||
intvalue = if (left.floatvalue!=0.0 && right.floatvalue!=0.0) 1 else 0,
|
intvalue = if (left.floatvalue!=0.0 && right.floatvalue!=0.0) 1 else 0)
|
||||||
position = left.position)
|
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
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.intvalue!=null && right.intvalue !=null) {
|
||||||
return LiteralValue(intvalue = left.intvalue.xor(right.intvalue), position = left.position)
|
val litval = LiteralValue(intvalue = left.intvalue.xor(right.intvalue))
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
|
}
|
||||||
throw ExpressionException("cannot calculate $left ^ $right")
|
throw ExpressionException("cannot calculate $left ^ $right")
|
||||||
}
|
}
|
||||||
|
|
||||||
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.intvalue!=null && right.intvalue !=null) {
|
||||||
return LiteralValue(intvalue = left.intvalue.or(right.intvalue), position = left.position)
|
val litval = LiteralValue(intvalue = left.intvalue.or(right.intvalue))
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
|
}
|
||||||
throw ExpressionException("cannot calculate $left | $right")
|
throw ExpressionException("cannot calculate $left | $right")
|
||||||
}
|
}
|
||||||
|
|
||||||
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.intvalue!=null && right.intvalue !=null) {
|
||||||
return LiteralValue(intvalue = left.intvalue.and(right.intvalue), position = left.position)
|
val litval = LiteralValue(intvalue = left.intvalue.and(right.intvalue))
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
|
}
|
||||||
throw ExpressionException("cannot calculate $left & $right")
|
throw ExpressionException("cannot calculate $left & $right")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,122 +337,138 @@ class ConstExprEvaluator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shiftright(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun shiftright(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
if(left.intvalue!=null && right.intvalue !=null)
|
if(left.intvalue!=null && right.intvalue !=null) {
|
||||||
return LiteralValue(intvalue = left.intvalue.shr(right.intvalue), position = left.position)
|
val litval = LiteralValue(intvalue = left.intvalue.shr(right.intvalue))
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
|
}
|
||||||
throw ExpressionException("cannot calculate $left >> $right")
|
throw ExpressionException("cannot calculate $left >> $right")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shiftleft(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun shiftleft(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
if(left.intvalue!=null && right.intvalue !=null)
|
if(left.intvalue!=null && right.intvalue !=null) {
|
||||||
return LiteralValue(intvalue = left.intvalue.shl(right.intvalue), position = left.position)
|
val litval = LiteralValue(intvalue = left.intvalue.shl(right.intvalue))
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
|
}
|
||||||
throw ExpressionException("cannot calculate $left << $right")
|
throw ExpressionException("cannot calculate $left << $right")
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt(), position = left.position)
|
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue.toDouble().pow(right.intvalue).toInt())
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue), position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue.toDouble().pow(right.floatvalue))
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue), position = left.position)
|
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.intvalue))
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue), position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue.pow(right.floatvalue))
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun plus(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot add $left and $right"
|
val error = "cannot add $left and $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue + right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue + right.floatvalue)
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue + right.floatvalue)
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun minus(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun minus(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot subtract $left and $right"
|
val error = "cannot subtract $left and $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue - right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue - right.floatvalue)
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue - right.floatvalue)
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue {
|
private fun multiply(left: LiteralValue, right: LiteralValue): LiteralValue {
|
||||||
val error = "cannot multiply $left and $right"
|
val error = "cannot multiply $left and $right"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(intvalue = left.intvalue * right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.intvalue * right.floatvalue)
|
||||||
right.strvalue!=null -> {
|
right.strvalue!=null -> {
|
||||||
if(right.strvalue.length * left.intvalue > 65535) throw ExpressionException("string too large")
|
if(right.strvalue.length * left.intvalue > 65535) throw ExpressionException("string too large")
|
||||||
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue), position = left.position)
|
LiteralValue(strvalue = right.strvalue.repeat(left.intvalue))
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue, position = left.position)
|
right.intvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.intvalue)
|
||||||
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue, position = left.position)
|
right.floatvalue!=null -> LiteralValue(floatvalue = left.floatvalue * right.floatvalue)
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.strvalue!=null -> when {
|
left.strvalue!=null -> when {
|
||||||
right.intvalue!=null -> {
|
right.intvalue!=null -> {
|
||||||
if(left.strvalue.length * right.intvalue > 65535) throw ExpressionException("string too large")
|
if(left.strvalue.length * right.intvalue > 65535) throw ExpressionException("string too large")
|
||||||
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue), position=left.position)
|
LiteralValue(strvalue = left.strvalue.repeat(right.intvalue))
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
|
|
||||||
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"
|
||||||
return when {
|
val litval = when {
|
||||||
left.intvalue!=null -> when {
|
left.intvalue!=null -> when {
|
||||||
right.intvalue!=null -> {
|
right.intvalue!=null -> {
|
||||||
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
|
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
|
||||||
LiteralValue(intvalue = left.intvalue / right.intvalue, position = left.position)
|
LiteralValue(intvalue = left.intvalue / right.intvalue)
|
||||||
}
|
}
|
||||||
right.floatvalue!=null -> {
|
right.floatvalue!=null -> {
|
||||||
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
|
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
|
||||||
LiteralValue(floatvalue = left.intvalue / right.floatvalue, position = left.position)
|
LiteralValue(floatvalue = left.intvalue / right.floatvalue)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
left.floatvalue!=null -> when {
|
left.floatvalue!=null -> when {
|
||||||
right.intvalue!=null -> {
|
right.intvalue!=null -> {
|
||||||
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
|
if(right.intvalue==0) throw ExpressionException("attempt to divide by zero")
|
||||||
LiteralValue(floatvalue = left.floatvalue / right.intvalue, position = left.position)
|
LiteralValue(floatvalue = left.floatvalue / right.intvalue)
|
||||||
}
|
}
|
||||||
right.floatvalue!=null -> {
|
right.floatvalue!=null -> {
|
||||||
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
|
if(right.floatvalue==0.0) throw ExpressionException("attempt to divide by zero")
|
||||||
LiteralValue(floatvalue = left.floatvalue / right.floatvalue, position = left.position)
|
LiteralValue(floatvalue = left.floatvalue / right.floatvalue)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
else -> throw ExpressionException(error)
|
else -> throw ExpressionException(error)
|
||||||
}
|
}
|
||||||
|
litval.position = left.position
|
||||||
|
return litval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,12 +50,14 @@ fun loadModule(filename: String) : Module {
|
|||||||
// TODO the comments:
|
// TODO the comments:
|
||||||
// tokens.commentTokens().forEach { println(it) }
|
// tokens.commentTokens().forEach { println(it) }
|
||||||
|
|
||||||
// convert to Ast (optimizing this is done as a final step)
|
// convert to Ast and optimize
|
||||||
var moduleAst = parseTree.toAst(fileName.toString(),true)
|
var moduleAst = parseTree.toAst(fileName.toString(),true).optimized()
|
||||||
|
moduleAst.linkParents()
|
||||||
|
|
||||||
val checkResult = moduleAst.checkValid()
|
val checkResult = moduleAst.checkValid()
|
||||||
checkResult.forEach { it.printError() }
|
checkResult.forEach { it.printError() }
|
||||||
if(checkResult.isNotEmpty())
|
if(checkResult.isNotEmpty())
|
||||||
throw ParsingFailedError("There are ${checkResult.size} syntax errors in '$fileName'.")
|
throw ParsingFailedError("There are ${checkResult.size} errors in '$fileName'.")
|
||||||
|
|
||||||
// process imports
|
// process imports
|
||||||
val lines = moduleAst.lines.toMutableList()
|
val lines = moduleAst.lines.toMutableList()
|
||||||
@ -65,7 +67,7 @@ fun loadModule(filename: String) : Module {
|
|||||||
.map { Pair(it.first, executeImportDirective(it.second as Directive)) }
|
.map { Pair(it.first, executeImportDirective(it.second as Directive)) }
|
||||||
|
|
||||||
imports.reversed().forEach {
|
imports.reversed().forEach {
|
||||||
println("IMPORT [in ${moduleAst.name}]: $it")
|
println("IMPORT [in ${moduleAst.name}]: $it") // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleAst.lines = lines
|
moduleAst.lines = lines
|
||||||
@ -77,14 +79,15 @@ fun executeImportDirective(import: Directive): Module {
|
|||||||
if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null)
|
if(import.directive!="%import" || import.args.size!=1 || import.args[0].name==null)
|
||||||
throw SyntaxError("invalid import directive", import)
|
throw SyntaxError("invalid import directive", import)
|
||||||
|
|
||||||
return Module("???", emptyList(), null) // TODO
|
return Module("???", emptyList()) // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
println("Reading source file: ${args[0]}")
|
println("Reading source file: ${args[0]}")
|
||||||
try {
|
try {
|
||||||
val moduleAst = loadModule(args[0]).optimized()
|
val moduleAst = loadModule(args[0]).optimized() // one final global optimization
|
||||||
|
moduleAst.linkParents() // re-link parents in final configuration
|
||||||
|
|
||||||
moduleAst.lines.map {
|
moduleAst.lines.map {
|
||||||
println(it)
|
println(it)
|
||||||
|
@ -51,11 +51,15 @@ interface IAstProcessor {
|
|||||||
fun process(expr: PrefixExpression): IExpression
|
fun process(expr: PrefixExpression): IExpression
|
||||||
fun process(expr: BinaryExpression): IExpression
|
fun process(expr: BinaryExpression): IExpression
|
||||||
fun process(directive: Directive): IStatement
|
fun process(directive: Directive): IStatement
|
||||||
|
fun process(block: Block): IStatement
|
||||||
|
fun process(decl: VarDecl): IStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Node {
|
interface Node {
|
||||||
val position: Position? // optional for the sake of easy unit testing
|
val position: Position? // optional for the sake of easy unit testing
|
||||||
|
var parent: Node? // will be linked correctly later
|
||||||
|
fun linkParents(parent: Node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -65,39 +69,84 @@ interface IStatement : Node {
|
|||||||
|
|
||||||
|
|
||||||
data class Module(val name: String,
|
data class Module(val name: String,
|
||||||
var lines: List<IStatement>,
|
var lines: List<IStatement>) : Node {
|
||||||
override val position: Position? = null) : Node {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent=parent
|
||||||
|
}
|
||||||
|
fun linkParents() {
|
||||||
|
parent = null
|
||||||
|
lines.forEach {it.linkParents(this)}
|
||||||
|
}
|
||||||
|
|
||||||
fun process(processor: IAstProcessor): Module {
|
fun process(processor: IAstProcessor): Module {
|
||||||
lines = lines.map { it.process(processor) }
|
lines = lines.map { it.process(processor) }
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Block(val name: String, val address: Int?, var statements: List<IStatement>,
|
|
||||||
override val position: Position? = null) : IStatement {
|
data class Block(val name: String,
|
||||||
override fun process(processor: IAstProcessor) : IStatement {
|
val address: Int?,
|
||||||
statements = statements.map { it.process(processor) }
|
var statements: List<IStatement>) : IStatement {
|
||||||
return this
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
statements.forEach {it.linkParents(this)}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data class Directive(val directive: String, val args: List<DirectiveArg>) : IStatement {
|
||||||
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
args.forEach{it.linkParents(this)}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data class DirectiveArg(val str: String?, val name: String?, val int: Int?) : Node {
|
||||||
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Directive(val directive: String, val args: List<DirectiveArg>,
|
|
||||||
override val position: Position? = null) : IStatement {
|
data class Label(val name: String) : IStatement {
|
||||||
override fun process(processor: IAstProcessor) : IStatement {
|
override var position: Position? = null
|
||||||
return processor.process(this)
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
data class DirectiveArg(val str: String?, val name: String?, val int: Int?,
|
|
||||||
override val position: Position? = null) : Node
|
|
||||||
|
|
||||||
data class Label(val name: String,
|
|
||||||
override val position: Position? = null) : IStatement {
|
|
||||||
override fun process(processor: IAstProcessor) = this
|
override fun process(processor: IAstProcessor) = this
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Return(var values: List<IExpression>,
|
|
||||||
override val position: Position? = null) : IStatement {
|
data class Return(var values: List<IExpression>) : IStatement {
|
||||||
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
values.forEach {it.linkParents(this)}
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
override fun process(processor: IAstProcessor): IStatement {
|
||||||
values = values.map { it.process(processor) }
|
values = values.map { it.process(processor) }
|
||||||
return this
|
return this
|
||||||
@ -105,52 +154,57 @@ data class Return(var values: List<IExpression>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface IVarDecl : IStatement {
|
data class ArraySpec(var x: IExpression, var y: IExpression?) : Node {
|
||||||
val datatype: DataType
|
override var position: Position? = null
|
||||||
val arrayspec: ArraySpec?
|
override var parent: Node? = null
|
||||||
val name: String
|
|
||||||
var value: IExpression?
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ArraySpec(var x: IExpression,
|
override fun linkParents(parent: Node) {
|
||||||
var y: IExpression?,
|
this.parent = parent
|
||||||
override val position: Position? = null) : Node
|
x.linkParents(this)
|
||||||
|
y?.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
data class VarDecl(override val datatype: DataType,
|
fun process(processor: IAstProcessor) {
|
||||||
override val arrayspec: ArraySpec?,
|
x = x.process(processor)
|
||||||
override val name: String,
|
y = y?.process(processor)
|
||||||
override var value: IExpression?,
|
|
||||||
override val position: Position? = null) : IVarDecl {
|
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
|
||||||
value = value?.process(processor)
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ConstDecl(override val datatype: DataType,
|
|
||||||
override val arrayspec: ArraySpec?,
|
enum class VarDeclType {
|
||||||
override val name: String,
|
VAR,
|
||||||
override var value: IExpression?,
|
CONST,
|
||||||
override val position: Position? = null) : IVarDecl {
|
MEMORY
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
|
||||||
value = value?.process(processor)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MemoryVarDecl(override val datatype: DataType,
|
data class VarDecl(val type: VarDeclType,
|
||||||
override val arrayspec: ArraySpec?,
|
val datatype: DataType,
|
||||||
override val name: String,
|
val arrayspec: ArraySpec?,
|
||||||
override var value: IExpression?,
|
val name: String,
|
||||||
override val position: Position? = null) : IVarDecl {
|
var value: IExpression?) : IStatement {
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
override var position: Position? = null
|
||||||
value = value?.process(processor)
|
override var parent: Node? = null
|
||||||
return this
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
arrayspec?.linkParents(this)
|
||||||
|
value?.linkParents(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun process(processor: IAstProcessor) = processor.process(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExpression,
|
|
||||||
override val position: Position? = null) : IStatement {
|
data class Assignment(var target: AssignTarget, val aug_op : String?, var value: IExpression) : IStatement {
|
||||||
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
target.linkParents(this)
|
||||||
|
value.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
override fun process(processor: IAstProcessor): IStatement {
|
||||||
target = target.process(processor)
|
target = target.process(processor)
|
||||||
value = value.process(processor)
|
value = value.process(processor)
|
||||||
@ -158,8 +212,15 @@ data class Assignment(var target: AssignTarget, val aug_op : String?, var value:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AssignTarget(val register: Register?, val identifier: Identifier?,
|
data class AssignTarget(val register: Register?, val identifier: Identifier?) : Node {
|
||||||
override val position: Position? = null) : Node {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
identifier?.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
fun process(processor: IAstProcessor) = this // for now
|
fun process(processor: IAstProcessor) = this // for now
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,8 +233,15 @@ interface IExpression: Node {
|
|||||||
|
|
||||||
// note: some expression elements are mutable, to be able to rewrite/process the expression tree
|
// note: some expression elements are mutable, to be able to rewrite/process the expression tree
|
||||||
|
|
||||||
data class PrefixExpression(val operator: String, var expression: IExpression,
|
data class PrefixExpression(val operator: String, var expression: IExpression) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
expression.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? {
|
override fun constValue(): LiteralValue? {
|
||||||
throw ExpressionException("should have been optimized away before const value was asked")
|
throw ExpressionException("should have been optimized away before const value was asked")
|
||||||
}
|
}
|
||||||
@ -182,8 +250,16 @@ data class PrefixExpression(val operator: String, var expression: IExpression,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression,
|
data class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
left.linkParents(this)
|
||||||
|
right.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? {
|
override fun constValue(): LiteralValue? {
|
||||||
throw ExpressionException("should have been optimized away before const value was asked")
|
throw ExpressionException("should have been optimized away before const value was asked")
|
||||||
}
|
}
|
||||||
@ -194,15 +270,54 @@ data class BinaryExpression(var left: IExpression, val operator: String, var rig
|
|||||||
data class LiteralValue(val intvalue: Int? = null,
|
data class LiteralValue(val intvalue: Int? = null,
|
||||||
val floatvalue: Double? = null,
|
val floatvalue: Double? = null,
|
||||||
val strvalue: String? = null,
|
val strvalue: String? = null,
|
||||||
val arrayvalue: List<IExpression>? = null,
|
val arrayvalue: List<IExpression>? = null) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
fun asInt(): Int? {
|
||||||
|
return when {
|
||||||
|
intvalue!=null -> intvalue
|
||||||
|
floatvalue!=null -> floatvalue.toInt()
|
||||||
|
else -> {
|
||||||
|
if(strvalue!=null || arrayvalue!=null)
|
||||||
|
throw AstException("attempt to get int value from non-integer $this")
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun asFloat(): Double? {
|
||||||
|
return when {
|
||||||
|
floatvalue!=null -> floatvalue
|
||||||
|
intvalue!=null -> intvalue.toDouble()
|
||||||
|
else -> {
|
||||||
|
if(strvalue!=null || arrayvalue!=null)
|
||||||
|
throw AstException("attempt to get float value from non-integer $this")
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
arrayvalue?.forEach {it.linkParents(this)}
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? = this
|
override fun constValue(): LiteralValue? = this
|
||||||
override fun process(processor: IAstProcessor) = this
|
override fun process(processor: IAstProcessor) = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class RangeExpr(var from: IExpression, var to: IExpression,
|
data class RangeExpr(var from: IExpression, var to: IExpression) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
from.linkParents(this)
|
||||||
|
to.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? = null
|
override fun constValue(): LiteralValue? = null
|
||||||
override fun process(processor: IAstProcessor): IExpression {
|
override fun process(processor: IAstProcessor): IExpression {
|
||||||
from = from.process(processor)
|
from = from.process(processor)
|
||||||
@ -212,15 +327,27 @@ data class RangeExpr(var from: IExpression, var to: IExpression,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class RegisterExpr(val register: Register,
|
data class RegisterExpr(val register: Register) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? = null
|
override fun constValue(): LiteralValue? = null
|
||||||
override fun process(processor: IAstProcessor) = this
|
override fun process(processor: IAstProcessor) = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class Identifier(val name: String, val scope: List<String>,
|
data class Identifier(val name: String, val scope: List<String>) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? {
|
override fun constValue(): LiteralValue? {
|
||||||
// @todo should look up the identifier and return its value if that is a compile time const
|
// @todo should look up the identifier and return its value if that is a compile time const
|
||||||
return null
|
return null
|
||||||
@ -230,14 +357,28 @@ data class Identifier(val name: String, val scope: List<String>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class CallTarget(val address: Int?, val identifier: Identifier?,
|
data class CallTarget(val address: Int?, val identifier: Identifier?) : Node {
|
||||||
override val position: Position? = null) : Node {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
identifier?.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
fun process(processor: IAstProcessor) = this
|
fun process(processor: IAstProcessor) = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class PostIncrDecr(var target: AssignTarget, val operator: String,
|
data class PostIncrDecr(var target: AssignTarget, val operator: String) : IStatement {
|
||||||
override val position: Position? = null) : IStatement {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
target.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
override fun process(processor: IAstProcessor): IStatement {
|
||||||
target = target.process(processor)
|
target = target.process(processor)
|
||||||
return this
|
return this
|
||||||
@ -245,8 +386,15 @@ data class PostIncrDecr(var target: AssignTarget, val operator: String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class Jump(var target: CallTarget,
|
data class Jump(var target: CallTarget) : IStatement {
|
||||||
override val position: Position? = null) : IStatement {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
target.linkParents(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor): IStatement {
|
override fun process(processor: IAstProcessor): IStatement {
|
||||||
target = target.process(processor)
|
target = target.process(processor)
|
||||||
return this
|
return this
|
||||||
@ -254,8 +402,16 @@ data class Jump(var target: CallTarget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>,
|
data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>) : IExpression {
|
||||||
override val position: Position? = null) : IExpression {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
target.linkParents(this)
|
||||||
|
arglist.forEach { it.linkParents(this) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun constValue(): LiteralValue? {
|
override fun constValue(): LiteralValue? {
|
||||||
// if the function is a built-in function and the args are consts, should evaluate!
|
// if the function is a built-in function and the args are consts, should evaluate!
|
||||||
return null
|
return null
|
||||||
@ -269,8 +425,14 @@ data class FunctionCall(var target: CallTarget, var arglist: List<IExpression>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class InlineAssembly(val assembly: String,
|
data class InlineAssembly(val assembly: String) : IStatement {
|
||||||
override val position: Position? = null) : IStatement {
|
override var position: Position? = null
|
||||||
|
override var parent: Node? = null
|
||||||
|
|
||||||
|
override fun linkParents(parent: Node) {
|
||||||
|
this.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(processor: IAstProcessor) = this
|
override fun process(processor: IAstProcessor) = this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,14 +441,18 @@ data class InlineAssembly(val assembly: String,
|
|||||||
|
|
||||||
fun ParserRuleContext.toPosition(withPosition: Boolean) : Position? {
|
fun ParserRuleContext.toPosition(withPosition: Boolean) : Position? {
|
||||||
return if (withPosition)
|
return if (withPosition)
|
||||||
|
// note: be ware of TAB characters in the source text, they count as 1 column...
|
||||||
Position(start.line, start.charPositionInLine, stop.charPositionInLine+stop.text.length)
|
Position(start.line, start.charPositionInLine, stop.charPositionInLine+stop.text.length)
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) =
|
fun il65Parser.ModuleContext.toAst(name: String, withPosition: Boolean) : Module {
|
||||||
Module(name, modulestatement().map { it.toAst(withPosition) }, toPosition(withPosition))
|
val module = Module(name, modulestatement().map { it.toAst(withPosition) })
|
||||||
|
module.position = toPosition(withPosition)
|
||||||
|
return module
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : IStatement {
|
fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : IStatement {
|
||||||
@ -301,89 +467,112 @@ fun il65Parser.ModulestatementContext.toAst(withPosition: Boolean) : IStatement
|
|||||||
|
|
||||||
|
|
||||||
fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
|
fun il65Parser.BlockContext.toAst(withPosition: Boolean) : IStatement {
|
||||||
return Block(identifier().text,
|
val block= Block(identifier().text,
|
||||||
integerliteral()?.toAst(),
|
integerliteral()?.toAst(),
|
||||||
statement().map { it.toAst(withPosition) },
|
statement().map { it.toAst(withPosition) })
|
||||||
toPosition(withPosition))
|
block.position = toPosition(withPosition)
|
||||||
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
|
fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
|
||||||
val vardecl = vardecl()
|
val vardecl = vardecl()
|
||||||
if(vardecl!=null) {
|
if(vardecl!=null) {
|
||||||
return VarDecl(vardecl.datatype().toAst(),
|
val decl= VarDecl(VarDeclType.VAR,
|
||||||
|
vardecl.datatype().toAst(),
|
||||||
vardecl.arrayspec()?.toAst(withPosition),
|
vardecl.arrayspec()?.toAst(withPosition),
|
||||||
vardecl.identifier().text,
|
vardecl.identifier().text,
|
||||||
null,
|
null)
|
||||||
vardecl.toPosition(withPosition))
|
decl.position = vardecl.toPosition(withPosition)
|
||||||
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
val varinit = varinitializer()
|
val varinit = varinitializer()
|
||||||
if(varinit!=null) {
|
if(varinit!=null) {
|
||||||
return VarDecl(varinit.datatype().toAst(),
|
val decl= VarDecl(VarDeclType.VAR,
|
||||||
|
varinit.datatype().toAst(),
|
||||||
varinit.arrayspec()?.toAst(withPosition),
|
varinit.arrayspec()?.toAst(withPosition),
|
||||||
varinit.identifier().text,
|
varinit.identifier().text,
|
||||||
varinit.expression().toAst(withPosition),
|
varinit.expression().toAst(withPosition))
|
||||||
varinit.toPosition(withPosition))
|
decl.position = varinit.toPosition(withPosition)
|
||||||
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
val constdecl = constdecl()
|
val constdecl = constdecl()
|
||||||
if(constdecl!=null) {
|
if(constdecl!=null) {
|
||||||
val cvarinit = constdecl.varinitializer()
|
val cvarinit = constdecl.varinitializer()
|
||||||
return ConstDecl(cvarinit.datatype().toAst(),
|
val decl = VarDecl(VarDeclType.CONST,
|
||||||
|
cvarinit.datatype().toAst(),
|
||||||
cvarinit.arrayspec()?.toAst(withPosition),
|
cvarinit.arrayspec()?.toAst(withPosition),
|
||||||
cvarinit.identifier().text,
|
cvarinit.identifier().text,
|
||||||
cvarinit.expression().toAst(withPosition),
|
cvarinit.expression().toAst(withPosition))
|
||||||
cvarinit.toPosition(withPosition))
|
decl.position = cvarinit.toPosition(withPosition)
|
||||||
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
val memdecl = memoryvardecl()
|
val memdecl = memoryvardecl()
|
||||||
if(memdecl!=null) {
|
if(memdecl!=null) {
|
||||||
val mvarinit = memdecl.varinitializer()
|
val mvarinit = memdecl.varinitializer()
|
||||||
return MemoryVarDecl(mvarinit.datatype().toAst(),
|
val decl = VarDecl(VarDeclType.MEMORY,
|
||||||
|
mvarinit.datatype().toAst(),
|
||||||
mvarinit.arrayspec()?.toAst(withPosition),
|
mvarinit.arrayspec()?.toAst(withPosition),
|
||||||
mvarinit.identifier().text,
|
mvarinit.identifier().text,
|
||||||
mvarinit.expression().toAst(withPosition),
|
mvarinit.expression().toAst(withPosition))
|
||||||
mvarinit.toPosition(withPosition))
|
decl.position = mvarinit.toPosition(withPosition)
|
||||||
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
val assign = assignment()
|
val assign = assignment()
|
||||||
if (assign!=null) {
|
if (assign!=null) {
|
||||||
return Assignment(assign.assign_target().toAst(withPosition),
|
val ast =Assignment(assign.assign_target().toAst(withPosition),
|
||||||
null, assign.expression().toAst(withPosition),
|
null, assign.expression().toAst(withPosition))
|
||||||
assign.toPosition(withPosition))
|
ast.position = assign.toPosition(withPosition)
|
||||||
|
return ast
|
||||||
}
|
}
|
||||||
|
|
||||||
val augassign = augassignment()
|
val augassign = augassignment()
|
||||||
if (augassign!=null)
|
if (augassign!=null) {
|
||||||
return Assignment(augassign.assign_target().toAst(withPosition),
|
val aug= Assignment(augassign.assign_target().toAst(withPosition),
|
||||||
augassign.operator.text,
|
augassign.operator.text,
|
||||||
augassign.expression().toAst(withPosition),
|
augassign.expression().toAst(withPosition))
|
||||||
augassign.toPosition(withPosition))
|
aug.position = augassign.toPosition(withPosition)
|
||||||
|
return aug
|
||||||
|
}
|
||||||
|
|
||||||
val post = postincrdecr()
|
val post = postincrdecr()
|
||||||
if(post!=null)
|
if(post!=null) {
|
||||||
return PostIncrDecr(post.assign_target().toAst(withPosition),
|
val ast = PostIncrDecr(post.assign_target().toAst(withPosition), post.operator.text)
|
||||||
post.operator.text, post.toPosition(withPosition))
|
ast.position = post.toPosition(withPosition)
|
||||||
|
return ast
|
||||||
|
}
|
||||||
|
|
||||||
val directive = directive()?.toAst(withPosition)
|
val directive = directive()?.toAst(withPosition)
|
||||||
if(directive!=null) return directive
|
if(directive!=null) return directive
|
||||||
|
|
||||||
val label=labeldef()
|
val label=labeldef()
|
||||||
if(label!=null)
|
if(label!=null) {
|
||||||
return Label(label.text, label.toPosition(withPosition))
|
val lbl = Label(label.text)
|
||||||
|
lbl.position = label.toPosition(withPosition)
|
||||||
|
return lbl
|
||||||
|
}
|
||||||
|
|
||||||
val jump = unconditionaljump()
|
val jump = unconditionaljump()
|
||||||
if(jump!=null)
|
if(jump!=null) {
|
||||||
return Jump(jump.call_location().toAst(withPosition), jump.toPosition(withPosition))
|
val ast = Jump(jump.call_location().toAst(withPosition))
|
||||||
|
ast.position = jump.toPosition(withPosition)
|
||||||
|
return ast
|
||||||
|
}
|
||||||
|
|
||||||
val returnstmt = returnstmt()
|
val returnstmt = returnstmt()
|
||||||
if(returnstmt!=null)
|
if(returnstmt!=null)
|
||||||
return Return(returnstmt.expression_list().toAst(withPosition))
|
return Return(returnstmt.expression_list().toAst(withPosition))
|
||||||
|
|
||||||
val asm = inlineasm()
|
val asm = inlineasm()
|
||||||
if(asm!=null)
|
if(asm!=null) {
|
||||||
return InlineAssembly(asm.INLINEASMBLOCK().text, asm.toPosition(withPosition))
|
val ast = InlineAssembly(asm.INLINEASMBLOCK().text)
|
||||||
|
ast.position = asm.toPosition(withPosition)
|
||||||
|
return ast
|
||||||
|
}
|
||||||
|
|
||||||
throw UnsupportedOperationException(text)
|
throw UnsupportedOperationException(text)
|
||||||
}
|
}
|
||||||
@ -392,20 +581,23 @@ fun il65Parser.StatementContext.toAst(withPosition: Boolean) : IStatement {
|
|||||||
fun il65Parser.Call_locationContext.toAst(withPosition: Boolean) : CallTarget {
|
fun il65Parser.Call_locationContext.toAst(withPosition: Boolean) : CallTarget {
|
||||||
val address = integerliteral()?.toAst()
|
val address = integerliteral()?.toAst()
|
||||||
val identifier = identifier()
|
val identifier = identifier()
|
||||||
return if(identifier!=null)
|
val result =
|
||||||
CallTarget(address, identifier.toAst(withPosition), toPosition(withPosition))
|
if(identifier!=null) CallTarget(address, identifier.toAst(withPosition))
|
||||||
else
|
else CallTarget(address, scoped_identifier().toAst(withPosition))
|
||||||
CallTarget(address, scoped_identifier().toAst(withPosition), toPosition(withPosition))
|
result.position = toPosition(withPosition)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.Assign_targetContext.toAst(withPosition: Boolean) : AssignTarget {
|
fun il65Parser.Assign_targetContext.toAst(withPosition: Boolean) : AssignTarget {
|
||||||
val register = register()?.toAst()
|
val register = register()?.toAst()
|
||||||
val identifier = identifier()
|
val identifier = identifier()
|
||||||
return if(identifier!=null)
|
val result = if(identifier!=null)
|
||||||
AssignTarget(register, identifier.toAst(withPosition), toPosition(withPosition))
|
AssignTarget(register, identifier.toAst(withPosition))
|
||||||
else
|
else
|
||||||
AssignTarget(register, scoped_identifier()?.toAst(withPosition), toPosition(withPosition))
|
AssignTarget(register, scoped_identifier()?.toAst(withPosition))
|
||||||
|
result.position = toPosition(withPosition)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -415,22 +607,29 @@ fun il65Parser.RegisterContext.toAst() = Register.valueOf(text.toUpperCase())
|
|||||||
fun il65Parser.DatatypeContext.toAst() = DataType.valueOf(text.toUpperCase())
|
fun il65Parser.DatatypeContext.toAst() = DataType.valueOf(text.toUpperCase())
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.ArrayspecContext.toAst(withPosition: Boolean) = ArraySpec(
|
fun il65Parser.ArrayspecContext.toAst(withPosition: Boolean) : ArraySpec {
|
||||||
|
val spec = ArraySpec(
|
||||||
expression(0).toAst(withPosition),
|
expression(0).toAst(withPosition),
|
||||||
if (expression().size > 1) expression(1).toAst(withPosition) else null,
|
if (expression().size > 1) expression(1).toAst(withPosition) else null)
|
||||||
toPosition(withPosition)
|
spec.position = toPosition(withPosition)
|
||||||
)
|
return spec
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.DirectiveContext.toAst(withPosition: Boolean) =
|
fun il65Parser.DirectiveContext.toAst(withPosition: Boolean) : Directive {
|
||||||
Directive(directivename.text, directivearg().map { it.toAst(withPosition) }, toPosition(withPosition))
|
val dir = Directive(directivename.text, directivearg().map { it.toAst(withPosition) })
|
||||||
|
dir.position = toPosition(withPosition)
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) =
|
fun il65Parser.DirectiveargContext.toAst(withPosition: Boolean) : DirectiveArg {
|
||||||
DirectiveArg(stringliteral()?.text,
|
val darg = DirectiveArg(stringliteral()?.text,
|
||||||
identifier()?.text,
|
identifier()?.text,
|
||||||
integerliteral()?.toAst(),
|
integerliteral()?.toAst())
|
||||||
toPosition(withPosition))
|
darg.position = toPosition(withPosition)
|
||||||
|
return darg
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun il65Parser.IntegerliteralContext.toAst(): Int {
|
fun il65Parser.IntegerliteralContext.toAst(): Int {
|
||||||
@ -449,18 +648,23 @@ fun il65Parser.ExpressionContext.toAst(withPosition: Boolean) : IExpression {
|
|||||||
val litval = literalvalue()
|
val litval = literalvalue()
|
||||||
if(litval!=null) {
|
if(litval!=null) {
|
||||||
val booleanlit = litval.booleanliteral()?.toAst()
|
val booleanlit = litval.booleanliteral()?.toAst()
|
||||||
|
val value =
|
||||||
if(booleanlit!=null)
|
if(booleanlit!=null)
|
||||||
return LiteralValue(intvalue = if(booleanlit) 1 else 0)
|
LiteralValue(intvalue = if(booleanlit) 1 else 0)
|
||||||
return LiteralValue(litval.integerliteral()?.toAst(),
|
else
|
||||||
|
LiteralValue(litval.integerliteral()?.toAst(),
|
||||||
litval.floatliteral()?.toAst(),
|
litval.floatliteral()?.toAst(),
|
||||||
litval.stringliteral()?.text,
|
litval.stringliteral()?.text,
|
||||||
litval.arrayliteral()?.toAst(withPosition),
|
litval.arrayliteral()?.toAst(withPosition))
|
||||||
litval.toPosition(withPosition)
|
value.position = litval.toPosition(withPosition)
|
||||||
)
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
if(register()!=null)
|
if(register()!=null) {
|
||||||
return RegisterExpr(register().toAst(), register().toPosition(withPosition))
|
val reg = RegisterExpr(register().toAst())
|
||||||
|
reg.position = register().toPosition(withPosition)
|
||||||
|
return reg
|
||||||
|
}
|
||||||
|
|
||||||
if(identifier()!=null)
|
if(identifier()!=null)
|
||||||
return identifier().toAst(withPosition)
|
return identifier().toAst(withPosition)
|
||||||
@ -468,28 +672,37 @@ fun il65Parser.ExpressionContext.toAst(withPosition: Boolean) : IExpression {
|
|||||||
if(scoped_identifier()!=null)
|
if(scoped_identifier()!=null)
|
||||||
return scoped_identifier().toAst(withPosition)
|
return scoped_identifier().toAst(withPosition)
|
||||||
|
|
||||||
if(bop!=null)
|
if(bop!=null) {
|
||||||
return BinaryExpression(left.toAst(withPosition),
|
val expr = BinaryExpression(left.toAst(withPosition),
|
||||||
bop.text,
|
bop.text,
|
||||||
right.toAst(withPosition),
|
right.toAst(withPosition))
|
||||||
toPosition(withPosition))
|
expr.position = toPosition(withPosition)
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
if(prefix!=null)
|
if(prefix!=null) {
|
||||||
return PrefixExpression(prefix.text,
|
val expr = PrefixExpression(prefix.text,
|
||||||
expression(0).toAst(withPosition),
|
expression(0).toAst(withPosition))
|
||||||
toPosition(withPosition))
|
expr.position = toPosition(withPosition)
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
val funcall = functioncall()
|
val funcall = functioncall()
|
||||||
if(funcall!=null) {
|
if(funcall!=null) {
|
||||||
val location = funcall.call_location().toAst(withPosition)
|
val location = funcall.call_location().toAst(withPosition)
|
||||||
return if(funcall.expression_list()==null)
|
val fcall = if(funcall.expression_list()==null)
|
||||||
FunctionCall(location, emptyList(), funcall.toPosition(withPosition))
|
FunctionCall(location, emptyList())
|
||||||
else
|
else
|
||||||
FunctionCall(location, funcall.expression_list().toAst(withPosition), funcall.toPosition(withPosition))
|
FunctionCall(location, funcall.expression_list().toAst(withPosition))
|
||||||
|
fcall.position = funcall.toPosition(withPosition)
|
||||||
|
return fcall
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rangefrom!=null && rangeto!=null)
|
if (rangefrom!=null && rangeto!=null) {
|
||||||
return RangeExpr(rangefrom.toAst(withPosition), rangeto.toAst(withPosition), toPosition(withPosition))
|
val rexp = RangeExpr(rangefrom.toAst(withPosition), rangeto.toAst(withPosition))
|
||||||
|
rexp.position = toPosition(withPosition)
|
||||||
|
return rexp
|
||||||
|
}
|
||||||
|
|
||||||
if(childCount==3 && children[0].text=="(" && children[2].text==")")
|
if(childCount==3 && children[0].text=="(" && children[2].text==")")
|
||||||
return expression(0).toAst(withPosition) // expression within ( )
|
return expression(0).toAst(withPosition) // expression within ( )
|
||||||
@ -502,7 +715,9 @@ fun il65Parser.Expression_listContext.toAst(withPosition: Boolean) = expression(
|
|||||||
|
|
||||||
|
|
||||||
fun il65Parser.IdentifierContext.toAst(withPosition: Boolean) : Identifier {
|
fun il65Parser.IdentifierContext.toAst(withPosition: Boolean) : Identifier {
|
||||||
return Identifier(text, emptyList(), toPosition(withPosition))
|
val ident = Identifier(text, emptyList())
|
||||||
|
ident.position = toPosition(withPosition)
|
||||||
|
return ident
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -510,7 +725,9 @@ fun il65Parser.Scoped_identifierContext.toAst(withPosition: Boolean) : Identifie
|
|||||||
val names = NAME()
|
val names = NAME()
|
||||||
val name = names.last().text
|
val name = names.last().text
|
||||||
val scope = names.take(names.size-1)
|
val scope = names.take(names.size-1)
|
||||||
return Identifier(name, scope.map { it.text }, toPosition(withPosition))
|
val ident = Identifier(name, scope.map { it.text })
|
||||||
|
ident.position = toPosition(withPosition)
|
||||||
|
return ident
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user