1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-04 10:35:08 +02:00

issue-607: add object(array)Literal into memberExpression (#616)

This commit is contained in:
Vladimir Fetisov 2021-04-19 20:55:24 +03:00 committed by GitHub
parent d9360af487
commit 7601c903d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 573 additions and 444 deletions

View File

@ -3,9 +3,10 @@ package compiler_test
import (
"context"
"fmt"
"testing"
"github.com/MontFerret/ferret/pkg/compiler"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func TestMember(t *testing.T) {
@ -120,6 +121,124 @@ func TestMember(t *testing.T) {
So(string(out), ShouldEqual, `"wsx"`)
})
Convey("ObjectDecl by literal", func() {
c := compiler.New()
p, err := c.Compile(`
RETURN { foo: "bar" }.foo
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `"bar"`)
})
Convey("ObjectDecl by literal passed to func call", func() {
c := compiler.New()
p, err := c.Compile(`
RETURN KEEP_KEYS({first: {second: "third"}}.first, "second")
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `{"second":"third"}`)
})
Convey("ObjectDecl by literal as forSource", func() {
c := compiler.New()
p, err := c.Compile(`
FOR v, k IN {f: {foo: "bar"}}.f
RETURN [k, v]
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `[["foo","bar"]]`)
})
Convey("ObjectDecl by literal as expression", func() {
c := compiler.New()
p, err := c.Compile(`
LET inexp = 1 IN {'foo': [1]}.foo
LET ternaryexp = FALSE ? TRUE : {foo: TRUE}.foo
RETURN inexp && ternaryexp
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})
Convey("ArrayDecl by literal", func() {
c := compiler.New()
p, err := c.Compile(`
RETURN ["bar", "foo"][0]
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `"bar"`)
})
Convey("ArrayDecl by literal passed to func call", func() {
c := compiler.New()
p, err := c.Compile(`
RETURN FIRST([[1, 2]][0])
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `1`)
})
Convey("ArrayDecl by literal as forSource", func() {
c := compiler.New()
p, err := c.Compile(`
FOR i IN [[1, 2]][0]
RETURN i
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `[1,2]`)
})
Convey("ArrayDecl by literal as expression", func() {
c := compiler.New()
p, err := c.Compile(`
LET inexp = 1 IN [[1]][0]
LET ternaryexp = FALSE ? TRUE : [TRUE][0]
RETURN inexp && ternaryexp
`)
So(err, ShouldBeNil)
out, err := p.Run(context.Background())
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})
Convey("Deep path", func() {
c := compiler.New()

View File

@ -46,7 +46,6 @@ func (v *visitor) VisitProgram(ctx *fql.ProgramContext) interface{} {
gs := newGlobalScope()
rs := newRootScope(gs)
block, err := v.doVisitBody(ctx.Body().(*fql.BodyContext), rs)
if err != nil {
return nil, err
}
@ -131,7 +130,6 @@ func (v *visitor) doVisitBody(ctx *fql.BodyContext, scope *scope) (core.Expressi
for _, stmt := range statements {
e, err := v.doVisitBodyStatement(stmt.(*fql.BodyStatementContext), scope)
if err != nil {
return nil, err
}
@ -143,7 +141,6 @@ func (v *visitor) doVisitBody(ctx *fql.BodyContext, scope *scope) (core.Expressi
if exp != nil {
e, err := v.doVisitBodyExpression(exp.(*fql.BodyExpressionContext), scope)
if err != nil {
return nil, err
}
@ -194,7 +191,6 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
if expCtx != nil {
out, err := v.doVisitExpression(expCtx.(*fql.ExpressionContext), scope)
if err != nil {
return nil, err
}
@ -208,7 +204,6 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
if forIn != nil {
out, err := v.doVisitForExpression(ctx.ForExpression().(*fql.ForExpressionContext), scope.Fork())
if err != nil {
return nil, err
}
@ -222,7 +217,6 @@ func (v *visitor) doVisitReturnExpression(ctx *fql.ReturnExpressionContext, scop
if forInTernary != nil {
out, err := v.doVisitForTernaryExpression(forInTernary.(*fql.ForTernaryExpressionContext), scope)
if err != nil {
return nil, err
}
@ -253,7 +247,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
if !isWhileLoop {
srcCtx := ctx.ForExpressionSource().(*fql.ForExpressionSourceContext)
srcExp, err := v.doVisitForExpressionSource(srcCtx, scope)
if err != nil {
return nil, err
}
@ -271,7 +264,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
} else {
whileExpCtx := ctx.Expression().(*fql.ExpressionContext)
conditionExp, err := v.doVisitExpression(whileExpCtx, scope)
if err != nil {
return nil, err
}
@ -321,7 +313,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
valVarName,
keyVarName,
)
if err != nil {
return nil, err
}
@ -332,7 +323,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
statementCtx.(*fql.ForExpressionStatementContext),
forInScope,
)
if err != nil {
return nil, err
}
@ -350,7 +340,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
if returnCtx != nil {
returnCtx := returnCtx.(*fql.ReturnExpressionContext)
returnExp, err := v.doVisitReturnExpression(returnCtx, forInScope)
if err != nil {
return nil, err
}
@ -365,7 +354,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
} else {
forInCtx := forRetCtx.ForExpression().(*fql.ForExpressionContext)
forInExp, err := v.doVisitForExpression(forInCtx, forInScope)
if err != nil {
return nil, err
}
@ -382,7 +370,6 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
distinct,
spread,
)
if err != nil {
return nil, err
}
@ -434,7 +421,6 @@ func (v *visitor) doVisitLimitClauseValue(ctx *fql.LimitClauseValueContext, scop
if literalCtx != nil {
i, err := strconv.Atoi(literalCtx.GetText())
if err != nil {
return nil, err
}
@ -459,7 +445,6 @@ func (v *visitor) doVisitSortClause(ctx *fql.SortClauseContext, scope *scope) ([
for idx, sortExpCtx := range sortExpCtxs {
sortExpCtx := sortExpCtx.(*fql.SortClauseExpressionContext)
exp, err := v.doVisitExpression(sortExpCtx.Expression().(*fql.ExpressionContext), scope)
if err != nil {
return nil, err
}
@ -475,7 +460,6 @@ func (v *visitor) doVisitSortClause(ctx *fql.SortClauseContext, scope *scope) ([
exp,
direction,
)
if err != nil {
return nil, err
}
@ -506,7 +490,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
for _, cs := range collectSelectors {
selector, err := v.doVisitCollectSelector(cs.(*fql.CollectSelectorContext), scope)
if err != nil {
return nil, err
}
@ -526,7 +509,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
// if projection expression is defined like WITH group = { foo: i.bar }
if projectionSelectorCtx != nil {
selector, err := v.doVisitCollectSelector(projectionSelectorCtx.(*fql.CollectSelectorContext), scope)
if err != nil {
return nil, err
}
@ -538,7 +520,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
if projectionIdentifier != nil {
varExp, err := expressions.NewVariableExpression(v.getSourceMap(projectionCtx), valVarName)
if err != nil {
return nil, err
}
@ -549,7 +530,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
strLitExp,
varExp,
)
if err != nil {
return nil, err
}
@ -557,7 +537,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
projectionSelectorExp := literals.NewObjectLiteralWith(propExp)
selector, err := clauses.NewCollectSelector(projectionIdentifier.GetText(), projectionSelectorExp)
if err != nil {
return nil, err
}
@ -601,7 +580,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
for _, sc := range selectorCtxs {
selector, err := v.doVisitCollectAggregateSelector(sc.(*fql.CollectAggregateSelectorContext), scope)
if err != nil {
return nil, err
}
@ -632,7 +610,6 @@ func (v *visitor) doVisitCollectClause(ctx *fql.CollectClauseContext, scope *sco
func (v *visitor) doVisitCollectSelector(ctx *fql.CollectSelectorContext, scope *scope) (*clauses.CollectSelector, error) {
variable := ctx.Identifier().GetText()
exp, err := v.doVisitExpression(ctx.Expression().(*fql.ExpressionContext), scope)
if err != nil {
return nil, err
}
@ -646,7 +623,6 @@ func (v *visitor) doVisitCollectAggregateSelector(ctx *fql.CollectAggregateSelec
if fnCtx != nil {
exp, err := v.doVisitFunctionCallExpression(fnCtx.(*fql.FunctionCallExpressionContext), scope)
if err != nil {
return nil, err
}
@ -714,7 +690,6 @@ func (v *visitor) doVisitForExpressionClause(ctx *fql.ForExpressionClauseContext
if limitCtx != nil {
limit, offset, err := v.doVisitLimitClause(limitCtx.(*fql.LimitClauseContext), scope)
if err != nil {
return nil, err
}
@ -728,7 +703,6 @@ func (v *visitor) doVisitForExpressionClause(ctx *fql.ForExpressionClauseContext
if filterCtx != nil {
filterExp, err := v.doVisitFilterClause(filterCtx.(*fql.FilterClauseContext), scope)
if err != nil {
return nil, err
}
@ -743,7 +717,6 @@ func (v *visitor) doVisitForExpressionClause(ctx *fql.ForExpressionClauseContext
if sortCtx != nil {
sortCtx := sortCtx.(*fql.SortClauseContext)
sortExps, err := v.doVisitSortClause(sortCtx, scope)
if err != nil {
return nil, err
}
@ -758,7 +731,6 @@ func (v *visitor) doVisitForExpressionClause(ctx *fql.ForExpressionClauseContext
if collectCtx != nil {
collectCtx := collectCtx.(*fql.CollectClauseContext)
params, err := v.doVisitCollectClause(collectCtx, scope, valVarName)
if err != nil {
return nil, err
}
@ -779,7 +751,6 @@ func (v *visitor) doVisitForExpressionStatement(ctx *fql.ForExpressionStatementC
variableCtx.(*fql.VariableDeclarationContext),
scope,
)
if err != nil {
return nil, err
}
@ -796,7 +767,6 @@ func (v *visitor) doVisitForExpressionStatement(ctx *fql.ForExpressionStatementC
fnCallCtx.(*fql.FunctionCallExpressionContext),
scope,
)
if err != nil {
return nil, err
}
@ -811,7 +781,6 @@ func (v *visitor) doVisitForExpressionStatement(ctx *fql.ForExpressionStatementC
func (v *visitor) doVisitMemberExpression(ctx *fql.MemberExpressionContext, scope *scope) (core.Expression, error) {
member, err := v.doVisitMember(ctx.Member().(*fql.MemberContext), scope)
if err != nil {
return nil, err
}
@ -861,7 +830,6 @@ func (v *visitor) doVisitMemberExpression(ctx *fql.MemberExpressionContext, scop
member,
path,
)
if err != nil {
return nil, err
}
@ -880,7 +848,6 @@ func (v *visitor) doVisitMember(ctx *fql.MemberContext, scope *scope) (core.Expr
}
exp, err := expressions.NewVariableExpression(v.getSourceMap(ctx), varName)
if err != nil {
return nil, err
}
@ -892,7 +859,6 @@ func (v *visitor) doVisitMember(ctx *fql.MemberContext, scope *scope) (core.Expr
if fnCall != nil {
exp, err := v.doVisitFunctionCallExpression(fnCall.(*fql.FunctionCallExpressionContext), scope)
if err != nil {
return nil, err
}
@ -902,13 +868,38 @@ func (v *visitor) doVisitMember(ctx *fql.MemberContext, scope *scope) (core.Expr
param := ctx.Param()
exp, err := v.doVisitParamContext(param.(*fql.ParamContext), scope)
if param != nil {
exp, err := v.doVisitParamContext(param.(*fql.ParamContext), scope)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
return exp, nil
}
return exp, nil
objectLiteral := ctx.ObjectLiteral()
if objectLiteral != nil {
exp, err := v.doVisitObjectLiteral(objectLiteral.(*fql.ObjectLiteralContext), scope)
if err != nil {
return nil, err
}
return exp, nil
}
arrayLiteral := ctx.ArrayLiteral()
if arrayLiteral != nil {
exp, err := v.doVisitArrayLiteral(arrayLiteral.(*fql.ArrayLiteralContext), scope)
if err != nil {
return nil, err
}
return exp, nil
}
return nil, core.ErrNotImplemented
}
func (v *visitor) doVisitObjectLiteral(ctx *fql.ObjectLiteralContext, scope *scope) (core.Expression, error) {
@ -950,7 +941,6 @@ func (v *visitor) doVisitObjectLiteral(ctx *fql.ObjectLiteralContext, scope *sco
}
pa, err := literals.NewObjectPropertyAssignment(name, value)
if err != nil {
return nil, err
}
@ -976,7 +966,6 @@ func (v *visitor) doVisitPropertyNameContext(ctx *fql.PropertyNameContext, scope
name = string(runes[1 : len(runes)-1])
} else {
param, err := v.doVisitParamContext(ctx.Param().(*fql.ParamContext), scope)
if err != nil {
return nil, err
}
@ -1019,7 +1008,6 @@ func (v *visitor) doVisitArrayLiteral(ctx *fql.ArrayLiteralContext, scope *scope
for _, e := range exp {
element, err := v.visit(e, scope)
if err != nil {
return nil, err
}
@ -1032,7 +1020,6 @@ func (v *visitor) doVisitArrayLiteral(ctx *fql.ArrayLiteralContext, scope *scope
func (v *visitor) doVisitFloatLiteral(ctx *fql.FloatLiteralContext) (core.Expression, error) {
val, err := strconv.ParseFloat(ctx.GetText(), 64)
if err != nil {
return nil, err
}
@ -1042,7 +1029,6 @@ func (v *visitor) doVisitFloatLiteral(ctx *fql.FloatLiteralContext) (core.Expres
func (v *visitor) doVisitIntegerLiteral(ctx *fql.IntegerLiteralContext) (core.Expression, error) {
val, err := strconv.Atoi(ctx.GetText())
if err != nil {
return nil, err
}
@ -1128,7 +1114,6 @@ func (v *visitor) doVisitVariableDeclaration(ctx *fql.VariableDeclarationContext
func (v *visitor) doVisitRangeOperator(ctx *fql.RangeOperatorContext, scope *scope) (core.Expression, error) {
exp, err := v.doVisitChildren(ctx, scope)
if err != nil {
return nil, err
}
@ -1156,7 +1141,6 @@ func (v *visitor) doVisitFunctionCallExpression(context *fql.FunctionCallExpress
for _, arg := range argsCtx.AllExpression() {
exp, err := v.doVisitExpression(arg.(*fql.ExpressionContext), scope)
if err != nil {
return nil, err
}
@ -1204,7 +1188,6 @@ func (v *visitor) doVisitAllExpressions(contexts []fql.IExpressionContext, scope
for _, ctx := range contexts {
exp, err := v.doVisitExpression(ctx.(*fql.ExpressionContext), scope)
if err != nil {
return nil, err
}
@ -1232,7 +1215,6 @@ func (v *visitor) doVisitMathOperator(ctx *fql.ExpressionContext, scope *scope)
}
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1250,7 +1232,6 @@ func (v *visitor) doVisitMathOperator(ctx *fql.ExpressionContext, scope *scope)
func (v *visitor) doVisitUnaryOperator(ctx *fql.ExpressionContext, op *fql.UnaryOperatorContext, scope *scope) (core.OperatorExpression, error) {
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1282,7 +1263,6 @@ func (v *visitor) doVisitLogicalOperator(ctx *fql.ExpressionContext, scope *scop
}
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1295,7 +1275,6 @@ func (v *visitor) doVisitLogicalOperator(ctx *fql.ExpressionContext, scope *scop
func (v *visitor) doVisitEqualityOperator(ctx *fql.ExpressionContext, op *fql.EqualityOperatorContext, scope *scope) (core.OperatorExpression, error) {
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1309,7 +1288,6 @@ func (v *visitor) doVisitEqualityOperator(ctx *fql.ExpressionContext, op *fql.Eq
func (v *visitor) doVisitRegexpOperator(ctx *fql.ExpressionContext, op *fql.RegexpOperatorContext, scope *scope) (core.Expression, error) {
rawExps := ctx.AllExpression()
exps, err := v.doVisitAllExpressions(rawExps, scope)
if err != nil {
return nil, err
}
@ -1320,7 +1298,6 @@ func (v *visitor) doVisitRegexpOperator(ctx *fql.ExpressionContext, op *fql.Rege
switch lit := right.(type) {
case literals.StringLiteral:
_, err := regexp.Compile(string(lit))
if err != nil {
src := v.getSourceMap(rawExps[1])
@ -1337,7 +1314,6 @@ func (v *visitor) doVisitRegexpOperator(ctx *fql.ExpressionContext, op *fql.Rege
func (v *visitor) doVisitInOperator(ctx *fql.ExpressionContext, scope *scope) (core.OperatorExpression, error) {
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1361,7 +1337,6 @@ func (v *visitor) doVisitInOperator(ctx *fql.ExpressionContext, scope *scope) (c
func (v *visitor) doVisitLikeOperator(ctx *fql.ExpressionContext, op *fql.LikeOperatorContext, s *scope) (core.Expression, error) {
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), s)
if err != nil {
return nil, err
}
@ -1389,7 +1364,6 @@ func (v *visitor) doVisitArrayOperator(ctx *fql.ExpressionContext, scope *scope)
}
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1402,7 +1376,6 @@ func (v *visitor) doVisitArrayOperator(ctx *fql.ExpressionContext, scope *scope)
right := exps[1]
aotype, err := operators.ToIsValidArrayOperatorType(ctx.ArrayOperator().GetText())
if err != nil {
return nil, err
}
@ -1480,6 +1453,7 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
}
if exp := ctx.Variable(); exp != nil {
fmt.Println("HEHRE")
return v.doVisitVariable(exp.(*fql.VariableContext), scope)
}
@ -1513,7 +1487,6 @@ func (v *visitor) doVisitExpression(ctx *fql.ExpressionContext, scope *scope) (c
if exp := ctx.QuestionMark(); exp != nil {
exps, err := v.doVisitAllExpressions(ctx.AllExpression(), scope)
if err != nil {
return nil, err
}
@ -1553,7 +1526,6 @@ func (v *visitor) doVisitChildren(node antlr.RuleNode, scope *scope) ([]core.Exp
}
out, err := v.visit(child, scope)
if err != nil {
return nil, err
}
@ -1608,7 +1580,6 @@ func (v *visitor) visit(node antlr.Tree, scope *scope) (core.Expression, error)
func (v *visitor) doVisitForTernaryExpression(ctx *fql.ForTernaryExpressionContext, scope *scope) (*expressions.ConditionExpression, error) {
exps, err := v.doVisitChildren(ctx, scope)
if err != nil {
return nil, err
}

View File

@ -1,3 +1,5 @@
// $antlr-format off <-- used by VS Code Antlr extension
parser grammar FqlParser;
options { tokenVocab=FqlLexer; }
@ -262,6 +264,8 @@ member
: Identifier
| functionCallExpression
| param
| objectLiteral
| arrayLiteral
;
memberPath

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
// Code generated from antlr/FqlLexer.g4 by ANTLR 4.9.1. DO NOT EDIT.
// Code generated from antlr/FqlLexer.g4 by ANTLR 4.9.2. DO NOT EDIT.
package fql

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.1. DO NOT EDIT.
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.2. DO NOT EDIT.
package fql // FqlParser
import "github.com/antlr/antlr4/runtime/Go/antlr"

View File

@ -1,4 +1,4 @@
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.1. DO NOT EDIT.
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.2. DO NOT EDIT.
package fql // FqlParser
import "github.com/antlr/antlr4/runtime/Go/antlr"

View File

@ -1,4 +1,4 @@
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.1. DO NOT EDIT.
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.2. DO NOT EDIT.
package fql // FqlParser
import "github.com/antlr/antlr4/runtime/Go/antlr"

View File

@ -1,4 +1,4 @@
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.1. DO NOT EDIT.
// Code generated from antlr/FqlParser.g4 by ANTLR 4.9.2. DO NOT EDIT.
package fql // FqlParser
import "github.com/antlr/antlr4/runtime/Go/antlr"