From fcb0a2c80e074aafd0b759a08330cce1b3297bc4 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 21 Sep 2025 11:37:56 +0200 Subject: [PATCH] Implemented reads from arrays of structs --- src/core/compileStoreField.go | 17 +-------- src/core/evaluateDot.go | 18 +++------ src/core/structFieldMemory.go | 38 +++++++++++++++++++ ...{int-array-custom.q => array-int-custom.q} | 0 ...rray-parameter.q => array-int-parameter.q} | 0 tests/{int-array.q => array-int.q} | 0 tests/array-struct.q | 19 ++++++++++ tests/tests_test.go | 7 ++-- 8 files changed, 67 insertions(+), 32 deletions(-) create mode 100644 src/core/structFieldMemory.go rename tests/{int-array-custom.q => array-int-custom.q} (100%) rename tests/{int-array-parameter.q => array-int-parameter.q} (100%) rename tests/{int-array.q => array-int.q} (100%) create mode 100644 tests/array-struct.q diff --git a/src/core/compileStoreField.go b/src/core/compileStoreField.go index 2cb05c4..7516a25 100644 --- a/src/core/compileStoreField.go +++ b/src/core/compileStoreField.go @@ -78,22 +78,7 @@ func (f *Function) compileStoreField(node *ast.Assign) error { return nil } - memory, isMemory := addressValue.(*ssa.Memory) - - if isMemory { - if memory.Scale { - memorySize := f.Append(&ssa.Int{Int: memory.Typ.Size()}) - memory.Index = f.Append(&ssa.BinaryOp{Op: token.Mul, Left: memory.Index, Right: memorySize}) - memory.Scale = false - } - - if field.Offset != 0 { - offset := f.Append(&ssa.Int{Int: int(field.Offset)}) - memory.Index = f.Append(&ssa.BinaryOp{Op: token.Add, Left: memory.Index, Right: offset}) - } - - memory.Typ = field.Type - } + memory := f.structField(addressValue, field) f.Append(&ssa.Store{ Memory: memory, diff --git a/src/core/evaluateDot.go b/src/core/evaluateDot.go index 83da6a7..4ebb9e6 100644 --- a/src/core/evaluateDot.go +++ b/src/core/evaluateDot.go @@ -87,26 +87,18 @@ func (f *Function) evaluateDot(expr *expression.Expression) (ssa.Value, error) { leftUnwrapped := types.Unwrap(leftValue.Type()) pointer, isPointer := leftUnwrapped.(*types.Pointer) - if !isPointer { - return nil, errors.New(&NotDataStruct{TypeName: leftValue.Type().Name()}, f.File, left.Source().StartPos) + if isPointer { + leftUnwrapped = pointer.To } - structure, isStructPointer := pointer.To.(*types.Struct) + structure, isStructPointer := leftUnwrapped.(*types.Struct) if !isStructPointer { - return nil, errors.New(&NotDataStruct{TypeName: pointer.To.Name()}, f.File, left.Source().StartPos) + return nil, errors.New(&NotDataStruct{TypeName: leftUnwrapped.Name()}, f.File, left.Source().StartPos) } field := structure.FieldByName(rightText) - offset := f.Append(&ssa.Int{Int: int(field.Offset)}) - - memory := &ssa.Memory{ - Address: leftValue, - Index: offset, - Scale: false, - Typ: field.Type, - } - + memory := f.structField(leftValue, field) load := f.Append(&ssa.Load{Memory: memory}) return load, nil } \ No newline at end of file diff --git a/src/core/structFieldMemory.go b/src/core/structFieldMemory.go new file mode 100644 index 0000000..3db6bd5 --- /dev/null +++ b/src/core/structFieldMemory.go @@ -0,0 +1,38 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/ssa" + "git.urbach.dev/cli/q/src/token" + "git.urbach.dev/cli/q/src/types" +) + +// structField returns the memory for the struct field. +func (f *Function) structField(leftValue ssa.Value, field *types.Field) *ssa.Memory { + memory, isMemory := leftValue.(*ssa.Memory) + + if isMemory { + if memory.Scale { + memorySize := f.Append(&ssa.Int{Int: memory.Typ.Size()}) + memory.Index = f.Append(&ssa.BinaryOp{Op: token.Mul, Left: memory.Index, Right: memorySize}) + memory.Scale = false + } + + if field.Offset != 0 { + offset := f.Append(&ssa.Int{Int: int(field.Offset)}) + memory.Index = f.Append(&ssa.BinaryOp{Op: token.Add, Left: memory.Index, Right: offset}) + } + + memory.Typ = field.Type + } else { + offset := f.Append(&ssa.Int{Int: int(field.Offset)}) + + memory = &ssa.Memory{ + Address: leftValue, + Index: offset, + Scale: false, + Typ: field.Type, + } + } + + return memory +} \ No newline at end of file diff --git a/tests/int-array-custom.q b/tests/array-int-custom.q similarity index 100% rename from tests/int-array-custom.q rename to tests/array-int-custom.q diff --git a/tests/int-array-parameter.q b/tests/array-int-parameter.q similarity index 100% rename from tests/int-array-parameter.q rename to tests/array-int-parameter.q diff --git a/tests/int-array.q b/tests/array-int.q similarity index 100% rename from tests/int-array.q rename to tests/array-int.q diff --git a/tests/array-struct.q b/tests/array-struct.q new file mode 100644 index 0000000..834ec5d --- /dev/null +++ b/tests/array-struct.q @@ -0,0 +1,19 @@ +main() { + p := new(Point, 2) + assert p.len == 2 + + p[0].x = 1 + p[0].y = 2 + p[1].x = 3 + p[1].y = 4 + + assert p[0].x == 1 + assert p[0].y == 2 + assert p[1].x == 3 + assert p[1].y == 4 +} + +Point { + x int + y int +} \ No newline at end of file diff --git a/tests/tests_test.go b/tests/tests_test.go index ec3ba26..8c98b2a 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -105,9 +105,10 @@ var tests = []run{ {"resource", "", "", 0}, {"function-pointer", "", "", 0}, {"type-cast", "", "", 0}, - {"int-array", "", "", 0}, - {"int-array-custom", "", "", 0}, - {"int-array-parameter", "", "", 0}, + {"array-int", "", "", 0}, + {"array-int-custom", "", "", 0}, + {"array-int-parameter", "", "", 0}, + {"array-struct", "", "", 0}, {"pointer-to-pointer", "", "", 0}, } -- 2.51.2