mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
couple of small shortcuts on identifier ast to lookup what it is pointing to
This commit is contained in:
parent
f219ae43f7
commit
dfcb57a0b0
@ -1 +1 @@
|
||||
1.6
|
||||
1.7
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
"+" -> {
|
||||
|
Loading…
Reference in New Issue
Block a user