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"`
|
||||
}
|
||||
|
||||
type astMaybeSub struct {
|
||||
Sub *astPipeline `parser:"@@?"`
|
||||
}
|
||||
|
||||
type astCmdArg struct {
|
||||
Literal *astLiteral `parser:"@@"`
|
||||
Ident *string `parser:"| @Ident"`
|
||||
Var *string `parser:"| DOLLAR @Ident"`
|
||||
Sub *astPipeline `parser:"| LP @@ RP"`
|
||||
MaybeSub *astMaybeSub `parser:"| LP @@ RP"`
|
||||
ListOrHash *astListOrHash `parser:"| @@"`
|
||||
Block *astBlock `parser:"| @@"`
|
||||
}
|
||||
|
||||
type astCmd struct {
|
||||
Name string `parser:"@Ident"`
|
||||
Name 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) {
|
||||
if cmd := ec.lookupInvokable(ast.Name); cmd != nil {
|
||||
switch {
|
||||
case ast.Name.Ident != nil:
|
||||
name := *ast.Name.Ident
|
||||
|
||||
// Regular command
|
||||
if cmd := ec.lookupInvokable(name); cmd != nil {
|
||||
return e.evalInvokable(ctx, ec, currentStream, ast, cmd)
|
||||
} else if macro := ec.lookupMacro(ast.Name); macro != nil {
|
||||
} 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
|
||||
}
|
||||
|
||||
return nil, errors.New("unknown command")
|
||||
inv, ok := nameElem.(invokable)
|
||||
if !ok {
|
||||
return nil, errors.New("command is not invokable")
|
||||
}
|
||||
|
||||
return e.evalInvokable(ctx, ec, currentStream, ast, inv)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -143,8 +167,12 @@ func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (objec
|
|||
return v, nil
|
||||
}
|
||||
return nil, nil
|
||||
case n.Sub != nil:
|
||||
return e.evalSub(ctx, ec, n.Sub)
|
||||
case n.MaybeSub != nil:
|
||||
sub := n.MaybeSub.Sub
|
||||
if sub == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return e.evalSub(ctx, ec, sub)
|
||||
case n.ListOrHash != nil:
|
||||
return e.evalListOrHash(ctx, ec, n.ListOrHash)
|
||||
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.
|
||||
// Otherwise, a singleton stream is returned.
|
||||
func asStream(v object) stream {
|
||||
if s, ok := v.(stream); ok {
|
||||
switch s := v.(type) {
|
||||
case stream:
|
||||
return s
|
||||
case listObject:
|
||||
return &listIterStream{list: s}
|
||||
}
|
||||
|
||||
return &singletonStream{t: v}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue