mirror of
https://github.com/MontFerret/ferret.git
synced 2025-07-17 01:32:22 +02:00
Added support of error supression to inline expressions (#671)
* Added support of error supression to inline expressions
This commit is contained in:
@ -28,6 +28,18 @@ func TestForTernaryExpression(t *testing.T) {
|
|||||||
So(string(out2), ShouldEqual, `true`)
|
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() {
|
Convey("RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||||
c := compiler.New()
|
c := compiler.New()
|
||||||
|
|
||||||
@ -48,6 +60,26 @@ func TestForTernaryExpression(t *testing.T) {
|
|||||||
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
|
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() {
|
Convey("LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)", t, func() {
|
||||||
c := compiler.New()
|
c := compiler.New()
|
||||||
|
|
||||||
@ -91,6 +123,26 @@ func TestForTernaryExpression(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(out2), ShouldEqual, `[1,2,3,4,5]`)
|
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) {
|
func BenchmarkForTernary(b *testing.B) {
|
||||||
|
@ -22,6 +22,18 @@ func TestForTernaryWhileExpression(t *testing.T) {
|
|||||||
So(string(out1), ShouldEqual, `[]`)
|
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() {
|
Convey("RETURN foo ? TRUE : (FOR i WHILE F() < 10 RETURN i*2)", t, func() {
|
||||||
c := compiler.New()
|
c := compiler.New()
|
||||||
|
|
||||||
|
@ -104,6 +104,22 @@ func TestFunctionCall(t *testing.T) {
|
|||||||
So(string(out), ShouldEqual, `null`)
|
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() {
|
Convey("Should return NONE when error is handled", t, func() {
|
||||||
c := compiler.New()
|
c := compiler.New()
|
||||||
c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
|
c.RegisterFunction("ERROR", func(ctx context.Context, args ...core.Value) (core.Value, error) {
|
||||||
@ -122,6 +138,38 @@ func TestFunctionCall(t *testing.T) {
|
|||||||
|
|
||||||
So(string(out), ShouldEqual, `null`)
|
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) {
|
func BenchmarkFunctionCallArg1(b *testing.B) {
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/MontFerret/ferret/pkg/compiler"
|
"github.com/MontFerret/ferret/pkg/compiler"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"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"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -179,11 +181,35 @@ func TestLet(t *testing.T) {
|
|||||||
So(string(out), ShouldEqual, "[1,2,3]")
|
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()
|
c := compiler.New()
|
||||||
|
|
||||||
p, err := c.Compile(`
|
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
|
RETURN i
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@ -193,7 +219,30 @@ func TestLet(t *testing.T) {
|
|||||||
out, err := p.Run(context.Background())
|
out, err := p.Run(context.Background())
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
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() {
|
Convey("Should compile LET i = { items: [1,2,3]} FOR el IN i.items RETURN i", t, func() {
|
||||||
@ -262,4 +311,30 @@ func TestLet(t *testing.T) {
|
|||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(string(out), ShouldEqual, `"data"`)
|
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`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -185,11 +185,7 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
|
|||||||
var out core.Expression
|
var out core.Expression
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if exp := ctx.ForExpression(); exp != nil {
|
if exp := ctx.Expression(); exp != nil {
|
||||||
out, err = v.doVisitForExpression(exp.(*fql.ForExpressionContext), scope.Fork())
|
|
||||||
} else if exp := ctx.WaitForExpression(); exp != nil {
|
|
||||||
out, err = v.doVisitWaitForExpressionContext(exp.(*fql.WaitForExpressionContext), scope)
|
|
||||||
} else if exp := ctx.Expression(); exp != nil {
|
|
||||||
out, err = v.doVisitExpression(exp.(*fql.ExpressionContext), scope)
|
out, err = v.doVisitExpression(exp.(*fql.ExpressionContext), scope)
|
||||||
} else {
|
} else {
|
||||||
return nil, core.Error(ErrInvalidToken, ctx.GetText())
|
return nil, core.Error(ErrInvalidToken, ctx.GetText())
|
||||||
@ -202,6 +198,36 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
|
|||||||
return expressions.NewReturnExpression(v.getSourceMap(ctx), out)
|
return expressions.NewReturnExpression(v.getSourceMap(ctx), out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *visitor) doVisitInlineHighLevelExpression(ctx *fql.InlineHighLevelExpressionContext, scope *scope) (core.Expression, error) {
|
||||||
|
hlexpCtx := ctx.HighLevelExpression()
|
||||||
|
|
||||||
|
if hlexpCtx == nil {
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
|
||||||
|
exp, err := v.doVisitHighLevelExpression(hlexpCtx.(*fql.HighLevelExpressionContext), scope.Fork())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.ErrorOperator() == nil {
|
||||||
|
return exp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return expressions.SuppressErrors(exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *visitor) doVisitHighLevelExpression(ctx *fql.HighLevelExpressionContext, scope *scope) (core.Expression, error) {
|
||||||
|
if exp := ctx.ForExpression(); exp != nil {
|
||||||
|
return v.doVisitForExpression(exp.(*fql.ForExpressionContext), scope.Fork())
|
||||||
|
} else if exp := ctx.WaitForExpression(); exp != nil {
|
||||||
|
return v.doVisitWaitForExpressionContext(exp.(*fql.WaitForExpressionContext), scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, ErrInvalidToken
|
||||||
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *scope) (core.Expression, error) {
|
func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *scope) (core.Expression, error) {
|
||||||
var err error
|
var err error
|
||||||
var valVarName string
|
var valVarName string
|
||||||
@ -599,6 +625,7 @@ func (v *visitor) doVisitCollectAggregateSelector(ctx *fql.CollectAggregateSelec
|
|||||||
|
|
||||||
if fnCtx != nil {
|
if fnCtx != nil {
|
||||||
exp, err := v.doVisitFunctionCallExpression(fnCtx.(*fql.FunctionCallExpressionContext), scope)
|
exp, err := v.doVisitFunctionCallExpression(fnCtx.(*fql.FunctionCallExpressionContext), scope)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -945,7 +972,7 @@ func (v *visitor) doVisitMemberExpressionSource(ctx *fql.MemberExpressionSourceC
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fnCall := ctx.FunctionCall(); fnCall != nil {
|
if fnCall := ctx.FunctionCall(); fnCall != nil {
|
||||||
return v.doVisitFunctionCall(fnCall.(*fql.FunctionCallContext), false, scope)
|
return v.doVisitFunctionCall(fnCall.(*fql.FunctionCallContext), scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
if objectLiteral := ctx.ObjectLiteral(); objectLiteral != nil {
|
if objectLiteral := ctx.ObjectLiteral(); objectLiteral != nil {
|
||||||
@ -1113,10 +1140,6 @@ func (v *visitor) doVisitVariableDeclaration(ctx *fql.VariableDeclarationContext
|
|||||||
|
|
||||||
if exp := ctx.Expression(); exp != nil {
|
if exp := ctx.Expression(); exp != nil {
|
||||||
init, err = v.doVisitExpression(ctx.Expression().(*fql.ExpressionContext), scope)
|
init, err = v.doVisitExpression(ctx.Expression().(*fql.ExpressionContext), scope)
|
||||||
} else if exp := ctx.ForExpression(); exp != nil {
|
|
||||||
init, err = v.doVisitForExpression(exp.(*fql.ForExpressionContext), scope)
|
|
||||||
} else if exp := ctx.WaitForExpression(); exp != nil {
|
|
||||||
init, err = v.doVisitWaitForExpressionContext(exp.(*fql.WaitForExpressionContext), scope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1150,7 +1173,7 @@ func (v *visitor) doVisitRangeOperator(ctx *fql.RangeOperatorContext, scope *sco
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitFunctionCall(context *fql.FunctionCallContext, ignoreErrors bool, scope *scope) (core.Expression, error) {
|
func (v *visitor) doVisitFunctionCall(context *fql.FunctionCallContext, scope *scope) (core.Expression, error) {
|
||||||
args := make([]core.Expression, 0, 5)
|
args := make([]core.Expression, 0, 5)
|
||||||
argsCtx := context.Arguments()
|
argsCtx := context.Arguments()
|
||||||
|
|
||||||
@ -1186,17 +1209,25 @@ func (v *visitor) doVisitFunctionCall(context *fql.FunctionCallContext, ignoreEr
|
|||||||
return expressions.NewFunctionCallExpression(
|
return expressions.NewFunctionCallExpression(
|
||||||
v.getSourceMap(context),
|
v.getSourceMap(context),
|
||||||
fun,
|
fun,
|
||||||
ignoreErrors,
|
|
||||||
args...,
|
args...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitFunctionCallExpression(context *fql.FunctionCallExpressionContext, scope *scope) (core.Expression, error) {
|
func (v *visitor) doVisitFunctionCallExpression(context *fql.FunctionCallExpressionContext, scope *scope) (core.Expression, error) {
|
||||||
return v.doVisitFunctionCall(
|
exp, err := v.doVisitFunctionCall(
|
||||||
context.FunctionCall().(*fql.FunctionCallContext),
|
context.FunctionCall().(*fql.FunctionCallContext),
|
||||||
context.QuestionMark() != nil,
|
|
||||||
scope,
|
scope,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if context.ErrorOperator() == nil {
|
||||||
|
return exp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return expressions.SuppressErrors(exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitParamContext(context *fql.ParamContext, s *scope) (core.Expression, error) {
|
func (v *visitor) doVisitParamContext(context *fql.ParamContext, s *scope) (core.Expression, error) {
|
||||||
@ -1417,13 +1448,23 @@ func (v *visitor) doVisitArrayOperator(ctx *fql.ExpressionContext, scope *scope)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitExpressionGroup(ctx *fql.ExpressionGroupContext, scope *scope) (core.Expression, error) {
|
func (v *visitor) doVisitExpressionGroup(ctx *fql.ExpressionGroupContext, scope *scope) (core.Expression, error) {
|
||||||
exp := ctx.Expression()
|
expCtx := ctx.Expression()
|
||||||
|
|
||||||
if exp == nil {
|
if expCtx == nil {
|
||||||
return nil, ErrInvalidToken
|
return nil, ErrInvalidToken
|
||||||
}
|
}
|
||||||
|
|
||||||
return v.doVisitExpression(exp.(*fql.ExpressionContext), scope)
|
exp, err := v.doVisitExpression(expCtx.(*fql.ExpressionContext), scope)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.ErrorOperator() == nil {
|
||||||
|
return exp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return expressions.SuppressErrors(exp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (core.Expression, error) {
|
func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (core.Expression, error) {
|
||||||
@ -1515,19 +1556,6 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
|
|||||||
return v.doVisitNoneLiteral(exp.(*fql.NoneLiteralContext))
|
return v.doVisitNoneLiteral(exp.(*fql.NoneLiteralContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
if exp := ctx.QuestionMark(); exp != nil {
|
|
||||||
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return v.createTernaryOperator(
|
|
||||||
v.getSourceMap(ctx),
|
|
||||||
exps,
|
|
||||||
scope,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if exp := ctx.RangeOperator(); exp != nil {
|
if exp := ctx.RangeOperator(); exp != nil {
|
||||||
return v.doVisitRangeOperator(exp.(*fql.RangeOperatorContext), scope)
|
return v.doVisitRangeOperator(exp.(*fql.RangeOperatorContext), scope)
|
||||||
}
|
}
|
||||||
@ -1536,6 +1564,10 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
|
|||||||
return v.doVisitParamContext(param.(*fql.ParamContext), scope)
|
return v.doVisitParamContext(param.(*fql.ParamContext), scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if exp := ctx.InlineHighLevelExpression(); exp != nil {
|
||||||
|
return v.doVisitInlineHighLevelExpression(exp.(*fql.InlineHighLevelExpressionContext), scope)
|
||||||
|
}
|
||||||
|
|
||||||
return nil, ErrNotImplemented
|
return nil, ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,20 @@ bodyExpression
|
|||||||
;
|
;
|
||||||
|
|
||||||
variableDeclaration
|
variableDeclaration
|
||||||
: Let Identifier Assign OpenParen (forExpression | waitForExpression) CloseParen
|
: Let Identifier Assign expression
|
||||||
| Let Identifier Assign expression
|
|
||||||
;
|
;
|
||||||
|
|
||||||
returnExpression
|
returnExpression
|
||||||
: Return Distinct? OpenParen (forExpression | waitForExpression) CloseParen
|
: Return Distinct? expression
|
||||||
| Return Distinct? expression
|
;
|
||||||
|
|
||||||
|
inlineHighLevelExpression
|
||||||
|
: OpenParen highLevelExpression CloseParen errorOperator?
|
||||||
|
;
|
||||||
|
|
||||||
|
highLevelExpression
|
||||||
|
: forExpression
|
||||||
|
| waitForExpression
|
||||||
;
|
;
|
||||||
|
|
||||||
forExpression
|
forExpression
|
||||||
@ -223,10 +230,6 @@ noneLiteral
|
|||||||
| None
|
| None
|
||||||
;
|
;
|
||||||
|
|
||||||
expressionGroup
|
|
||||||
: OpenParen expression CloseParen
|
|
||||||
;
|
|
||||||
|
|
||||||
expression
|
expression
|
||||||
: unaryOperator expression
|
: unaryOperator expression
|
||||||
| expression multiplicativeOperator expression
|
| expression multiplicativeOperator expression
|
||||||
@ -238,9 +241,6 @@ expression
|
|||||||
| expression regexpOperator expression
|
| expression regexpOperator expression
|
||||||
| expression logicalAndOperator expression
|
| expression logicalAndOperator expression
|
||||||
| expression logicalOrOperator expression
|
| expression logicalOrOperator expression
|
||||||
| expression QuestionMark OpenParen (forExpression | waitForExpression) CloseParen Colon OpenParen (forExpression | waitForExpression) CloseParen
|
|
||||||
| expression QuestionMark expression Colon OpenParen (forExpression | waitForExpression) CloseParen
|
|
||||||
| expression QuestionMark OpenParen (forExpression | waitForExpression) CloseParen Colon expression
|
|
||||||
| expression QuestionMark expression? Colon expression
|
| expression QuestionMark expression? Colon expression
|
||||||
| rangeOperator
|
| rangeOperator
|
||||||
| stringLiteral
|
| stringLiteral
|
||||||
@ -255,6 +255,11 @@ expression
|
|||||||
| variable
|
| variable
|
||||||
| noneLiteral
|
| noneLiteral
|
||||||
| expressionGroup
|
| expressionGroup
|
||||||
|
| inlineHighLevelExpression
|
||||||
|
;
|
||||||
|
|
||||||
|
expressionGroup
|
||||||
|
: OpenParen expression CloseParen errorOperator?
|
||||||
;
|
;
|
||||||
|
|
||||||
memberExpression
|
memberExpression
|
||||||
@ -274,7 +279,7 @@ functionCall
|
|||||||
;
|
;
|
||||||
|
|
||||||
functionCallExpression
|
functionCallExpression
|
||||||
: functionCall QuestionMark?
|
: functionCall errorOperator?
|
||||||
;
|
;
|
||||||
|
|
||||||
memberExpressionPath
|
memberExpressionPath
|
||||||
@ -282,6 +287,10 @@ memberExpressionPath
|
|||||||
| (QuestionMark Dot)? computedPropertyName
|
| (QuestionMark Dot)? computedPropertyName
|
||||||
;
|
;
|
||||||
|
|
||||||
|
errorOperator
|
||||||
|
: QuestionMark
|
||||||
|
;
|
||||||
|
|
||||||
functionIdentifier
|
functionIdentifier
|
||||||
: Identifier
|
: Identifier
|
||||||
| And
|
| And
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -80,6 +80,20 @@ func (s *BaseFqlParserListener) EnterReturnExpression(ctx *ReturnExpressionConte
|
|||||||
// ExitReturnExpression is called when production returnExpression is exited.
|
// ExitReturnExpression is called when production returnExpression is exited.
|
||||||
func (s *BaseFqlParserListener) ExitReturnExpression(ctx *ReturnExpressionContext) {}
|
func (s *BaseFqlParserListener) ExitReturnExpression(ctx *ReturnExpressionContext) {}
|
||||||
|
|
||||||
|
// EnterInlineHighLevelExpression is called when production inlineHighLevelExpression is entered.
|
||||||
|
func (s *BaseFqlParserListener) EnterInlineHighLevelExpression(ctx *InlineHighLevelExpressionContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExitInlineHighLevelExpression is called when production inlineHighLevelExpression is exited.
|
||||||
|
func (s *BaseFqlParserListener) ExitInlineHighLevelExpression(ctx *InlineHighLevelExpressionContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnterHighLevelExpression is called when production highLevelExpression is entered.
|
||||||
|
func (s *BaseFqlParserListener) EnterHighLevelExpression(ctx *HighLevelExpressionContext) {}
|
||||||
|
|
||||||
|
// ExitHighLevelExpression is called when production highLevelExpression is exited.
|
||||||
|
func (s *BaseFqlParserListener) ExitHighLevelExpression(ctx *HighLevelExpressionContext) {}
|
||||||
|
|
||||||
// EnterForExpression is called when production forExpression is entered.
|
// EnterForExpression is called when production forExpression is entered.
|
||||||
func (s *BaseFqlParserListener) EnterForExpression(ctx *ForExpressionContext) {}
|
func (s *BaseFqlParserListener) EnterForExpression(ctx *ForExpressionContext) {}
|
||||||
|
|
||||||
@ -284,18 +298,18 @@ func (s *BaseFqlParserListener) EnterNoneLiteral(ctx *NoneLiteralContext) {}
|
|||||||
// ExitNoneLiteral is called when production noneLiteral is exited.
|
// ExitNoneLiteral is called when production noneLiteral is exited.
|
||||||
func (s *BaseFqlParserListener) ExitNoneLiteral(ctx *NoneLiteralContext) {}
|
func (s *BaseFqlParserListener) ExitNoneLiteral(ctx *NoneLiteralContext) {}
|
||||||
|
|
||||||
// EnterExpressionGroup is called when production expressionGroup is entered.
|
|
||||||
func (s *BaseFqlParserListener) EnterExpressionGroup(ctx *ExpressionGroupContext) {}
|
|
||||||
|
|
||||||
// ExitExpressionGroup is called when production expressionGroup is exited.
|
|
||||||
func (s *BaseFqlParserListener) ExitExpressionGroup(ctx *ExpressionGroupContext) {}
|
|
||||||
|
|
||||||
// EnterExpression is called when production expression is entered.
|
// EnterExpression is called when production expression is entered.
|
||||||
func (s *BaseFqlParserListener) EnterExpression(ctx *ExpressionContext) {}
|
func (s *BaseFqlParserListener) EnterExpression(ctx *ExpressionContext) {}
|
||||||
|
|
||||||
// ExitExpression is called when production expression is exited.
|
// ExitExpression is called when production expression is exited.
|
||||||
func (s *BaseFqlParserListener) ExitExpression(ctx *ExpressionContext) {}
|
func (s *BaseFqlParserListener) ExitExpression(ctx *ExpressionContext) {}
|
||||||
|
|
||||||
|
// EnterExpressionGroup is called when production expressionGroup is entered.
|
||||||
|
func (s *BaseFqlParserListener) EnterExpressionGroup(ctx *ExpressionGroupContext) {}
|
||||||
|
|
||||||
|
// ExitExpressionGroup is called when production expressionGroup is exited.
|
||||||
|
func (s *BaseFqlParserListener) ExitExpressionGroup(ctx *ExpressionGroupContext) {}
|
||||||
|
|
||||||
// EnterMemberExpression is called when production memberExpression is entered.
|
// EnterMemberExpression is called when production memberExpression is entered.
|
||||||
func (s *BaseFqlParserListener) EnterMemberExpression(ctx *MemberExpressionContext) {}
|
func (s *BaseFqlParserListener) EnterMemberExpression(ctx *MemberExpressionContext) {}
|
||||||
|
|
||||||
@ -326,6 +340,12 @@ func (s *BaseFqlParserListener) EnterMemberExpressionPath(ctx *MemberExpressionP
|
|||||||
// ExitMemberExpressionPath is called when production memberExpressionPath is exited.
|
// ExitMemberExpressionPath is called when production memberExpressionPath is exited.
|
||||||
func (s *BaseFqlParserListener) ExitMemberExpressionPath(ctx *MemberExpressionPathContext) {}
|
func (s *BaseFqlParserListener) ExitMemberExpressionPath(ctx *MemberExpressionPathContext) {}
|
||||||
|
|
||||||
|
// EnterErrorOperator is called when production errorOperator is entered.
|
||||||
|
func (s *BaseFqlParserListener) EnterErrorOperator(ctx *ErrorOperatorContext) {}
|
||||||
|
|
||||||
|
// ExitErrorOperator is called when production errorOperator is exited.
|
||||||
|
func (s *BaseFqlParserListener) ExitErrorOperator(ctx *ErrorOperatorContext) {}
|
||||||
|
|
||||||
// EnterFunctionIdentifier is called when production functionIdentifier is entered.
|
// EnterFunctionIdentifier is called when production functionIdentifier is entered.
|
||||||
func (s *BaseFqlParserListener) EnterFunctionIdentifier(ctx *FunctionIdentifierContext) {}
|
func (s *BaseFqlParserListener) EnterFunctionIdentifier(ctx *FunctionIdentifierContext) {}
|
||||||
|
|
||||||
|
@ -47,6 +47,14 @@ func (v *BaseFqlParserVisitor) VisitReturnExpression(ctx *ReturnExpressionContex
|
|||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *BaseFqlParserVisitor) VisitInlineHighLevelExpression(ctx *InlineHighLevelExpressionContext) interface{} {
|
||||||
|
return v.VisitChildren(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *BaseFqlParserVisitor) VisitHighLevelExpression(ctx *HighLevelExpressionContext) interface{} {
|
||||||
|
return v.VisitChildren(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *BaseFqlParserVisitor) VisitForExpression(ctx *ForExpressionContext) interface{} {
|
func (v *BaseFqlParserVisitor) VisitForExpression(ctx *ForExpressionContext) interface{} {
|
||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
@ -183,11 +191,11 @@ func (v *BaseFqlParserVisitor) VisitNoneLiteral(ctx *NoneLiteralContext) interfa
|
|||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *BaseFqlParserVisitor) VisitExpressionGroup(ctx *ExpressionGroupContext) interface{} {
|
func (v *BaseFqlParserVisitor) VisitExpression(ctx *ExpressionContext) interface{} {
|
||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *BaseFqlParserVisitor) VisitExpression(ctx *ExpressionContext) interface{} {
|
func (v *BaseFqlParserVisitor) VisitExpressionGroup(ctx *ExpressionGroupContext) interface{} {
|
||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +219,10 @@ func (v *BaseFqlParserVisitor) VisitMemberExpressionPath(ctx *MemberExpressionPa
|
|||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *BaseFqlParserVisitor) VisitErrorOperator(ctx *ErrorOperatorContext) interface{} {
|
||||||
|
return v.VisitChildren(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (v *BaseFqlParserVisitor) VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{} {
|
func (v *BaseFqlParserVisitor) VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{} {
|
||||||
return v.VisitChildren(ctx)
|
return v.VisitChildren(ctx)
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,12 @@ type FqlParserListener interface {
|
|||||||
// EnterReturnExpression is called when entering the returnExpression production.
|
// EnterReturnExpression is called when entering the returnExpression production.
|
||||||
EnterReturnExpression(c *ReturnExpressionContext)
|
EnterReturnExpression(c *ReturnExpressionContext)
|
||||||
|
|
||||||
|
// EnterInlineHighLevelExpression is called when entering the inlineHighLevelExpression production.
|
||||||
|
EnterInlineHighLevelExpression(c *InlineHighLevelExpressionContext)
|
||||||
|
|
||||||
|
// EnterHighLevelExpression is called when entering the highLevelExpression production.
|
||||||
|
EnterHighLevelExpression(c *HighLevelExpressionContext)
|
||||||
|
|
||||||
// EnterForExpression is called when entering the forExpression production.
|
// EnterForExpression is called when entering the forExpression production.
|
||||||
EnterForExpression(c *ForExpressionContext)
|
EnterForExpression(c *ForExpressionContext)
|
||||||
|
|
||||||
@ -139,12 +145,12 @@ type FqlParserListener interface {
|
|||||||
// EnterNoneLiteral is called when entering the noneLiteral production.
|
// EnterNoneLiteral is called when entering the noneLiteral production.
|
||||||
EnterNoneLiteral(c *NoneLiteralContext)
|
EnterNoneLiteral(c *NoneLiteralContext)
|
||||||
|
|
||||||
// EnterExpressionGroup is called when entering the expressionGroup production.
|
|
||||||
EnterExpressionGroup(c *ExpressionGroupContext)
|
|
||||||
|
|
||||||
// EnterExpression is called when entering the expression production.
|
// EnterExpression is called when entering the expression production.
|
||||||
EnterExpression(c *ExpressionContext)
|
EnterExpression(c *ExpressionContext)
|
||||||
|
|
||||||
|
// EnterExpressionGroup is called when entering the expressionGroup production.
|
||||||
|
EnterExpressionGroup(c *ExpressionGroupContext)
|
||||||
|
|
||||||
// EnterMemberExpression is called when entering the memberExpression production.
|
// EnterMemberExpression is called when entering the memberExpression production.
|
||||||
EnterMemberExpression(c *MemberExpressionContext)
|
EnterMemberExpression(c *MemberExpressionContext)
|
||||||
|
|
||||||
@ -160,6 +166,9 @@ type FqlParserListener interface {
|
|||||||
// EnterMemberExpressionPath is called when entering the memberExpressionPath production.
|
// EnterMemberExpressionPath is called when entering the memberExpressionPath production.
|
||||||
EnterMemberExpressionPath(c *MemberExpressionPathContext)
|
EnterMemberExpressionPath(c *MemberExpressionPathContext)
|
||||||
|
|
||||||
|
// EnterErrorOperator is called when entering the errorOperator production.
|
||||||
|
EnterErrorOperator(c *ErrorOperatorContext)
|
||||||
|
|
||||||
// EnterFunctionIdentifier is called when entering the functionIdentifier production.
|
// EnterFunctionIdentifier is called when entering the functionIdentifier production.
|
||||||
EnterFunctionIdentifier(c *FunctionIdentifierContext)
|
EnterFunctionIdentifier(c *FunctionIdentifierContext)
|
||||||
|
|
||||||
@ -235,6 +244,12 @@ type FqlParserListener interface {
|
|||||||
// ExitReturnExpression is called when exiting the returnExpression production.
|
// ExitReturnExpression is called when exiting the returnExpression production.
|
||||||
ExitReturnExpression(c *ReturnExpressionContext)
|
ExitReturnExpression(c *ReturnExpressionContext)
|
||||||
|
|
||||||
|
// ExitInlineHighLevelExpression is called when exiting the inlineHighLevelExpression production.
|
||||||
|
ExitInlineHighLevelExpression(c *InlineHighLevelExpressionContext)
|
||||||
|
|
||||||
|
// ExitHighLevelExpression is called when exiting the highLevelExpression production.
|
||||||
|
ExitHighLevelExpression(c *HighLevelExpressionContext)
|
||||||
|
|
||||||
// ExitForExpression is called when exiting the forExpression production.
|
// ExitForExpression is called when exiting the forExpression production.
|
||||||
ExitForExpression(c *ForExpressionContext)
|
ExitForExpression(c *ForExpressionContext)
|
||||||
|
|
||||||
@ -337,12 +352,12 @@ type FqlParserListener interface {
|
|||||||
// ExitNoneLiteral is called when exiting the noneLiteral production.
|
// ExitNoneLiteral is called when exiting the noneLiteral production.
|
||||||
ExitNoneLiteral(c *NoneLiteralContext)
|
ExitNoneLiteral(c *NoneLiteralContext)
|
||||||
|
|
||||||
// ExitExpressionGroup is called when exiting the expressionGroup production.
|
|
||||||
ExitExpressionGroup(c *ExpressionGroupContext)
|
|
||||||
|
|
||||||
// ExitExpression is called when exiting the expression production.
|
// ExitExpression is called when exiting the expression production.
|
||||||
ExitExpression(c *ExpressionContext)
|
ExitExpression(c *ExpressionContext)
|
||||||
|
|
||||||
|
// ExitExpressionGroup is called when exiting the expressionGroup production.
|
||||||
|
ExitExpressionGroup(c *ExpressionGroupContext)
|
||||||
|
|
||||||
// ExitMemberExpression is called when exiting the memberExpression production.
|
// ExitMemberExpression is called when exiting the memberExpression production.
|
||||||
ExitMemberExpression(c *MemberExpressionContext)
|
ExitMemberExpression(c *MemberExpressionContext)
|
||||||
|
|
||||||
@ -358,6 +373,9 @@ type FqlParserListener interface {
|
|||||||
// ExitMemberExpressionPath is called when exiting the memberExpressionPath production.
|
// ExitMemberExpressionPath is called when exiting the memberExpressionPath production.
|
||||||
ExitMemberExpressionPath(c *MemberExpressionPathContext)
|
ExitMemberExpressionPath(c *MemberExpressionPathContext)
|
||||||
|
|
||||||
|
// ExitErrorOperator is called when exiting the errorOperator production.
|
||||||
|
ExitErrorOperator(c *ErrorOperatorContext)
|
||||||
|
|
||||||
// ExitFunctionIdentifier is called when exiting the functionIdentifier production.
|
// ExitFunctionIdentifier is called when exiting the functionIdentifier production.
|
||||||
ExitFunctionIdentifier(c *FunctionIdentifierContext)
|
ExitFunctionIdentifier(c *FunctionIdentifierContext)
|
||||||
|
|
||||||
|
@ -37,6 +37,12 @@ type FqlParserVisitor interface {
|
|||||||
// Visit a parse tree produced by FqlParser#returnExpression.
|
// Visit a parse tree produced by FqlParser#returnExpression.
|
||||||
VisitReturnExpression(ctx *ReturnExpressionContext) interface{}
|
VisitReturnExpression(ctx *ReturnExpressionContext) interface{}
|
||||||
|
|
||||||
|
// Visit a parse tree produced by FqlParser#inlineHighLevelExpression.
|
||||||
|
VisitInlineHighLevelExpression(ctx *InlineHighLevelExpressionContext) interface{}
|
||||||
|
|
||||||
|
// Visit a parse tree produced by FqlParser#highLevelExpression.
|
||||||
|
VisitHighLevelExpression(ctx *HighLevelExpressionContext) interface{}
|
||||||
|
|
||||||
// Visit a parse tree produced by FqlParser#forExpression.
|
// Visit a parse tree produced by FqlParser#forExpression.
|
||||||
VisitForExpression(ctx *ForExpressionContext) interface{}
|
VisitForExpression(ctx *ForExpressionContext) interface{}
|
||||||
|
|
||||||
@ -139,12 +145,12 @@ type FqlParserVisitor interface {
|
|||||||
// Visit a parse tree produced by FqlParser#noneLiteral.
|
// Visit a parse tree produced by FqlParser#noneLiteral.
|
||||||
VisitNoneLiteral(ctx *NoneLiteralContext) interface{}
|
VisitNoneLiteral(ctx *NoneLiteralContext) interface{}
|
||||||
|
|
||||||
// Visit a parse tree produced by FqlParser#expressionGroup.
|
|
||||||
VisitExpressionGroup(ctx *ExpressionGroupContext) interface{}
|
|
||||||
|
|
||||||
// Visit a parse tree produced by FqlParser#expression.
|
// Visit a parse tree produced by FqlParser#expression.
|
||||||
VisitExpression(ctx *ExpressionContext) interface{}
|
VisitExpression(ctx *ExpressionContext) interface{}
|
||||||
|
|
||||||
|
// Visit a parse tree produced by FqlParser#expressionGroup.
|
||||||
|
VisitExpressionGroup(ctx *ExpressionGroupContext) interface{}
|
||||||
|
|
||||||
// Visit a parse tree produced by FqlParser#memberExpression.
|
// Visit a parse tree produced by FqlParser#memberExpression.
|
||||||
VisitMemberExpression(ctx *MemberExpressionContext) interface{}
|
VisitMemberExpression(ctx *MemberExpressionContext) interface{}
|
||||||
|
|
||||||
@ -160,6 +166,9 @@ type FqlParserVisitor interface {
|
|||||||
// Visit a parse tree produced by FqlParser#memberExpressionPath.
|
// Visit a parse tree produced by FqlParser#memberExpressionPath.
|
||||||
VisitMemberExpressionPath(ctx *MemberExpressionPathContext) interface{}
|
VisitMemberExpressionPath(ctx *MemberExpressionPathContext) interface{}
|
||||||
|
|
||||||
|
// Visit a parse tree produced by FqlParser#errorOperator.
|
||||||
|
VisitErrorOperator(ctx *ErrorOperatorContext) interface{}
|
||||||
|
|
||||||
// Visit a parse tree produced by FqlParser#functionIdentifier.
|
// Visit a parse tree produced by FqlParser#functionIdentifier.
|
||||||
VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{}
|
VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{}
|
||||||
|
|
||||||
|
@ -46,11 +46,9 @@ func NewDefaultWhileIterator(mode WhileMode, predicate WhilePredicate) (Iterator
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (iterator *WhileIterator) Next(ctx context.Context, scope *core.Scope) (*core.Scope, error) {
|
func (iterator *WhileIterator) Next(ctx context.Context, scope *core.Scope) (*core.Scope, error) {
|
||||||
counter := values.NewInt(iterator.pos)
|
|
||||||
|
|
||||||
// if it's Post conditional execution, step in always
|
// if it's Post conditional execution, step in always
|
||||||
// Otherwise, it's not the first iteration
|
// Otherwise, it's not the first iteration
|
||||||
if iterator.mode == WhileModePost || counter > 0 {
|
if iterator.mode == WhileModePost || iterator.pos > 0 {
|
||||||
doNext, err := iterator.predicate(ctx, scope)
|
doNext, err := iterator.predicate(ctx, scope)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -62,6 +60,7 @@ func (iterator *WhileIterator) Next(ctx context.Context, scope *core.Scope) (*co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
counter := values.NewInt(iterator.pos)
|
||||||
iterator.pos++
|
iterator.pos++
|
||||||
|
|
||||||
nextScope := scope.Fork()
|
nextScope := scope.Fork()
|
||||||
|
@ -7,23 +7,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FunctionCallExpression struct {
|
type FunctionCallExpression struct {
|
||||||
src core.SourceMap
|
src core.SourceMap
|
||||||
fun core.Function
|
fun core.Function
|
||||||
ignoreErrors bool
|
args []core.Expression
|
||||||
args []core.Expression
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFunctionCallExpression(
|
func NewFunctionCallExpression(
|
||||||
src core.SourceMap,
|
src core.SourceMap,
|
||||||
fun core.Function,
|
fun core.Function,
|
||||||
ignoreErrors bool,
|
|
||||||
args ...core.Expression,
|
args ...core.Expression,
|
||||||
) (*FunctionCallExpression, error) {
|
) (*FunctionCallExpression, error) {
|
||||||
if fun == nil {
|
if fun == nil {
|
||||||
return nil, core.Error(core.ErrMissedArgument, "function")
|
return nil, core.Error(core.ErrMissedArgument, "function")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &FunctionCallExpression{src, fun, ignoreErrors, args}, nil
|
return &FunctionCallExpression{src, fun, args}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *FunctionCallExpression) Arguments() []core.Expression {
|
func (e *FunctionCallExpression) Arguments() []core.Expression {
|
||||||
@ -31,18 +29,6 @@ func (e *FunctionCallExpression) Arguments() []core.Expression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *FunctionCallExpression) Function() core.Function {
|
func (e *FunctionCallExpression) Function() core.Function {
|
||||||
if e.ignoreErrors {
|
|
||||||
return func(ctx context.Context, args ...core.Value) (core.Value, error) {
|
|
||||||
out, err := e.fun(ctx, args...)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return values.None, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.fun
|
return e.fun
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +49,7 @@ func (e *FunctionCallExpression) Exec(ctx context.Context, scope *core.Scope) (c
|
|||||||
out, err := arg.Exec(ctx, scope)
|
out, err := arg.Exec(ctx, scope)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, e.maybeError(core.SourceError(e.src, err))
|
return values.None, core.SourceError(e.src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
args[idx] = out
|
args[idx] = out
|
||||||
@ -73,17 +59,9 @@ func (e *FunctionCallExpression) Exec(ctx context.Context, scope *core.Scope) (c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return values.None, e.maybeError(core.SourceError(e.src, err))
|
return values.None, core.SourceError(e.src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *FunctionCallExpression) maybeError(err error) error {
|
|
||||||
if !e.ignoreErrors {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -22,7 +22,6 @@ func TestFunctionCallExpression(t *testing.T) {
|
|||||||
|
|
||||||
return values.True, nil
|
return values.True, nil
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
@ -48,7 +47,6 @@ func TestFunctionCallExpression(t *testing.T) {
|
|||||||
|
|
||||||
return values.True, nil
|
return values.True, nil
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
args...,
|
args...,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -75,7 +73,6 @@ func TestFunctionCallExpression(t *testing.T) {
|
|||||||
|
|
||||||
return values.True, nil
|
return values.True, nil
|
||||||
},
|
},
|
||||||
false,
|
|
||||||
args...,
|
args...,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,11 +93,15 @@ func TestFunctionCallExpression(t *testing.T) {
|
|||||||
func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
func(ctx context.Context, args ...core.Value) (value core.Value, e error) {
|
||||||
return values.NewString("booo"), core.ErrNotImplemented
|
return values.NewString("booo"), core.ErrNotImplemented
|
||||||
},
|
},
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
out, err := f.Exec(context.Background(), rootScope.Fork())
|
|
||||||
|
fse, err := expressions.SuppressErrors(f)
|
||||||
|
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
out, err := fse.Exec(context.Background(), rootScope.Fork())
|
||||||
|
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(out.Type().String(), ShouldEqual, types.None.String())
|
So(out.Type().String(), ShouldEqual, types.None.String())
|
||||||
|
32
pkg/runtime/expressions/suppressible.go
Normal file
32
pkg/runtime/expressions/suppressible.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package expressions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SuppressibleExpression struct {
|
||||||
|
exp core.Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
func SuppressErrors(exp core.Expression) (core.Expression, error) {
|
||||||
|
if exp == nil {
|
||||||
|
return nil, core.Error(core.ErrMissedArgument, "expression")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SuppressibleExpression{exp}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (exp *SuppressibleExpression) Exec(ctx context.Context, scope *core.Scope) (core.Value, error) {
|
||||||
|
return exp.Maybe(exp.exp.Exec(ctx, scope))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (exp *SuppressibleExpression) Maybe(value core.Value, err error) (core.Value, error) {
|
||||||
|
if err != nil {
|
||||||
|
return values.None, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
Reference in New Issue
Block a user