couple of small shortcuts on identifier ast to lookup what it is pointing to

This commit is contained in:
Irmen de Jong 2019-04-12 23:04:19 +02:00
parent f219ae43f7
commit dfcb57a0b0
8 changed files with 31 additions and 29 deletions

View File

@ -1 +1 @@
1.6
1.7

View File

@ -1410,13 +1410,15 @@ class RegisterExpr(val register: Register, override val position: Position) : IE
data class IdentifierReference(val nameInSource: List<String>, override val position: Position) : IExpression {
override lateinit var parent: Node
// TODO make a shortcut for idref.targetStatement(namespace) as VarDecl
fun targetStatement(namespace: INameScope) =
if(nameInSource.size==1 && nameInSource[0] in BuiltinFunctions)
BuiltinFunctionStatementPlaceholder(nameInSource[0], position)
else
namespace.lookup(nameInSource, this)
fun targetVarDecl(namespace: INameScope): VarDecl? = targetStatement(namespace) as? VarDecl
fun targetSubroutine(namespace: INameScope): Subroutine? = targetStatement(namespace) as? Subroutine
override fun linkParents(parent: Node) {
this.parent = parent
}

View File

@ -150,7 +150,7 @@ private class AstChecker(private val namespace: INameScope,
checkResult.add(ExpressionError("register can only loop over bytes", forLoop.position))
} else {
// loop variable
val loopvar = forLoop.loopVar!!.targetStatement(namespace) as? VarDecl
val loopvar = forLoop.loopVar!!.targetVarDecl(namespace)
if(loopvar==null || loopvar.type==VarDeclType.CONST) {
checkResult.add(SyntaxError("for loop requires a variable to loop with", forLoop.position))
@ -456,7 +456,7 @@ private class AstChecker(private val namespace: INameScope,
}
override fun process(addressOf: AddressOf): IExpression {
val variable=addressOf.identifier.targetStatement(namespace) as? VarDecl
val variable=addressOf.identifier.targetVarDecl(namespace)
if(variable==null)
checkResult.add(ExpressionError("pointer-of operand must be the name of a heap variable", addressOf.position))
else {

View File

@ -232,7 +232,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
override fun process(addressOf: AddressOf): IExpression {
// register the scoped name of the referenced identifier
val variable= addressOf.identifier.targetStatement(namespace) as? VarDecl ?: return addressOf
val variable= addressOf.identifier.targetVarDecl(namespace) ?: return addressOf
addressOf.scopedname = variable.scopedname
return super.process(addressOf)
}

View File

@ -254,7 +254,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
override fun process(functionCall: FunctionCall): IExpression {
val targetStatement = functionCall.target.targetStatement(namespace) as? Subroutine
val targetStatement = functionCall.target.targetSubroutine(namespace)
if(targetStatement!=null) {
var node: Node = functionCall
while(node !is IStatement)
@ -265,7 +265,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
}
override fun process(functionCallStatement: FunctionCallStatement): IStatement {
val targetStatement = functionCallStatement.target.targetStatement(namespace) as? Subroutine
val targetStatement = functionCallStatement.target.targetSubroutine(namespace)
if(targetStatement!=null)
addAddressOfExprIfNeeded(targetStatement, functionCallStatement.arglist, functionCallStatement)
return functionCallStatement
@ -280,7 +280,7 @@ private class VarInitValueAndAddressOfCreator(private val namespace: INameScope)
val idref = argparam.second as? IdentifierReference
val strvalue = argparam.second as? LiteralValue
if(idref!=null) {
val variable = idref.targetStatement(namespace) as? VarDecl
val variable = idref.targetVarDecl(namespace)
if(variable!=null && (variable.datatype in StringDatatypes || variable.datatype in ArrayDatatypes)) {
val pointerExpr = AddressOf(idref, idref.position)
pointerExpr.scopedname = parent.makeScopedName(idref.nameInSource.single())

View File

@ -818,7 +818,7 @@ internal class Compiler(private val rootModule: Module,
"any", "all" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
prog.instr(Opcode.PUSH_BYTE, length)
when (arg.resultingDatatype(namespace, heap)) {
@ -831,7 +831,7 @@ internal class Compiler(private val rootModule: Module,
"avg" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
val arrayDt=arg.resultingDatatype(namespace, heap)
prog.instr(Opcode.PUSH_BYTE, length)
@ -862,7 +862,7 @@ internal class Compiler(private val rootModule: Module,
"min", "max", "sum" -> {
// 1 array argument, type determines the exact syscall to use
val arg=args.single() as IdentifierReference
val target=arg.targetStatement(namespace) as VarDecl
val target=arg.targetVarDecl(namespace)!!
val length=Value(DataType.UBYTE, target.arrayspec!!.size()!!)
prog.instr(Opcode.PUSH_BYTE, length)
when (arg.resultingDatatype(namespace, heap)) {
@ -1383,7 +1383,7 @@ internal class Compiler(private val rootModule: Module,
}
private fun translate(arrayindexed: ArrayIndexedExpression, write: Boolean) {
val variable = arrayindexed.identifier.targetStatement(namespace) as VarDecl
val variable = arrayindexed.identifier.targetVarDecl(namespace)!!
translate(arrayindexed.arrayspec.x)
if (write)
prog.instr(opcodeWriteindexedvar(variable.datatype), callLabel = variable.scopedname)
@ -1434,14 +1434,14 @@ internal class Compiler(private val rootModule: Module,
"--" -> prog.instr(Opcode.DEC_VAR_UB, callLabel = stmt.target.register!!.name)
}
stmt.target.identifier != null -> {
val targetStatement = stmt.target.identifier!!.targetStatement(namespace) as VarDecl
val targetStatement = stmt.target.identifier!!.targetVarDecl(namespace)!!
when(stmt.operator) {
"++" -> prog.instr(opcodeIncvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
"--" -> prog.instr(opcodeDecvar(targetStatement.datatype), callLabel = targetStatement.scopedname)
}
}
stmt.target.arrayindexed != null -> {
val variable = stmt.target.arrayindexed!!.identifier.targetStatement(namespace) as VarDecl
val variable = stmt.target.arrayindexed!!.identifier.targetVarDecl(namespace)!!
translate(stmt.target.arrayindexed!!.arrayspec.x)
when(stmt.operator) {
"++" -> prog.instr(opcodeIncArrayindexedVar(variable.datatype), callLabel = variable.scopedname)
@ -1501,7 +1501,7 @@ internal class Compiler(private val rootModule: Module,
DataType.STR, DataType.STR_S -> pushHeapVarAddress(stmt.value, true)
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_F -> {
if (stmt.value is IdentifierReference) {
val vardecl = (stmt.value as IdentifierReference).targetStatement(namespace) as VarDecl
val vardecl = (stmt.value as IdentifierReference).targetVarDecl(namespace)!!
prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
@ -1538,7 +1538,7 @@ internal class Compiler(private val rootModule: Module,
when (value) {
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
val vardecl = value.targetVarDecl(namespace)!!
if(removeLastOpcode) prog.removeLastInstruction()
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
@ -1550,7 +1550,7 @@ internal class Compiler(private val rootModule: Module,
when (value) {
is LiteralValue -> throw CompilerException("can only push address of float that is a variable on the heap")
is IdentifierReference -> {
val vardecl = value.targetStatement(namespace) as VarDecl
val vardecl = value.targetVarDecl(namespace)!!
prog.instr(Opcode.PUSH_ADDR_HEAPVAR, callLabel = vardecl.scopedname)
}
else -> throw CompilerException("can only take address of a the float as constant literal or variable")
@ -1629,7 +1629,7 @@ internal class Compiler(private val rootModule: Module,
loopVarName = reg.name
loopVarDt = DataType.UBYTE
} else {
val loopvar = (loop.loopVar!!.targetStatement(namespace) as VarDecl)
val loopvar = loop.loopVar!!.targetVarDecl(namespace)!!
loopVarName = loopvar.scopedname
loopVarDt = loopvar.datatype
}
@ -1678,7 +1678,7 @@ internal class Compiler(private val rootModule: Module,
when {
loop.iterable is IdentifierReference -> {
val idRef = loop.iterable as IdentifierReference
val vardecl = (idRef.targetStatement(namespace) as VarDecl)
val vardecl = idRef.targetVarDecl(namespace)!!
val iterableValue = vardecl.value as LiteralValue
if(!iterableValue.isIterable(namespace, heap))
throw CompilerException("loop over something that isn't iterable ${loop.iterable}")
@ -1942,7 +1942,7 @@ internal class Compiler(private val rootModule: Module,
lvTarget.linkParents(body)
val targetStatement: VarDecl? =
if(lvTarget.identifier!=null) {
lvTarget.identifier.targetStatement(namespace) as VarDecl
lvTarget.identifier.targetVarDecl(namespace)
} else {
null
}
@ -2138,7 +2138,7 @@ internal class Compiler(private val rootModule: Module,
}
private fun translate(addrof: AddressOf) {
val target = addrof.identifier.targetStatement(namespace) as VarDecl
val target = addrof.identifier.targetVarDecl(namespace)!!
if(target.datatype in ArrayDatatypes || target.datatype in StringDatatypes|| target.datatype==DataType.FLOAT) {
pushHeapVarAddress(addrof.identifier, false)
}

View File

@ -156,7 +156,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
}
private fun typeCastConstArguments(functionCall: IFunctionCall) {
val subroutine = functionCall.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCall.target.targetSubroutine(namespace)
if(subroutine!=null) {
// if types differ, try to typecast constant arguments to the function call to the desired data type of the parameter
for(arg in functionCall.arglist.withIndex().zip(subroutine.parameters)) {
@ -493,7 +493,7 @@ class ConstantFolding(private val namespace: INameScope, private val heap: HeapV
val rangeTo = iterableRange.to as? LiteralValue
if(rangeFrom==null || rangeTo==null) return resultStmt
val loopvar = resultStmt.loopVar!!.targetStatement(namespace) as? VarDecl
val loopvar = resultStmt.loopVar!!.targetVarDecl(namespace)
if(loopvar!=null) {
val stepLiteral = iterableRange.step as? LiteralValue
when(loopvar.datatype) {

View File

@ -101,12 +101,12 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
if(target.memoryAddress!=null)
return false
if(target.arrayindexed!=null) {
val targetStmt = target.arrayindexed.identifier.targetStatement(namespace) as? VarDecl
val targetStmt = target.arrayindexed.identifier.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!=VarDeclType.MEMORY
}
if(target.identifier!=null) {
val targetStmt = target.identifier.targetStatement(namespace) as? VarDecl
val targetStmt = target.identifier.targetVarDecl(namespace)
if(targetStmt!=null)
return targetStmt.type!=VarDeclType.MEMORY
}
@ -156,7 +156,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
// if it calls a subroutine,
// and the first instruction in the subroutine is a jump, call that jump target instead
// if the first instruction in the subroutine is a return statement, replace with a nop instruction
val subroutine = functionCallStatement.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCallStatement.target.targetSubroutine(namespace)
if(subroutine!=null) {
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
if(first is Jump && first.identifier!=null) {
@ -176,7 +176,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
// if it calls a subroutine,
// and the first instruction in the subroutine is a jump, call that jump target instead
// if the first instruction in the subroutine is a return statement with constant value, replace with the constant value
val subroutine = functionCall.target.targetStatement(namespace) as? Subroutine
val subroutine = functionCall.target.targetSubroutine(namespace)
if(subroutine!=null) {
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
if(first is Jump && first.identifier!=null) {
@ -341,7 +341,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
}
override fun process(jump: Jump): IStatement {
val subroutine = jump.identifier?.targetStatement(namespace) as? Subroutine
val subroutine = jump.identifier?.targetSubroutine(namespace)
if(subroutine!=null) {
// if the first instruction in the subroutine is another jump, shortcut this one
val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
@ -380,7 +380,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
if (same(target, bexpr.left)) {
// remove assignments that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
// A = A <operator> B
val vardeclDt = (target.identifier?.targetStatement(namespace) as? VarDecl)?.type
val vardeclDt = (target.identifier?.targetVarDecl(namespace))?.type
when (bexpr.operator) {
"+" -> {