mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +00:00 
			
		
		
		
	revert & to untyped pointer, added && for typed pointer address-of
This commit is contained in:
		@@ -39,14 +39,14 @@ internal class BeforeAsmTypecastCleaner(val program: Program,
 | 
				
			|||||||
                        listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
 | 
					                        listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        listOf(IAstModification.ReplaceNode(typecast,
 | 
					                        listOf(IAstModification.ReplaceNode(typecast,
 | 
				
			||||||
                            AddressOf(identifier, null, null, false, typecast.position), parent))
 | 
					                            AddressOf(identifier, null, null, false, false,typecast.position), parent))
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else if (typecast.expression is IFunctionCall) {
 | 
					                } else if (typecast.expression is IFunctionCall) {
 | 
				
			||||||
                    return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
 | 
					                    return listOf(IAstModification.ReplaceNode(typecast, typecast.expression, parent))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else if(sourceDt.isString && typecast.type.isPointer && typecast.type.sub==BaseDataType.UBYTE) {
 | 
					            } else if(sourceDt.isString && typecast.type.isPointer && typecast.type.sub==BaseDataType.UBYTE) {
 | 
				
			||||||
                // casting a string to a ^^ubyte is just taking the address of the string.
 | 
					                // casting a string to a ^^ubyte is just taking the address of the string.
 | 
				
			||||||
                val addr = AddressOf(typecast.expression as IdentifierReference, null, null, false, typecast.position)
 | 
					                val addr = AddressOf(typecast.expression as IdentifierReference, null, null, false, true, typecast.position)
 | 
				
			||||||
                return listOf(IAstModification.ReplaceNode(typecast, addr, parent))
 | 
					                return listOf(IAstModification.ReplaceNode(typecast, addr, parent))
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                errors.err("cannot cast pass-by-reference value to type ${typecast.type} (only to UWORD)", typecast.position)
 | 
					                errors.err("cannot cast pass-by-reference value to type ${typecast.type} (only to UWORD)", typecast.position)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -317,7 +317,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
 | 
				
			|||||||
                            if(!argDt.isString || it.second is IdentifierReference) {
 | 
					                            if(!argDt.isString || it.second is IdentifierReference) {
 | 
				
			||||||
                                modifications += IAstModification.ReplaceNode(
 | 
					                                modifications += IAstModification.ReplaceNode(
 | 
				
			||||||
                                    identifier,
 | 
					                                    identifier,
 | 
				
			||||||
                                    AddressOf(identifier, null, null, false, it.second.position),
 | 
					                                    AddressOf(identifier, null, null, false, true, it.second.position),
 | 
				
			||||||
                                    call as Node
 | 
					                                    call as Node
 | 
				
			||||||
                                )
 | 
					                                )
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
@@ -337,7 +337,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
 | 
				
			|||||||
                        // take the address of the identifier
 | 
					                        // take the address of the identifier
 | 
				
			||||||
                        modifications += IAstModification.ReplaceNode(
 | 
					                        modifications += IAstModification.ReplaceNode(
 | 
				
			||||||
                            identifier,
 | 
					                            identifier,
 | 
				
			||||||
                            AddressOf(identifier, null, null, false, it.second.position),
 | 
					                            AddressOf(identifier, null, null, false, false,it.second.position),
 | 
				
			||||||
                            call as Node
 | 
					                            call as Node
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                    } else if(dt.isUnknown) {
 | 
					                    } else if(dt.isUnknown) {
 | 
				
			||||||
@@ -346,7 +346,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
 | 
				
			|||||||
                            // take the address of the subroutine or label
 | 
					                            // take the address of the subroutine or label
 | 
				
			||||||
                            modifications += IAstModification.ReplaceNode(
 | 
					                            modifications += IAstModification.ReplaceNode(
 | 
				
			||||||
                                identifier,
 | 
					                                identifier,
 | 
				
			||||||
                                AddressOf(identifier, null, null, false, it.second.position),
 | 
					                                AddressOf(identifier, null, null, false, false, it.second.position),
 | 
				
			||||||
                                call as Node
 | 
					                                call as Node
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@@ -481,7 +481,7 @@ class TypecastsAdder(val program: Program, val options: CompilationOptions, val
 | 
				
			|||||||
                val eltType = elt.inferType(program)
 | 
					                val eltType = elt.inferType(program)
 | 
				
			||||||
                val tgt = elt.targetStatement()
 | 
					                val tgt = elt.targetStatement()
 | 
				
			||||||
                if(eltType.isIterable || tgt is Subroutine || tgt is Label || tgt is Block)  {
 | 
					                if(eltType.isIterable || tgt is Subroutine || tgt is Label || tgt is Block)  {
 | 
				
			||||||
                    val addressof = AddressOf(elt, null, null, false, elt.position)
 | 
					                    val addressof = AddressOf(elt, null, null, false, false, elt.position)
 | 
				
			||||||
                    addressof.linkParents(array)
 | 
					                    addressof.linkParents(array)
 | 
				
			||||||
                    array.value[index] = addressof
 | 
					                    array.value[index] = addressof
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,9 +12,7 @@ import prog8.ast.expressions.ArrayIndexedExpression
 | 
				
			|||||||
import prog8.ast.expressions.DirectMemoryRead
 | 
					import prog8.ast.expressions.DirectMemoryRead
 | 
				
			||||||
import prog8.ast.expressions.PtrDereference
 | 
					import prog8.ast.expressions.PtrDereference
 | 
				
			||||||
import prog8.ast.statements.*
 | 
					import prog8.ast.statements.*
 | 
				
			||||||
import prog8.code.ast.PtAssignment
 | 
					import prog8.code.ast.*
 | 
				
			||||||
import prog8.code.ast.PtReturn
 | 
					 | 
				
			||||||
import prog8.code.ast.PtSubSignature
 | 
					 | 
				
			||||||
import prog8.code.core.BaseDataType
 | 
					import prog8.code.core.BaseDataType
 | 
				
			||||||
import prog8.code.core.DataType
 | 
					import prog8.code.core.DataType
 | 
				
			||||||
import prog8.code.core.IMemSizer
 | 
					import prog8.code.core.IMemSizer
 | 
				
			||||||
@@ -585,7 +583,7 @@ main {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("type of & operator (address-of)") {
 | 
					    test("internal type for address-of") {
 | 
				
			||||||
        DataType.BYTE.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.BYTE)
 | 
					        DataType.BYTE.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.BYTE)
 | 
				
			||||||
        DataType.WORD.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.WORD)
 | 
					        DataType.WORD.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.WORD)
 | 
				
			||||||
        DataType.FLOAT.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.FLOAT)
 | 
					        DataType.FLOAT.typeForAddressOf(false) shouldBe DataType.pointer(BaseDataType.FLOAT)
 | 
				
			||||||
@@ -605,6 +603,31 @@ main {
 | 
				
			|||||||
        DataType.pointer(BaseDataType.BOOL).typeForAddressOf(false) shouldBe DataType.UWORD
 | 
					        DataType.pointer(BaseDataType.BOOL).typeForAddressOf(false) shouldBe DataType.UWORD
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test("untyped and typed address-of operators") {
 | 
				
			||||||
 | 
					        val src="""
 | 
				
			||||||
 | 
					%option enable_floats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main {
 | 
				
			||||||
 | 
					    sub start() {
 | 
				
			||||||
 | 
					        float f
 | 
				
			||||||
 | 
					        cx16.r0 = &f+1
 | 
				
			||||||
 | 
					        cx16.r1 = &&f+1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val result = compileText(VMTarget(), false, src, outputDir, writeAssembly = true)!!
 | 
				
			||||||
 | 
					        val st = result.codegenAst!!.entrypoint()!!.children
 | 
				
			||||||
 | 
					        st.size shouldBe 6
 | 
				
			||||||
 | 
					        val r0v = (st[3] as PtAssignment).value as PtBinaryExpression
 | 
				
			||||||
 | 
					        val r1v = (st[4] as PtAssignment).value as PtBinaryExpression
 | 
				
			||||||
 | 
					        r0v.left shouldBe instanceOf<PtAddressOf>()
 | 
				
			||||||
 | 
					        r0v.right shouldBe instanceOf<PtNumber>()
 | 
				
			||||||
 | 
					        (r0v.right as PtNumber).number shouldBe 1.0
 | 
				
			||||||
 | 
					        r1v.left shouldBe instanceOf<PtAddressOf>()
 | 
				
			||||||
 | 
					        r1v.right shouldBe instanceOf<PtNumber>()
 | 
				
			||||||
 | 
					        (r1v.right as PtNumber).number shouldBe VMTarget.FLOAT_MEM_SIZE
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test("address-of struct fields") {
 | 
					    test("address-of struct fields") {
 | 
				
			||||||
        val src="""
 | 
					        val src="""
 | 
				
			||||||
%option enable_floats
 | 
					%option enable_floats
 | 
				
			||||||
@@ -1375,7 +1398,7 @@ main {
 | 
				
			|||||||
        val errors = ErrorReporterForTests()
 | 
					        val errors = ErrorReporterForTests()
 | 
				
			||||||
        compileText(VMTarget(), false, src, outputDir, errors = errors) shouldBe null
 | 
					        compileText(VMTarget(), false, src, outputDir, errors = errors) shouldBe null
 | 
				
			||||||
        errors.errors.size shouldBe 999
 | 
					        errors.errors.size shouldBe 999
 | 
				
			||||||
        // TODO
 | 
					        // TODO implement this test
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xtest("array of pointers as subroutine param") {
 | 
					    xtest("array of pointers as subroutine param") {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,13 +65,13 @@ class TestAsmGenSymbols: StringSpec({
 | 
				
			|||||||
            position = Position.DUMMY
 | 
					            position = Position.DUMMY
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        val assign1 = Assignment(tgt, IdentifierReference(listOf("localvar"), Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign1 = Assignment(tgt, IdentifierReference(listOf("localvar"), Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign2 = Assignment(tgt, AddressOf(IdentifierReference(listOf("locallabel"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign2 = Assignment(tgt, AddressOf(IdentifierReference(listOf("locallabel"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign3 = Assignment(tgt, AddressOf(IdentifierReference(listOf("var_outside"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign3 = Assignment(tgt, AddressOf(IdentifierReference(listOf("var_outside"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign4 = Assignment(tgt, AddressOf(IdentifierReference(listOf("label_outside"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign4 = Assignment(tgt, AddressOf(IdentifierReference(listOf("label_outside"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign5 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","localvar"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign5 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","localvar"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign6 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","locallabel"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign6 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","start","locallabel"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign7 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","var_outside"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign7 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","var_outside"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
        val assign8 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","label_outside"), Position.DUMMY), null, null, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
					        val assign8 = Assignment(tgt, AddressOf(IdentifierReference(listOf("main","label_outside"), Position.DUMMY), null, null, false, false, Position.DUMMY), AssignmentOrigin.USERCODE, Position.DUMMY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
 | 
					        val statements = mutableListOf(varInSub, var2InSub, labelInSub, assign1, assign2, assign3, assign4, assign5, assign6, assign7, assign8)
 | 
				
			||||||
        val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY)
 | 
					        val subroutine = Subroutine("start", mutableListOf(), mutableListOf(), emptyList(), emptyList(), emptySet(), null, false, false, false, statements, Position.DUMMY)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -280,10 +280,17 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor<Node
 | 
				
			|||||||
        val msb = ctx.ADDRESS_OF_MSB()!=null
 | 
					        val msb = ctx.ADDRESS_OF_MSB()!=null
 | 
				
			||||||
        // note: &<  (ADDRESS_OF_LSB)  is equivalent to a regular &.
 | 
					        // note: &<  (ADDRESS_OF_LSB)  is equivalent to a regular &.
 | 
				
			||||||
        val index = ctx.arrayindex()?.accept(this) as? ArrayIndex
 | 
					        val index = ctx.arrayindex()?.accept(this) as? ArrayIndex
 | 
				
			||||||
        return if(index!=null) {
 | 
					        var typed = false
 | 
				
			||||||
            AddressOf(identifier, index, null, msb, ctx.toPosition())
 | 
					        if(ctx.TYPED_ADDRESS_OF()!=null) {
 | 
				
			||||||
 | 
					            // new typed AddressOf
 | 
				
			||||||
 | 
					            if(msb)
 | 
				
			||||||
 | 
					                throw SyntaxError("typed address of not allowed with msb", ctx.toPosition())
 | 
				
			||||||
 | 
					            typed = true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return if (index != null) {
 | 
				
			||||||
 | 
					            AddressOf(identifier, index, null, msb, typed, ctx.toPosition())
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            AddressOf(identifier,null, null, msb, ctx.toPosition())
 | 
					            AddressOf(identifier, null, null, msb, typed, ctx.toPosition())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -502,7 +502,8 @@ class TypecastExpression(var expression: Expression, var type: DataType, val imp
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: ArrayIndex?, var dereference: PtrDereference?, val msb: Boolean, override val position: Position) : Expression() {
 | 
					data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: ArrayIndex?, var dereference: PtrDereference?,
 | 
				
			||||||
 | 
					                     val msb: Boolean, val typed: Boolean, override val position: Position) : Expression() {
 | 
				
			||||||
    override lateinit var parent: Node
 | 
					    override lateinit var parent: Node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun linkParents(parent: Node) {
 | 
					    override fun linkParents(parent: Node) {
 | 
				
			||||||
@@ -538,7 +539,7 @@ data class AddressOf(var identifier: IdentifierReference?, var arrayIndex: Array
 | 
				
			|||||||
        replacement.parent = this
 | 
					        replacement.parent = this
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun copy() = AddressOf(identifier?.copy(), arrayIndex?.copy(), dereference?.copy(), msb, position)
 | 
					    override fun copy() = AddressOf(identifier?.copy(), arrayIndex?.copy(), dereference?.copy(), msb, typed, position)
 | 
				
			||||||
    override fun constValue(program: Program): NumericLiteral? {
 | 
					    override fun constValue(program: Program): NumericLiteral? {
 | 
				
			||||||
        if(msb)
 | 
					        if(msb)
 | 
				
			||||||
            return null
 | 
					            return null
 | 
				
			||||||
@@ -574,8 +575,9 @@ 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.InferredType = InferredTypes.knownFor(BaseDataType.UWORD)   // TODO orignal behavior
 | 
					 | 
				
			||||||
    override fun inferType(program: Program): InferredTypes.InferredType {
 | 
					    override fun inferType(program: Program): InferredTypes.InferredType {
 | 
				
			||||||
 | 
					        if(!typed)
 | 
				
			||||||
 | 
					            return InferredTypes.knownFor(BaseDataType.UWORD)   // orignal pre-v12 untyped AddressOf
 | 
				
			||||||
        if(identifier!=null) {
 | 
					        if(identifier!=null) {
 | 
				
			||||||
            val type = identifier!!.inferType(program).getOrUndef()
 | 
					            val type = identifier!!.inferType(program).getOrUndef()
 | 
				
			||||||
            val addrofDt = type.typeForAddressOf(msb)
 | 
					            val addrofDt = type.typeForAddressOf(msb)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -270,7 +270,7 @@ class VarDecl(
 | 
				
			|||||||
                // parameter variable memory mapped to a R0-R15 virtual register
 | 
					                // parameter variable memory mapped to a R0-R15 virtual register
 | 
				
			||||||
                val regname = param.registerOrPair.asScopedNameVirtualReg(param.type)
 | 
					                val regname = param.registerOrPair.asScopedNameVirtualReg(param.type)
 | 
				
			||||||
                decltype = VarDeclType.MEMORY
 | 
					                decltype = VarDeclType.MEMORY
 | 
				
			||||||
                value = AddressOf(IdentifierReference(regname, param.position), null, null, false, param.position)
 | 
					                value = AddressOf(IdentifierReference(regname, param.position), null, null, false, false,param.position)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            val dt = if(param.type.isArray) DataType.UWORD else param.type
 | 
					            val dt = if(param.type.isArray) DataType.UWORD else param.type
 | 
				
			||||||
            return VarDecl(decltype, VarDeclOrigin.SUBROUTINEPARAM, dt, param.zp, SplitWish.DONTCARE, null, param.name, emptyList(), value,
 | 
					            return VarDecl(decltype, VarDeclOrigin.SUBROUTINEPARAM, dt, param.zp, SplitWish.DONTCARE, null, param.name, emptyList(), value,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -999,7 +999,7 @@ containment check:  ``in``
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
address of:  ``&``,   ``&<``,   ``&>``
 | 
					address of:  ``&``,   ``&<``,   ``&>``,   ``&&``
 | 
				
			||||||
    This is a prefix operator that can be applied to a string or array variable or literal value.
 | 
					    This is a prefix operator that can be applied to a string or array variable or literal value.
 | 
				
			||||||
    It results in the memory address (UWORD) of that string or array in memory:  ``uword a = &stringvar``
 | 
					    It results in the memory address (UWORD) of that string or array in memory:  ``uword a = &stringvar``
 | 
				
			||||||
    Sometimes the compiler silently inserts this operator to make it easier for instance
 | 
					    Sometimes the compiler silently inserts this operator to make it easier for instance
 | 
				
			||||||
@@ -1012,6 +1012,11 @@ address of:  ``&``,   ``&<``,   ``&>``
 | 
				
			|||||||
    and MSB byte array separately, respectively.   Note that ``&<`` is just the same as ``&`` in this case.
 | 
					    and MSB byte array separately, respectively.   Note that ``&<`` is just the same as ``&`` in this case.
 | 
				
			||||||
    For more details on split word arrays, see :ref:`arrayvars`.
 | 
					    For more details on split word arrays, see :ref:`arrayvars`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    **Typed pointer version:** the single ``&`` operator still returns an untyped uword address for
 | 
				
			||||||
 | 
					    backward compatibility reasons, so existing programs keep working. The *double ampersand* ``&&`` operator
 | 
				
			||||||
 | 
					    however returns a *typed* pointer to the value. The semantics are slightly different because adding or subtracting
 | 
				
			||||||
 | 
					    a number from a typed pointer uses *pointer arithmetic* that takes the size of the value that it points to into account.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ternary:
 | 
					ternary:
 | 
				
			||||||
    Prog8 doesn't have a ternary operator to choose one of two values (``x? y : z`` in many other languages)
 | 
					    Prog8 doesn't have a ternary operator to choose one of two values (``x? y : z`` in many other languages)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,3 +81,11 @@ Typed pointer to Struct type
 | 
				
			|||||||
----------------------------
 | 
					----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Work in progress.
 | 
					Work in progress.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Address-Of: untyped vs typed
 | 
				
			||||||
 | 
					----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``&`` still returns untyped (uword) pointer, as it did in older Prog8 versions. This is for backward compatibility reasons so existing programs don't break.
 | 
				
			||||||
 | 
					The *double ampersand* operator ``&&`` returns a *typed* pointer to the value. The semantics are slightly different from the old untyped address-of operator, because adding or subtracting
 | 
				
			||||||
 | 
					a number from a typed pointer uses *pointer arithmetic* that takes the size of the value that it points to into account.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,6 @@
 | 
				
			|||||||
TODO
 | 
					TODO
 | 
				
			||||||
====
 | 
					====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What to do with the changed adress-of behavior? &x now returns a typed pointer to &x + 10 will now be calculated differently (C pointer arithmetic semantics rather than simply byte addition)
 | 
					 | 
				
			||||||
compiler flag to select old behavior? new operator that has the new behavior?    Don't want to break existing code that used &....
 | 
					 | 
				
			||||||
Old behavior can be put back by always returning UWORD as the inferred type for AddressOf nodes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
STRUCTS and TYPED POINTERS
 | 
					STRUCTS and TYPED POINTERS
 | 
				
			||||||
--------------------------
 | 
					--------------------------
 | 
				
			||||||
@@ -58,6 +54,7 @@ STRUCTS and TYPED POINTERS
 | 
				
			|||||||
- DONE: fix _msb/_lsb storage of the split-words pointer-arrays
 | 
					- DONE: fix _msb/_lsb storage of the split-words pointer-arrays
 | 
				
			||||||
- DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
 | 
					- DONE: what about static initialization of an array of struct pointers? -> impossible right now because the pointer values are not constants.
 | 
				
			||||||
- DONE: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
 | 
					- DONE: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
 | 
				
			||||||
 | 
					- DONE: existing '&' address-of still returns untyped uword (for backward compatibility). New '&&' operator returns typed pointer.
 | 
				
			||||||
- DONE: allow  list1^^ = list2^^  (value wise assignment of List structures) by replacing it with a sys.memcopy(list2, list1, sizeof(List)) call.
 | 
					- DONE: allow  list1^^ = list2^^  (value wise assignment of List structures) by replacing it with a sys.memcopy(list2, list1, sizeof(List)) call.
 | 
				
			||||||
- DONE: allow  a.b.ptr[i].value  (equiv to a.b.ptr[i]^^.value)  expressions  (assignment target doesn't parse yet, see below)
 | 
					- DONE: allow  a.b.ptr[i].value  (equiv to a.b.ptr[i]^^.value)  expressions  (assignment target doesn't parse yet, see below)
 | 
				
			||||||
- DONE: check passing arrays to typed ptr sub-parameters.  NOTE: word array can only be a @nosplit array if the parameter type is ^^word, because the words need to be sequential in memory there
 | 
					- DONE: check passing arrays to typed ptr sub-parameters.  NOTE: word array can only be a @nosplit array if the parameter type is ^^word, because the words need to be sequential in memory there
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,48 +5,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
main {
 | 
					main {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ubyte @shared thingIndex = 10
 | 
					 | 
				
			||||||
    uword[20] @shared dummy
 | 
					 | 
				
			||||||
    uword[10] @split curframesplit
 | 
					 | 
				
			||||||
    uword[10] @nosplit curframe
 | 
					 | 
				
			||||||
    uword p1, p2
 | 
					 | 
				
			||||||
    float f
 | 
					    float f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub start() {
 | 
					    sub start() {
 | 
				
			||||||
        classic()
 | 
					        txt.print("classic float pointer+1: ")
 | 
				
			||||||
        ; new()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sub classic() {
 | 
					 | 
				
			||||||
        txt.print("float pointer+1: ")
 | 
					 | 
				
			||||||
        txt.print_uwhex(&f, true)
 | 
					        txt.print_uwhex(&f, true)
 | 
				
			||||||
        txt.spc()
 | 
					        txt.spc()
 | 
				
			||||||
        txt.print_uwhex(&f + 1, true)
 | 
					        txt.print_uwhex(&f + 1, true)
 | 
				
			||||||
 | 
					        txt.spc()
 | 
				
			||||||
 | 
					        txt.print_uw(&f + 1 - &f)
 | 
				
			||||||
        txt.nl()
 | 
					        txt.nl()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        p1 = &curframesplit[thingIndex]
 | 
					        txt.print("typed float pointer+1: ")
 | 
				
			||||||
        p2 = &curframe[thingIndex]
 | 
					        txt.print_uwhex(&&f, true)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        txt.print("&array (split): ")
 | 
					 | 
				
			||||||
        txt.print_uwhex(&curframesplit, true)
 | 
					 | 
				
			||||||
        txt.spc()
 | 
					        txt.spc()
 | 
				
			||||||
        txt.print_uwhex(p1, true)
 | 
					        txt.print_uwhex(&&f + 1, true)
 | 
				
			||||||
        txt.spc()
 | 
					        txt.spc()
 | 
				
			||||||
        txt.print_uw(p1 - &curframesplit)
 | 
					        txt.print_uw(&&f + 1 - &&f)
 | 
				
			||||||
        txt.spc()
 | 
					 | 
				
			||||||
        txt.print_uwhex(p1 + &curframesplit, true)
 | 
					 | 
				
			||||||
        txt.nl()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        txt.print("&array (normal): ")
 | 
					 | 
				
			||||||
        txt.print_uwhex(&curframe, true)
 | 
					 | 
				
			||||||
        txt.spc()
 | 
					 | 
				
			||||||
        txt.print_uwhex(p2, true)
 | 
					 | 
				
			||||||
        txt.spc()
 | 
					 | 
				
			||||||
        txt.print_uw(p2 - &curframe)
 | 
					 | 
				
			||||||
        txt.spc()
 | 
					 | 
				
			||||||
        txt.print_uwhex(p2 + &curframe, true)
 | 
					 | 
				
			||||||
        txt.nl()
 | 
					        txt.nl()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ; 6502 data size: $0251
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,9 +37,9 @@ DEC_INTEGER :  DEC_DIGIT (DEC_DIGIT | '_')* ;
 | 
				
			|||||||
HEX_INTEGER :  '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
 | 
					HEX_INTEGER :  '$' HEX_DIGIT (HEX_DIGIT | '_')* ;
 | 
				
			||||||
BIN_INTEGER :  '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
 | 
					BIN_INTEGER :  '%' BIN_DIGIT (BIN_DIGIT | '_')* ;
 | 
				
			||||||
ADDRESS_OF: '&' ;
 | 
					ADDRESS_OF: '&' ;
 | 
				
			||||||
 | 
					TYPED_ADDRESS_OF: '&&' ;
 | 
				
			||||||
ADDRESS_OF_MSB: '&>' ;
 | 
					ADDRESS_OF_MSB: '&>' ;
 | 
				
			||||||
ADDRESS_OF_LSB: '&<' ;
 | 
					ADDRESS_OF_LSB: '&<' ;
 | 
				
			||||||
INVALID_AND_COMPOSITE: '&&' ;
 | 
					 | 
				
			||||||
POINTER: '^^';
 | 
					POINTER: '^^';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fragment HEX_DIGIT: ('a'..'f') | ('A'..'F') | ('0'..'9') ;
 | 
					fragment HEX_DIGIT: ('a'..'f') | ('A'..'F') | ('0'..'9') ;
 | 
				
			||||||
@@ -241,7 +241,7 @@ typecast : 'as' datatype;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
directmemory : '@' '(' expression ')';
 | 
					directmemory : '@' '(' expression ')';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
addressof : <assoc=right> (ADDRESS_OF | ADDRESS_OF_LSB | ADDRESS_OF_MSB) scoped_identifier arrayindex? ;
 | 
					addressof : <assoc=right> (ADDRESS_OF | TYPED_ADDRESS_OF | | ADDRESS_OF_LSB | ADDRESS_OF_MSB) scoped_identifier arrayindex? ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
functioncall : scoped_identifier '(' expression_list? ')'  ;
 | 
					functioncall : scoped_identifier '(' expression_list? ')'  ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user