mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
fix function arguments
This commit is contained in:
parent
7ddc01f883
commit
2f0c0f6fcd
@ -4,10 +4,12 @@ import prog8.ast.base.AstException
|
||||
import prog8.compiler.CompilationResult
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.parser.ParsingFailedError
|
||||
import prog8.vm.astvm.AstVm
|
||||
import prog8.repl.Repl
|
||||
import java.lang.Exception
|
||||
import java.nio.file.*
|
||||
import prog8.vm.astvm.AstVm
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardWatchEventKinds
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@ -103,12 +105,15 @@ private fun compileMain(args: Array<String>) {
|
||||
|
||||
try {
|
||||
compilationResult = compileProgram(filepath, optimize, optimizeInlining, writeAssembly)
|
||||
if(!compilationResult.success)
|
||||
exitProcess(1)
|
||||
} catch (x: ParsingFailedError) {
|
||||
exitProcess(1)
|
||||
} catch (x: AstException) {
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
println("LAUNCH VM!@")
|
||||
if (launchAstVm) {
|
||||
println("\nLaunching AST-based vm...")
|
||||
val vm = AstVm(compilationResult.programAst)
|
||||
|
@ -37,7 +37,7 @@ internal fun Program.anonscopeVarsCleanup() {
|
||||
|
||||
|
||||
internal fun Program.reorderStatements() {
|
||||
val initvalueCreator = VarInitValueAndAddressOfCreator(namespace, heap)
|
||||
val initvalueCreator = VarInitValueAndAddressOfCreator(this)
|
||||
initvalueCreator.visit(this)
|
||||
|
||||
val checker = StatementReorderer(this)
|
||||
|
@ -240,7 +240,7 @@ data class AddressOf(var identifier: IdentifierReference, override val position:
|
||||
identifier.parent=this
|
||||
}
|
||||
|
||||
var scopedname: String? = null // will be set in a later state by the compiler
|
||||
var scopedname: String? = null // will be set in a later state by the compiler // TODO get rid of this??
|
||||
override fun constValue(program: Program): NumericLiteralValue? = null
|
||||
override fun referencesIdentifiers(vararg name: String) = false
|
||||
override fun inferType(program: Program) = DataType.UWORD
|
||||
|
@ -3,13 +3,16 @@ package prog8.ast.processing
|
||||
import prog8.ast.INameScope
|
||||
import prog8.ast.Module
|
||||
import prog8.ast.Node
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.HeapValues
|
||||
import prog8.compiler.CompilerException
|
||||
import prog8.functions.BuiltinFunctions
|
||||
import prog8.functions.FunctionSignature
|
||||
|
||||
|
||||
internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope, private val heap: HeapValues): IAstModifyingVisitor {
|
||||
internal class VarInitValueAndAddressOfCreator(private val program: Program): IAstModifyingVisitor {
|
||||
// For VarDecls that declare an initialization value:
|
||||
// Replace the vardecl with an assignment (to set the initial value),
|
||||
// and add a new vardecl with the default constant value of that type (usually zero) to the scope.
|
||||
@ -42,7 +45,7 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
val array = ReferenceLiteralValue(decl.datatype, null,
|
||||
Array(arraysize) { NumericLiteralValue.optimalInteger(0, decl.position) },
|
||||
null, decl.position)
|
||||
array.addToHeap(heap)
|
||||
array.addToHeap(program.heap)
|
||||
decl.value = array
|
||||
}
|
||||
|
||||
@ -73,20 +76,29 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
}
|
||||
|
||||
override fun visit(functionCall: FunctionCall): Expression {
|
||||
val targetStatement = functionCall.target.targetSubroutine(namespace)
|
||||
var parentStatement: Node = functionCall
|
||||
while(parentStatement !is Statement)
|
||||
parentStatement = parentStatement.parent
|
||||
val targetStatement = functionCall.target.targetSubroutine(program.namespace)
|
||||
if(targetStatement!=null) {
|
||||
var node: Node = functionCall
|
||||
while(node !is Statement)
|
||||
node=node.parent
|
||||
addAddressOfExprIfNeeded(targetStatement, functionCall.arglist, node)
|
||||
addAddressOfExprIfNeeded(targetStatement, functionCall.arglist, parentStatement)
|
||||
} else {
|
||||
val builtinFunc = BuiltinFunctions[functionCall.target.nameInSource.joinToString (".")]
|
||||
if(builtinFunc!=null)
|
||||
addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCall.arglist, parentStatement)
|
||||
}
|
||||
return functionCall
|
||||
}
|
||||
|
||||
override fun visit(functionCallStatement: FunctionCallStatement): Statement {
|
||||
val targetStatement = functionCallStatement.target.targetSubroutine(namespace)
|
||||
if(targetStatement!=null)
|
||||
val targetStatement = functionCallStatement.target.targetSubroutine(program.namespace)
|
||||
if(targetStatement!=null) {
|
||||
addAddressOfExprIfNeeded(targetStatement, functionCallStatement.arglist, functionCallStatement)
|
||||
} else {
|
||||
val builtinFunc = BuiltinFunctions[functionCallStatement.target.nameInSource.joinToString (".")]
|
||||
if(builtinFunc!=null)
|
||||
addAddressOfExprIfNeededForBuiltinFuncs(builtinFunc, functionCallStatement.arglist, functionCallStatement)
|
||||
}
|
||||
return functionCallStatement
|
||||
}
|
||||
|
||||
@ -99,7 +111,7 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
val idref = argparam.second as? IdentifierReference
|
||||
val strvalue = argparam.second as? ReferenceLiteralValue
|
||||
if(idref!=null) {
|
||||
val variable = idref.targetVarDecl(namespace)
|
||||
val variable = idref.targetVarDecl(program.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())
|
||||
@ -110,7 +122,7 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
else if(strvalue!=null) {
|
||||
if(strvalue.isString) {
|
||||
// add a vardecl so that the autovar can be resolved in later lookups
|
||||
val variable = VarDecl.createAuto(strvalue, heap)
|
||||
val variable = VarDecl.createAuto(strvalue, program.heap)
|
||||
addVarDecl(strvalue.definingScope(), variable)
|
||||
// replace the argument with &autovar
|
||||
val autoHeapvarRef = IdentifierReference(listOf(variable.name), strvalue.position)
|
||||
@ -124,6 +136,22 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
||||
}
|
||||
}
|
||||
|
||||
private fun addAddressOfExprIfNeededForBuiltinFuncs(signature: FunctionSignature, args: MutableList<Expression>, parent: Statement) {
|
||||
for(arg in args.withIndex().zip(signature.parameters)) {
|
||||
val argvalue = arg.first.value
|
||||
val argDt = argvalue.inferType(program)
|
||||
if(DataType.UWORD in arg.second.possibleDatatypes && argDt in PassByReferenceDatatypes) {
|
||||
if(argvalue !is IdentifierReference)
|
||||
throw CompilerException("pass-by-reference parameter isn't an identifier? $argvalue")
|
||||
val addrOf = AddressOf(argvalue, argvalue.position)
|
||||
args[arg.first.index] = addrOf
|
||||
addrOf.scopedname = parent.makeScopedName(argvalue.nameInSource.single())
|
||||
addrOf.linkParents(parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun addVarDecl(scope: INameScope, variable: VarDecl) {
|
||||
if(scope !in vardeclsToAdd)
|
||||
vardeclsToAdd[scope] = mutableListOf()
|
||||
|
@ -1,5 +1,6 @@
|
||||
package prog8.compiler
|
||||
|
||||
import com.sun.org.apache.xpath.internal.functions.FuncFalse
|
||||
import prog8.ast.AstToSourceCode
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
@ -17,7 +18,10 @@ import java.nio.file.Path
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
|
||||
class CompilationResult(val programAst: Program, val programName: String, val importedFiles: List<Path>)
|
||||
class CompilationResult(val success: Boolean,
|
||||
val programAst: Program,
|
||||
val programName: String,
|
||||
val importedFiles: List<Path>)
|
||||
|
||||
|
||||
fun compileProgram(filepath: Path,
|
||||
@ -27,6 +31,7 @@ fun compileProgram(filepath: Path,
|
||||
var programName: String? = null
|
||||
|
||||
var importedFiles: List<Path> = emptyList()
|
||||
var success=false
|
||||
|
||||
try {
|
||||
val totalTime = measureTimeMillis {
|
||||
@ -65,11 +70,6 @@ fun compileProgram(filepath: Path,
|
||||
//println(" time2: $time2")
|
||||
val time3 = measureTimeMillis {
|
||||
programAst.removeNopsFlattenAnonScopes()
|
||||
|
||||
// if you want to print the AST, do it before shuffling the statements around below
|
||||
//printAst(programAst)
|
||||
|
||||
|
||||
programAst.reorderStatements() // reorder statements and add type casts, to please the compiler later
|
||||
}
|
||||
//println(" time3: $time3")
|
||||
@ -95,7 +95,7 @@ fun compileProgram(filepath: Path,
|
||||
programAst.checkValid(compilerOptions) // check if final tree is valid
|
||||
programAst.checkRecursion() // check if there are recursive subroutine calls
|
||||
|
||||
//printAst(programAst)
|
||||
printAst(programAst)
|
||||
|
||||
if(writeAssembly) {
|
||||
// asm generation directly from the Ast, no need for intermediate code
|
||||
@ -105,6 +105,7 @@ fun compileProgram(filepath: Path,
|
||||
assembly.assemble(compilerOptions)
|
||||
programName = assembly.name
|
||||
}
|
||||
success = true
|
||||
}
|
||||
println("\nTotal compilation+assemble time: ${totalTime / 1000.0} sec.")
|
||||
|
||||
@ -129,7 +130,7 @@ fun compileProgram(filepath: Path,
|
||||
System.out.flush()
|
||||
throw x
|
||||
}
|
||||
return CompilationResult(programAst, programName ?: "", importedFiles)
|
||||
return CompilationResult(success, programAst, programName ?: "", importedFiles)
|
||||
}
|
||||
|
||||
fun printAst(programAst: Program) {
|
||||
|
@ -238,11 +238,6 @@ internal class AsmGen2(val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw AssemblyError("huh, var is already in zp $fullName")
|
||||
// it was already allocated on the zp, what to do?
|
||||
// out("${variable.name} = ${zpVar.first}\t; zp ${zpVar.second}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -647,7 +642,7 @@ internal class AsmGen2(val program: Program,
|
||||
out(" ldx c64.SCRATCH_ZPREGX") // restore X again
|
||||
}
|
||||
|
||||
private fun translateSubroutineArgument(arg: IndexedValue<SubroutineParameter>, value: Expression, sub: Subroutine) {
|
||||
fun translateSubroutineArgument(arg: IndexedValue<SubroutineParameter>, value: Expression, sub: Subroutine) {
|
||||
val sourceDt = value.inferType(program)!!
|
||||
if(!argumentTypeCompatible(sourceDt, arg.value.type))
|
||||
throw AssemblyError("argument type incompatible")
|
||||
|
@ -54,11 +54,11 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
"mkword" -> {
|
||||
translateFunctionArguments(fcall.arglist)
|
||||
translateFunctionArguments(fcall.arglist, func)
|
||||
asmgen.out(" inx | lda $ESTACK_LO_HEX,x | sta $ESTACK_HI_PLUS1_HEX,x")
|
||||
}
|
||||
"abs" -> {
|
||||
translateFunctionArguments(fcall.arglist)
|
||||
translateFunctionArguments(fcall.arglist, func)
|
||||
val dt = fcall.arglist.single().inferType(program)!!
|
||||
when (dt) {
|
||||
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b")
|
||||
@ -72,7 +72,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
"ln", "log2", "sqrt", "rad",
|
||||
"deg", "round", "floor", "ceil",
|
||||
"rdnf" -> {
|
||||
translateFunctionArguments(fcall.arglist)
|
||||
translateFunctionArguments(fcall.arglist, func)
|
||||
asmgen.out(" jsr c64flt.func_$functionName")
|
||||
}
|
||||
/*
|
||||
@ -224,14 +224,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
translateFunctionArguments(fcall.arglist)
|
||||
translateFunctionArguments(fcall.arglist, func)
|
||||
asmgen.out(" jsr prog8_lib.func_$functionName")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateFunctionArguments(args: MutableList<Expression>) {
|
||||
args.forEach { asmgen.translateExpression(it) }
|
||||
private fun translateFunctionArguments(args: MutableList<Expression>, signature: FunctionSignature) {
|
||||
args.forEach {
|
||||
asmgen.translateExpression(it)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import prog8.ast.expressions.Expression
|
||||
import prog8.ast.expressions.IdentifierReference
|
||||
import prog8.ast.expressions.NumericLiteralValue
|
||||
import prog8.ast.statements.*
|
||||
import prog8.compiler.IntegerOrAddressOf
|
||||
import prog8.compiler.target.c64.MachineDefinition
|
||||
import prog8.compiler.target.c64.Petscii
|
||||
import prog8.vm.RuntimeValue
|
||||
@ -877,27 +878,31 @@ class AstVm(val program: Program) {
|
||||
RuntimeValue(DataType.UBYTE, args[0].str!!.length)
|
||||
}
|
||||
"memset" -> {
|
||||
val target = args[0].array!!
|
||||
val heapId = args[0].wordval!!
|
||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||
val amount = args[1].integerValue()
|
||||
val value = args[2].integerValue()
|
||||
for (i in 0 until amount) {
|
||||
target[i] = value
|
||||
target[i] = IntegerOrAddressOf(value, null)
|
||||
}
|
||||
null
|
||||
}
|
||||
"memsetw" -> {
|
||||
val target = args[0].array!!
|
||||
val heapId = args[0].wordval!!
|
||||
val target = program.heap.get(heapId).array ?: throw VmExecutionException("memset target is not an array")
|
||||
val amount = args[1].integerValue()
|
||||
val value = args[2].integerValue()
|
||||
for (i in 0 until amount step 2) {
|
||||
target[i * 2] = value and 255
|
||||
target[i * 2 + 1] = value ushr 8
|
||||
target[i * 2] = IntegerOrAddressOf(value and 255, null)
|
||||
target[i * 2 + 1] = IntegerOrAddressOf(value ushr 8, null)
|
||||
}
|
||||
null
|
||||
}
|
||||
"memcopy" -> {
|
||||
val source = args[0].array!!
|
||||
val dest = args[1].array!!
|
||||
val sourceHeapId = args[0].wordval!!
|
||||
val destHeapId = args[1].wordval!!
|
||||
val source = program.heap.get(sourceHeapId).array!!
|
||||
val dest = program.heap.get(destHeapId).array!!
|
||||
val amount = args[2].integerValue()
|
||||
for(i in 0 until amount) {
|
||||
dest[i] = source[i]
|
||||
|
@ -1,45 +1,20 @@
|
||||
%import c64utils
|
||||
%zeropage basicsafe
|
||||
%import c64lib
|
||||
|
||||
|
||||
main {
|
||||
|
||||
ubyte[256] sieve
|
||||
ubyte candidate_prime = 2
|
||||
|
||||
sub start() {
|
||||
memset(sieve, 256, false)
|
||||
ending()
|
||||
|
||||
c64scr.print("prime numbers up to 255:\n\n")
|
||||
ubyte amount=0
|
||||
while true {
|
||||
ubyte prime = find_next_prime()
|
||||
if prime==0
|
||||
break
|
||||
c64scr.print_ub(prime)
|
||||
c64scr.print(", ")
|
||||
amount++
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print("number of primes (expected 54): ")
|
||||
c64scr.print_ub(amount)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
|
||||
sub find_next_prime() -> ubyte {
|
||||
|
||||
while sieve[candidate_prime] {
|
||||
candidate_prime++
|
||||
if candidate_prime==0
|
||||
return 0
|
||||
sub ending() {
|
||||
if A
|
||||
c64scr.print("bla")
|
||||
else {
|
||||
c64scr.print("bla")
|
||||
c64scr.print("bla")
|
||||
}
|
||||
|
||||
sieve[candidate_prime] = true
|
||||
uword multiple = candidate_prime
|
||||
while multiple < len(sieve) {
|
||||
sieve[lsb(multiple)] = true
|
||||
multiple += candidate_prime
|
||||
}
|
||||
return candidate_prime
|
||||
c64scr.print("bla")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user