mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
struct fixes
This commit is contained in:
parent
9f6fa60bf1
commit
717b5f3b07
@ -571,7 +571,7 @@ private fun prog8Parser.When_choiceContext.toAst(): WhenChoice {
|
|||||||
|
|
||||||
private fun prog8Parser.VardeclContext.toAst(): VarDecl {
|
private fun prog8Parser.VardeclContext.toAst(): VarDecl {
|
||||||
return VarDecl(
|
return VarDecl(
|
||||||
if(structname!=null) VarDeclType.STRUCT else VarDeclType.VAR,
|
VarDeclType.VAR,
|
||||||
datatype()?.toAst() ?: DataType.STRUCT,
|
datatype()?.toAst() ?: DataType.STRUCT,
|
||||||
ZEROPAGE() != null,
|
ZEROPAGE() != null,
|
||||||
arrayindex()?.toAst(),
|
arrayindex()?.toAst(),
|
||||||
|
@ -94,8 +94,7 @@ enum class BranchCondition {
|
|||||||
enum class VarDeclType {
|
enum class VarDeclType {
|
||||||
VAR,
|
VAR,
|
||||||
CONST,
|
CONST,
|
||||||
MEMORY,
|
MEMORY
|
||||||
STRUCT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val IterableDatatypes = setOf(
|
val IterableDatatypes = setOf(
|
||||||
|
@ -6,7 +6,7 @@ import prog8.ast.processing.*
|
|||||||
import prog8.ast.statements.Assignment
|
import prog8.ast.statements.Assignment
|
||||||
import prog8.ast.statements.ForLoop
|
import prog8.ast.statements.ForLoop
|
||||||
import prog8.compiler.CompilationOptions
|
import prog8.compiler.CompilationOptions
|
||||||
import prog8.optimizer.RemoveNops
|
import prog8.optimizer.FlattenAnonymousScopesAndRemoveNops
|
||||||
|
|
||||||
|
|
||||||
// the name of the subroutine that should be called for every block to initialize its variables
|
// the name of the subroutine that should be called for every block to initialize its variables
|
||||||
@ -17,9 +17,9 @@ internal const val initvarsSubName="prog8_init_vars"
|
|||||||
internal const val autoHeapValuePrefix = "auto_heap_value_"
|
internal const val autoHeapValuePrefix = "auto_heap_value_"
|
||||||
|
|
||||||
|
|
||||||
internal fun Program.removeNops() {
|
internal fun Program.removeNopsFlattenAnonScopes() {
|
||||||
val remover = RemoveNops()
|
val flattener = FlattenAnonymousScopesAndRemoveNops()
|
||||||
remover.visit(this)
|
flattener.visit(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -489,6 +489,14 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
when(decl.type) {
|
when(decl.type) {
|
||||||
VarDeclType.VAR, VarDeclType.CONST -> {
|
VarDeclType.VAR, VarDeclType.CONST -> {
|
||||||
|
if(decl.struct!=null || decl.datatype==DataType.STRUCT) {
|
||||||
|
if(decl.datatype!=DataType.STRUCT)
|
||||||
|
throw FatalAstException("struct vardecl should be of data type struct $decl")
|
||||||
|
if(decl.struct==null)
|
||||||
|
throw FatalAstException("struct vardecl should be linked to its struct $decl")
|
||||||
|
if(decl.zeropage)
|
||||||
|
err("struct can not be in zeropage")
|
||||||
|
}
|
||||||
if (decl.value == null) {
|
if (decl.value == null) {
|
||||||
when {
|
when {
|
||||||
decl.datatype in NumericDatatypes -> {
|
decl.datatype in NumericDatatypes -> {
|
||||||
@ -502,6 +510,9 @@ internal class AstChecker(private val program: Program,
|
|||||||
litVal.parent = decl
|
litVal.parent = decl
|
||||||
decl.value = litVal
|
decl.value = litVal
|
||||||
}
|
}
|
||||||
|
decl.datatype == DataType.STRUCT -> {
|
||||||
|
// TODO structs are not initialized with a literal value yet, should be an array of zeros!
|
||||||
|
}
|
||||||
decl.type== VarDeclType.VAR -> {
|
decl.type== VarDeclType.VAR -> {
|
||||||
val litVal = LiteralValue(decl.datatype, initHeapId = heapStringSentinel, position = decl.position) // point to the sentinel heap value instead
|
val litVal = LiteralValue(decl.datatype, initHeapId = heapStringSentinel, position = decl.position) // point to the sentinel heap value instead
|
||||||
litVal.parent=decl
|
litVal.parent=decl
|
||||||
@ -558,16 +569,6 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VarDeclType.STRUCT -> {
|
|
||||||
if(decl.struct==null)
|
|
||||||
throw FatalAstException("struct vardecl should be linked to its struct $decl")
|
|
||||||
if(decl.datatype!=DataType.STRUCT)
|
|
||||||
throw FatalAstException("struct vardecl should be of data type struct $decl")
|
|
||||||
if(decl.zeropage)
|
|
||||||
err("struct can not be in zeropage")
|
|
||||||
if(decl.value!=null)
|
|
||||||
err("struct can not have an initialization value") // TODO allow struct to have initalization values
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.visit(decl)
|
return super.visit(decl)
|
||||||
@ -1274,7 +1275,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
else {
|
else {
|
||||||
if(decl.zeropage)
|
if(decl.zeropage)
|
||||||
checkResult.add(SyntaxError("struct can not contain zeropage members", decl.position))
|
checkResult.add(SyntaxError("struct can not contain zeropage members", decl.position))
|
||||||
if(decl.type == VarDeclType.STRUCT)
|
if(decl.datatype==DataType.STRUCT)
|
||||||
checkResult.add(SyntaxError("structs can not be nested", decl.position))
|
checkResult.add(SyntaxError("structs can not be nested", decl.position))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
|
|
||||||
// is it a struct variable? then define all its struct members as mangled names,
|
// is it a struct variable? then define all its struct members as mangled names,
|
||||||
// and include the original decl as well.
|
// and include the original decl as well.
|
||||||
if(decl.type==VarDeclType.STRUCT) {
|
if(decl.datatype==DataType.STRUCT) {
|
||||||
if(decl.structHasBeenFlattened)
|
if(decl.structHasBeenFlattened)
|
||||||
return decl // don't do this multiple times
|
return decl // don't do this multiple times
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ import prog8.ast.expressions.FunctionCall
|
|||||||
import prog8.ast.expressions.IdentifierReference
|
import prog8.ast.expressions.IdentifierReference
|
||||||
import prog8.ast.expressions.LiteralValue
|
import prog8.ast.expressions.LiteralValue
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
import prog8.compiler.CompilerException
|
||||||
|
|
||||||
|
|
||||||
internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope): IAstModifyingVisitor {
|
internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope): IAstModifyingVisitor {
|
||||||
// For VarDecls that declare an initialization value:
|
// For VarDecls that declare an initialization value:
|
||||||
@ -59,6 +61,24 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
|||||||
decl.position
|
decl.position
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(decl.datatype==DataType.STRUCT) {
|
||||||
|
// a struct initialization value
|
||||||
|
// flatten it to assignment statements
|
||||||
|
val sourceArray = (decl.value as LiteralValue).arrayvalue!!
|
||||||
|
val memberAssignments = decl.struct!!.statements.zip(sourceArray).map { member ->
|
||||||
|
val memberDecl = member.first as VarDecl
|
||||||
|
val mangled = mangledStructMemberName(decl.name, memberDecl.name)
|
||||||
|
val idref = IdentifierReference(listOf(mangled), decl.position)
|
||||||
|
val target = AssignTarget(null, idref, null, null, decl.position)
|
||||||
|
val assign = VariableInitializationAssignment(target, null, member.second, member.second.position)
|
||||||
|
assign
|
||||||
|
}
|
||||||
|
val scope = AnonymousScope(memberAssignments.toMutableList(), decl.position)
|
||||||
|
scope.linkParents(decl.parent)
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,16 +103,10 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(decl: VarDecl) {
|
override fun visit(decl: VarDecl) {
|
||||||
// if(decl.hiddenButDoNotRemove) {
|
|
||||||
// // skip autogenerated vardecl
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
when(decl.type) {
|
when(decl.type) {
|
||||||
VarDeclType.VAR -> {}
|
VarDeclType.VAR -> {}
|
||||||
VarDeclType.CONST -> output("const ")
|
VarDeclType.CONST -> output("const ")
|
||||||
VarDeclType.MEMORY -> output("&")
|
VarDeclType.MEMORY -> output("&")
|
||||||
VarDeclType.STRUCT -> output("${decl.struct!!.name} ")
|
|
||||||
}
|
}
|
||||||
output(decl.struct?.name ?: "")
|
output(decl.struct?.name ?: "")
|
||||||
output(datatypeString(decl.datatype))
|
output(datatypeString(decl.datatype))
|
||||||
@ -185,7 +179,7 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
|||||||
private fun outputStatements(statements: List<IStatement>) {
|
private fun outputStatements(statements: List<IStatement>) {
|
||||||
for(stmt in statements) {
|
for(stmt in statements) {
|
||||||
if(stmt is VarDecl && stmt.hiddenButDoNotRemove)
|
if(stmt is VarDecl && stmt.hiddenButDoNotRemove)
|
||||||
continue // skip autogenerated decls
|
continue // skip autogenerated decls (to avoid generating a newline)
|
||||||
outputi("")
|
outputi("")
|
||||||
stmt.accept(this)
|
stmt.accept(this)
|
||||||
output("\n")
|
output("\n")
|
||||||
@ -436,6 +430,6 @@ class AstToSourceCode(val output: (text: String) -> Unit): IAstVisitor {
|
|||||||
outputln("")
|
outputln("")
|
||||||
}
|
}
|
||||||
override fun visit(nopStatement: NopStatement) {
|
override fun visit(nopStatement: NopStatement) {
|
||||||
output("; NOP")
|
output("; NOP @ ${nopStatement.position} $nopStatement")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -682,7 +682,6 @@ internal class Compiler(private val program: Program) {
|
|||||||
else -> throw CompilerException("invalid datatype for memory variable expression: $target")
|
else -> throw CompilerException("invalid datatype for memory variable expression: $target")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VarDeclType.STRUCT -> TODO("decltype struct")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1448,23 +1447,7 @@ internal class Compiler(private val program: Program) {
|
|||||||
}
|
}
|
||||||
DataType.STRUCT -> {
|
DataType.STRUCT -> {
|
||||||
// Assume the value is an array. Flatten the struct assignment into memberwise assignments.
|
// Assume the value is an array. Flatten the struct assignment into memberwise assignments.
|
||||||
val identifier = stmt.target.identifier!!
|
flattenStructAssignment(stmt, program).forEach { translate(it) }
|
||||||
val identifierName = identifier.nameInSource.single()
|
|
||||||
val targetVar = identifier.targetVarDecl(program.namespace)!!
|
|
||||||
val struct = targetVar.struct!!
|
|
||||||
val sourceVar = (stmt.value as IdentifierReference).targetVarDecl(program.namespace)!!
|
|
||||||
if(!sourceVar.isArray)
|
|
||||||
throw CompilerException("can only assign arrays to structs")
|
|
||||||
val sourceArray = (sourceVar.value as LiteralValue).arrayvalue!!
|
|
||||||
for(member in struct.statements.zip(sourceArray)) {
|
|
||||||
val decl = member.first as VarDecl
|
|
||||||
val value = member.second.constValue(program)!!
|
|
||||||
val mangled = mangledStructMemberName(identifierName, decl.name)
|
|
||||||
val idref = IdentifierReference(listOf(mangled), stmt.position)
|
|
||||||
val assign = Assignment(AssignTarget(null, idref, null, null, stmt.position), null, value, value.position)
|
|
||||||
assign.linkParents(stmt)
|
|
||||||
translate(assign)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
in StringDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
in StringDatatypes -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
|
||||||
@ -1481,6 +1464,26 @@ internal class Compiler(private val program: Program) {
|
|||||||
popValueIntoTarget(stmt.target, datatype)
|
popValueIntoTarget(stmt.target, datatype)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun flattenStructAssignment(structAssignment: Assignment, program: Program): List<Assignment> {
|
||||||
|
val identifier = structAssignment.target.identifier!!
|
||||||
|
val identifierName = identifier.nameInSource.single()
|
||||||
|
val targetVar = identifier.targetVarDecl(program.namespace)!!
|
||||||
|
val struct = targetVar.struct!!
|
||||||
|
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
|
||||||
|
if(!sourceVar.isArray)
|
||||||
|
throw CompilerException("can only assign arrays to structs")
|
||||||
|
val sourceArray = (sourceVar.value as LiteralValue).arrayvalue!!
|
||||||
|
return struct.statements.zip(sourceArray).map { member ->
|
||||||
|
val decl = member.first as VarDecl
|
||||||
|
val mangled = mangledStructMemberName(identifierName, decl.name)
|
||||||
|
val idref = IdentifierReference(listOf(mangled), structAssignment.position)
|
||||||
|
val assign = Assignment(AssignTarget(null, idref, null, null, structAssignment.position),
|
||||||
|
null, member.second, member.second.position)
|
||||||
|
assign.linkParents(structAssignment)
|
||||||
|
assign
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun pushHeapVarAddress(value: IExpression, removeLastOpcode: Boolean) {
|
private fun pushHeapVarAddress(value: IExpression, removeLastOpcode: Boolean) {
|
||||||
when (value) {
|
when (value) {
|
||||||
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
|
is LiteralValue -> throw CompilerException("can only push address of string or array (value on the heap)")
|
||||||
@ -1520,9 +1523,6 @@ internal class Compiler(private val program: Program) {
|
|||||||
prog.instr(opcode, RuntimeValue(DataType.UWORD, address))
|
prog.instr(opcode, RuntimeValue(DataType.UWORD, address))
|
||||||
}
|
}
|
||||||
VarDeclType.CONST -> throw CompilerException("cannot assign to const")
|
VarDeclType.CONST -> throw CompilerException("cannot assign to const")
|
||||||
VarDeclType.STRUCT -> {
|
|
||||||
TODO("decltype struct $assignTarget")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else throw CompilerException("invalid assignment target type ${target::class}")
|
} else throw CompilerException("invalid assignment target type ${target::class}")
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ fun compileProgram(filepath: Path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
programAst.removeNops()
|
programAst.removeNopsFlattenAnonScopes()
|
||||||
programAst.checkValid(compilerOptions) // check if final tree is valid
|
programAst.checkValid(compilerOptions) // check if final tree is valid
|
||||||
programAst.checkRecursion() // check if there are recursive subroutine calls
|
programAst.checkRecursion() // check if there are recursive subroutine calls
|
||||||
|
|
||||||
|
@ -415,6 +415,10 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
throw CompilerException("array should already be in the heap")
|
throw CompilerException("array should already be in the heap")
|
||||||
RuntimeValue(decl.datatype, heapId = litval.heapId)
|
RuntimeValue(decl.datatype, heapId = litval.heapId)
|
||||||
}
|
}
|
||||||
|
DataType.STRUCT -> {
|
||||||
|
// struct variables have been flattened already
|
||||||
|
return
|
||||||
|
}
|
||||||
else -> throw CompilerException("weird datatype")
|
else -> throw CompilerException("weird datatype")
|
||||||
}
|
}
|
||||||
currentBlock.variables[scopedname] = value
|
currentBlock.variables[scopedname] = value
|
||||||
@ -435,9 +439,6 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
if(lv.type in IntegerDatatypes)
|
if(lv.type in IntegerDatatypes)
|
||||||
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
|
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
|
||||||
}
|
}
|
||||||
VarDeclType.STRUCT -> {
|
|
||||||
// the struct decl itself will be replaced by mangled declarations for each of their members.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,14 +31,6 @@ internal fun Program.constantFold() {
|
|||||||
internal fun Program.optimizeStatements(optimizeInlining: Boolean): Int {
|
internal fun Program.optimizeStatements(optimizeInlining: Boolean): Int {
|
||||||
val optimizer = StatementOptimizer(this, optimizeInlining)
|
val optimizer = StatementOptimizer(this, optimizeInlining)
|
||||||
optimizer.visit(this)
|
optimizer.visit(this)
|
||||||
for(scope in optimizer.scopesToFlatten.reversed()) {
|
|
||||||
val namescope = scope.parent as INameScope
|
|
||||||
val idx = namescope.statements.indexOf(scope as IStatement)
|
|
||||||
if(idx>=0) {
|
|
||||||
namescope.statements[idx] = NopStatement.insteadOf(namescope.statements[idx])
|
|
||||||
namescope.statements.addAll(idx, scope.statements)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modules.forEach { it.linkParents(this.namespace) } // re-link in final configuration
|
modules.forEach { it.linkParents(this.namespace) } // re-link in final configuration
|
||||||
|
|
||||||
return optimizer.optimizationsDone
|
return optimizer.optimizationsDone
|
||||||
|
@ -20,7 +20,6 @@ import kotlin.math.floor
|
|||||||
internal class StatementOptimizer(private val program: Program, private val optimizeInlining: Boolean) : IAstModifyingVisitor {
|
internal class StatementOptimizer(private val program: Program, private val optimizeInlining: Boolean) : IAstModifyingVisitor {
|
||||||
var optimizationsDone: Int = 0
|
var optimizationsDone: Int = 0
|
||||||
private set
|
private set
|
||||||
var scopesToFlatten = mutableListOf<INameScope>()
|
|
||||||
|
|
||||||
private val pureBuiltinFunctions = BuiltinFunctions.filter { it.value.pure }
|
private val pureBuiltinFunctions = BuiltinFunctions.filter { it.value.pure }
|
||||||
private val callgraph = CallGraph(program)
|
private val callgraph = CallGraph(program)
|
||||||
@ -621,11 +620,6 @@ internal class StatementOptimizer(private val program: Program, private val opti
|
|||||||
if(linesToRemove.isNotEmpty()) {
|
if(linesToRemove.isNotEmpty()) {
|
||||||
linesToRemove.reversed().forEach{scope.statements.removeAt(it)}
|
linesToRemove.reversed().forEach{scope.statements.removeAt(it)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scope.parent is INameScope) {
|
|
||||||
scopesToFlatten.add(scope) // get rid of the anonymous scope
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.visit(scope)
|
return super.visit(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,17 +636,38 @@ internal class StatementOptimizer(private val program: Program, private val opti
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal class RemoveNops: IAstVisitor {
|
internal class FlattenAnonymousScopesAndRemoveNops: IAstVisitor {
|
||||||
val nopStatements = mutableListOf<NopStatement>()
|
private var scopesToFlatten = mutableListOf<INameScope>()
|
||||||
|
private val nopStatements = mutableListOf<NopStatement>()
|
||||||
|
|
||||||
override fun visit(program: Program) {
|
override fun visit(program: Program) {
|
||||||
super.visit(program)
|
super.visit(program)
|
||||||
// at the end, remove the encountered NOP statements
|
for(scope in scopesToFlatten.reversed()) {
|
||||||
|
val namescope = scope.parent as INameScope
|
||||||
|
val idx = namescope.statements.indexOf(scope as IStatement)
|
||||||
|
if(idx>=0) {
|
||||||
|
val nop = NopStatement.insteadOf(namescope.statements[idx])
|
||||||
|
nop.parent = namescope as Node
|
||||||
|
namescope.statements[idx] = nop
|
||||||
|
namescope.statements.addAll(idx, scope.statements)
|
||||||
|
scope.statements.forEach { it.parent = namescope as Node }
|
||||||
|
visit(nop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.nopStatements.forEach {
|
this.nopStatements.forEach {
|
||||||
it.definingScope().remove(it)
|
it.definingScope().remove(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visit(scope: AnonymousScope) {
|
||||||
|
if(scope.parent is INameScope) {
|
||||||
|
scopesToFlatten.add(scope) // get rid of the anonymous scope
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.visit(scope)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visit(nopStatement: NopStatement) {
|
override fun visit(nopStatement: NopStatement) {
|
||||||
nopStatements.add(nopStatement)
|
nopStatements.add(nopStatement)
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,6 @@ class AstVm(val program: Program) {
|
|||||||
mem.setUByte(addr,newval.toShort())
|
mem.setUByte(addr,newval.toShort())
|
||||||
}
|
}
|
||||||
VarDeclType.CONST -> throw VmExecutionException("can't be const")
|
VarDeclType.CONST -> throw VmExecutionException("can't be const")
|
||||||
VarDeclType.STRUCT -> TODO("struct decltype")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stmt.target.memoryAddress != null -> {
|
stmt.target.memoryAddress != null -> {
|
||||||
|
@ -101,7 +101,7 @@ fun evaluate(expr: IExpression, ctx: EvalContext): RuntimeValue {
|
|||||||
if(variable is VarDecl) {
|
if(variable is VarDecl) {
|
||||||
if(variable.type==VarDeclType.VAR)
|
if(variable.type==VarDeclType.VAR)
|
||||||
return ctx.runtimeVars.get(variable.definingScope(), variable.name)
|
return ctx.runtimeVars.get(variable.definingScope(), variable.name)
|
||||||
else if(variable.type==VarDeclType.STRUCT) {
|
else if(variable.datatype==DataType.STRUCT) {
|
||||||
throw VmExecutionException("cannot process structs by-value. at ${expr.position}")
|
throw VmExecutionException("cannot process structs by-value. at ${expr.position}")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -49,9 +49,6 @@ class VariablesCreator(private val runtimeVariables: RuntimeVariables, private v
|
|||||||
VarDeclType.CONST -> {
|
VarDeclType.CONST -> {
|
||||||
// consts should have been const-folded away
|
// consts should have been const-folded away
|
||||||
}
|
}
|
||||||
VarDeclType.STRUCT -> {
|
|
||||||
// struct vardecl can be skipped because its members have been flattened out
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.visit(decl)
|
return super.visit(decl)
|
||||||
|
@ -7,46 +7,46 @@
|
|||||||
uword derp
|
uword derp
|
||||||
ubyte[] v = [22,33,44]
|
ubyte[] v = [22,33,44]
|
||||||
|
|
||||||
Color foreground
|
Color foreground = [1,2,3]
|
||||||
Color foreground2 = [11,22,33]
|
c64scr.print_ub(foreground.red)
|
||||||
|
c64.CHROUT(':')
|
||||||
|
c64scr.print_ub(foreground.green)
|
||||||
|
c64.CHROUT(':')
|
||||||
|
c64scr.print_ub(foreground.blue)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
foreground.red = 111
|
|
||||||
; foreground2.red = 111
|
|
||||||
}
|
|
||||||
|
|
||||||
; sub test() {
|
Color background = [255,255,255] ; @todo make zeros if no value is given
|
||||||
; Color foreground ; = [0,1,2] ;@todo init values
|
Color cursor
|
||||||
; Color background
|
|
||||||
; Color cursor
|
foreground.red=99
|
||||||
;
|
background.blue=foreground.red
|
||||||
; foreground.red=99
|
|
||||||
; background.blue=foreground.red
|
cursor = [1,2,3] ; assign all members at once
|
||||||
;
|
cursor = v
|
||||||
; cursor = [1,2,3] ; assign all members at once
|
|
||||||
; cursor = v
|
|
||||||
;cursor=foreground ; @todo memberwise assignment
|
;cursor=foreground ; @todo memberwise assignment
|
||||||
;
|
|
||||||
; c64scr.print_ub(foreground.red)
|
c64scr.print_ub(foreground.red)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(foreground.green)
|
c64scr.print_ub(foreground.green)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(foreground.blue)
|
c64scr.print_ub(foreground.blue)
|
||||||
; c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
; c64scr.print_ub(background.red)
|
c64scr.print_ub(background.red)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(background.green)
|
c64scr.print_ub(background.green)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(background.blue)
|
c64scr.print_ub(background.blue)
|
||||||
; c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
; c64scr.print_ub(cursor.red)
|
c64scr.print_ub(cursor.red)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(cursor.green)
|
c64scr.print_ub(cursor.green)
|
||||||
; c64.CHROUT(':')
|
c64.CHROUT(':')
|
||||||
; c64scr.print_ub(cursor.blue)
|
c64scr.print_ub(cursor.blue)
|
||||||
; c64.CHROUT('\n')
|
c64.CHROUT('\n')
|
||||||
;
|
|
||||||
; return
|
return
|
||||||
; }
|
}
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
ubyte red
|
ubyte red
|
||||||
|
Loading…
Reference in New Issue
Block a user