Add expr.ExperimentalPipes() config

This commit is contained in:
Anton Medvedev
2023-08-15 15:39:59 +02:00
parent 9454bc646c
commit bac96c2c29
6 changed files with 35 additions and 8 deletions
+1
View File
@@ -22,6 +22,7 @@ type Config struct {
ConstFns map[string]reflect.Value
Visitors []ast.Visitor
Functions map[string]*builtin.Function
Pipes bool
}
// CreateNew creates new config with default values.
+12 -1
View File
@@ -130,6 +130,13 @@ func Function(name string, fn func(params ...interface{}) (interface{}, error),
}
}
// ExperimentalPipes enables pipes syntax.
func ExperimentalPipes() Option {
return func(c *conf.Config) {
c.Pipes = true
}
}
// Compile parses and compiles given input expression to bytecode program.
func Compile(input string, ops ...Option) (*vm.Program, error) {
config := conf.CreateNew()
@@ -146,7 +153,11 @@ func Compile(input string, ops ...Option) (*vm.Program, error) {
})
}
tree, err := parser.Parse(input)
parseConfig := parser.Config{
Pipes: config.Pipes,
}
tree, err := parser.ParseWithConfig(input, parseConfig)
if err != nil {
return nil, err
}
+15
View File
@@ -77,6 +77,7 @@ type parser struct {
pos int
err *file.Error
depth int // closure call depth
pipes bool
}
type Tree struct {
@@ -84,7 +85,15 @@ type Tree struct {
Source *file.Source
}
type Config struct {
Pipes bool
}
func Parse(input string) (*Tree, error) {
return ParseWithConfig(input, Config{})
}
func ParseWithConfig(input string, config Config) (*Tree, error) {
source := file.NewSource(input)
tokens, err := Lex(source)
@@ -95,6 +104,7 @@ func Parse(input string) (*Tree, error) {
p := &parser{
tokens: tokens,
current: tokens[0],
pipes: config.Pipes,
}
node := p.parseExpression(0)
@@ -592,6 +602,11 @@ func (p *parser) parsePostfixExpression(node Node) Node {
}
func (p *parser) parsePipe(node Node) Node {
if !p.pipes {
p.error("enable Pipes via expr.ExperimentalPipes()")
return &NilNode{}
}
identifier := p.current
p.expect(Identifier)
+2 -2
View File
@@ -453,7 +453,7 @@ func TestParse(t *testing.T) {
&BoolNode{Value: true}}}},
}
for _, test := range parseTests {
actual, err := parser.Parse(test.input)
actual, err := parser.ParseWithConfig(test.input, parser.Config{Pipes: true})
if err != nil {
t.Errorf("%s:\n%v", test.input, err)
continue
@@ -657,7 +657,7 @@ func TestParse_pipe_operator(t *testing.T) {
Property: &StringNode{Value: "foo"},
}}}}}}}}
actual, err := parser.Parse(input)
actual, err := parser.ParseWithConfig(input, parser.Config{Pipes: true})
require.NoError(t, err)
assert.Equal(t, Dump(expect), Dump(actual.Node))
}
+2 -2
View File
@@ -37,7 +37,7 @@ func TestPipes(t *testing.T) {
for _, test := range tests {
t.Run(test.input, func(t *testing.T) {
program, err := expr.Compile(test.input, expr.Env(env))
program, err := expr.Compile(test.input, expr.Env(env), expr.ExperimentalPipes())
require.NoError(t, err)
out, err := expr.Run(program, env)
@@ -48,7 +48,7 @@ func TestPipes(t *testing.T) {
}
func TestPipes_map_filter(t *testing.T) {
program, err := expr.Compile(`1..9 | map(# + 1) | filter(# % 2 == 0)`)
program, err := expr.Compile(`1..9 | map(# + 1) | filter(# % 2 == 0)`, expr.ExperimentalPipes())
require.NoError(t, err)
out, err := expr.Run(program, nil)
+3 -3
View File
@@ -120,15 +120,15 @@ func TestTime_date(t *testing.T) {
want time.Time
}{
{
`'2017-10-23' | date()`,
`date('2017-10-23')`,
time.Date(2017, 10, 23, 0, 0, 0, 0, time.UTC),
},
{
`'24.11.1987 20:30' | date("02.01.2006 15:04", "Europe/Zurich")`,
`date('24.11.1987 20:30', "02.01.2006 15:04", "Europe/Zurich")`,
time.Date(1987, 11, 24, 20, 30, 0, 0, time.FixedZone("Europe/Zurich", 3600)),
},
{
`'24.11.1987 20:30 MSK' | date("02.01.2006 15:04 MST", "Europe/Zurich")`,
`date('24.11.1987 20:30 MSK', "02.01.2006 15:04 MST", "Europe/Zurich")`,
time.Date(1987, 11, 24, 20, 30, 0, 0, time.FixedZone("MSK", 0)),
},
}