mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
registers
This commit is contained in:
parent
343978d164
commit
d68360461b
@ -335,6 +335,8 @@ interface Node {
|
||||
if(this is Label && this.name.startsWith("builtin::")) {
|
||||
return BuiltinFunctionScopePlaceholder
|
||||
}
|
||||
if(this is GlobalNamespace)
|
||||
return this
|
||||
throw FatalAstException("scope missing from $this")
|
||||
}
|
||||
}
|
||||
@ -527,14 +529,10 @@ class Module(override val name: String,
|
||||
val importedBy = mutableListOf<Module>()
|
||||
val imports = mutableSetOf<Module>()
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent=parent
|
||||
}
|
||||
|
||||
var loadAddress: Int = 0 // can be set with the %address directive
|
||||
|
||||
fun linkParents() {
|
||||
parent = ParentSentinel
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
statements.forEach {it.linkParents(this)}
|
||||
}
|
||||
|
||||
@ -544,14 +542,14 @@ class Module(override val name: String,
|
||||
}
|
||||
|
||||
|
||||
class GlobalNamespace(val modules: List<Module>): INameScope {
|
||||
class GlobalNamespace(val modules: List<Module>): Node, INameScope {
|
||||
override val name = "<<<global>>>"
|
||||
override val position = Position("<<<global>>>", 0, 0, 0)
|
||||
override val statements = mutableListOf<IStatement>()
|
||||
override val parent: Node = ParentSentinel
|
||||
override var parent: Node = ParentSentinel
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
modules.forEach { it.linkParents(ParentSentinel) }
|
||||
modules.forEach { it.linkParents(this) }
|
||||
}
|
||||
|
||||
override fun lookup(scopedName: List<String>, localContext: Node): IStatement? {
|
||||
|
@ -163,7 +163,7 @@ private class AstIdentifiersChecker(private val namespace: INameScope) : IAstPro
|
||||
// additional interation count variable in their scope.
|
||||
if(forLoop.loopRegister!=null) {
|
||||
if(forLoop.decltype!=null)
|
||||
checkResult.add(SyntaxError("register loop variables cannot be explicitly declared with a datatype", forLoop.position))
|
||||
checkResult.add(SyntaxError("register loop variables have a fixed implicit datatype", forLoop.position))
|
||||
if(forLoop.loopRegister == Register.X)
|
||||
printWarning("writing to the X register is dangerous, because it's used as an internal pointer", forLoop.position)
|
||||
} else if(forLoop.loopVar!=null) {
|
||||
|
@ -6,7 +6,6 @@ package prog8.ast
|
||||
*/
|
||||
|
||||
internal fun Module.checkImportedValid() {
|
||||
this.linkParents()
|
||||
val checker = ImportedAstChecker()
|
||||
checker.process(this)
|
||||
printErrors(checker.result(), name)
|
||||
|
@ -169,7 +169,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
}
|
||||
is BuiltinFunctionStatementPlaceholder -> {
|
||||
TODO("$stmt")
|
||||
TODO("builtinfun $stmt")
|
||||
}
|
||||
is Return -> throw LoopControlReturn(stmt.values.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) })
|
||||
is Continue -> throw LoopControlContinue()
|
||||
@ -181,13 +181,14 @@ class AstVm(val program: Program) {
|
||||
if(target!=null) {
|
||||
when {
|
||||
target.identifier!=null -> {
|
||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as VarDecl
|
||||
val ident = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val value = evaluate(stmt.value, program, runtimeVariables, ::executeSubroutine)
|
||||
val identScope = ident.definingScope()
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
}
|
||||
target.memoryAddress!=null -> {
|
||||
TODO("$stmt")
|
||||
TODO("assign memory $stmt")
|
||||
}
|
||||
target.arrayindexed!=null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, program, runtimeVariables, ::executeSubroutine)
|
||||
@ -220,7 +221,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else TODO("$stmt")
|
||||
else TODO("assign multitarget $stmt")
|
||||
}
|
||||
is PostIncrDecr -> {
|
||||
when {
|
||||
@ -236,15 +237,15 @@ class AstVm(val program: Program) {
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
}
|
||||
stmt.target.memoryAddress!=null -> {
|
||||
TODO("$stmt")
|
||||
TODO("postincrdecr memory $stmt")
|
||||
}
|
||||
stmt.target.arrayindexed!=null -> {
|
||||
TODO("$stmt")
|
||||
TODO("postincrdecr array $stmt")
|
||||
}
|
||||
}
|
||||
}
|
||||
is Jump -> {
|
||||
TODO("$stmt")
|
||||
TODO("jump $stmt")
|
||||
}
|
||||
is InlineAssembly -> {
|
||||
throw VmExecutionException("can't execute inline assembly in $sub")
|
||||
@ -258,40 +259,32 @@ class AstVm(val program: Program) {
|
||||
executeAnonymousScope(stmt.elsepart)
|
||||
}
|
||||
is BranchStatement -> {
|
||||
TODO("$stmt")
|
||||
TODO("branch $stmt")
|
||||
}
|
||||
is ForLoop -> {
|
||||
val iterable = evaluate(stmt.iterable, program, runtimeVariables, ::executeSubroutine)
|
||||
if (iterable.type !in IterableDatatypes && iterable !is RuntimeValueRange)
|
||||
throw VmExecutionException("can only iterate over an iterable value: $stmt")
|
||||
val iterator: Iterator<Any> = iterable.iterator()
|
||||
if(stmt.loopRegister!=null)
|
||||
TODO("for with register")
|
||||
else if(stmt.loopVar!=null) {
|
||||
for(v in iterator) {
|
||||
try {
|
||||
val value: LiteralValue =
|
||||
when(stmt.loopVar.resultingDatatype(program)!!) {
|
||||
DataType.UBYTE -> LiteralValue(DataType.UBYTE, (v as Number).toShort(), position=stmt.position)
|
||||
DataType.BYTE -> LiteralValue(DataType.BYTE, (v as Number).toShort(), position=stmt.position)
|
||||
DataType.UWORD -> LiteralValue(DataType.UWORD, wordvalue = (v as Int), position=stmt.position)
|
||||
DataType.WORD -> LiteralValue(DataType.WORD, wordvalue = (v as Int), position=stmt.position)
|
||||
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue = (v as Double), position=stmt.position)
|
||||
DataType.STR, DataType.STR_S -> LiteralValue(DataType.UBYTE, (v as Char).toShort(), position=stmt.position)
|
||||
else -> TODO("weird loopvar type")
|
||||
}
|
||||
val assignment = Assignment(listOf(AssignTarget(null, stmt.loopVar, null, null,
|
||||
position=stmt.loopVar.position)), null, value, stmt.iterable.position)
|
||||
assignment.linkParents(stmt.body)
|
||||
executeStatement(stmt.body, assignment) // assign the new loop value to the loopvar
|
||||
executeAnonymousScope(stmt.body) // and run the code
|
||||
} catch (b: LoopControlBreak) {
|
||||
break
|
||||
} catch (c: LoopControlContinue) {
|
||||
continue
|
||||
}
|
||||
val loopvarDt: DataType
|
||||
val loopvar: IdentifierReference
|
||||
if(stmt.loopRegister!=null) {
|
||||
loopvarDt = DataType.UBYTE
|
||||
loopvar = IdentifierReference(listOf(stmt.loopRegister.name), stmt.position)
|
||||
}
|
||||
else {
|
||||
loopvarDt = stmt.loopVar!!.resultingDatatype(program)!!
|
||||
loopvar = stmt.loopVar
|
||||
}
|
||||
val iterator = iterable.iterator()
|
||||
for(loopvalue in iterator) {
|
||||
try {
|
||||
oneForCycle(stmt, loopvarDt, loopvalue, loopvar)
|
||||
} catch (b: LoopControlBreak) {
|
||||
break
|
||||
} catch (c: LoopControlContinue) {
|
||||
continue
|
||||
}
|
||||
} else TODO("strange for $stmt")
|
||||
}
|
||||
}
|
||||
is WhileLoop -> {
|
||||
var condition = evaluate(stmt.condition, program, runtimeVariables, ::executeSubroutine)
|
||||
@ -324,6 +317,23 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun oneForCycle(stmt: ForLoop, loopvarDt: DataType, loopValue: Number, loopVar: IdentifierReference) {
|
||||
val value: LiteralValue =
|
||||
when (loopvarDt) {
|
||||
DataType.UBYTE -> LiteralValue(DataType.UBYTE, loopValue.toShort(), position = stmt.position)
|
||||
DataType.BYTE -> LiteralValue(DataType.BYTE, loopValue.toShort(), position = stmt.position)
|
||||
DataType.UWORD -> LiteralValue(DataType.UWORD, wordvalue = (loopValue as Int), position = stmt.position)
|
||||
DataType.WORD -> LiteralValue(DataType.WORD, wordvalue = (loopValue as Int), position = stmt.position)
|
||||
DataType.FLOAT -> LiteralValue(DataType.FLOAT, floatvalue = (loopValue as Double), position = stmt.position)
|
||||
else -> TODO("weird loopvar type $loopvarDt")
|
||||
}
|
||||
val assignment = Assignment(listOf(AssignTarget(null, loopVar, null, null,
|
||||
position = loopVar.position)), null, value, stmt.iterable.position)
|
||||
assignment.linkParents(stmt.body)
|
||||
executeStatement(stmt.body, assignment) // assign the new loop value to the loopvar
|
||||
executeAnonymousScope(stmt.body) // and run the code
|
||||
}
|
||||
|
||||
private fun evaluate(args: List<IExpression>): List<RuntimeValue> = args.map { evaluate(it, program, runtimeVariables, ::executeSubroutine) }
|
||||
|
||||
private fun performBuiltinFunction(name: String, args: List<RuntimeValue>) {
|
||||
|
@ -16,7 +16,7 @@ fun evaluate(expr: IExpression, program: Program, runtimeVars: RuntimeVariables,
|
||||
return RuntimeValue.from(expr, program.heap)
|
||||
}
|
||||
is PrefixExpression -> {
|
||||
TODO("$expr")
|
||||
TODO("prefixexpr $expr")
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
val left = evaluate(expr.left, program, runtimeVars, executeSubroutine)
|
||||
@ -61,14 +61,12 @@ fun evaluate(expr: IExpression, program: Program, runtimeVars: RuntimeVariables,
|
||||
return RuntimeValue(DataType.UWORD, heapId)
|
||||
}
|
||||
is DirectMemoryRead -> {
|
||||
TODO("$expr")
|
||||
TODO("memoryread $expr")
|
||||
}
|
||||
is DirectMemoryWrite -> {
|
||||
TODO("$expr")
|
||||
}
|
||||
is RegisterExpr -> {
|
||||
TODO("$expr")
|
||||
TODO("memorywrite $expr")
|
||||
}
|
||||
is RegisterExpr -> return runtimeVars.get(program.namespace, expr.register.name)
|
||||
is IdentifierReference -> {
|
||||
val scope = expr.definingScope()
|
||||
val variable = scope.lookup(expr.nameInSource, expr)
|
||||
@ -76,7 +74,7 @@ fun evaluate(expr: IExpression, program: Program, runtimeVars: RuntimeVariables,
|
||||
val stmt = scope.lookup(listOf(variable.name), expr)!!
|
||||
return runtimeVars.get(stmt.definingScope(), variable.name)
|
||||
} else
|
||||
TODO("$variable")
|
||||
TODO("weird ref $variable")
|
||||
}
|
||||
is FunctionCall -> {
|
||||
val sub = expr.target.targetStatement(program.namespace)
|
||||
|
@ -6,6 +6,26 @@ import prog8.compiler.RuntimeValue
|
||||
|
||||
class VariablesCreator(private val runtimeVariables: RuntimeVariables, private val heap: HeapValues) : IAstProcessor {
|
||||
|
||||
override fun process(program: Program) {
|
||||
// define the three registers as global variables
|
||||
runtimeVariables.define(program.namespace, Register.A.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
runtimeVariables.define(program.namespace, Register.X.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
runtimeVariables.define(program.namespace, Register.Y.name, RuntimeValue(DataType.UBYTE, 0))
|
||||
|
||||
val globalpos = Position("<<global>>", 0, 0, 0)
|
||||
val vdA = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.A.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
val vdX = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.X.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
val vdY = VarDecl(VarDeclType.VAR, DataType.UBYTE, false, null, false, Register.Y.name, LiteralValue.optimalInteger(0, globalpos), globalpos)
|
||||
vdA.linkParents(program.namespace)
|
||||
vdX.linkParents(program.namespace)
|
||||
vdY.linkParents(program.namespace)
|
||||
program.namespace.statements.add(vdA)
|
||||
program.namespace.statements.add(vdX)
|
||||
program.namespace.statements.add(vdY)
|
||||
|
||||
super.process(program)
|
||||
}
|
||||
|
||||
override fun process(decl: VarDecl): IStatement {
|
||||
if(decl.type==VarDeclType.VAR) {
|
||||
val value = when (decl.datatype) {
|
||||
|
@ -502,7 +502,7 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
||||
}
|
||||
}
|
||||
|
||||
open fun iterator(): Iterator<Any> {
|
||||
open fun iterator(): Iterator<Number> {
|
||||
return when (type) {
|
||||
in StringDatatypes -> {
|
||||
Petscii.encodePetscii(str!!, true).iterator()
|
||||
@ -517,7 +517,7 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
||||
|
||||
|
||||
class RuntimeValueRange(type: DataType, val range: IntProgression): RuntimeValue(type, 0) {
|
||||
override fun iterator(): Iterator<Any> {
|
||||
override fun iterator(): Iterator<Number> {
|
||||
return range.iterator()
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +533,7 @@ class ConstantFolding(private val program: Program) : IAstProcessor {
|
||||
val rangeTo = iterableRange.to as? LiteralValue
|
||||
if(rangeFrom==null || rangeTo==null) return resultStmt
|
||||
|
||||
val loopvar = resultStmt.loopVar!!.targetVarDecl(program.namespace)
|
||||
val loopvar = resultStmt.loopVar?.targetVarDecl(program.namespace)
|
||||
if(loopvar!=null) {
|
||||
val stepLiteral = iterableRange.step as? LiteralValue
|
||||
when(loopvar.datatype) {
|
||||
|
@ -21,7 +21,7 @@ internal fun Program.constantFold() {
|
||||
optimizer.errors.forEach { System.err.println(it) }
|
||||
throw ParsingFailedError("There are ${optimizer.errors.size} errors.")
|
||||
} else {
|
||||
modules.forEach { it.linkParents() } // re-link in final configuration
|
||||
modules.forEach { it.linkParents(namespace) } // re-link in final configuration
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ internal fun Program.optimizeStatements(optimizeInlining: Boolean): Int {
|
||||
namescope.statements.addAll(idx, scope.statements)
|
||||
}
|
||||
}
|
||||
modules.forEach { it.linkParents() } // re-link in final configuration
|
||||
modules.forEach { it.linkParents(this.namespace) } // re-link in final configuration
|
||||
|
||||
return optimizer.optimizationsDone
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ internal fun importModule(program: Program, stream: CharStream, modulePath: Path
|
||||
// tokens.commentTokens().forEach { println(it) }
|
||||
|
||||
// convert to Ast
|
||||
val moduleAst = parseTree.toAst(moduleName.toString(), isLibrary, modulePath)
|
||||
val moduleAst = parseTree.toAst(moduleName, isLibrary, modulePath)
|
||||
moduleAst.program = program
|
||||
moduleAst.linkParents()
|
||||
moduleAst.linkParents(program.namespace)
|
||||
program.modules.add(moduleAst)
|
||||
|
||||
// process additional imports
|
||||
|
@ -4,38 +4,23 @@
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
ubyte i=99
|
||||
|
||||
for ubyte j in 20 to 40 step 5 {
|
||||
c64scr.print_ub(j)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for uword j in 200 to 400 step 5 {
|
||||
c64scr.print_uw(j)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for i in 200 to 50 step -20 {
|
||||
c64scr.print_ub(i)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for i in "hello" {
|
||||
c64scr.print_ub(i)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for i in [1,2,3,4,5] {
|
||||
c64scr.print_ub(i)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
|
||||
c64.CHROUT('\n')
|
||||
Y=99
|
||||
A=200
|
||||
Y=A
|
||||
ubyte r = subt()
|
||||
c64scr.print_ub(r)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
sub subt() -> ubyte {
|
||||
|
||||
for Y in 20 to 50 step 5 {
|
||||
c64scr.print_ub(Y)
|
||||
c64.CHROUT(',')
|
||||
if Y>40
|
||||
return 99
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
return 10
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user