Skip to content

Commit

Permalink
👷 Evaluate SUB operator in prefix expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
ChmielewskiKamil committed Oct 3, 2024
1 parent 100b4a1 commit 2ac4449
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
26 changes: 22 additions & 4 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package evaluator

import (
"fmt"
"math/big"
"solbot/ast"
"solbot/object"
"solbot/token"
Expand All @@ -17,6 +18,8 @@ var (

func Eval(node ast.Node) object.Object {
switch node := node.(type) {
default:
return retEvalErrorObj(fmt.Sprintf("Unhandled ast node: %T", node))
// File

case *ast.File:
Expand Down Expand Up @@ -46,8 +49,6 @@ func Eval(node ast.Node) object.Object {
right := Eval(node.Right)
return evalPrefixExpression(node.Operator, right)
}

return nil
}

func evalDeclarations(decls []ast.Declaration) object.Object {
Expand Down Expand Up @@ -84,11 +85,13 @@ func evalPrefixExpression(operator token.Token, right object.Object) object.Obje
return retEvalErrorObj(
fmt.Sprintf("Unknown prefix operator: %s", operator.String()))
case token.NOT:
return evalNotOperatorExpression(right)
return evalNotPrefixOperatorExpression(right)
case token.SUB:
return evalSubPrefixOperatorExpression(right)
}
}

func evalNotOperatorExpression(right object.Object) *object.Boolean {
func evalNotPrefixOperatorExpression(right object.Object) object.Object {
switch right {
default:
return FALSE
Expand All @@ -99,6 +102,21 @@ func evalNotOperatorExpression(right object.Object) *object.Boolean {
}
}

func evalSubPrefixOperatorExpression(right object.Object) object.Object {
if right.Type() != object.INTEGER_OBJ {
return retEvalErrorObj(
fmt.Sprintf(
"The '-' prefix operator can only be used with integers. Got: %T instead.",
right))
}

value := right.(*object.Integer).Value
return &object.Integer{Value: *new(big.Int).Neg(&value)}
}

// retEvalErrorObj is an error handling helper. Since evaluation functions
// expect some kind of object to be returned and we don't have nil, we
// just return EvalError object. The caller can decide what to do with it.
func retEvalErrorObj(message string) *object.EvalError {
return &object.EvalError{Message: message}
}
2 changes: 2 additions & 0 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ func Test_EvalIntegerExpression(t *testing.T) {
}{
{"1", big.NewInt(1)},
{"50", big.NewInt(50)},
{"-1", big.NewInt(-1)},
{"-50", big.NewInt(-50)},
}

for _, tt := range tests {
Expand Down
2 changes: 2 additions & 0 deletions object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type Object interface {
}

type (
// Special object used to handle errors in object evaluation phase. It is
// not connected to the Solidity language.
EvalError struct {
Message string
}
Expand Down

0 comments on commit 2ac4449

Please sign in to comment.