mirror of
https://github.com/irmen/prog8.git
synced 2025-11-03 04:17:16 +00:00
allow ptr1^^ = ptr^^ (replaces it with memcopy)
This commit is contained in:
@@ -29,6 +29,7 @@ internal class NormalMemSizer(val floatsize: Int): IMemSizer {
|
||||
dt.isFloat -> floatsize * (numElements ?: 1)
|
||||
dt.isLong -> 4 * (numElements ?: 1)
|
||||
dt.isPointer -> 2 // pointer is just a uword
|
||||
dt.isStructInstance -> dt.subType!!.memsize(this)
|
||||
dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size")
|
||||
else -> 2 * (numElements ?: 1)
|
||||
}
|
||||
|
||||
@@ -2367,8 +2367,12 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
else if(targetDatatype.isString && sourceDatatype.isUnsignedWord)
|
||||
errors.err("can't assign uword to str. If the source is a string pointer and you actually want to overwrite the target string, use an explicit strings.copy(src,tgt) instead.", position)
|
||||
else if(targetDatatype.isStructInstance)
|
||||
else if(targetDatatype.isStructInstance) {
|
||||
if(sourceDatatype.isStructInstance && sourceDatatype != targetDatatype)
|
||||
errors.err("value type $sourceDatatype doesn't match target type $targetDatatype", position)
|
||||
else
|
||||
errors.err("assigning to struct instance not supported (use pointers)", position)
|
||||
}
|
||||
else
|
||||
errors.err("value type $sourceDatatype doesn't match target type $targetDatatype", position)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ internal class CodeDesugarer(val program: Program, private val target: ICompilat
|
||||
// - convert on..goto/call to jumpaddr array and separate goto/call
|
||||
// - replace implicit pointer dereference chains (a.b.c.d) with explicit ones (a^^.b^^.c^^.d)
|
||||
// - replace ptr^^ by @(ptr) if ptr is just an uword.
|
||||
// - replace p1^^ = p2^^ by memcopy.
|
||||
|
||||
override fun after(alias: Alias, parent: Node): Iterable<IAstModification> {
|
||||
return listOf(IAstModification.Remove(alias, parent as IStatementContainer))
|
||||
@@ -556,4 +557,24 @@ _after:
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
|
||||
val targetDt = assignment.target.inferType(program)
|
||||
val sourceDt = assignment.value.inferType(program)
|
||||
if(targetDt.isStructInstance && sourceDt.isStructInstance) {
|
||||
if(targetDt == sourceDt) {
|
||||
val size = program.memsizer.memorySize(sourceDt.getOrUndef(), null)
|
||||
require(program.memsizer.memorySize(targetDt.getOrUndef(), null)==size)
|
||||
val sourcePtr = IdentifierReference((assignment.value as PtrDereference).chain, assignment.position)
|
||||
val targetPtr = IdentifierReference(assignment.target.pointerDereference!!.chain, assignment.position)
|
||||
val numBytes = NumericLiteral.optimalInteger(size, assignment.position)
|
||||
val memcopy = FunctionCallStatement(IdentifierReference(listOf("sys", "memcopy"), assignment.position),
|
||||
mutableListOf(sourcePtr, targetPtr, numBytes),
|
||||
false, assignment.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment, memcopy, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import prog8.ast.expressions.ArrayIndexedExpression
|
||||
import prog8.ast.expressions.DirectMemoryRead
|
||||
import prog8.ast.expressions.PtrDereference
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.ast.statements.FunctionCallStatement
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.code.ast.PtAssignment
|
||||
import prog8.code.ast.PtReturn
|
||||
@@ -844,4 +845,71 @@ main {
|
||||
|
||||
compileText(VMTarget(), true, src, outputDir) shouldNotBe null
|
||||
}
|
||||
|
||||
test("assigning pointer dereferences via memcopy") {
|
||||
val src="""
|
||||
%option enable_floats
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
struct List {
|
||||
bool b
|
||||
word w
|
||||
float f
|
||||
^^List next
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
byte bb
|
||||
}
|
||||
|
||||
^^List l1 = 2000
|
||||
^^List l2 = 3000
|
||||
^^Foo f1 = 4000
|
||||
|
||||
l1^^ = l2^^
|
||||
}
|
||||
}"""
|
||||
|
||||
val result = compileText(VMTarget(), false, src, outputDir)!!
|
||||
val st = result.compilerAst.entrypoint.statements
|
||||
st.size shouldBe 10
|
||||
(st[8] as FunctionCallStatement).target.nameInSource shouldBe listOf("sys", "memcopy")
|
||||
}
|
||||
|
||||
test("assigning pointer dereferences should be same type") {
|
||||
val src="""
|
||||
%option enable_floats
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
struct List {
|
||||
bool b
|
||||
word w
|
||||
float f
|
||||
^^List next
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
byte bb
|
||||
}
|
||||
|
||||
^^List l1 = 2000
|
||||
^^List l2 = 3000
|
||||
^^Foo f1 = 4000
|
||||
^^bool bptr = 5000
|
||||
|
||||
l1^^ = f1^^
|
||||
l1^^ = bptr^^
|
||||
l1^^ = 4242
|
||||
}
|
||||
}"""
|
||||
|
||||
val errors=ErrorReporterForTests()
|
||||
compileText(VMTarget(), false, src, outputDir, errors=errors)
|
||||
errors.errors.size shouldBe 3
|
||||
errors.errors[0] shouldContain "doesn't match"
|
||||
errors.errors[1] shouldContain "assigning to struct instance not supported"
|
||||
errors.errors[2] shouldContain "assigning to struct instance not supported"
|
||||
}
|
||||
})
|
||||
@@ -57,10 +57,10 @@ STRUCTS and TYPED POINTERS
|
||||
- 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: make typeForAddressOf() be even more specific about the typed pointers it returns for the address-of operator.
|
||||
- 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.
|
||||
- add unit tests for expected AST elements for all syntaxes dealing with pointers, dereference(chain), derefs, and indexing (both as value and assigntargets)
|
||||
- fix parse error "barray[2]^^" where barray is ^^bool[10]
|
||||
- add unit tests for all changes (pointers and structs)
|
||||
- fix parse error "barray[2]^^" where barray is ^^bool[10]
|
||||
- try to fix parse error l1^^.s[0] = 4242 (equivalent to l1.s[0]=4242 , which does parse correctly)
|
||||
- try to make sizeof(^^type) parse correctly (or maybe replace it immediately with sys.SIZEOF_POINTER)
|
||||
- 6502 codegen: remove checks in checkForPointerTypesOn6502()
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
%option enable_floats
|
||||
%import floats
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
bool @shared b
|
||||
float @shared f
|
||||
word @shared w
|
||||
const long ll = 9999999
|
||||
struct List {
|
||||
bool b
|
||||
word w
|
||||
@@ -15,60 +11,39 @@ main {
|
||||
^^List next
|
||||
}
|
||||
|
||||
^^List @shared l1
|
||||
^^float @shared fptr
|
||||
struct Foo {
|
||||
byte bb
|
||||
}
|
||||
|
||||
txt.print_ub(sys.SIZEOF_BOOL)
|
||||
^^List l1 = 2000
|
||||
^^List l2 = 3000
|
||||
^^Foo f1 = 4000
|
||||
|
||||
l1.b = true
|
||||
l1.w = 1111
|
||||
l1.f = 11.234
|
||||
|
||||
l2.b = false
|
||||
l2.w = 2222
|
||||
l2.f = 222.222
|
||||
|
||||
txt.print_uwhex(l1, true)
|
||||
txt.spc()
|
||||
txt.print_ub(sys.SIZEOF_WORD)
|
||||
txt.print_bool(l1.b)
|
||||
txt.spc()
|
||||
txt.print_ub(sys.SIZEOF_POINTER)
|
||||
txt.print_w(l1.w)
|
||||
txt.spc()
|
||||
txt.print_ub(sys.SIZEOF_LONG)
|
||||
txt.spc()
|
||||
txt.print_ub(sys.SIZEOF_FLOAT)
|
||||
txt.print_f(l1.f)
|
||||
txt.nl()
|
||||
|
||||
txt.print_ub(sizeof(true))
|
||||
l1^^ = l2^^
|
||||
txt.print_uwhex(l1, true)
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(1234))
|
||||
txt.print_bool(l1.b)
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(12345678))
|
||||
txt.print_w(l1.w)
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(9.999))
|
||||
txt.nl()
|
||||
|
||||
txt.print_ub(sizeof(b))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(w))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(ll))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(f))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(l1))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(fptr^^))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(l1^^))
|
||||
txt.nl()
|
||||
|
||||
txt.print_ub(sizeof(bool))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(word))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(long))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(float))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(List))
|
||||
txt.spc()
|
||||
txt.print_ub(sizeof(&w))
|
||||
txt.spc()
|
||||
; txt.print_ub(sizeof(^^float)) ; TODO parse this
|
||||
; txt.spc()
|
||||
; txt.print_ub(sizeof(^^List)) ; TODO parse this
|
||||
; txt.spc()
|
||||
txt.print_f(l1.f)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user