mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
fixes
This commit is contained in:
parent
d5b12fb01d
commit
78d7849197
@ -15,11 +15,6 @@ import java.io.File
|
|||||||
internal class AstChecker(private val program: Program,
|
internal class AstChecker(private val program: Program,
|
||||||
private val compilerOptions: CompilationOptions) : IAstVisitor {
|
private val compilerOptions: CompilationOptions) : IAstVisitor {
|
||||||
private val checkResult: MutableList<AstException> = mutableListOf()
|
private val checkResult: MutableList<AstException> = mutableListOf()
|
||||||
private val heapIdSentinel: Int
|
|
||||||
init {
|
|
||||||
val stringSentinel = program.heap.allEntries().firstOrNull {it.value.str==""}
|
|
||||||
heapIdSentinel = stringSentinel?.key ?: program.heap.addString(DataType.STR, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun result(): List<AstException> {
|
fun result(): List<AstException> {
|
||||||
return checkResult
|
return checkResult
|
||||||
@ -358,13 +353,13 @@ internal class AstChecker(private val program: Program,
|
|||||||
|
|
||||||
override fun visit(assignTarget: AssignTarget) {
|
override fun visit(assignTarget: AssignTarget) {
|
||||||
val memAddr = assignTarget.memoryAddress?.addressExpression?.constValue(program)?.number?.toInt()
|
val memAddr = assignTarget.memoryAddress?.addressExpression?.constValue(program)?.number?.toInt()
|
||||||
if(memAddr!=null) {
|
if (memAddr != null) {
|
||||||
if(memAddr<0 || memAddr>=65536)
|
if (memAddr < 0 || memAddr >= 65536)
|
||||||
checkResult.add(ExpressionError("address out of range", assignTarget.position))
|
checkResult.add(ExpressionError("address out of range", assignTarget.position))
|
||||||
}
|
}
|
||||||
|
|
||||||
val assignment = assignTarget.parent as Assignment
|
val assignment = assignTarget.parent as IStatement
|
||||||
if(assignTarget.identifier!=null) {
|
if (assignTarget.identifier != null) {
|
||||||
val targetName = assignTarget.identifier.nameInSource
|
val targetName = assignTarget.identifier.nameInSource
|
||||||
val targetSymbol = program.namespace.lookup(targetName, assignment)
|
val targetSymbol = program.namespace.lookup(targetName, assignment)
|
||||||
when (targetSymbol) {
|
when (targetSymbol) {
|
||||||
@ -377,7 +372,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if(targetSymbol.type == VarDeclType.CONST) {
|
if (targetSymbol.type == VarDeclType.CONST) {
|
||||||
checkResult.add(ExpressionError("cannot assign new value to a constant", assignment.position))
|
checkResult.add(ExpressionError("cannot assign new value to a constant", assignment.position))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -385,15 +380,17 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(assignment.aug_op!=null)
|
if (assignment is Assignment) {
|
||||||
throw FatalAstException("augmented assignment should have been converted into normal assignment")
|
|
||||||
|
|
||||||
val targetDatatype = assignTarget.inferType(program, assignment)
|
if (assignment.aug_op != null)
|
||||||
if(targetDatatype!=null) {
|
throw FatalAstException("augmented assignment should have been converted into normal assignment")
|
||||||
val constVal = assignment.value.constValue(program)
|
|
||||||
if(constVal!=null) {
|
val targetDatatype = assignTarget.inferType(program, assignment)
|
||||||
checkValueTypeAndRange(targetDatatype, constVal)
|
if (targetDatatype != null) {
|
||||||
// TODO what about arrays etc:
|
val constVal = assignment.value.constValue(program)
|
||||||
|
if (constVal != null) {
|
||||||
|
checkValueTypeAndRange(targetDatatype, constVal)
|
||||||
|
// TODO what about arrays etc:
|
||||||
// val targetVar =
|
// val targetVar =
|
||||||
// if(target.identifier!=null)
|
// if(target.identifier!=null)
|
||||||
// program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
// program.namespace.lookup(target.identifier.nameInSource, assignment) as? VarDecl
|
||||||
@ -403,19 +400,18 @@ internal class AstChecker(private val program: Program,
|
|||||||
// checkValueTypeAndRange(targetDatatype, targetVar?.struct,
|
// checkValueTypeAndRange(targetDatatype, targetVar?.struct,
|
||||||
// arrayspec ?: ArrayIndex(NumericLiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
// arrayspec ?: ArrayIndex(NumericLiteralValue.optimalInteger(-1, assignment.position), assignment.position),
|
||||||
// constVal, program.heap)
|
// constVal, program.heap)
|
||||||
} else {
|
} else {
|
||||||
val sourceDatatype: DataType? = assignment.value.inferType(program)
|
val sourceDatatype: DataType? = assignment.value.inferType(program)
|
||||||
if(sourceDatatype==null) {
|
if (sourceDatatype == null) {
|
||||||
if (assignment.value is FunctionCall) {
|
if (assignment.value is FunctionCall) {
|
||||||
val targetStmt = (assignment.value as FunctionCall).target.targetStatement(program.namespace)
|
val targetStmt = (assignment.value as FunctionCall).target.targetStatement(program.namespace)
|
||||||
if(targetStmt!=null)
|
if (targetStmt != null)
|
||||||
checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position))
|
checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position))
|
||||||
|
} else
|
||||||
|
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
|
||||||
|
} else {
|
||||||
|
checkAssignmentCompatible(targetDatatype, assignTarget, sourceDatatype, assignment.value, assignment.position)
|
||||||
}
|
}
|
||||||
else
|
|
||||||
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
checkAssignmentCompatible(targetDatatype, assignTarget, sourceDatatype, assignment.value, assignment.position)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package prog8.ast.processing
|
|||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.base.autoHeapValuePrefix
|
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.functions.BuiltinFunctions
|
import prog8.functions.BuiltinFunctions
|
||||||
@ -12,7 +11,8 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
private val checkResult: MutableList<AstException> = mutableListOf()
|
private val checkResult: MutableList<AstException> = mutableListOf()
|
||||||
|
|
||||||
private var blocks = mutableMapOf<String, Block>()
|
private var blocks = mutableMapOf<String, Block>()
|
||||||
internal val anonymousVariablesFromHeap = mutableMapOf<String, Pair<ReferenceLiteralValue, VarDecl>>()
|
internal val anonymousVariablesFromHeap = mutableMapOf<String, Pair<ReferenceLiteralValue, VarDecl>>() // TODO
|
||||||
|
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()
|
||||||
|
|
||||||
internal fun result(): List<AstException> {
|
internal fun result(): List<AstException> {
|
||||||
return checkResult
|
return checkResult
|
||||||
@ -23,8 +23,14 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(module: Module) {
|
override fun visit(module: Module) {
|
||||||
|
vardeclsToAdd.clear()
|
||||||
blocks.clear() // blocks may be redefined within a different module
|
blocks.clear() // blocks may be redefined within a different module
|
||||||
super.visit(module)
|
super.visit(module)
|
||||||
|
// add any new vardecls to the various scopes
|
||||||
|
for((where, decls) in vardeclsToAdd) {
|
||||||
|
where.statements.addAll(0, decls)
|
||||||
|
decls.forEach { it.linkParents(where as Node) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(block: Block): IStatement {
|
override fun visit(block: Block): IStatement {
|
||||||
@ -208,20 +214,13 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(refLiteral: ReferenceLiteralValue): ReferenceLiteralValue {
|
override fun visit(refLiteral: ReferenceLiteralValue): ReferenceLiteralValue {
|
||||||
if(refLiteral.heapId!=null && refLiteral.parent !is VarDecl) {
|
if(refLiteral.parent !is VarDecl) {
|
||||||
// a literal value that's not declared as a variable, which refers to something on the heap.
|
// a referencetype literal value that's not declared as a variable
|
||||||
// we need to introduce an auto-generated variable for this to be able to refer to the value!
|
// we need to introduce an auto-generated variable for this to be able to refer to the value
|
||||||
// (note: ususally, this has been taken care of already when the var was created)
|
|
||||||
val declaredType = if(refLiteral.isArray) ArrayElementTypes.getValue(refLiteral.type) else refLiteral.type
|
val declaredType = if(refLiteral.isArray) ArrayElementTypes.getValue(refLiteral.type) else refLiteral.type
|
||||||
val variable = VarDecl(VarDeclType.VAR,
|
val variable = VarDecl.createAuto(refLiteral)
|
||||||
declaredType,
|
addVarDecl(refLiteral.definingScope(), variable)
|
||||||
ZeropageWish.NOT_IN_ZEROPAGE,
|
// TODO anonymousVariablesFromHeap[variable.name] = Pair(refLiteral, variable)
|
||||||
null,
|
|
||||||
"$autoHeapValuePrefix${refLiteral.heapId}",
|
|
||||||
null,
|
|
||||||
refLiteral,
|
|
||||||
isArray = refLiteral.isArray, autogeneratedDontRemove = true, position = refLiteral.position)
|
|
||||||
anonymousVariablesFromHeap[variable.name] = Pair(refLiteral, variable)
|
|
||||||
}
|
}
|
||||||
return super.visit(refLiteral)
|
return super.visit(refLiteral)
|
||||||
}
|
}
|
||||||
@ -243,4 +242,12 @@ internal class AstIdentifiersChecker(private val namespace: INameScope) : IAstMo
|
|||||||
return super.visit(structDecl)
|
return super.visit(structDecl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addVarDecl(scope: INameScope, variable: VarDecl) {
|
||||||
|
if(scope !in vardeclsToAdd)
|
||||||
|
vardeclsToAdd[scope] = mutableListOf()
|
||||||
|
val declList = vardeclsToAdd.getValue(scope)
|
||||||
|
if(declList.all{it.name!=variable.name})
|
||||||
|
declList.add(variable)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package prog8.ast.processing
|
|||||||
|
|
||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import prog8.ast.base.*
|
import prog8.ast.base.*
|
||||||
import prog8.ast.base.autoHeapValuePrefix
|
|
||||||
import prog8.ast.expressions.*
|
import prog8.ast.expressions.*
|
||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
|
|
||||||
@ -24,7 +23,6 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
|||||||
override fun visit(module: Module) {
|
override fun visit(module: Module) {
|
||||||
vardeclsToAdd.clear()
|
vardeclsToAdd.clear()
|
||||||
super.visit(module)
|
super.visit(module)
|
||||||
|
|
||||||
// add any new vardecls to the various scopes
|
// add any new vardecls to the various scopes
|
||||||
for((where, decls) in vardeclsToAdd) {
|
for((where, decls) in vardeclsToAdd) {
|
||||||
where.statements.addAll(0, decls)
|
where.statements.addAll(0, decls)
|
||||||
@ -96,17 +94,15 @@ internal class VarInitValueAndAddressOfCreator(private val namespace: INameScope
|
|||||||
}
|
}
|
||||||
else if(strvalue!=null) {
|
else if(strvalue!=null) {
|
||||||
if(strvalue.isString) {
|
if(strvalue.isString) {
|
||||||
|
// add a vardecl so that the autovar can be resolved in later lookups
|
||||||
|
val variable = VarDecl.createAuto(strvalue)
|
||||||
|
addVarDecl(strvalue.definingScope(), variable)
|
||||||
// replace the argument with &autovar
|
// replace the argument with &autovar
|
||||||
val autoVarName = "$autoHeapValuePrefix${strvalue.heapId}"
|
val autoHeapvarRef = IdentifierReference(listOf(variable.name), strvalue.position)
|
||||||
val autoHeapvarRef = IdentifierReference(listOf(autoVarName), strvalue.position)
|
|
||||||
val pointerExpr = AddressOf(autoHeapvarRef, strvalue.position)
|
val pointerExpr = AddressOf(autoHeapvarRef, strvalue.position)
|
||||||
pointerExpr.scopedname = parent.makeScopedName(autoVarName)
|
pointerExpr.scopedname = parent.makeScopedName(variable.name)
|
||||||
pointerExpr.linkParents(arglist[argparam.first.index].parent)
|
pointerExpr.linkParents(arglist[argparam.first.index].parent)
|
||||||
arglist[argparam.first.index] = pointerExpr
|
arglist[argparam.first.index] = pointerExpr
|
||||||
// add a vardecl so that the autovar can be resolved in later lookups
|
|
||||||
val variable = VarDecl(VarDeclType.VAR, strvalue.type, ZeropageWish.NOT_IN_ZEROPAGE, null, autoVarName, null, strvalue,
|
|
||||||
isArray = false, autogeneratedDontRemove = false, position = strvalue.position)
|
|
||||||
addVarDecl(strvalue.definingScope(), variable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,14 @@ class VarDecl(val type: VarDeclType,
|
|||||||
override val expensiveToInline
|
override val expensiveToInline
|
||||||
get() = value!=null && value !is NumericLiteralValue
|
get() = value!=null && value !is NumericLiteralValue
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun createAuto(refLv: ReferenceLiteralValue): VarDecl {
|
||||||
|
val autoVarName = "$autoHeapValuePrefix${refLv.heapId}"
|
||||||
|
return VarDecl(VarDeclType.VAR, refLv.type, ZeropageWish.NOT_IN_ZEROPAGE, null, autoVarName, null, refLv,
|
||||||
|
isArray = false, autogeneratedDontRemove = true, position = refLv.position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
|
val datatypeErrors = mutableListOf<SyntaxError>() // don't crash at init time, report them in the AstChecker
|
||||||
val datatype =
|
val datatype =
|
||||||
if (!isArray) declaredDatatype
|
if (!isArray) declaredDatatype
|
||||||
|
@ -116,7 +116,7 @@ class HeapValues {
|
|||||||
|
|
||||||
fun get(heapId: Int): HeapValue {
|
fun get(heapId: Int): HeapValue {
|
||||||
return heap[heapId] ?:
|
return heap[heapId] ?:
|
||||||
throw IllegalArgumentException("heapId not found in heap")
|
throw IllegalArgumentException("heapId $heapId not found in heap")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allEntries() = heap.entries
|
fun allEntries() = heap.entries
|
||||||
@ -746,7 +746,8 @@ internal class Compiler(private val program: Program) {
|
|||||||
val arg=args.single()
|
val arg=args.single()
|
||||||
when (arg.inferType(program)) {
|
when (arg.inferType(program)) {
|
||||||
DataType.STR, DataType.STR_S -> createSyscall("${funcname}_str")
|
DataType.STR, DataType.STR_S -> createSyscall("${funcname}_str")
|
||||||
else -> throw CompilerException("wrong datatype for len()")
|
in ArrayDatatypes -> throw CompilerException("len() of an array type should have been const-folded")
|
||||||
|
else -> throw CompilerException("wrong datatype for len() $arg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"any", "all" -> {
|
"any", "all" -> {
|
||||||
|
@ -417,10 +417,10 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
|
|||||||
RuntimeValue(decl.datatype, heapId = litval.heapId)
|
RuntimeValue(decl.datatype, heapId = litval.heapId)
|
||||||
}
|
}
|
||||||
in ArrayDatatypes -> {
|
in ArrayDatatypes -> {
|
||||||
val litval = (decl.value as ReferenceLiteralValue)
|
val litval = (decl.value as? ReferenceLiteralValue)
|
||||||
if(litval.heapId==null)
|
if(litval!=null && litval.heapId==null)
|
||||||
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 ?: -999)
|
||||||
}
|
}
|
||||||
DataType.STRUCT -> {
|
DataType.STRUCT -> {
|
||||||
// struct variables have been flattened already
|
// struct variables have been flattened already
|
||||||
|
@ -7,6 +7,7 @@ import prog8.ast.expressions.IdentifierReference
|
|||||||
import prog8.ast.expressions.NumericLiteralValue
|
import prog8.ast.expressions.NumericLiteralValue
|
||||||
import prog8.ast.expressions.ReferenceLiteralValue
|
import prog8.ast.expressions.ReferenceLiteralValue
|
||||||
import prog8.ast.statements.VarDecl
|
import prog8.ast.statements.VarDecl
|
||||||
|
import prog8.compiler.CompilerException
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
|
|
||||||
@ -336,44 +337,40 @@ private fun builtinLen(args: List<IExpression>, position: Position, program: Pro
|
|||||||
// note: in some cases the length is > 255 and then we have to return a UWORD type instead of a UBYTE.
|
// note: in some cases the length is > 255 and then we have to return a UWORD type instead of a UBYTE.
|
||||||
if(args.size!=1)
|
if(args.size!=1)
|
||||||
throw SyntaxError("len requires one argument", position)
|
throw SyntaxError("len requires one argument", position)
|
||||||
var argument = args[0].constValue(program)
|
val constArg = args[0].constValue(program)
|
||||||
if(argument==null) {
|
if(constArg!=null)
|
||||||
val directMemVar = ((args[0] as? DirectMemoryRead)?.addressExpression as? IdentifierReference)?.targetVarDecl(program.namespace)
|
throw SyntaxError("len of weird argument ${args[0]}", position)
|
||||||
val arraySize = directMemVar?.arraysize?.size()
|
|
||||||
if(arraySize != null)
|
val directMemVar = ((args[0] as? DirectMemoryRead)?.addressExpression as? IdentifierReference)?.targetVarDecl(program.namespace)
|
||||||
return NumericLiteralValue.optimalInteger(arraySize, position)
|
var arraySize = directMemVar?.arraysize?.size()
|
||||||
if(args[0] !is IdentifierReference)
|
if(arraySize != null)
|
||||||
throw SyntaxError("len argument should be an identifier, but is ${args[0]}", position)
|
return NumericLiteralValue.optimalInteger(arraySize, position)
|
||||||
val target = (args[0] as IdentifierReference).targetStatement(program.namespace)
|
if(args[0] !is IdentifierReference)
|
||||||
val argValue = (target as? VarDecl)?.value
|
throw SyntaxError("len argument should be an identifier, but is ${args[0]}", position)
|
||||||
argument = argValue?.constValue(program)
|
val target = (args[0] as IdentifierReference).targetStatement(program.namespace) as VarDecl
|
||||||
?: throw NotConstArgumentException()
|
|
||||||
|
return when(target.datatype) {
|
||||||
|
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||||
|
arraySize = target.arraysize!!.size()!!
|
||||||
|
if(arraySize>256)
|
||||||
|
throw CompilerException("array length exceeds byte limit ${target.position}")
|
||||||
|
NumericLiteralValue.optimalInteger(arraySize, args[0].position)
|
||||||
|
}
|
||||||
|
DataType.ARRAY_F -> {
|
||||||
|
arraySize = target.arraysize!!.size()!!
|
||||||
|
if(arraySize>256)
|
||||||
|
throw CompilerException("array length exceeds byte limit ${target.position}")
|
||||||
|
NumericLiteralValue.optimalInteger(arraySize, args[0].position)
|
||||||
|
}
|
||||||
|
in StringDatatypes -> {
|
||||||
|
val refLv = target.value as ReferenceLiteralValue
|
||||||
|
if(refLv.str!!.length>255)
|
||||||
|
throw CompilerException("string length exceeds byte limit ${refLv.position}")
|
||||||
|
NumericLiteralValue.optimalInteger(refLv.str.length, args[0].position)
|
||||||
|
}
|
||||||
|
in NumericDatatypes -> throw SyntaxError("len of weird argument ${args[0]}", position)
|
||||||
|
else -> throw CompilerException("weird datatype")
|
||||||
}
|
}
|
||||||
|
|
||||||
TODO("collection functions over iterables (array, string) $argument")
|
|
||||||
|
|
||||||
// return when(argument.type) {
|
|
||||||
// DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
|
||||||
// val arraySize = argument.arrayvalue?.size ?: program.heap.get(argument.heapId!!).arraysize
|
|
||||||
// if(arraySize>256)
|
|
||||||
// throw CompilerException("array length exceeds byte limit ${argument.position}")
|
|
||||||
// LiteralValue.optimalInteger(arraySize, args[0].position)
|
|
||||||
// }
|
|
||||||
// DataType.ARRAY_F -> {
|
|
||||||
// val arraySize = argument.arrayvalue?.size ?: program.heap.get(argument.heapId!!).arraysize
|
|
||||||
// if(arraySize>256)
|
|
||||||
// throw CompilerException("array length exceeds byte limit ${argument.position}")
|
|
||||||
// LiteralValue.optimalInteger(arraySize, args[0].position)
|
|
||||||
// }
|
|
||||||
// in StringDatatypes -> {
|
|
||||||
// val str = argument.strvalue!!
|
|
||||||
// if(str.length>255)
|
|
||||||
// throw CompilerException("string length exceeds byte limit ${argument.position}")
|
|
||||||
// LiteralValue.optimalInteger(str.length, args[0].position)
|
|
||||||
// }
|
|
||||||
// in NumericDatatypes -> throw SyntaxError("len of weird argument ${args[0]}", position)
|
|
||||||
// else -> throw CompilerException("weird datatype")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -618,20 +618,19 @@ class ConstantFolding(private val program: Program) : IAstModifyingVisitor {
|
|||||||
throw FatalAstException("missing array value")
|
throw FatalAstException("missing array value")
|
||||||
}
|
}
|
||||||
|
|
||||||
val array = litval.array!!
|
val typesInArray = litval.array.mapNotNull { it.inferType(program) }.toSet()
|
||||||
val typesInArray = array.mapNotNull { it.inferType(program) }.toSet()
|
|
||||||
val arrayDt =
|
val arrayDt =
|
||||||
when {
|
when {
|
||||||
array.any { it is AddressOf } -> DataType.ARRAY_UW
|
litval.array.any { it is AddressOf } -> DataType.ARRAY_UW
|
||||||
DataType.FLOAT in typesInArray -> DataType.ARRAY_F
|
DataType.FLOAT in typesInArray -> DataType.ARRAY_F
|
||||||
DataType.WORD in typesInArray -> DataType.ARRAY_W
|
DataType.WORD in typesInArray -> DataType.ARRAY_W
|
||||||
else -> {
|
else -> {
|
||||||
val allElementsAreConstantOrAddressOf = array.fold(true) { c, expr-> c and (expr is NumericLiteralValue|| expr is AddressOf)}
|
val allElementsAreConstantOrAddressOf = litval.array.fold(true) { c, expr-> c and (expr is NumericLiteralValue|| expr is AddressOf)}
|
||||||
if(!allElementsAreConstantOrAddressOf) {
|
if(!allElementsAreConstantOrAddressOf) {
|
||||||
addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", litval.position))
|
addError(ExpressionError("array literal can only consist of constant primitive numerical values or memory pointers", litval.position))
|
||||||
return litval
|
return litval
|
||||||
} else {
|
} else {
|
||||||
val integerArray = array.map { it.constValue(program)!!.number.toInt() }
|
val integerArray = litval.array.map { it.constValue(program)!!.number.toInt() }
|
||||||
val maxValue = integerArray.max()!!
|
val maxValue = integerArray.max()!!
|
||||||
val minValue = integerArray.min()!!
|
val minValue = integerArray.min()!!
|
||||||
if (minValue >= 0) {
|
if (minValue >= 0) {
|
||||||
|
@ -226,18 +226,18 @@ class Program (val name: String,
|
|||||||
if(valueStr[0] !='"' && ':' !in valueStr)
|
if(valueStr[0] !='"' && ':' !in valueStr)
|
||||||
throw VmExecutionException("missing value type character")
|
throw VmExecutionException("missing value type character")
|
||||||
val value = when(val type = DataType.valueOf(typeStr.toUpperCase())) {
|
val value = when(val type = DataType.valueOf(typeStr.toUpperCase())) {
|
||||||
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, valueStr.substring(3).toShort(16))
|
DataType.UBYTE -> RuntimeValue(DataType.UBYTE, valueStr.substring(3).substringBefore(' ').toShort(16))// TODO process ZP and struct info?
|
||||||
DataType.BYTE -> RuntimeValue(DataType.BYTE, valueStr.substring(2).toShort(16))
|
DataType.BYTE -> RuntimeValue(DataType.BYTE, valueStr.substring(2).substringBefore(' ').toShort(16))// TODO process ZP and struct info?
|
||||||
DataType.UWORD -> RuntimeValue(DataType.UWORD, valueStr.substring(3).toInt(16))
|
DataType.UWORD -> RuntimeValue(DataType.UWORD, valueStr.substring(3).substringBefore(' ').toInt(16))// TODO process ZP and struct info?
|
||||||
DataType.WORD -> RuntimeValue(DataType.WORD, valueStr.substring(2).toInt(16))
|
DataType.WORD -> RuntimeValue(DataType.WORD, valueStr.substring(2).substringBefore(' ').toInt(16))// TODO process ZP and struct info?
|
||||||
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, valueStr.substring(2).toDouble())
|
DataType.FLOAT -> RuntimeValue(DataType.FLOAT, valueStr.substring(2).substringBefore(' ').toDouble())// TODO process ZP and struct info?
|
||||||
in StringDatatypes -> {
|
in StringDatatypes -> {
|
||||||
if(valueStr.startsWith('"') && valueStr.endsWith('"'))
|
if(valueStr.startsWith('"') && valueStr.endsWith('"'))
|
||||||
throw VmExecutionException("encountered a var with a string value, but all string values should already have been moved into the heap")
|
throw VmExecutionException("encountered a var with a string value, but all string values should already have been moved into the heap")
|
||||||
else if(!valueStr.startsWith("heap:"))
|
else if(!valueStr.startsWith("heap:"))
|
||||||
throw VmExecutionException("invalid string value, should be a heap reference")
|
throw VmExecutionException("invalid string value, should be a heap reference")
|
||||||
else {
|
else {
|
||||||
val heapId = valueStr.substring(5).toInt()
|
val heapId = valueStr.substring(5).substringBefore(' ').toInt() // TODO process ZP and struct info?
|
||||||
RuntimeValue(type, heapId = heapId)
|
RuntimeValue(type, heapId = heapId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ class Program (val name: String,
|
|||||||
if(!valueStr.startsWith("heap:"))
|
if(!valueStr.startsWith("heap:"))
|
||||||
throw VmExecutionException("invalid array value, should be a heap reference")
|
throw VmExecutionException("invalid array value, should be a heap reference")
|
||||||
else {
|
else {
|
||||||
val heapId = valueStr.substring(5).toInt()
|
val heapId = valueStr.substring(5).substringBefore(' ').toInt() // TODO process ZP and struct info?
|
||||||
RuntimeValue(type, heapId = heapId)
|
RuntimeValue(type, heapId = heapId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ Variable declarations
|
|||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Variables should be declared with their exact type and size so the compiler can allocate storage
|
Variables should be declared with their exact type and size so the compiler can allocate storage
|
||||||
for them. You must give them an initial value as well. That value can be a simple literal value,
|
for them. You can give them an initial value as well. That value can be a simple literal value,
|
||||||
or an expression. You can add a ``@zp`` zeropage-tag, to tell the compiler to prioritize it
|
or an expression. You can add a ``@zp`` zeropage-tag, to tell the compiler to prioritize it
|
||||||
when selecting variables to be put into zeropage.
|
when selecting variables to be put into zeropage.
|
||||||
The syntax is::
|
The syntax is::
|
||||||
|
@ -3,41 +3,17 @@
|
|||||||
|
|
||||||
~ main {
|
~ main {
|
||||||
|
|
||||||
struct Color {
|
|
||||||
uword red
|
|
||||||
ubyte green
|
|
||||||
ubyte blue
|
|
||||||
}
|
|
||||||
|
|
||||||
str naam = "irmen"
|
|
||||||
word[] array = [1,2,3,4]
|
|
||||||
uword uw = $ab12
|
|
||||||
Color rgb = [255,128,0]
|
|
||||||
Color rgb2 = [111,222,33]
|
|
||||||
|
|
||||||
ubyte @zp zpvar=99
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
uword fake_address
|
str naam = "irmen"
|
||||||
|
|
||||||
fake_address = &naam
|
|
||||||
c64scr.print_uwhex(1, fake_address)
|
|
||||||
c64scr.print(", ")
|
|
||||||
|
|
||||||
fake_address = &array
|
|
||||||
c64scr.print_uwhex(1, fake_address)
|
|
||||||
c64scr.print(", ")
|
|
||||||
|
|
||||||
fake_address = &rgb
|
|
||||||
c64scr.print_uwhex(1, fake_address)
|
|
||||||
c64scr.print("\n")
|
|
||||||
|
|
||||||
; @todo only works once reference types are actually references:
|
|
||||||
;str name2 = naam ; @todo name2 points to same str as naam
|
|
||||||
;str name2 = fake_address ; @todo fake_address hopefully points to a str
|
|
||||||
;Color colz = fake_address ; @todo fake_address hopefully points to a Color
|
|
||||||
|
|
||||||
|
ubyte length = len(naam)
|
||||||
|
c64scr.print(naam)
|
||||||
|
c64scr.print("irmen")
|
||||||
|
c64scr.print("irmen2")
|
||||||
|
c64scr.print("irmen2")
|
||||||
|
ubyte length2 = len("irmen") ; @todo same string as 'naam'
|
||||||
|
ubyte length3 = len("zxfdsfsf") ; @todo new string
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user