From 8353c689ca291223d2f1ff31c38eab93fd70e15d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 8 May 2025 22:40:26 +0200 Subject: [PATCH] start making '&' (address-of) return a typed pointer, fixes some errors --- codeCore/src/prog8/code/core/Enumerations.kt | 22 ++ .../src/prog8/codegen/cpu6502/AsmGen.kt | 13 +- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 10 +- .../codegen/cpu6502/FunctionCallAsmGen.kt | 2 +- .../cpu6502/assignment/AssignmentAsmGen.kt | 14 +- .../compiler/astprocessing/AstChecker.kt | 15 + .../astprocessing/SimplifiedAstMaker.kt | 5 +- compiler/test/TestPointers.kt | 2 +- compiler/test/ast/TestConst.kt | 16 +- .../src/prog8/ast/antlr/Antlr2Kotlin.kt | 12 +- .../prog8/ast/expressions/AstExpressions.kt | 12 +- docs/source/todo.rst | 4 +- examples/test.p8 | 307 +++--------------- parser/src/main/antlr/Prog8ANTLR.g4 | 2 +- .../src/prog8/code/ast/AstExpressions.kt | 2 +- 15 files changed, 135 insertions(+), 303 deletions(-) diff --git a/codeCore/src/prog8/code/core/Enumerations.kt b/codeCore/src/prog8/code/core/Enumerations.kt index 33e5ee7a2..3962b7273 100644 --- a/codeCore/src/prog8/code/core/Enumerations.kt +++ b/codeCore/src/prog8/code/core/Enumerations.kt @@ -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) { diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index 9373303bd..1992e3d4f 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -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) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 74ce67440..cab936e3c 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -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) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index f6cf7787e..f35a13ac8 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -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) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 63113b496..554507ae9 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -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") } } diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 1c4250b39..161cfd169 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -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) { diff --git a/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt b/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt index b6f5c120f..5cdea0c18 100644 --- a/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/SimplifiedAstMaker.kt @@ -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 } diff --git a/compiler/test/TestPointers.kt b/compiler/test/TestPointers.kt index 587ede077..d0b3653cf 100644 --- a/compiler/test/TestPointers.kt +++ b/compiler/test/TestPointers.kt @@ -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() { diff --git a/compiler/test/ast/TestConst.kt b/compiler/test/ast/TestConst.kt index ceabe1796..532c9f7ae 100644 --- a/compiler/test/ast/TestConst.kt +++ b/compiler/test/ast/TestConst.kt @@ -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 diff --git a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt index 9b0b3b40f..0ed125ee4 100644 --- a/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt +++ b/compilerAst/src/prog8/ast/antlr/Antlr2Kotlin.kt @@ -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()) } } diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index e486d515a..3076d4dfc 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -553,7 +553,17 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array return null } override fun referencesIdentifier(nameInSource: List) = 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) } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 570bd7669..4359d0076 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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 diff --git a/examples/test.p8 b/examples/test.p8 index 1c0f12772..43ee5d3ec 100644 --- a/examples/test.p8 +++ b/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() + } +} +*/ diff --git a/parser/src/main/antlr/Prog8ANTLR.g4 b/parser/src/main/antlr/Prog8ANTLR.g4 index f5020c5d3..cb80a83e0 100644 --- a/parser/src/main/antlr/Prog8ANTLR.g4 +++ b/parser/src/main/antlr/Prog8ANTLR.g4 @@ -231,7 +231,7 @@ typecast : 'as' datatype; directmemory : '@' '(' expression ')'; -addressof : (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) (scoped_identifier | arrayindexed) ; +addressof : (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) scoped_identifier arrayindex? ; functioncall : scoped_identifier '(' expression_list? ')' ; diff --git a/simpleAst/src/prog8/code/ast/AstExpressions.kt b/simpleAst/src/prog8/code/ast/AstExpressions.kt index 6a8427d64..2cfe52096 100644 --- a/simpleAst/src/prog8/code/ast/AstExpressions.kt +++ b/simpleAst/src/prog8/code/ast/AstExpressions.kt @@ -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?