Skip to content

Commit

Permalink
Added support of error supression to inline expressions (#671)
Browse files Browse the repository at this point in the history
* Added support of error supression to inline expressions
  • Loading branch information
ziflex authored Sep 20, 2021
1 parent 658e929 commit 2f399c6
Show file tree
Hide file tree
Showing 16 changed files with 1,874 additions and 1,566 deletions.
52 changes: 52 additions & 0 deletions pkg/compiler/compiler_for_ternary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ func TestForTernaryExpression(t *testing.T) {
So(string(out2), ShouldEqual, `true`)
})

Convey("RETURN foo ? TRUE : (FOR i IN 1..5 T::FAIL() RETURN i*2)?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i IN 1..5 T::FAIL() RETURN i*2)?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)
})

Convey("RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)", t, func() {
c := compiler.New()

Expand All @@ -48,6 +60,26 @@ func TestForTernaryExpression(t *testing.T) {
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
})

Convey("RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL())? : (FOR i IN 1..5 RETURN T::FAIL())?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL()) : (FOR i IN 1..5 RETURN T::FAIL())?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)

out2, err := c.MustCompile(`
LET foo = TRUE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL())? : (FOR i IN 1..5 RETURN T::FAIL())
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `null`)
})

Convey("LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)", t, func() {
c := compiler.New()

Expand Down Expand Up @@ -91,6 +123,26 @@ func TestForTernaryExpression(t *testing.T) {
So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
})

Convey("LET res = (FOR i IN 1..5 RETURN T::FAIL())? ? TRUE : FALSE", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET res = (FOR i IN 1..5 RETURN T::FAIL())? ? TRUE : FALSE
RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `false`)

out2, err := c.MustCompile(`
LET res = (FOR i IN 1..5 RETURN i)? ? TRUE : FALSE
RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out2), ShouldEqual, `true`)
})
}

func BenchmarkForTernary(b *testing.B) {
Expand Down
12 changes: 12 additions & 0 deletions pkg/compiler/compiler_for_while_ternary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ func TestForTernaryWhileExpression(t *testing.T) {
So(string(out1), ShouldEqual, `[]`)
})

Convey("RETURN foo ? TRUE : (FOR i WHILE T::FAIL() RETURN i*2)?", t, func() {
c := compiler.New()

out1, err := c.MustCompile(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i WHILE T::FAIL() RETURN i*2)?
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out1), ShouldEqual, `null`)
})

Convey("RETURN foo ? TRUE : (FOR i WHILE F() < 10 RETURN i*2)", t, func() {
c := compiler.New()

Expand Down
48 changes: 48 additions & 0 deletions pkg/compiler/compiler_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ func TestFunctionCall(t *testing.T) {
So(string(out), ShouldEqual, `null`)
})

Convey("Should handle errors when ? is used within a group", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN (FALSE OR T::FAIL())?
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `null`)
})

Convey("Should return NONE when error is handled", t, func() {
c := compiler.New()
c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
Expand All @@ -122,6 +138,38 @@ func TestFunctionCall(t *testing.T) {

So(string(out), ShouldEqual, `null`)
})

Convey("Should be able to use FOR as an argument", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN FIRST((FOR i IN 1..10 RETURN i * 2))
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `2`)
})

Convey("Should be able to use FOR as arguments", t, func() {
c := compiler.New()

p, err := c.Compile(`
RETURN UNION((FOR i IN 0..5 RETURN i), (FOR i IN 6..10 RETURN i))
`)

So(err, ShouldBeNil)

out, err := p.Run(context.Background())

So(err, ShouldBeNil)

So(string(out), ShouldEqual, `[0,1,2,3,4,5,6,7,8,9,10]`)
})
}

func BenchmarkFunctionCallArg1(b *testing.B) {
Expand Down
81 changes: 78 additions & 3 deletions pkg/compiler/compiler_let_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"github.com/MontFerret/ferret/pkg/compiler"
"github.com/MontFerret/ferret/pkg/runtime"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
Expand Down Expand Up @@ -179,11 +181,35 @@ func TestLet(t *testing.T) {
So(string(out), ShouldEqual, "[1,2,3]")
})

Convey("Should compile LET i = (FOR i WHILE 0 > 1 RETURN i) RETURN i", t, func() {
Convey("Should compile LET src = NONE LET i = (FOR i IN NONE RETURN i)? RETURN i == NONE", t, func() {
c := compiler.New()

p, err := c.Compile(`
LET i = (FOR i WHILE 0 > 1 RETURN i)
LET src = NONE
LET i = (FOR i IN src RETURN i)?
RETURN i == NONE
`)

So(err, ShouldBeNil)
So(p, ShouldHaveSameTypeAs, &runtime.Program{})

out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "true")
})

Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 RETURN i) RETURN i", t, func() {
c := compiler.New()
counter := -1
c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++

return values.NewInt(counter), nil
})

p, err := c.Compile(`
LET i = (FOR i WHILE COUNTER() < 5 RETURN i)
RETURN i
`)

Expand All @@ -193,7 +219,30 @@ func TestLet(t *testing.T) {
out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "[]")
So(string(out), ShouldEqual, "[0,1,2,3,4]")
})

Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)? RETURN i == NONE", t, func() {
c := compiler.New()
counter := -1
c.RegisterFunction("COUNTER", func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++

return values.NewInt(counter), nil
})

p, err := c.Compile(`
LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)?
RETURN i == NONE
`)

So(err, ShouldBeNil)
So(p, ShouldHaveSameTypeAs, &runtime.Program{})

out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "true")
})

Convey("Should compile LET i = { items: [1,2,3]} FOR el IN i.items RETURN i", t, func() {
Expand Down Expand Up @@ -262,4 +311,30 @@ func TestLet(t *testing.T) {
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `"data"`)
})

Convey("Should handle error from WAITFOR EVENT", t, func() {
out, err := newCompilerWithObservable().MustCompile(`
LET obj = X::CREATE()
LET res = (WAITFOR EVENT "event" IN obj 100)?
RETURN res == NONE
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})

Convey("Should compare result of handled error", t, func() {
out, err := newCompilerWithObservable().MustCompile(`
LET obj = X::CREATE()
LET res = (WAITFOR EVENT "event" IN obj 100)? != NONE
RETURN res
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `false`)
})
}
Loading

0 comments on commit 2f399c6

Please sign in to comment.