Skip to content

Commit

Permalink
fix call function to last(), rest() and first() must be immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
gravataLonga committed Jul 5, 2022
1 parent 4943447 commit dbbb6a6
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 6 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,29 @@ delete a["key"];
a["testing"] = "hello";
```

### Enum

```
enum STATUS {
case OK: true;
case NOK: false;
}
enum RESPONSE {
case OK: 200;
case NOT_FOUND: 404;
case ERR_MSG: "There are some errors"
case TIME: 32.2 + 43.3;
case TEST: if (true) { 0 } else { 1 };
}
```


then you can use his values:

```
puts(STATUS::OK);
```

## Conditions

Expand Down
4 changes: 4 additions & 0 deletions evaluator/builtins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ func TestBuiltinFunctions(t *testing.T) {
{`first([1, 2, 3])`, 1, false},
{`first([])`, nil, false},
{`first(1)`, "TypeError: first() expected argument #1 to be `ARRAY` got `INTEGER`", false},
// builtin function last must be immutable
{`var a = [[0, 1]];var b = first(a);b[0] = b[0] + 1; a[0][0];`, 0, false},
{`last([1, 2, 3])`, 3, false},
// builtin function last must be immutable
{`var a = [[0, 1]];var b = last(a);b[0] = b[0] + 1; a[0][0];`, 0, false},
{`last([])`, nil, false},
{`last(1)`, "TypeError: last() expected argument #1 to be `ARRAY` got `INTEGER`", false},
{`rest([1, 2, 3])`, []int{2, 3}, false},
// builtin function last must be immutable
{`var a = [[0, 1], [0, 1]];var b = rest(a);b[0] = b[0] + 1; a[1][0];`, 0, false},
{`rest([])`, nil, false},
{`push([], 1)`, []int{1}, false},
{`push(1, 1)`, "TypeError: push() expected argument #1 to be `ARRAY` got `INTEGER`", false},
Expand Down
39 changes: 36 additions & 3 deletions object/array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,48 @@ package object
import "testing"

func TestArray_Inspect(t *testing.T) {
arr := &Array{Elements: []Object{&Integer{Value: 1}, &String{Value: "Hello"}}}
arr := &Array{Elements: []Object{&Integer{Value: 1}, &String{Value: "Hello"}, TRUE, NULL, &Float{Value: 1}}}

if arr.Inspect() == "[1, \"Hello\"]" {
if arr.Inspect() != "[1, Hello, true, null, 1.000000]" {
t.Fatalf("Array.Inspect() expected [1, \"Hello\"]. Got: %s", arr.Inspect())
}
}

func TestArray_Clone(t *testing.T) {
arr := &Array{Elements: []Object{&Integer{Value: 1}, &String{Value: "Hello"}, TRUE, NULL, &Float{Value: 1}}}
arrClone := arr.Clone()

arr1, ok := arrClone.(*Array)
if !ok {
t.Fatalf("Array.Clone() didn't produce an array")
}

if arr == arr1 {
t.Fatalf("Array.Clone() didn't clone array")
}
}

func TestArray_CloneDeep(t *testing.T) {
// array[array[1]]
arr := &Array{Elements: []Object{&Array{Elements: []Object{&Integer{Value: 1}}}}}
arrClone := arr.Clone()

arr1, ok := arrClone.(*Array)
if !ok {
t.Fatalf("Array.Clone() didn't produce an array")
}

arrDeep, _ := arr.Elements[0].(*Array)
// this will work but, if we change directly value on Elements[0].Value = 2 isn't working
arrDeep.Elements[0] = &Integer{Value: 2}

if arr.Inspect() == arr1.Inspect() {
t.Fatalf("Array.Clone() didn't clone array deep values, %s == %s", arr.Inspect(), arr1.Inspect())
}
}

func BenchmarkArrayInspect(b *testing.B) {
arr := &Array{Elements: []Object{&Integer{Value: 1}, &String{Value: "Hello"}}}
arr := &Array{Elements: []Object{&Integer{Value: 1}, &String{Value: "Hello"}, TRUE, NULL, &Float{Value: 1}}}
for n := 0; n < b.N; n++ {
arr.Inspect()
}
Expand Down
2 changes: 1 addition & 1 deletion parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func New(l *lexer.Lexer) *Parser {
p.registerPrefix(token.LBRACE, p.parseHashLiteral)
p.registerPrefix(token.FOR, p.parseLoopLiteral)
p.registerPrefix(token.IMPORT, p.parseImport)
// p.registerPrefix(token.BIT_NOT, p.parsePrefixExpression)

p.infixParseFns = make(map[token.TokenType]infixParseFn)
p.registerInfix(token.ASSIGN, p.parseInfixAssignExpression)
Expand All @@ -113,7 +114,6 @@ func New(l *lexer.Lexer) *Parser {
p.registerInfix(token.OR, p.parseInfixExpression)
p.registerInfix(token.BIT_AND, p.parseInfixExpression)
p.registerInfix(token.BIT_OR, p.parseInfixExpression)
p.registerInfix(token.BIT_NOT, p.parseInfixExpression)
p.registerInfix(token.BIT_XOR, p.parseInfixExpression)
p.registerInfix(token.SHIFT_RIGHT, p.parseInfixExpression)
p.registerInfix(token.SHIFT_LEFT, p.parseInfixExpression)
Expand Down
9 changes: 8 additions & 1 deletion stdlib/first.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ func First(args ...object.Object) object.Object {
return object.NewError(err.Error())
}

arr := args[0].(*object.Array)
cloneable, ok := args[0].(object.Cloneable)
if !ok {
return object.NewErrorFormat("object isn't cloneable.")
}

arrClone := cloneable.Clone()
arr := arrClone.(*object.Array)

if len(arr.Elements) > 0 {
return arr.Elements[0]
}
Expand Down
1 change: 0 additions & 1 deletion stdlib/last.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ func Last(args ...object.Object) object.Object {
}

arrClone := cloneable.Clone()

arr := arrClone.(*object.Array)

length := len(arr.Elements)
Expand Down

0 comments on commit dbbb6a6

Please sign in to comment.