mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
function call arguments
This commit is contained in:
parent
595e58ec46
commit
0782f6ecf1
@ -1,5 +1,7 @@
|
||||
package prog8.ast
|
||||
|
||||
import prog8.functions.BuiltinFunctions
|
||||
|
||||
internal fun Program.reorderStatements() {
|
||||
val initvalueCreator = VarInitValueAndAddressOfCreator(namespace)
|
||||
initvalueCreator.process(this)
|
||||
@ -24,6 +26,7 @@ private class StatementReorderer(private val program: Program): IAstProcessor {
|
||||
// - all other subroutines will be moved to the end of their block.
|
||||
//
|
||||
// Also, makes sure any value assignments get the proper type casts if needed to cast them into the target variable's type.
|
||||
// (this includes function call arguments)
|
||||
|
||||
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option")
|
||||
|
||||
@ -192,7 +195,6 @@ private class StatementReorderer(private val program: Program): IAstProcessor {
|
||||
statements.addAll(result)
|
||||
}
|
||||
|
||||
|
||||
override fun process(assignment: Assignment): IStatement {
|
||||
val target=assignment.singleTarget
|
||||
if(target!=null) {
|
||||
@ -210,6 +212,56 @@ private class StatementReorderer(private val program: Program): IAstProcessor {
|
||||
return super.process(assignment)
|
||||
}
|
||||
|
||||
override fun process(functionCallStatement: FunctionCallStatement): IStatement {
|
||||
checkFunctionCallArguments(functionCallStatement, functionCallStatement.definingScope())
|
||||
return super.process(functionCallStatement)
|
||||
}
|
||||
|
||||
override fun process(functionCall: FunctionCall): IExpression {
|
||||
checkFunctionCallArguments(functionCall, functionCall.definingScope())
|
||||
return super.process(functionCall)
|
||||
}
|
||||
|
||||
private fun checkFunctionCallArguments(call: IFunctionCall, scope: INameScope) {
|
||||
// see if a typecast is needed to convert the arguments into the required parameter's type
|
||||
val sub = call.target.targetStatement(scope)
|
||||
when(sub) {
|
||||
is Subroutine -> {
|
||||
for(arg in sub.parameters.zip(call.arglist.withIndex())) {
|
||||
val argtype = arg.second.value.resultingDatatype(program)
|
||||
if(argtype!=null) {
|
||||
val requiredType = arg.first.type
|
||||
if (requiredType != argtype) {
|
||||
if (argtype isAssignableTo requiredType) {
|
||||
val typecasted = TypecastExpression(arg.second.value, requiredType, arg.second.value.position)
|
||||
call.arglist[arg.second.index] = typecasted
|
||||
}
|
||||
// if they're not assignable, we'll get a proper error later from the AstChecker
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is BuiltinFunctionStatementPlaceholder -> {
|
||||
val func = BuiltinFunctions.getValue(sub.name)
|
||||
for(arg in func.parameters.zip(call.arglist.withIndex())) {
|
||||
val argtype = arg.second.value.resultingDatatype(program)
|
||||
if(argtype!=null) {
|
||||
if(arg.first.possibleDatatypes.any{ argtype == it})
|
||||
continue
|
||||
for(possibleType in arg.first.possibleDatatypes) {
|
||||
if(argtype isAssignableTo possibleType) {
|
||||
val typecasted = TypecastExpression(arg.second.value, possibleType, arg.second.value.position)
|
||||
call.arglist[arg.second.index] = typecasted
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> TODO("call to something weird $sub")
|
||||
}
|
||||
}
|
||||
|
||||
private fun sortConstantAssignmentSequence(first: Assignment, stmtIter: MutableIterator<IStatement>): Pair<List<Assignment>, IStatement?> {
|
||||
val sequence= mutableListOf(first)
|
||||
var trailing: IStatement? = null
|
||||
|
@ -87,7 +87,7 @@ class AstVm(val program: Program) {
|
||||
init.process(program)
|
||||
|
||||
// initialize all global variables
|
||||
for(m in program.modules) {
|
||||
for (m in program.modules) {
|
||||
for (b in m.statements.filterIsInstance<Block>()) {
|
||||
for (s in b.statements.filterIsInstance<Subroutine>()) {
|
||||
if (s.name == initvarsSubName) {
|
||||
@ -109,7 +109,7 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
println("PROGRAM EXITED!")
|
||||
dialog.title = "PROGRAM EXITED"
|
||||
} catch(bp: VmBreakpointException) {
|
||||
} catch (bp: VmBreakpointException) {
|
||||
println("Breakpoint: execution halted. Press enter to resume.")
|
||||
readLine()
|
||||
} catch (tx: VmTerminationException) {
|
||||
@ -123,15 +123,24 @@ class AstVm(val program: Program) {
|
||||
private val runtimeVariables = RuntimeVariables()
|
||||
private val functions = BuiltinFunctions()
|
||||
|
||||
class LoopControlBreak: Exception()
|
||||
class LoopControlContinue: Exception()
|
||||
class LoopControlReturn(val returnvalues: List<RuntimeValue>): Exception()
|
||||
class LoopControlBreak : Exception()
|
||||
class LoopControlContinue : Exception()
|
||||
class LoopControlReturn(val returnvalues: List<RuntimeValue>) : Exception()
|
||||
|
||||
internal fun executeSubroutine(sub: Subroutine, arguments: List<RuntimeValue>): List<RuntimeValue> {
|
||||
assert(!sub.isAsmSubroutine)
|
||||
if (sub.statements.isEmpty())
|
||||
throw VmTerminationException("scope contains no statements: $sub")
|
||||
// TODO process arguments if it's a subroutine
|
||||
if (arguments.size != sub.parameters.size)
|
||||
throw VmTerminationException("number of args doesn't match number of required parameters")
|
||||
|
||||
for (arg in sub.parameters.zip(arguments)) {
|
||||
val idref = IdentifierReference(listOf(arg.first.name), sub.position)
|
||||
performAssignment(AssignTarget(null, idref, null, null, idref.position),
|
||||
arg.second, sub.statements.first(),
|
||||
EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine))
|
||||
}
|
||||
|
||||
try {
|
||||
for (s in sub.statements) {
|
||||
executeStatement(sub, s)
|
||||
@ -151,16 +160,16 @@ class AstVm(val program: Program) {
|
||||
private fun executeStatement(sub: INameScope, stmt: IStatement) {
|
||||
val evalCtx = EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine)
|
||||
instructionCounter++
|
||||
if(instructionCounter % 100 == 0)
|
||||
if (instructionCounter % 100 == 0)
|
||||
Thread.sleep(1)
|
||||
when (stmt) {
|
||||
is NopStatement, is Label, is Subroutine -> {
|
||||
// do nothing, skip this instruction
|
||||
}
|
||||
is Directive -> {
|
||||
if(stmt.directive=="%breakpoint")
|
||||
if (stmt.directive == "%breakpoint")
|
||||
throw VmBreakpointException()
|
||||
else if(stmt.directive=="%asm")
|
||||
else if (stmt.directive == "%asm")
|
||||
throw VmExecutionException("can't execute assembly code")
|
||||
}
|
||||
is VarDecl -> {
|
||||
@ -168,14 +177,14 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
is FunctionCallStatement -> {
|
||||
val target = stmt.target.targetStatement(program.namespace)
|
||||
when(target) {
|
||||
when (target) {
|
||||
is Subroutine -> {
|
||||
val args = evaluate(stmt.arglist)
|
||||
if(target.isAsmSubroutine) {
|
||||
if (target.isAsmSubroutine) {
|
||||
performSyscall(target, args)
|
||||
} else {
|
||||
val results = executeSubroutine(target, args)
|
||||
// TODO process result values
|
||||
executeSubroutine(target, args)
|
||||
// any return value(s) are discarded
|
||||
}
|
||||
}
|
||||
is BuiltinFunctionStatementPlaceholder -> {
|
||||
@ -183,7 +192,7 @@ class AstVm(val program: Program) {
|
||||
functions.performBuiltinFunction(target.name, args)
|
||||
}
|
||||
else -> {
|
||||
TODO("CALL $target")
|
||||
TODO("weird call $target")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -194,101 +203,31 @@ class AstVm(val program: Program) {
|
||||
is Continue -> throw LoopControlContinue()
|
||||
is Break -> throw LoopControlBreak()
|
||||
is Assignment -> {
|
||||
if(stmt.aug_op!=null)
|
||||
if (stmt.aug_op != null)
|
||||
throw VmExecutionException("augmented assignment should have been converted into regular one $stmt")
|
||||
val target = stmt.singleTarget
|
||||
if(target!=null) {
|
||||
if (target != null) {
|
||||
val value = evaluate(stmt.value, evalCtx)
|
||||
when {
|
||||
target.identifier!=null -> {
|
||||
val decl = stmt.definingScope().lookup(target.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
if(decl.type==VarDeclType.MEMORY) {
|
||||
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
||||
when(decl.datatype) {
|
||||
DataType.UBYTE -> mem.setUByte(address, value.byteval!!)
|
||||
DataType.BYTE -> mem.setSByte(address, value.byteval!!)
|
||||
DataType.UWORD -> mem.setUWord(address, value.wordval!!)
|
||||
DataType.WORD -> mem.setSWord(address, value.wordval!!)
|
||||
DataType.FLOAT -> mem.setFloat(address, value.floatval!!)
|
||||
DataType.STR -> mem.setString(address, value.str!!)
|
||||
DataType.STR_S -> mem.setScreencodeString(address, value.str!!)
|
||||
else -> TODO("set memvar $decl")
|
||||
}
|
||||
} else
|
||||
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
target.memoryAddress!=null -> {
|
||||
TODO("assign memory $stmt")
|
||||
}
|
||||
target.arrayindexed!=null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, evalCtx)
|
||||
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx)
|
||||
when(array.type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
if(value.type!=DataType.UBYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
if(value.type!=DataType.BYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
if(value.type!=DataType.UWORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
if(value.type!=DataType.WORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(value.type!=DataType.FLOAT)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
if(value.type !in ByteDatatypes)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||
}
|
||||
if(array.type in ArrayDatatypes)
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
else if(array.type in StringDatatypes) {
|
||||
val indexInt = index.integerValue()
|
||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||
val newstr = array.str!!.replaceRange(indexInt, indexInt+1, newchr)
|
||||
val ident = stmt.definingScope().lookup(target.arrayindexed.identifier.nameInSource, stmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
program.heap.update(array.heapId!!, newstr)
|
||||
runtimeVariables.set(identScope, ident.name, RuntimeValue(array.type, str=newstr, heapId=array.heapId))
|
||||
}
|
||||
}
|
||||
target.register!=null -> {
|
||||
runtimeVariables.set(program.namespace, target.register.name, value)
|
||||
}
|
||||
else -> TODO("assign $target")
|
||||
}
|
||||
}
|
||||
else TODO("assign multitarget $stmt")
|
||||
performAssignment(target, value, stmt, evalCtx)
|
||||
} else TODO("assign multitarget $stmt")
|
||||
}
|
||||
is PostIncrDecr -> {
|
||||
when {
|
||||
stmt.target.identifier!=null -> {
|
||||
stmt.target.identifier != null -> {
|
||||
val ident = stmt.definingScope().lookup(stmt.target.identifier!!.nameInSource, stmt) as VarDecl
|
||||
val identScope = ident.definingScope()
|
||||
var value = runtimeVariables.get(identScope, ident.name)
|
||||
value = when {
|
||||
stmt.operator=="++" -> value.add(RuntimeValue(value.type, 1))
|
||||
stmt.operator=="--" -> value.sub(RuntimeValue(value.type, 1))
|
||||
stmt.operator == "++" -> value.add(RuntimeValue(value.type, 1))
|
||||
stmt.operator == "--" -> value.sub(RuntimeValue(value.type, 1))
|
||||
else -> throw VmExecutionException("strange postincdec operator $stmt")
|
||||
}
|
||||
runtimeVariables.set(identScope, ident.name, value)
|
||||
}
|
||||
stmt.target.memoryAddress!=null -> {
|
||||
stmt.target.memoryAddress != null -> {
|
||||
TODO("postincrdecr memory $stmt")
|
||||
}
|
||||
stmt.target.arrayindexed!=null -> {
|
||||
stmt.target.arrayindexed != null -> {
|
||||
TODO("postincrdecr array $stmt")
|
||||
}
|
||||
}
|
||||
@ -297,8 +236,8 @@ class AstVm(val program: Program) {
|
||||
TODO("jump $stmt")
|
||||
}
|
||||
is InlineAssembly -> {
|
||||
if(sub is Subroutine) {
|
||||
when(sub.scopedname) {
|
||||
if (sub is Subroutine) {
|
||||
when (sub.scopedname) {
|
||||
"c64flt.print_f" -> {
|
||||
val arg = runtimeVariables.get(sub, sub.parameters.single().name)
|
||||
performSyscall(sub, listOf(arg))
|
||||
@ -312,7 +251,7 @@ class AstVm(val program: Program) {
|
||||
is AnonymousScope -> executeAnonymousScope(stmt)
|
||||
is IfStatement -> {
|
||||
val condition = evaluate(stmt.condition, evalCtx)
|
||||
if(condition.asBoolean)
|
||||
if (condition.asBoolean)
|
||||
executeAnonymousScope(stmt.truepart)
|
||||
else
|
||||
executeAnonymousScope(stmt.elsepart)
|
||||
@ -326,16 +265,15 @@ class AstVm(val program: Program) {
|
||||
throw VmExecutionException("can only iterate over an iterable value: $stmt")
|
||||
val loopvarDt: DataType
|
||||
val loopvar: IdentifierReference
|
||||
if(stmt.loopRegister!=null) {
|
||||
if (stmt.loopRegister != null) {
|
||||
loopvarDt = DataType.UBYTE
|
||||
loopvar = IdentifierReference(listOf(stmt.loopRegister.name), stmt.position)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
loopvarDt = stmt.loopVar!!.resultingDatatype(program)!!
|
||||
loopvar = stmt.loopVar
|
||||
}
|
||||
val iterator = iterable.iterator()
|
||||
for(loopvalue in iterator) {
|
||||
for (loopvalue in iterator) {
|
||||
try {
|
||||
oneForCycle(stmt, loopvarDt, loopvalue, loopvar)
|
||||
} catch (b: LoopControlBreak) {
|
||||
@ -351,9 +289,9 @@ class AstVm(val program: Program) {
|
||||
try {
|
||||
executeAnonymousScope(stmt.body)
|
||||
condition = evaluate(stmt.condition, evalCtx)
|
||||
} catch(b: LoopControlBreak) {
|
||||
} catch (b: LoopControlBreak) {
|
||||
break
|
||||
} catch(c: LoopControlContinue){
|
||||
} catch (c: LoopControlContinue) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -363,12 +301,12 @@ class AstVm(val program: Program) {
|
||||
val condition = evaluate(stmt.untilCondition, evalCtx)
|
||||
try {
|
||||
executeAnonymousScope(stmt.body)
|
||||
} catch(b: LoopControlBreak) {
|
||||
} catch (b: LoopControlBreak) {
|
||||
break
|
||||
} catch(c: LoopControlContinue){
|
||||
} catch (c: LoopControlContinue) {
|
||||
continue
|
||||
}
|
||||
} while(!condition.asBoolean)
|
||||
} while (!condition.asBoolean)
|
||||
}
|
||||
else -> {
|
||||
TODO("implement $stmt")
|
||||
@ -376,37 +314,101 @@ 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")
|
||||
fun performAssignment(target: AssignTarget, value: RuntimeValue, contextStmt: IStatement, evalCtx: EvalContext) {
|
||||
when {
|
||||
target.identifier != null -> {
|
||||
val decl = contextStmt.definingScope().lookup(target.identifier.nameInSource, contextStmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
if (decl.type == VarDeclType.MEMORY) {
|
||||
val address = runtimeVariables.getMemoryAddress(decl.definingScope(), decl.name)
|
||||
when (decl.datatype) {
|
||||
DataType.UBYTE -> mem.setUByte(address, value.byteval!!)
|
||||
DataType.BYTE -> mem.setSByte(address, value.byteval!!)
|
||||
DataType.UWORD -> mem.setUWord(address, value.wordval!!)
|
||||
DataType.WORD -> mem.setSWord(address, value.wordval!!)
|
||||
DataType.FLOAT -> mem.setFloat(address, value.floatval!!)
|
||||
DataType.STR -> mem.setString(address, value.str!!)
|
||||
DataType.STR_S -> mem.setScreencodeString(address, value.str!!)
|
||||
else -> TODO("set memvar $decl")
|
||||
}
|
||||
} else
|
||||
runtimeVariables.set(decl.definingScope(), decl.name, value)
|
||||
}
|
||||
target.memoryAddress != null -> {
|
||||
TODO("assign memory")
|
||||
}
|
||||
target.arrayindexed != null -> {
|
||||
val array = evaluate(target.arrayindexed.identifier, evalCtx)
|
||||
val index = evaluate(target.arrayindexed.arrayspec.index, evalCtx)
|
||||
when (array.type) {
|
||||
DataType.ARRAY_UB -> {
|
||||
if (value.type != DataType.UBYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_B -> {
|
||||
if (value.type != DataType.BYTE)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_UW -> {
|
||||
if (value.type != DataType.UWORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_W -> {
|
||||
if (value.type != DataType.WORD)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if (value.type != DataType.FLOAT)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
DataType.STR, DataType.STR_S -> {
|
||||
if (value.type !in ByteDatatypes)
|
||||
throw VmExecutionException("new value is of different datatype ${value.type} for $array")
|
||||
}
|
||||
else -> throw VmExecutionException("strange array type ${array.type}")
|
||||
}
|
||||
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
|
||||
if (array.type in ArrayDatatypes)
|
||||
array.array!![index.integerValue()] = value.numericValue()
|
||||
else if (array.type in StringDatatypes) {
|
||||
val indexInt = index.integerValue()
|
||||
val newchr = Petscii.decodePetscii(listOf(value.numericValue().toShort()), true)
|
||||
val newstr = array.str!!.replaceRange(indexInt, indexInt + 1, newchr)
|
||||
val ident = contextStmt.definingScope().lookup(target.arrayindexed.identifier.nameInSource, contextStmt) as? VarDecl
|
||||
?: throw VmExecutionException("can't find assignment target ${target.identifier}")
|
||||
val identScope = ident.definingScope()
|
||||
program.heap.update(array.heapId!!, newstr)
|
||||
runtimeVariables.set(identScope, ident.name, RuntimeValue(array.type, str = newstr, heapId = array.heapId))
|
||||
}
|
||||
}
|
||||
target.register != null -> {
|
||||
runtimeVariables.set(program.namespace, target.register.name, value)
|
||||
}
|
||||
else -> TODO("assign $target")
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluate(args: List<IExpression>): List<RuntimeValue> = args.map {
|
||||
evaluate(it, EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine))
|
||||
private fun oneForCycle(stmt: ForLoop, loopvarDt: DataType, loopValue: Number, loopVar: IdentifierReference) {
|
||||
// assign the new loop value to the loopvar, and run the code
|
||||
performAssignment(AssignTarget(null, loopVar, null, null, loopVar.position),
|
||||
RuntimeValue(loopvarDt, loopValue), stmt.body.statements.first(),
|
||||
EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine))
|
||||
executeAnonymousScope(stmt.body)
|
||||
}
|
||||
|
||||
private fun evaluate(args: List<IExpression>): List<RuntimeValue> {
|
||||
val ctx = EvalContext(program, mem, runtimeVariables, functions, ::executeSubroutine)
|
||||
return args.map { evaluate(it, ctx) }
|
||||
}
|
||||
|
||||
private fun performSyscall(sub: Subroutine, args: List<RuntimeValue>) {
|
||||
assert(sub.isAsmSubroutine)
|
||||
when(sub.scopedname) {
|
||||
when (sub.scopedname) {
|
||||
"c64scr.print" -> {
|
||||
// if the argument is an UWORD, consider it to be the "address" of the string (=heapId)
|
||||
if(args[0].wordval!=null) {
|
||||
if (args[0].wordval != null) {
|
||||
val str = program.heap.get(args[0].wordval!!).str!!
|
||||
dialog.canvas.printText(str, 1, true)
|
||||
}
|
||||
else
|
||||
} else
|
||||
dialog.canvas.printText(args[0].str!!, 1, true)
|
||||
}
|
||||
"c64scr.print_ub" -> {
|
||||
@ -416,7 +418,7 @@ class AstVm(val program: Program) {
|
||||
dialog.canvas.printText(args[0].byteval!!.toString(), 1, true)
|
||||
}
|
||||
"c64scr.print_ubhex" -> {
|
||||
val prefix = if(args[0].asBoolean) "$" else ""
|
||||
val prefix = if (args[0].asBoolean) "$" else ""
|
||||
val number = args[1].byteval!!
|
||||
dialog.canvas.printText("$prefix${number.toString(16).padStart(2, '0')}", 1, true)
|
||||
}
|
||||
@ -427,7 +429,7 @@ class AstVm(val program: Program) {
|
||||
dialog.canvas.printText(args[0].wordval!!.toString(), 1, true)
|
||||
}
|
||||
"c64scr.print_uwhex" -> {
|
||||
val prefix = if(args[0].asBoolean) "$" else ""
|
||||
val prefix = if (args[0].asBoolean) "$" else ""
|
||||
val number = args[1].wordval!!
|
||||
dialog.canvas.printText("$prefix${number.toString(16).padStart(4, '0')}", 1, true)
|
||||
}
|
||||
@ -441,34 +443,33 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setFlags(value: LiteralValue?) {
|
||||
if(value!=null) {
|
||||
when(value.type) {
|
||||
if (value != null) {
|
||||
when (value.type) {
|
||||
DataType.UBYTE -> {
|
||||
val v = value.bytevalue!!.toInt()
|
||||
P_negative = v>127
|
||||
P_zero = v==0
|
||||
P_negative = v > 127
|
||||
P_zero = v == 0
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
val v = value.bytevalue!!.toInt()
|
||||
P_negative = v<0
|
||||
P_zero = v==0
|
||||
P_negative = v < 0
|
||||
P_zero = v == 0
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
val v = value.wordvalue!!
|
||||
P_negative = v>32767
|
||||
P_zero = v==0
|
||||
P_negative = v > 32767
|
||||
P_zero = v == 0
|
||||
}
|
||||
DataType.WORD -> {
|
||||
val v = value.wordvalue!!
|
||||
P_negative = v<0
|
||||
P_zero = v==0
|
||||
P_negative = v < 0
|
||||
P_zero = v == 0
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
val flt = value.floatvalue!!
|
||||
P_negative = flt < 0.0
|
||||
P_zero = flt==0.0
|
||||
P_zero = flt == 0.0
|
||||
}
|
||||
else -> {
|
||||
// no flags for non-numeric type
|
||||
@ -477,3 +478,4 @@ class AstVm(val program: Program) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,19 @@ open class RuntimeValue(val type: DataType, num: Number?=null, val str: String?=
|
||||
}
|
||||
}
|
||||
|
||||
fun asLiteralValue(): LiteralValue {
|
||||
return when(type) {
|
||||
in ByteDatatypes -> LiteralValue(type, byteval, position = Position("", 0, 0, 0))
|
||||
in WordDatatypes -> LiteralValue(type, wordvalue = wordval, position = Position("", 0, 0, 0))
|
||||
DataType.FLOAT -> LiteralValue(type, floatvalue = floatval, position = Position("", 0, 0, 0))
|
||||
in StringDatatypes -> LiteralValue(type, strvalue = str, position = Position("", 0, 0, 0))
|
||||
in ArrayDatatypes -> LiteralValue(type,
|
||||
arrayvalue = array?.map { LiteralValue.optimalNumeric(it, Position("", 0, 0, 0)) }?.toTypedArray(),
|
||||
position = Position("", 0, 0, 0))
|
||||
else -> TODO("strange type")
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return when(type) {
|
||||
DataType.UBYTE -> "ub:%02x".format(byteval)
|
||||
|
@ -6,6 +6,28 @@
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
ubyte u1 = 100
|
||||
ubyte u2 = 30
|
||||
byte ub = -30
|
||||
|
||||
abs(ub)
|
||||
word r = moo(u1,u2)
|
||||
c64scr.print_w(r)
|
||||
|
||||
}
|
||||
|
||||
sub moo(ubyte p1, word p2) -> word {
|
||||
c64scr.print_ub(p1)
|
||||
c64.CHROUT(',')
|
||||
c64scr.print_w(p2)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for word ww in 200 to 300 step 13 {
|
||||
c64scr.print_w(ww)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
ubyte u1 = 100
|
||||
ubyte u2 = 30
|
||||
|
||||
@ -17,5 +39,6 @@
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(u2 * 7)
|
||||
c64.CHROUT('\n')
|
||||
return 12345
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user