Added the ability to use single values as the first argument
This commit is contained in:
parent
4b91bff641
commit
1cf10478e2
|
@ -34,17 +34,21 @@ type astBlock struct {
|
||||||
Statements []*astStatements `parser:"@@ NL? RC"`
|
Statements []*astStatements `parser:"@@ NL? RC"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type astMaybeSub struct {
|
||||||
|
Sub *astPipeline `parser:"@@?"`
|
||||||
|
}
|
||||||
|
|
||||||
type astCmdArg struct {
|
type astCmdArg struct {
|
||||||
Literal *astLiteral `parser:"@@"`
|
Literal *astLiteral `parser:"@@"`
|
||||||
Ident *string `parser:"| @Ident"`
|
Ident *string `parser:"| @Ident"`
|
||||||
Var *string `parser:"| DOLLAR @Ident"`
|
Var *string `parser:"| DOLLAR @Ident"`
|
||||||
Sub *astPipeline `parser:"| LP @@ RP"`
|
MaybeSub *astMaybeSub `parser:"| LP @@ RP"`
|
||||||
ListOrHash *astListOrHash `parser:"| @@"`
|
ListOrHash *astListOrHash `parser:"| @@"`
|
||||||
Block *astBlock `parser:"| @@"`
|
Block *astBlock `parser:"| @@"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type astCmd struct {
|
type astCmd struct {
|
||||||
Name string `parser:"@Ident"`
|
Name astCmdArg `parser:"@@"`
|
||||||
Args []astCmdArg `parser:"@@*"`
|
Args []astCmdArg `parser:"@@*"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,37 @@ func (e evaluator) evalPipeline(ctx context.Context, ec *evalCtx, n *astPipeline
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentStream stream, ast *astCmd) (object, error) {
|
func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentStream stream, ast *astCmd) (object, error) {
|
||||||
if cmd := ec.lookupInvokable(ast.Name); cmd != nil {
|
switch {
|
||||||
return e.evalInvokable(ctx, ec, currentStream, ast, cmd)
|
case ast.Name.Ident != nil:
|
||||||
} else if macro := ec.lookupMacro(ast.Name); macro != nil {
|
name := *ast.Name.Ident
|
||||||
return e.evalMacro(ctx, ec, currentStream, ast, macro)
|
|
||||||
|
// Regular command
|
||||||
|
if cmd := ec.lookupInvokable(name); cmd != nil {
|
||||||
|
return e.evalInvokable(ctx, ec, currentStream, ast, cmd)
|
||||||
|
} else if macro := ec.lookupMacro(name); macro != nil {
|
||||||
|
return e.evalMacro(ctx, ec, currentStream, ast, macro)
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("unknown command")
|
||||||
|
}
|
||||||
|
case len(ast.Args) > 0:
|
||||||
|
nameElem, err := e.evalArg(ctx, ec, ast.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inv, ok := nameElem.(invokable)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("command is not invokable")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.evalInvokable(ctx, ec, currentStream, ast, inv)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unknown command")
|
nameElem, err := e.evalArg(ctx, ec, ast.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nameElem, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e evaluator) evalInvokable(ctx context.Context, ec *evalCtx, currentStream stream, ast *astCmd, cmd invokable) (object, error) {
|
func (e evaluator) evalInvokable(ctx context.Context, ec *evalCtx, currentStream stream, ast *astCmd, cmd invokable) (object, error) {
|
||||||
|
@ -143,8 +167,12 @@ func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (objec
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case n.Sub != nil:
|
case n.MaybeSub != nil:
|
||||||
return e.evalSub(ctx, ec, n.Sub)
|
sub := n.MaybeSub.Sub
|
||||||
|
if sub == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return e.evalSub(ctx, ec, sub)
|
||||||
case n.ListOrHash != nil:
|
case n.ListOrHash != nil:
|
||||||
return e.evalListOrHash(ctx, ec, n.ListOrHash)
|
return e.evalListOrHash(ctx, ec, n.ListOrHash)
|
||||||
case n.Block != nil:
|
case n.Block != nil:
|
||||||
|
|
|
@ -47,9 +47,13 @@ func forEach(s stream, f func(object, int) error) (err error) {
|
||||||
// asStream converts an object to a stream. If t is already a stream, it's returned as is.
|
// asStream converts an object to a stream. If t is already a stream, it's returned as is.
|
||||||
// Otherwise, a singleton stream is returned.
|
// Otherwise, a singleton stream is returned.
|
||||||
func asStream(v object) stream {
|
func asStream(v object) stream {
|
||||||
if s, ok := v.(stream); ok {
|
switch s := v.(type) {
|
||||||
|
case stream:
|
||||||
return s
|
return s
|
||||||
|
case listObject:
|
||||||
|
return &listIterStream{list: s}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &singletonStream{t: v}
|
return &singletonStream{t: v}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue