From 87c823b148686d0e30f1c813ffb321fefd30c10a Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 27 Jul 2025 23:35:32 +0200 Subject: [PATCH] Added a test for missing operands --- src/ast/errors_test.go | 2 ++ src/ast/testdata/MissingOperand.q | 3 +++ src/ast/testdata/MissingOperand2.q | 3 +++ src/core/errors.go | 1 + src/core/errors_test.go | 1 + src/core/evaluate.go | 42 +++--------------------------- src/core/evaluateBinary.go | 33 +++++++++++++++++++++++ src/core/evaluateUnary.go | 29 +++++++++++++++++++++ src/core/testdata/MissingOperand.q | 3 +++ 9 files changed, 78 insertions(+), 39 deletions(-) create mode 100644 src/ast/testdata/MissingOperand.q create mode 100644 src/ast/testdata/MissingOperand2.q create mode 100644 src/core/evaluateBinary.go create mode 100644 src/core/evaluateUnary.go create mode 100644 src/core/testdata/MissingOperand.q diff --git a/src/ast/errors_test.go b/src/ast/errors_test.go index 1b1352f..9720c35 100644 --- a/src/ast/errors_test.go +++ b/src/ast/errors_test.go @@ -19,6 +19,8 @@ var errs = []struct { {"InvalidInstruction2.q", &ast.InvalidInstruction{Instruction: "42"}}, {"InvalidInstruction3.q", &ast.InvalidInstruction{Instruction: "2 + 3"}}, {"InvalidInstruction4.q", &ast.InvalidInstruction{Instruction: "\"not used\""}}, + {"MissingOperand.q", ast.MissingOperand}, + {"MissingOperand2.q", ast.MissingOperand}, } func TestErrors(t *testing.T) { diff --git a/src/ast/testdata/MissingOperand.q b/src/ast/testdata/MissingOperand.q new file mode 100644 index 0000000..4eefb33 --- /dev/null +++ b/src/ast/testdata/MissingOperand.q @@ -0,0 +1,3 @@ +main() { + x := +} \ No newline at end of file diff --git a/src/ast/testdata/MissingOperand2.q b/src/ast/testdata/MissingOperand2.q new file mode 100644 index 0000000..90b021a --- /dev/null +++ b/src/ast/testdata/MissingOperand2.q @@ -0,0 +1,3 @@ +main() { + x = +} \ No newline at end of file diff --git a/src/core/errors.go b/src/core/errors.go index 6ee13ad..0927fc6 100644 --- a/src/core/errors.go +++ b/src/core/errors.go @@ -11,6 +11,7 @@ var ( InvalidExpression = errors.String("Invalid expression") InvalidNumber = errors.String("Invalid number") InvalidRune = errors.String("Invalid rune") + MissingOperand = errors.String("Missing operand") ) // ParameterCountMismatch error is created when the number of provided parameters doesn't match the function signature. diff --git a/src/core/errors_test.go b/src/core/errors_test.go index b7bad42..b3b0822 100644 --- a/src/core/errors_test.go +++ b/src/core/errors_test.go @@ -19,6 +19,7 @@ var errs = []struct { {"InvalidExpression2.q", core.InvalidExpression}, {"InvalidExpression3.q", core.InvalidExpression}, {"InvalidExpression4.q", core.InvalidExpression}, + {"MissingOperand.q", core.MissingOperand}, {"ParameterCountMismatch.q", &core.ParameterCountMismatch{Function: "main.f", Count: 0, ExpectedCount: 1}}, {"ParameterCountMismatch2.q", &core.ParameterCountMismatch{Function: "main.f", Count: 2, ExpectedCount: 1}}, {"TypeMismatch.q", &core.TypeMismatch{Encountered: "string", Expected: "int64", ParameterName: "x", IsReturn: false}}, diff --git a/src/core/evaluate.go b/src/core/evaluate.go index db55bb2..8fb7b69 100644 --- a/src/core/evaluate.go +++ b/src/core/evaluate.go @@ -23,45 +23,9 @@ func (f *Function) evaluate(expr *expression.Expression) (ssa.Value, error) { panic("not implemented") } - if expr.Token.Kind.IsUnaryOperator() { - left := expr.Children[0] - - leftValue, err := f.evaluate(left) - - if err != nil { - return nil, err - } - - v := f.Append(&ssa.UnaryOp{ - Operand: leftValue, - Op: expr.Token.Kind, - Source: ssa.Source(expr.Source()), - }) - - return v, nil - } - - left := expr.Children[0] - right := expr.Children[1] - - leftValue, err := f.evaluate(left) - - if err != nil { - return nil, err - } - - rightValue, err := f.evaluate(right) - - if err != nil { - return nil, err + if len(expr.Children) == 1 { + return f.evaluateUnary(expr) } - v := f.Append(&ssa.BinaryOp{ - Left: leftValue, - Right: rightValue, - Op: expr.Token.Kind, - Source: ssa.Source(expr.Source()), - }) - - return v, nil + return f.evaluateBinary(expr) } \ No newline at end of file diff --git a/src/core/evaluateBinary.go b/src/core/evaluateBinary.go new file mode 100644 index 0000000..bd8ddbc --- /dev/null +++ b/src/core/evaluateBinary.go @@ -0,0 +1,33 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" +) + +// evaluateBinary converts a binary expression to an SSA value. +func (f *Function) evaluateBinary(expr *expression.Expression) (ssa.Value, error) { + left := expr.Children[0] + right := expr.Children[1] + + leftValue, err := f.evaluate(left) + + if err != nil { + return nil, err + } + + rightValue, err := f.evaluate(right) + + if err != nil { + return nil, err + } + + v := f.Append(&ssa.BinaryOp{ + Left: leftValue, + Right: rightValue, + Op: expr.Token.Kind, + Source: ssa.Source(expr.Source()), + }) + + return v, nil +} \ No newline at end of file diff --git a/src/core/evaluateUnary.go b/src/core/evaluateUnary.go new file mode 100644 index 0000000..993756b --- /dev/null +++ b/src/core/evaluateUnary.go @@ -0,0 +1,29 @@ +package core + +import ( + "git.urbach.dev/cli/q/src/errors" + "git.urbach.dev/cli/q/src/expression" + "git.urbach.dev/cli/q/src/ssa" +) + +// evaluateUnary converts a unary expression to an SSA value. +func (f *Function) evaluateUnary(expr *expression.Expression) (ssa.Value, error) { + if !expr.Token.Kind.IsUnaryOperator() { + return nil, errors.New(MissingOperand, f.File, expr.Token.End()) + } + + left := expr.Children[0] + leftValue, err := f.evaluate(left) + + if err != nil { + return nil, err + } + + v := f.Append(&ssa.UnaryOp{ + Operand: leftValue, + Op: expr.Token.Kind, + Source: ssa.Source(expr.Source()), + }) + + return v, nil +} \ No newline at end of file diff --git a/src/core/testdata/MissingOperand.q b/src/core/testdata/MissingOperand.q new file mode 100644 index 0000000..df46622 --- /dev/null +++ b/src/core/testdata/MissingOperand.q @@ -0,0 +1,3 @@ +main() { + syscall(1+) +} \ No newline at end of file -- 2.51.2