mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16: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")
|
||||
}
|
||||
|
||||
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) {
|
||||
BaseDataType.ARRAY -> {
|
||||
when(sub) {
|
||||
|
||||
@@ -175,10 +175,10 @@ private fun PtVariable.prefix(parent: PtNode, st: SymbolTable): PtVariable {
|
||||
if(elt.definingBlock()?.options?.noSymbolPrefixing==true)
|
||||
newValue.add(elt)
|
||||
else {
|
||||
val newAddr = PtAddressOf(elt.position)
|
||||
newAddr.children.add(elt.identifier!!.prefix(newAddr, st))
|
||||
val newAddr = PtAddressOf(elt.type, elt.position)
|
||||
newAddr.add(elt.identifier!!.prefix(newAddr, st))
|
||||
if (elt.arrayIndexExpr != null)
|
||||
newAddr.children.add(elt.arrayIndexExpr!!)
|
||||
newAddr.add(elt.arrayIndexExpr!!)
|
||||
newAddr.parent = arrayValue
|
||||
newValue.add(newAddr)
|
||||
}
|
||||
@@ -1109,17 +1109,18 @@ $repeatLabel""")
|
||||
}
|
||||
|
||||
private fun translate(ret: PtReturn) {
|
||||
val returnvalue = ret.children.singleOrNull()
|
||||
val returnvalue = ret.children.singleOrNull() as? PtExpression
|
||||
val sub = ret.definingSub()!!
|
||||
val returnRegs = sub.returnsWhatWhere()
|
||||
|
||||
if(returnvalue!=null) {
|
||||
if (sub.signature.returns.single().isNumericOrBool) {
|
||||
assignExpressionToRegister(returnvalue as PtExpression, returnRegs.single().first.registerOrPair!!)
|
||||
assignExpressionToRegister(returnvalue, returnRegs.single().first.registerOrPair!!)
|
||||
}
|
||||
else {
|
||||
// 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.parent = ret.parent
|
||||
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}"}
|
||||
|
||||
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.parent = fcall
|
||||
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 {
|
||||
return when (value) {
|
||||
is PtIdentifier -> {
|
||||
val addr = PtAddressOf(value.position)
|
||||
val addr = PtAddressOf(DataType.pointer(BaseDataType.FLOAT), value.position)
|
||||
addr.add(value)
|
||||
addr.parent = call
|
||||
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
||||
@@ -1302,7 +1302,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
|
||||
asmgen.subroutineExtra(scope).usedFloatEvalResultVar2 = true
|
||||
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.parent = call
|
||||
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.isPassByRef -> {
|
||||
// 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.parent = call
|
||||
AsmAssignSource.fromAstSource(addr, program, asmgen)
|
||||
@@ -1340,7 +1340,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
conv.dt==BaseDataType.FLOAT -> getSourceForFloat(value)
|
||||
conv.dt.isPassByRef -> {
|
||||
// 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.parent = call
|
||||
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) {
|
||||
if(value is PtIdentifier) {
|
||||
val addr = PtAddressOf(Position.DUMMY)
|
||||
val addr = PtAddressOf(value.type.typeForAddressOf(false),Position.DUMMY)
|
||||
addr.add(value)
|
||||
addr.parent = scope as PtNode
|
||||
AsmAssignSource.fromAstSource(addr, program, asmgen).adjustSignedUnsigned(target)
|
||||
|
||||
@@ -2129,7 +2129,7 @@ $endLabel""")
|
||||
assignExpressionToRegister(value, RegisterOrPair.A, valueDt.isSigned)
|
||||
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.A, valueDt.base)
|
||||
}
|
||||
valueDt.isWord -> {
|
||||
valueDt.isWord || valueDt.isPointer -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.AY, valueDt.isSigned)
|
||||
assignTypeCastedRegisters(target.asmVarname, targetDt.base, RegisterOrPair.AY, valueDt.base)
|
||||
}
|
||||
@@ -2607,6 +2607,18 @@ $endLabel""")
|
||||
}
|
||||
}
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1994,6 +1994,10 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
|
||||
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()
|
||||
if(uniqueFields.size!=struct.fields.size)
|
||||
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) {
|
||||
|
||||
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.
|
||||
if(deref.inferType(program).isUnknown)
|
||||
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) {
|
||||
if(expression.inferType(program) issimpletype BaseDataType.LONG) {
|
||||
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 {
|
||||
val addr = PtAddressOf(src.position, src.msb)
|
||||
val addr = PtAddressOf(src.inferType(program).getOrUndef(), src.position, src.msb)
|
||||
if(src.identifier!=null)
|
||||
addr.add(transform(src.identifier!!))
|
||||
if (src.arrayIndex != null)
|
||||
@@ -945,7 +945,8 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
private fun transform(srcCast: TypecastExpression): PtTypeCast {
|
||||
val cast = PtTypeCast(srcCast.type, srcCast.position)
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class TestPointers: FunSpec( {
|
||||
|
||||
val outputDir = tempdir().toPath()
|
||||
|
||||
test("block scoping still parsed correctly") {
|
||||
xtest("block scoping still parsed correctly") {
|
||||
val src="""
|
||||
main {
|
||||
sub start() {
|
||||
|
||||
@@ -261,16 +261,16 @@ main {
|
||||
}
|
||||
|
||||
test("const address-of memory mapped arrays") {
|
||||
val src="""
|
||||
val src= """
|
||||
main {
|
||||
sub start() {
|
||||
&uword[30] @nosplit wb = ${'$'}2000
|
||||
&uword[100] @nosplit array1 = ${'$'}9e00
|
||||
&uword[30] @nosplit wb = $2000
|
||||
&uword[100] @nosplit array1 = $9e00
|
||||
&uword[30] @nosplit array2 = &array1[len(wb)]
|
||||
|
||||
cx16.r0 = &array1 ; ${'$'}9e00
|
||||
cx16.r1 = &array1[len(wb)] ; ${'$'}9e3c
|
||||
cx16.r2 = &array2 ; ${'$'}9e3c
|
||||
cx16.r0 = &array1 ; $9e00
|
||||
cx16.r1 = &array1[len(wb)] ; $9e3c
|
||||
cx16.r2 = &array2 ; $9e3c
|
||||
}
|
||||
}"""
|
||||
val result = compileText(Cx16Target(), false, src, outputDir, writeAssembly = false)!!
|
||||
@@ -307,10 +307,10 @@ main {
|
||||
}
|
||||
|
||||
test("address of a const uword pointer array expression") {
|
||||
val src="""
|
||||
val src= """
|
||||
main {
|
||||
sub start() {
|
||||
const uword buffer = ${'$'}2000
|
||||
const uword buffer = $2000
|
||||
uword @shared addr = &buffer[2]
|
||||
|
||||
const ubyte width = 100
|
||||
|
||||
@@ -635,14 +635,14 @@ private fun ExpressionContext.toAst(insideParentheses: Boolean=false) : Expressi
|
||||
|
||||
if(addressof()!=null) {
|
||||
val addressOf = addressof()
|
||||
val identifier = addressOf.scoped_identifier()
|
||||
val identifier = addressOf.scoped_identifier().toAst()
|
||||
val msb = addressOf.ADDRESS_OF_MSB()!=null
|
||||
// note: &< (ADDRESS_OF_LSB) is equivalent to a regular &.
|
||||
return if (identifier != null)
|
||||
AddressOf(addressof().scoped_identifier().toAst(),null, null, msb, toPosition())
|
||||
else {
|
||||
val array = addressOf.arrayindexed()
|
||||
AddressOf(array.scoped_identifier().toAst(), array.arrayindex().toAst(), null, msb, toPosition())
|
||||
val index = addressOf.arrayindex()?.toAst()
|
||||
return if(index!=null) {
|
||||
AddressOf(identifier, index, null, msb, toPosition())
|
||||
} else {
|
||||
AddressOf(identifier,null, null, msb, toPosition())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -553,7 +553,17 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
|
||||
return null
|
||||
}
|
||||
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: 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: support @dirty on pointer vars -> uninitialized pointer placed in BSS_noclear segment
|
||||
- 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^^ += 10
|
||||
- implement augmented assignment on pointer dereference; ptr^^ *= 5
|
||||
- fix actual _msb/_lsb storage of the split-words pointer-arrays
|
||||
- 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)
|
||||
- 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?
|
||||
- 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
|
||||
|
||||
307
examples/test.p8
307
examples/test.p8
@@ -1,276 +1,47 @@
|
||||
%zeropage basicsafe
|
||||
%import math
|
||||
%import textio
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; put 9 nodes into the buffer sequentially.
|
||||
; each of the first 3 nodes points to the 4th, 5th, 6th.
|
||||
; these in turn point to the 7th, 8th and 9th.
|
||||
const uword buffer = $2000
|
||||
uword @shared addr = &buffer[2]
|
||||
|
||||
struct Node {
|
||||
bool flag
|
||||
ubyte value
|
||||
^^Node next
|
||||
}
|
||||
|
||||
|
||||
^^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
|
||||
const ubyte width = 100
|
||||
ubyte @shared i
|
||||
ubyte @shared j
|
||||
uword @shared addr2 = &buffer[i * width + j]
|
||||
txt.print_uw(addr)
|
||||
}
|
||||
}
|
||||
|
||||
;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 ')';
|
||||
|
||||
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? ')' ;
|
||||
|
||||
|
||||
@@ -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?
|
||||
get() = children[0] as? PtIdentifier
|
||||
val dereference: PtPointerDeref?
|
||||
|
||||
Reference in New Issue
Block a user