From 43a006e4af242cdd0b2ad2a81002d23289a07038 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Fri, 11 Apr 2025 14:21:51 +0200 Subject: [PATCH] Replaced builtin store function with a new syntax --- lib/mem/alloc_unix.q | 2 +- lib/mem/alloc_windows.q | 2 +- lib/thread/thread_linux.q | 4 ++-- src/core/CompileAssign.go | 7 ++++++ src/core/CompileCall.go | 3 --- src/core/CompileFor.go | 3 ++- src/core/CompileMemoryStore.go | 36 ------------------------------- src/core/EvaluateArray.go | 18 ++++++++++++++++ src/expression/Expression_test.go | 5 +++++ src/expression/Parse.go | 13 +++++++++-- tests/errors/TypeMismatch5.q | 4 ++++ tests/errors_test.go | 3 +++ 12 files changed, 54 insertions(+), 46 deletions(-) delete mode 100644 src/core/CompileMemoryStore.go create mode 100644 tests/errors/TypeMismatch5.q diff --git a/lib/mem/alloc_unix.q b/lib/mem/alloc_unix.q index e12a331..0720da0 100644 --- a/lib/mem/alloc_unix.q +++ b/lib/mem/alloc_unix.q @@ -7,6 +7,6 @@ alloc(length int) -> []byte { return x } - store(x, 8, length) + [x] = length return x + 8 } \ No newline at end of file diff --git a/lib/mem/alloc_windows.q b/lib/mem/alloc_windows.q index c0df727..1ee9838 100644 --- a/lib/mem/alloc_windows.q +++ b/lib/mem/alloc_windows.q @@ -5,7 +5,7 @@ alloc(length int) -> []byte { return x } - store(x, 8, length) + [x] = length return x + 8 } diff --git a/lib/thread/thread_linux.q b/lib/thread/thread_linux.q index 2e3db31..e452309 100644 --- a/lib/thread/thread_linux.q +++ b/lib/thread/thread_linux.q @@ -4,9 +4,9 @@ import sys create(func *any) -> int { stack := sys.mmap(0, 4096, 0x1|0x2, 0x02|0x20|0x100) stack += 4096 - 8 - store(stack, 8, core.exit) + [stack] = core.exit stack -= 8 - store(stack, 8, func) + [stack] = func return sys.clone(clone.vm|clone.fs|clone.files|clone.sighand|clone.parent|clone.thread|clone.io, stack, 0, 0, 0) } diff --git a/src/core/CompileAssign.go b/src/core/CompileAssign.go index af628ef..ee9d022 100644 --- a/src/core/CompileAssign.go +++ b/src/core/CompileAssign.go @@ -56,6 +56,13 @@ func (f *Function) CompileAssign(node *ast.Assign) error { return err } + leftSize := leftValue.Memory.Length + rightSize := uint8(rightValue.Type().Size()) + + if rightSize != 0 && leftSize != rightSize { + panic("memory store length mismatch") + } + f.ValueToMemory(rightValue, leftValue.Memory) return nil } diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index fc5937b..c1cc23f 100644 --- a/src/core/CompileCall.go +++ b/src/core/CompileCall.go @@ -41,9 +41,6 @@ func (f *Function) CompileCall(root *expression.Expression) ([]*Parameter, error case "delete": return nil, f.CompileDelete(root) - - case "store": - return nil, f.CompileMemoryStore(root) } } diff --git a/src/core/CompileFor.go b/src/core/CompileFor.go index 2bdf9da..45ad2c3 100644 --- a/src/core/CompileFor.go +++ b/src/core/CompileFor.go @@ -46,7 +46,7 @@ func (f *Function) CompileFor(loop *ast.For) error { panic("could not recognize loop header") } - _, err := f.ExpressionToRegister(from, counter) + typ, err := f.ExpressionToRegister(from, counter) if err != nil { return err @@ -98,6 +98,7 @@ func (f *Function) CompileFor(loop *ast.For) error { variable = &scope.Variable{ Name: name, Value: eval.Register{ + Typ: typ, Register: counter, Alive: ast.Count(loop.Body, f.File.Bytes, token.Identifier, name), }, diff --git a/src/core/CompileMemoryStore.go b/src/core/CompileMemoryStore.go deleted file mode 100644 index 75e6da7..0000000 --- a/src/core/CompileMemoryStore.go +++ /dev/null @@ -1,36 +0,0 @@ -package core - -import ( - "git.urbach.dev/cli/q/src/asm" - "git.urbach.dev/cli/q/src/errors" - "git.urbach.dev/cli/q/src/expression" -) - -// CompileMemoryStore compiles a variable-width store to memory. -func (f *Function) CompileMemoryStore(root *expression.Expression) error { - parameters := root.Children[1:] - name := parameters[0].Token.Text(f.File.Bytes) - numBytes, err := f.ToNumber(parameters[1].Token) - - if err != nil { - return err - } - - value := parameters[2] - variable := f.VariableByName(name) - - if variable == nil { - return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, parameters[0].Token.Position) - } - - defer f.UseVariable(variable) - - memory := asm.Memory{ - Base: variable.Value.Register, - OffsetRegister: -1, - Length: byte(numBytes), - } - - _, err = f.ExpressionToMemory(value, memory) - return err -} diff --git a/src/core/EvaluateArray.go b/src/core/EvaluateArray.go index 5e840a5..a114bf4 100644 --- a/src/core/EvaluateArray.go +++ b/src/core/EvaluateArray.go @@ -28,6 +28,24 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (*eval.Memory, err Length: byte(1), } + if len(expr.Children) == 1 { + pointer, isPointer := base.Value.Typ.(*types.Pointer) + + if !isPointer { + return nil, errors.New(&errors.TypeMismatch{Encountered: base.Value.Typ.Name(), Expected: types.AnyPointer.Name()}, f.File, expr.Token.Position) + } + + // TODO: This is a hack that needs to be removed + memory.Length = 8 + + value := &eval.Memory{ + Typ: pointer.To, + Memory: memory, + } + + return value, nil + } + indexExpr := expr.Children[1] index, err := f.Evaluate(indexExpr) diff --git a/src/expression/Expression_test.go b/src/expression/Expression_test.go index cfd2ea9..15c461c 100644 --- a/src/expression/Expression_test.go +++ b/src/expression/Expression_test.go @@ -112,6 +112,11 @@ func TestParse(t *testing.T) { {"Array access 6", "a.b()[c]", "(@ (λ (. a b)) c)"}, {"Array access 7", "a.b(c)[d]", "(@ (λ (. a b) c) d)"}, {"Array access 8", "a.b(c)[d][e]", "(@ (@ (λ (. a b) c) d) e)"}, + + {"Dereferencing", "[a]", "(@ a)"}, + {"Dereferencing 2", "[a+b]", "(@ (+ a b))"}, + {"Dereferencing 3", "[a+b]=c", "(= (@ (+ a b)) c)"}, + {"Dereferencing 3", "[a+b]=c+d", "(= (@ (+ a b)) (+ c d))"}, } for _, test := range tests { diff --git a/src/expression/Parse.go b/src/expression/Parse.go index 750fd29..cc61d6c 100644 --- a/src/expression/Parse.go +++ b/src/expression/Parse.go @@ -75,8 +75,17 @@ func Parse(tokens []token.Token) *Expression { group.Precedence = math.MaxInt8 if cursor == nil { - cursor = group - root = group + if t.Kind == token.ArrayEnd { + cursor = New() + cursor.Token.Position = tokens[groupPosition].Position + cursor.Token.Kind = token.Array + cursor.Precedence = precedence(token.Array) + cursor.AddChild(group) + root = cursor + } else { + cursor = group + root = group + } } else { cursor.AddChild(group) } diff --git a/tests/errors/TypeMismatch5.q b/tests/errors/TypeMismatch5.q new file mode 100644 index 0000000..9c01cd6 --- /dev/null +++ b/tests/errors/TypeMismatch5.q @@ -0,0 +1,4 @@ +main() { + a := 1 + [a] = 2 +} \ No newline at end of file diff --git a/tests/errors_test.go b/tests/errors_test.go index 8880905..5fa7c11 100644 --- a/tests/errors_test.go +++ b/tests/errors_test.go @@ -51,6 +51,9 @@ var errs = []struct { {"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}}, {"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}}, {"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}}, + {"TypeMismatch3.q", &errors.TypeMismatch{Expected: "int", Encountered: "[]uint8"}}, + {"TypeMismatch4.q", &errors.TypeMismatch{Expected: "int", Encountered: "[]uint8"}}, + {"TypeMismatch5.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int64"}}, {"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},