mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +00:00
start making '&' (address-of) return a typed pointer, fixes some errors
This commit is contained in:
@@ -173,6 +173,28 @@ class DataType private constructor(val base: BaseDataType, val sub: BaseDataType
|
|||||||
else -> throw IllegalArgumentException("not an array")
|
else -> throw IllegalArgumentException("not an array")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun typeForAddressOf(msb: Boolean): DataType {
|
||||||
|
// TODO implement typed address-of.
|
||||||
|
// TODO no typed pointer possible yet that points to an array
|
||||||
|
if (isUndefined)
|
||||||
|
return if(msb) pointer(BaseDataType.UBYTE) else UWORD
|
||||||
|
else {
|
||||||
|
// TODO implement these as well:
|
||||||
|
// if(isBasic)
|
||||||
|
// return pointer(base)
|
||||||
|
// if(isString)
|
||||||
|
// return pointer(BaseDataType.UBYTE)
|
||||||
|
if (subType != null)
|
||||||
|
return pointerToType(subType!!)
|
||||||
|
else if (isArray) {
|
||||||
|
if (msb || isSplitWordArray)
|
||||||
|
return pointer(BaseDataType.UBYTE)
|
||||||
|
return UWORD
|
||||||
|
} else
|
||||||
|
return UWORD // TODO("address-of type for $this")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String = when(base) {
|
override fun toString(): String = when(base) {
|
||||||
BaseDataType.ARRAY -> {
|
BaseDataType.ARRAY -> {
|
||||||
when(sub) {
|
when(sub) {
|
||||||
|
|||||||
@@ -175,10 +175,10 @@ private fun PtVariable.prefix(parent: PtNode, st: SymbolTable): PtVariable {
|
|||||||
if(elt.definingBlock()?.options?.noSymbolPrefixing==true)
|
if(elt.definingBlock()?.options?.noSymbolPrefixing==true)
|
||||||
newValue.add(elt)
|
newValue.add(elt)
|
||||||
else {
|
else {
|
||||||
val newAddr = PtAddressOf(elt.position)
|
val newAddr = PtAddressOf(elt.type, elt.position)
|
||||||
newAddr.children.add(elt.identifier!!.prefix(newAddr, st))
|
newAddr.add(elt.identifier!!.prefix(newAddr, st))
|
||||||
if (elt.arrayIndexExpr != null)
|
if (elt.arrayIndexExpr != null)
|
||||||
newAddr.children.add(elt.arrayIndexExpr!!)
|
newAddr.add(elt.arrayIndexExpr!!)
|
||||||
newAddr.parent = arrayValue
|
newAddr.parent = arrayValue
|
||||||
newValue.add(newAddr)
|
newValue.add(newAddr)
|
||||||
}
|
}
|
||||||
@@ -1109,17 +1109,18 @@ $repeatLabel""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(ret: PtReturn) {
|
private fun translate(ret: PtReturn) {
|
||||||
val returnvalue = ret.children.singleOrNull()
|
val returnvalue = ret.children.singleOrNull() as? PtExpression
|
||||||
val sub = ret.definingSub()!!
|
val sub = ret.definingSub()!!
|
||||||
val returnRegs = sub.returnsWhatWhere()
|
val returnRegs = sub.returnsWhatWhere()
|
||||||
|
|
||||||
if(returnvalue!=null) {
|
if(returnvalue!=null) {
|
||||||
if (sub.signature.returns.single().isNumericOrBool) {
|
if (sub.signature.returns.single().isNumericOrBool) {
|
||||||
assignExpressionToRegister(returnvalue as PtExpression, returnRegs.single().first.registerOrPair!!)
|
assignExpressionToRegister(returnvalue, returnRegs.single().first.registerOrPair!!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// all else take its address and assign that also to AY register pair
|
// all else take its address and assign that also to AY register pair
|
||||||
val addrofValue = PtAddressOf(returnvalue.position)
|
val addrOfDt = returnvalue.type.typeForAddressOf(false)
|
||||||
|
val addrofValue = PtAddressOf(addrOfDt, returnvalue.position)
|
||||||
addrofValue.add(returnvalue as PtIdentifier)
|
addrofValue.add(returnvalue as PtIdentifier)
|
||||||
addrofValue.parent = ret.parent
|
addrofValue.parent = ret.parent
|
||||||
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnRegs.single().first.registerOrPair!!, false)
|
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnRegs.single().first.registerOrPair!!, false)
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"}
|
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"}
|
||||||
|
|
||||||
val slabname = PtIdentifier("prog8_slabs.prog8_memoryslab_$name", DataType.UWORD, fcall.position)
|
val slabname = PtIdentifier("prog8_slabs.prog8_memoryslab_$name", DataType.UWORD, fcall.position)
|
||||||
val addressOf = PtAddressOf(fcall.position)
|
val addressOf = PtAddressOf(DataType.pointer(BaseDataType.UBYTE), fcall.position)
|
||||||
addressOf.add(slabname)
|
addressOf.add(slabname)
|
||||||
addressOf.parent = fcall
|
addressOf.parent = fcall
|
||||||
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = addressOf)
|
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = addressOf)
|
||||||
@@ -1288,7 +1288,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
fun getSourceForFloat(value: PtExpression): AsmAssignSource {
|
fun getSourceForFloat(value: PtExpression): AsmAssignSource {
|
||||||
return when (value) {
|
return when (value) {
|
||||||
is PtIdentifier -> {
|
is PtIdentifier -> {
|
||||||
val addr = PtAddressOf(value.position)
|
val addr = PtAddressOf(DataType.pointer(BaseDataType.FLOAT), value.position)
|
||||||
addr.add(value)
|
addr.add(value)
|
||||||
addr.parent = call
|
addr.parent = call
|
||||||
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
||||||
@@ -1302,7 +1302,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
|
|
||||||
asmgen.subroutineExtra(scope).usedFloatEvalResultVar2 = true
|
asmgen.subroutineExtra(scope).usedFloatEvalResultVar2 = true
|
||||||
val variable = PtIdentifier(subroutineFloatEvalResultVar2, DataType.FLOAT, value.position)
|
val variable = PtIdentifier(subroutineFloatEvalResultVar2, DataType.FLOAT, value.position)
|
||||||
val addr = PtAddressOf(value.position)
|
val addr = PtAddressOf(DataType.pointer(BaseDataType.FLOAT), value.position)
|
||||||
addr.add(variable)
|
addr.add(variable)
|
||||||
addr.parent = call
|
addr.parent = call
|
||||||
asmgen.assignExpressionToVariable(value, asmgen.asmVariableName(variable), DataType.FLOAT)
|
asmgen.assignExpressionToVariable(value, asmgen.asmVariableName(variable), DataType.FLOAT)
|
||||||
@@ -1322,7 +1322,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
|
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
|
||||||
conv.dt.isPassByRef -> {
|
conv.dt.isPassByRef -> {
|
||||||
// put the address of the argument in AY
|
// put the address of the argument in AY
|
||||||
val addr = PtAddressOf(value.position)
|
val addr = PtAddressOf(DataType.forDt(conv.dt).typeForAddressOf(false), value.position)
|
||||||
addr.add(value)
|
addr.add(value)
|
||||||
addr.parent = call
|
addr.parent = call
|
||||||
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
||||||
@@ -1340,7 +1340,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
|
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
|
||||||
conv.dt.isPassByRef -> {
|
conv.dt.isPassByRef -> {
|
||||||
// put the address of the argument in AY
|
// put the address of the argument in AY
|
||||||
val addr = PtAddressOf(value.position)
|
val addr = PtAddressOf(DataType.forDt(conv.dt).typeForAddressOf(false),value.position)
|
||||||
addr.add(value)
|
addr.add(value)
|
||||||
addr.parent = call
|
addr.parent = call
|
||||||
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
|||||||
}
|
}
|
||||||
val src = if(value.type.isPassByRef) {
|
val src = if(value.type.isPassByRef) {
|
||||||
if(value is PtIdentifier) {
|
if(value is PtIdentifier) {
|
||||||
val addr = PtAddressOf(Position.DUMMY)
|
val addr = PtAddressOf(value.type.typeForAddressOf(false),Position.DUMMY)
|
||||||
addr.add(value)
|
addr.add(value)
|
||||||
addr.parent = scope as PtNode
|
addr.parent = scope as PtNode
|
||||||
AsmAssignSource.fromAstSource(addr, program, asmgen).adjustSignedUnsigned(target)
|
AsmAssignSource.fromAstSource(addr, program, asmgen).adjustSignedUnsigned(target)
|
||||||
|
|||||||
@@ -2129,7 +2129,7 @@ $endLabel""")
|
|||||||
assignExpressionToRegister(value, RegisterOrPair.A, valueDt.isSigned)
|
assignExpressionToRegister(value, RegisterOrPair.A, valueDt.isSigned)
|
||||||
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.A, valueDt.base)
|
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.A, valueDt.base)
|
||||||
}
|
}
|
||||||
valueDt.isWord -> {
|
valueDt.isWord || valueDt.isPointer -> {
|
||||||
assignExpressionToRegister(value, RegisterOrPair.AY, valueDt.isSigned)
|
assignExpressionToRegister(value, RegisterOrPair.AY, valueDt.isSigned)
|
||||||
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.AY, valueDt.base)
|
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.AY, valueDt.base)
|
||||||
}
|
}
|
||||||
@@ -2607,6 +2607,18 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
BaseDataType.STR -> throw AssemblyError("cannot typecast a string value")
|
BaseDataType.STR -> throw AssemblyError("cannot typecast a string value")
|
||||||
|
BaseDataType.POINTER -> {
|
||||||
|
if(targetDt.isWord || targetDt.isPointer) {
|
||||||
|
when(regs) {
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" sta $targetAsmVarName | stx $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" sta $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" stx $targetAsmVarName | sty $targetAsmVarName+1")
|
||||||
|
else -> throw AssemblyError("non-word regs")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw AssemblyError("cannot assign pointer to $targetDt")
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw AssemblyError("weird type")
|
else -> throw AssemblyError("weird type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1994,6 +1994,10 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(struct: StructDecl) {
|
override fun visit(struct: StructDecl) {
|
||||||
|
|
||||||
|
if(compilerOptions.compTarget.name != VMTarget.NAME)
|
||||||
|
TODO("struct types are not yet supported in the 6502 compilation targets (only virtual) ${struct.position}")
|
||||||
|
|
||||||
val uniqueFields = struct.fields.map { it.second }.toSet()
|
val uniqueFields = struct.fields.map { it.second }.toSet()
|
||||||
if(uniqueFields.size!=struct.fields.size)
|
if(uniqueFields.size!=struct.fields.size)
|
||||||
errors.err("duplicate field names in struct", struct.position)
|
errors.err("duplicate field names in struct", struct.position)
|
||||||
@@ -2006,11 +2010,22 @@ internal class AstChecker(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(deref: PtrDereference) {
|
override fun visit(deref: PtrDereference) {
|
||||||
|
|
||||||
|
if(compilerOptions.compTarget.name != VMTarget.NAME)
|
||||||
|
TODO("typed pointers are not yet supported in the 6502 compilation targets (only virtual) ${deref.position}")
|
||||||
|
|
||||||
// unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet.
|
// unfortunately the AST regarding pointer dereferencing is a bit of a mess, and we cannot do precise type checking on elements inside such expressions yet.
|
||||||
if(deref.inferType(program).isUnknown)
|
if(deref.inferType(program).isUnknown)
|
||||||
errors.err("unable to determine type of dereferenced pointer expression", deref.position)
|
errors.err("unable to determine type of dereferenced pointer expression", deref.position)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visit(deref: PtrIndexedDereference) {
|
||||||
|
if(compilerOptions.compTarget.name != VMTarget.NAME)
|
||||||
|
TODO("typed pointers are not yet supported in the 6502 compilation targets (only virtual) ${deref.position}")
|
||||||
|
|
||||||
|
// TODO ast checks for this one?
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkLongType(expression: Expression) {
|
private fun checkLongType(expression: Expression) {
|
||||||
if(expression.inferType(program) issimpletype BaseDataType.LONG) {
|
if(expression.inferType(program) issimpletype BaseDataType.LONG) {
|
||||||
if((expression.parent as? VarDecl)?.type!=VarDeclType.CONST) {
|
if((expression.parent as? VarDecl)?.type!=VarDeclType.CONST) {
|
||||||
|
|||||||
@@ -687,7 +687,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun transform(src: AddressOf): PtAddressOf {
|
private fun transform(src: AddressOf): PtAddressOf {
|
||||||
val addr = PtAddressOf(src.position, src.msb)
|
val addr = PtAddressOf(src.inferType(program).getOrUndef(), src.position, src.msb)
|
||||||
if(src.identifier!=null)
|
if(src.identifier!=null)
|
||||||
addr.add(transform(src.identifier!!))
|
addr.add(transform(src.identifier!!))
|
||||||
if (src.arrayIndex != null)
|
if (src.arrayIndex != null)
|
||||||
@@ -945,7 +945,8 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
|||||||
private fun transform(srcCast: TypecastExpression): PtTypeCast {
|
private fun transform(srcCast: TypecastExpression): PtTypeCast {
|
||||||
val cast = PtTypeCast(srcCast.type, srcCast.position)
|
val cast = PtTypeCast(srcCast.type, srcCast.position)
|
||||||
cast.add(transformExpression(srcCast.expression))
|
cast.add(transformExpression(srcCast.expression))
|
||||||
require(cast.type!=cast.value.type)
|
require(cast.type!=cast.value.type) {
|
||||||
|
"bogus typecast shouldn't occur at ${srcCast.position}" }
|
||||||
return cast
|
return cast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class TestPointers: FunSpec( {
|
|||||||
|
|
||||||
val outputDir = tempdir().toPath()
|
val outputDir = tempdir().toPath()
|
||||||
|
|
||||||
test("block scoping still parsed correctly") {
|
xtest("block scoping still parsed correctly") {
|
||||||
val src="""
|
val src="""
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|||||||
@@ -261,16 +261,16 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("const address-of memory mapped arrays") {
|
test("const address-of memory mapped arrays") {
|
||||||
val src="""
|
val src= """
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
&uword[30] @nosplit wb = ${'$'}2000
|
&uword[30] @nosplit wb = $2000
|
||||||
&uword[100] @nosplit array1 = ${'$'}9e00
|
&uword[100] @nosplit array1 = $9e00
|
||||||
&uword[30] @nosplit array2 = &array1[len(wb)]
|
&uword[30] @nosplit array2 = &array1[len(wb)]
|
||||||
|
|
||||||
cx16.r0 = &array1 ; ${'$'}9e00
|
cx16.r0 = &array1 ; $9e00
|
||||||
cx16.r1 = &array1[len(wb)] ; ${'$'}9e3c
|
cx16.r1 = &array1[len(wb)] ; $9e3c
|
||||||
cx16.r2 = &array2 ; ${'$'}9e3c
|
cx16.r2 = &array2 ; $9e3c
|
||||||
}
|
}
|
||||||
}"""
|
}"""
|
||||||
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)!!
|
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)!!
|
||||||
@@ -307,10 +307,10 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test("address of a const uword pointer array expression") {
|
test("address of a const uword pointer array expression") {
|
||||||
val src="""
|
val src= """
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
const uword buffer = ${'$'}2000
|
const uword buffer = $2000
|
||||||
uword @shared addr = &buffer[2]
|
uword @shared addr = &buffer[2]
|
||||||
|
|
||||||
const ubyte width = 100
|
const ubyte width = 100
|
||||||
|
|||||||
@@ -635,14 +635,14 @@ private fun ExpressionContext.toAst(insideParentheses: Boolean=false) : Expressi
|
|||||||
|
|
||||||
if(addressof()!=null) {
|
if(addressof()!=null) {
|
||||||
val addressOf = addressof()
|
val addressOf = addressof()
|
||||||
val identifier = addressOf.scoped_identifier()
|
val identifier = addressOf.scoped_identifier().toAst()
|
||||||
val msb = addressOf.ADDRESS_OF_MSB()!=null
|
val msb = addressOf.ADDRESS_OF_MSB()!=null
|
||||||
// note: &< (ADDRESS_OF_LSB) is equivalent to a regular &.
|
// note: &< (ADDRESS_OF_LSB) is equivalent to a regular &.
|
||||||
return if (identifier != null)
|
val index = addressOf.arrayindex()?.toAst()
|
||||||
AddressOf(addressof().scoped_identifier().toAst(),null, null, msb, toPosition())
|
return if(index!=null) {
|
||||||
else {
|
AddressOf(identifier, index, null, msb, toPosition())
|
||||||
val array = addressOf.arrayindexed()
|
} else {
|
||||||
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), null, msb, toPosition())
|
AddressOf(identifier,null, null, msb, toPosition())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -553,7 +553,17 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
override fun referencesIdentifier(nameInSource: List<String>) = identifier?.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true || dereference?.referencesIdentifier(nameInSource)==true
|
override fun referencesIdentifier(nameInSource: List<String>) = identifier?.nameInSource==nameInSource || arrayIndex?.referencesIdentifier(nameInSource)==true || dereference?.referencesIdentifier(nameInSource)==true
|
||||||
override fun inferType(program: Program) = InferredTypes.knownFor(BaseDataType.UWORD)
|
override fun inferType(program: Program): InferredTypes.InferredType {
|
||||||
|
if(identifier!=null) {
|
||||||
|
val type = identifier!!.inferType(program).getOrUndef()
|
||||||
|
val addrofDt = type.typeForAddressOf(msb)
|
||||||
|
if(addrofDt.isUndefined) return InferredTypes.unknown()
|
||||||
|
else return InferredTypes.knownFor(addrofDt)
|
||||||
|
} else if(dereference!=null) {
|
||||||
|
TODO("address-of struct ptr deref field -> ptr type itself?")
|
||||||
|
} else
|
||||||
|
throw FatalAstException("invalid addressof")
|
||||||
|
}
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||||
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
override fun accept(visitor: AstWalker, parent: Node)= visitor.visit(this, parent)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ STRUCTS and TYPED POINTERS
|
|||||||
- DONE: start by making ptr.value++ work , and ptr.value = ptr.value+20, and ptr.value = cx16.r0L+20+ptr.value Likewise for subtraction. DON'T FORGET C POINTER SEMANTICS. Other operators are nonsensical for ptr arith
|
- DONE: start by making ptr.value++ work , and ptr.value = ptr.value+20, and ptr.value = cx16.r0L+20+ptr.value Likewise for subtraction. DON'T FORGET C POINTER SEMANTICS. Other operators are nonsensical for ptr arith
|
||||||
- DONE: support @dirty on pointer vars -> uninitialized pointer placed in BSS_noclear segment
|
- DONE: support @dirty on pointer vars -> uninitialized pointer placed in BSS_noclear segment
|
||||||
- DONE: support comparison operators on pointers
|
- DONE: support comparison operators on pointers
|
||||||
- fix REGRESSION: passing adress to array element errors with "at the moment it is not possible to chain array syntax" see unit test "block scoping still parsed correctly" https://discord.com/channels/547559626024157184/926342257290903552/1369394392980263022
|
- implement augmented assignment on pointer dereference; ptr^^ *= 5
|
||||||
- implement augmented assignment on pointer dereference; ptr^^ += 10
|
|
||||||
- fix actual _msb/_lsb storage of the split-words pointer-arrays
|
- fix actual _msb/_lsb storage of the split-words pointer-arrays
|
||||||
- pointer types in subroutine signatures (both normal and asm-subs)
|
- pointer types in subroutine signatures (both normal and asm-subs)
|
||||||
- support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
|
- support chaining pointer dereference on function calls that return a pointer. (type checking now fails on stuff like func().field and func().next.field)
|
||||||
|
- make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator. + unit test.
|
||||||
- are the ARRAY_POINTER and ARRAY_STRUCT data type enums realy needed? can't we just use ARRAY?
|
- are the ARRAY_POINTER and ARRAY_STRUCT data type enums realy needed? can't we just use ARRAY?
|
||||||
- fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
|
- fixing the pointer dereferencing issues (cursed hybrid beween IdentifierReference, PtrDereferece and PtrIndexedDereference) may require getting rid of scoped identifiers altogether and treat '.' as a "scope or pointer following operator"
|
||||||
- add unit tests for all changes
|
- add unit tests for all changes
|
||||||
|
|||||||
307
examples/test.p8
307
examples/test.p8
@@ -1,276 +1,47 @@
|
|||||||
%zeropage basicsafe
|
|
||||||
%import math
|
|
||||||
%import textio
|
%import textio
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
; put 9 nodes into the buffer sequentially.
|
const uword buffer = $2000
|
||||||
; each of the first 3 nodes points to the 4th, 5th, 6th.
|
uword @shared addr = &buffer[2]
|
||||||
; these in turn point to the 7th, 8th and 9th.
|
|
||||||
|
|
||||||
struct Node {
|
const ubyte width = 100
|
||||||
bool flag
|
ubyte @shared i
|
||||||
ubyte value
|
ubyte @shared j
|
||||||
^^Node next
|
uword @shared addr2 = &buffer[i * width + j]
|
||||||
}
|
txt.print_uw(addr)
|
||||||
|
|
||||||
|
|
||||||
^^Node @shared ptr = 2000
|
|
||||||
txt.print_uw(ptr)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
cx16.r0 = 0
|
|
||||||
ptr = cx16.r0 + ptr - 1
|
|
||||||
txt.print_uw(ptr)
|
|
||||||
txt.nl()
|
|
||||||
ptr = ptr - 1 - cx16.r0
|
|
||||||
txt.print_uw(ptr)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
cx16.r0=0
|
|
||||||
ptr = cx16.r0 + ptr - 10
|
|
||||||
txt.print_uw(ptr)
|
|
||||||
txt.nl()
|
|
||||||
ptr = ptr - 10 - cx16.r0
|
|
||||||
txt.print_uw(ptr)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
|
|
||||||
; static initializer syntax:
|
|
||||||
^^Node @shared node0 = Node() ; no initialization (will be in BSS and zeroed out at startup)
|
|
||||||
^^Node @shared node1 = Node( false, 11, 0 )
|
|
||||||
^^Node @shared node2 = Node( false, 22, 0 )
|
|
||||||
^^Node @shared node3 = Node( true, 33, 0 )
|
|
||||||
|
|
||||||
; list of pointers: (W.I.P.):
|
|
||||||
; ^^Node[5] @shared nodes
|
|
||||||
; for nptr in nodes {
|
|
||||||
; txt.print_uw(nptr)
|
|
||||||
; txt.spc()
|
|
||||||
; }
|
|
||||||
; txt.nl()
|
|
||||||
|
|
||||||
; link up
|
|
||||||
node0.next = node1
|
|
||||||
node1.next = node2
|
|
||||||
node2.next = node3
|
|
||||||
|
|
||||||
^^Node nptr = node0
|
|
||||||
while nptr {
|
|
||||||
txt.print("node at ")
|
|
||||||
txt.print_uw(nptr)
|
|
||||||
txt.print("\n flag=")
|
|
||||||
txt.print_bool(nptr.flag)
|
|
||||||
txt.print("\n value=")
|
|
||||||
txt.print_ub(nptr.value)
|
|
||||||
txt.nl()
|
|
||||||
nptr = nptr.next
|
|
||||||
}
|
|
||||||
|
|
||||||
^^Node n0,n1,n2,n3,n4,n5,n6,n7,n8
|
|
||||||
|
|
||||||
uword buf = memory("buffer", 2000, 0)
|
|
||||||
sys.memset(buf, 2000, 0)
|
|
||||||
|
|
||||||
n0 = buf + 0
|
|
||||||
n1 = buf + sizeof(Node)
|
|
||||||
n2 = buf + sizeof(Node)*2
|
|
||||||
n3 = buf + sizeof(Node)*3
|
|
||||||
n4 = buf + sizeof(Node)*4
|
|
||||||
n5 = buf + sizeof(Node)*5
|
|
||||||
n6 = buf + sizeof(Node)*6
|
|
||||||
n7 = buf + sizeof(Node)*7
|
|
||||||
n8 = buf + sizeof(Node)*8
|
|
||||||
|
|
||||||
n0.next = n3
|
|
||||||
n1.next = n4
|
|
||||||
n2.next = n5
|
|
||||||
n3.next = n6
|
|
||||||
n4.next = n7
|
|
||||||
n5.next = n8
|
|
||||||
|
|
||||||
n0.value = 'a'
|
|
||||||
n1.value = 'b'
|
|
||||||
n2.value = 'c'
|
|
||||||
n3.value = 'd'
|
|
||||||
n4.value = 'e'
|
|
||||||
n5.value = 'f'
|
|
||||||
n6.value = 'g'
|
|
||||||
n7.value = 'h'
|
|
||||||
n8.value = 'i'
|
|
||||||
|
|
||||||
txt.print("struct size: ")
|
|
||||||
txt.print_uw(sizeof(Node))
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("pointer values: ")
|
|
||||||
txt.print_uw(n0)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n1)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n2)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n3)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n4)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n5)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n6)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n7)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(n8)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("field address: ")
|
|
||||||
txt.print_uw(&n0.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n1.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n2.value)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(&n6.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n7.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n8.value)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(&n0.next.next.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n1.next.next.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(&n2.next.next.value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("node values: ")
|
|
||||||
txt.chrout(n0.value)
|
|
||||||
txt.chrout(n1.value)
|
|
||||||
txt.chrout(n2.value)
|
|
||||||
txt.chrout(n3.value)
|
|
||||||
txt.chrout(n4.value)
|
|
||||||
txt.chrout(n5.value)
|
|
||||||
txt.chrout(n6.value)
|
|
||||||
txt.chrout(n7.value)
|
|
||||||
txt.chrout(n8.value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("linked values:\n")
|
|
||||||
txt.print("n0: ")
|
|
||||||
ptr = n0
|
|
||||||
while ptr {
|
|
||||||
txt.chrout(ptr.value)
|
|
||||||
ptr = ptr.next
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
txt.print("n1: ")
|
|
||||||
ptr = n1
|
|
||||||
while ptr {
|
|
||||||
txt.chrout(ptr.value)
|
|
||||||
ptr = ptr.next
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
txt.print("n2: ")
|
|
||||||
ptr = n2
|
|
||||||
while ptr {
|
|
||||||
txt.chrout(ptr.value)
|
|
||||||
ptr = ptr.next
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("array syntax on nodes: ")
|
|
||||||
txt.chrout(n0[0].value)
|
|
||||||
txt.chrout(n0[1].value)
|
|
||||||
txt.chrout(n0[2].value)
|
|
||||||
txt.chrout(n0[3].value)
|
|
||||||
txt.chrout(n0[4].value)
|
|
||||||
txt.chrout(n0[5].value)
|
|
||||||
txt.chrout(n0[6].value)
|
|
||||||
txt.chrout(n0[7].value)
|
|
||||||
txt.chrout(n0[8].value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("array syntax followed by dereference: ")
|
|
||||||
txt.chrout(n0[0].next.next.value)
|
|
||||||
txt.chrout(n0[1].next.next.value)
|
|
||||||
txt.chrout(n0[2].next.next.value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("assigning to fields: ")
|
|
||||||
n0.value = 'q'
|
|
||||||
n1.value = 'w'
|
|
||||||
n2.value = 'e'
|
|
||||||
n0.next.next.value = 'x'
|
|
||||||
n1.next.next.value = 'y'
|
|
||||||
n2.next.next.value = 'z'
|
|
||||||
txt.chrout(n0.value)
|
|
||||||
txt.chrout(n1.value)
|
|
||||||
txt.chrout(n2.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.chrout(n0.next.next.value)
|
|
||||||
txt.chrout(n1.next.next.value)
|
|
||||||
txt.chrout(n2.next.next.value)
|
|
||||||
txt.spc()
|
|
||||||
txt.chrout(n6.value)
|
|
||||||
txt.chrout(n7.value)
|
|
||||||
txt.chrout(n8.value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("ptr to simple types: ")
|
|
||||||
word w_value = -9999
|
|
||||||
txt.print_w(w_value)
|
|
||||||
txt.spc()
|
|
||||||
^^word w_ptr = &w_value
|
|
||||||
w_ptr^^ = 5555
|
|
||||||
txt.print_w(w_value)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
word[] @nosplit warray = [1111,2222,3333,4444,5555,6666]
|
|
||||||
w_ptr = &warray
|
|
||||||
txt.print_w(w_ptr^^)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_w(w_ptr[4]^^)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
txt.print("function call and pointer comparisons: ")
|
|
||||||
cx16.r10=9998
|
|
||||||
^^uword uw_ptr = &cx16.r10
|
|
||||||
uw_ptr^^ = 4444
|
|
||||||
txt.print_uw(cx16.r10)
|
|
||||||
txt.spc()
|
|
||||||
^^uword uw_ptr2 = func(uw_ptr, 9000)
|
|
||||||
txt.print_uw(cx16.r10)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(uw_ptr2^^)
|
|
||||||
txt.nl()
|
|
||||||
uw_ptr2++
|
|
||||||
txt.print_bool(uw_ptr2 == uw_ptr)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(uw_ptr2 != uw_ptr)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(uw_ptr2 < uw_ptr)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(uw_ptr2 > uw_ptr)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(uw_ptr2 <= uw_ptr)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_bool(uw_ptr2 >= uw_ptr)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
;readbyte(&thing.name)
|
|
||||||
;readbyte(&thing.name[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
sub func(^^uword ptr, uword value) -> ^^uword {
|
|
||||||
ptr^^ = value * 2
|
|
||||||
return ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
sub readbyte(uword ptr) {
|
|
||||||
@(ptr) = 99
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
;thing {
|
/*
|
||||||
; str name = "irmen"
|
main {
|
||||||
;}
|
sub start() {
|
||||||
|
readbyte(&thing.name) ; ok
|
||||||
|
readbyte(&thing.name[1]) ; ok
|
||||||
|
readbyte(&thing.array) ; ok
|
||||||
|
cx16.r0 = &thing.array[1] ; TODO with typed &: fix error, register multiple types
|
||||||
|
readbyte(&thing.array[1]) ; TODO with typed &: fix error, register multiple types
|
||||||
|
}
|
||||||
|
|
||||||
|
sub readbyte(uword @requirezp ptr) {
|
||||||
|
thing.printpointer()
|
||||||
|
txt.spc()
|
||||||
|
txt.print_uw(ptr)
|
||||||
|
txt.nl()
|
||||||
|
ptr=0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thing {
|
||||||
|
str name = "error"
|
||||||
|
ubyte[10] array
|
||||||
|
|
||||||
|
sub printpointer() {
|
||||||
|
txt.print("&name=")
|
||||||
|
txt.print_uw(&name)
|
||||||
|
txt.print(" &array=")
|
||||||
|
txt.print_uw(&array)
|
||||||
|
txt.nl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ typecast : 'as' datatype;
|
|||||||
|
|
||||||
directmemory : '@' '(' expression ')';
|
directmemory : '@' '(' expression ')';
|
||||||
|
|
||||||
addressof : <assoc=right> (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) (scoped_identifier | arrayindexed) ;
|
addressof : <assoc=right> (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) scoped_identifier arrayindex? ;
|
||||||
|
|
||||||
functioncall : scoped_identifier '(' expression_list? ')' ;
|
functioncall : scoped_identifier '(' expression_list? ')' ;
|
||||||
|
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
class PtAddressOf(position: Position, val isMsbForSplitArray: Boolean=false) : PtExpression(DataType.UWORD, position) {
|
class PtAddressOf(type: DataType, position: Position, val isMsbForSplitArray: Boolean=false) : PtExpression(type, position) {
|
||||||
val identifier: PtIdentifier?
|
val identifier: PtIdentifier?
|
||||||
get() = children[0] as? PtIdentifier
|
get() = children[0] as? PtIdentifier
|
||||||
val dereference: PtPointerDeref?
|
val dereference: PtPointerDeref?
|
||||||
|
|||||||
Reference in New Issue
Block a user