Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ziflex committed Nov 8, 2024
1 parent 1145db6 commit 3228399
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 10 deletions.
7 changes: 7 additions & 0 deletions pkg/compiler/compiler_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,10 @@ func BenchmarkForNested(b *testing.B) {
RETURN {[prop]: val}
`)
}

func BenchmarkForTernary(b *testing.B) {
RunBenchmark(b, `
LET foo = FALSE
RETURN foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
`)
}
139 changes: 135 additions & 4 deletions pkg/compiler/compiler_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,15 @@ func TestRegexpOperator(t *testing.T) {
})
}

func TestAllArrayOperator(t *testing.T) {
func TestInOperator(t *testing.T) {
RunUseCases(t, []UseCase{
Case("RETURN 1 IN [1,2,3]", true),
Case("RETURN 4 IN [1,2,3]", false),
Case("RETURN 1 NOT IN [1,2,3]", false),
})
}

func TestArrayAllOperator(t *testing.T) {
RunUseCases(t, []UseCase{
Case("RETURN [1,2,3] ALL IN [1,2,3]", true, "All elements are in"),
})
Expand Down Expand Up @@ -829,21 +837,144 @@ func TestFor(t *testing.T) {
})
}

func TestForTernaryExpression(t *testing.T) {
RunUseCases(t, []UseCase{
CaseArray(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i IN 1..5 RETURN i*2)`,
[]any{2, 4, 6, 8, 10}),
CaseArray(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i IN 1..5 T::FAIL() RETURN i*2)?`,
[]any{}),
CaseArray(`
LET foo = FALSE
RETURN foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)`,
[]any{2, 4, 6, 8, 10}),
CaseArray(`
LET foo = FALSE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL()) : (FOR i IN 1..5 RETURN T::FAIL())?`,
[]any{}),
CaseArray(`
LET foo = TRUE
RETURN foo ? (FOR i IN 1..5 RETURN T::FAIL())? : (FOR i IN 1..5 RETURN T::FAIL())`,
[]any{}),
CaseArray(`
LET foo = FALSE
LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
RETURN res`,
[]any{2, 4, 6, 8, 10}),
Case(`
LET foo = TRUE
LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
RETURN res`,
true),
CaseArray(`
LET foo = FALSE
LET res = foo ? TRUE : (FOR i IN 1..5 RETURN i*2)
RETURN res`,
[]any{2, 4, 6, 8, 10}),
CaseArray(`
LET foo = FALSE
LET res = foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
RETURN res`,
[]any{2, 4, 6, 8, 10}),
CaseArray(`
LET foo = TRUE
LET res = foo ? (FOR i IN 1..5 RETURN i) : (FOR i IN 1..5 RETURN i*2)
RETURN res`,
[]any{1, 2, 3, 4, 5}),
Case(`
LET res = LENGTH((FOR i IN 1..5 RETURN T::FAIL())?) ? TRUE : FALSE
RETURN res`,
false),
Case(`
LET res = (FOR i IN 1..5 RETURN i)? ? TRUE : FALSE
RETURN res
`,
true),
})
}

func TestForWhile(t *testing.T) {
var counter int64
var untilCounter int
counter := -1
RunUseCases(t, []UseCase{
CaseArray("FOR i WHILE false RETURN i", []any{}),
CaseArray("FOR i WHILE UNTIL(5) RETURN i", []any{0, 1, 2, 3, 4}),
CaseArray(`
FOR i WHILE COUNTER() < 5
LET y = i + 1
FOR x IN 1..y
RETURN i * x
`, []any{0, 1, 2, 2, 4, 6, 3, 6, 9, 12, 4, 8, 12, 16, 20}),
}, runtime.WithFunctions(map[string]core.Function{
"UNTIL": func(ctx context.Context, args ...core.Value) (core.Value, error) {
if counter < int64(values.ToInt(args[0])) {
counter++
if untilCounter < int(values.ToInt(args[0])) {
untilCounter++

return values.True, nil
}

return values.False, nil
},
"COUNTER": func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++
return values.NewInt(counter), nil
},
}))
}

func TestForTernaryWhileExpression(t *testing.T) {
counter := -1
RunUseCases(t, []UseCase{
CaseArray(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i WHILE false RETURN i*2)
`, []any{}),
CaseArray(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i WHILE T::FAIL() RETURN i*2)?
`, []any{}),
CaseArray(`
LET foo = FALSE
RETURN foo ? TRUE : (FOR i WHILE COUNTER() < 10 RETURN i*2)`,
[]any{0, 2, 4, 6, 8, 10, 12, 14, 16, 18}),
}, runtime.WithFunctions(map[string]core.Function{
"COUNTER": func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++
return values.NewInt(counter), nil
},
}))
}

func TestForDoWhile(t *testing.T) {
counter := -1
counter2 := -1

RunUseCases(t, []UseCase{
CaseArray(`
FOR i DO WHILE false
RETURN i
`, []any{0}),
CaseArray(`
FOR i DO WHILE COUNTER() < 10
RETURN i`, []any{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
CaseArray(`
FOR i WHILE COUNTER2() < 5
LET y = i + 1
FOR x IN 1..y
RETURN i * x
`, []any{0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 2, 4, 6, 8, 0, 3, 6, 9, 12, 0, 4, 8, 12, 16}),
}, runtime.WithFunctions(map[string]core.Function{
"COUNTER": func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter++
return values.NewInt(counter), nil
},
"COUNTER2": func(ctx context.Context, args ...core.Value) (core.Value, error) {
counter2++
return values.NewInt(counter), nil
},
}))
}

Expand Down
13 changes: 8 additions & 5 deletions pkg/compiler/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ func (v *visitor) VisitForExpressionBody(ctx *fql.ForExpressionBodyContext) inte

func (v *visitor) VisitForExpressionClause(ctx *fql.ForExpressionClauseContext) interface{} {
if c := ctx.LimitClause(); c != nil {
// TODO: Implement
return c.Accept(v)
}

Expand Down Expand Up @@ -902,12 +901,16 @@ func (v *visitor) VisitPredicate(ctx *fql.PredicateContext) interface{} {
// TODO: Implement me
panic(core.Error(core.ErrNotImplemented, "array operator"))
} else if op := ctx.InOperator(); op != nil {
opcode = runtime.OpIn
} else if op := ctx.LikeOperator(); op != nil {
if op.(*fql.LikeOperatorContext).Not() != nil {
opcode = runtime.OpNotLike
if op.Not() == nil {
opcode = runtime.OpIn
} else {
opcode = runtime.OpNotIn
}
} else if op := ctx.LikeOperator(); op != nil {
if op.(*fql.LikeOperatorContext).Not() == nil {
opcode = runtime.OpLike
} else {
opcode = runtime.OpNotLike
}
}

Expand Down
8 changes: 7 additions & 1 deletion pkg/runtime/env_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ func WithParams(params []core.Value) EnvironmentOption {

func WithFunctions(functions map[string]core.Function) EnvironmentOption {
return func(env *Environment) {
env.functions = functions
if env.functions == nil {
env.functions = make(map[string]core.Function)
}

for name, function := range functions {
env.functions[name] = function
}
}
}

Expand Down

0 comments on commit 3228399

Please sign in to comment.