This commit is contained in:
parent
0f1ceba090
commit
51e35aa9a6
|
@ -105,7 +105,8 @@ type astDot struct {
|
|||
type astCmd struct {
|
||||
Pos lexer.Position
|
||||
Name astDot `parser:"@@"`
|
||||
Args []astDot `parser:"@@*"`
|
||||
Assign *astDot `parser:"( EQ @@"`
|
||||
InvokeArgs []astDot `parser:" | @@+ )?"`
|
||||
}
|
||||
|
||||
type astPipeline struct {
|
||||
|
@ -141,6 +142,7 @@ var scanner = lexer.MustStateful(lexer.Rules{
|
|||
{"RC", `\}`, nil},
|
||||
{"NL", `[;\n][; \n\t]*`, nil},
|
||||
{"PIPE", `\|`, nil},
|
||||
{"EQ", `=`, nil},
|
||||
{"Ident", `[-]*[a-zA-Z_][\w-!?]*`, nil},
|
||||
},
|
||||
"String": {
|
||||
|
|
54
ucl/eval.go
54
ucl/eval.go
|
@ -72,6 +72,14 @@ func (e evaluator) evalPipeline(ctx context.Context, ec *evalCtx, n *astPipeline
|
|||
|
||||
func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe Object, ast *astCmd) (Object, error) {
|
||||
switch {
|
||||
case ast.Assign != nil:
|
||||
// Assignment
|
||||
assignVal, err := e.evalDot(ctx, ec, *ast.Assign)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return e.assignDot(ctx, ec, ast.Assign, assignVal)
|
||||
case (ast.Name.Arg.Ident != nil) && len(ast.Name.DotSuffix) == 0:
|
||||
name := ast.Name.Arg.Ident.String()
|
||||
|
||||
|
@ -85,7 +93,7 @@ func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe Object,
|
|||
} else {
|
||||
return nil, errors.New("unknown command: " + name)
|
||||
}
|
||||
case len(ast.Args) > 0:
|
||||
case len(ast.InvokeArgs) > 0:
|
||||
nameElem, err := e.evalDot(ctx, ec, ast.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -117,7 +125,7 @@ func (e evaluator) evalInvokable(ctx context.Context, ec *evalCtx, currentPipe O
|
|||
if currentPipe != nil {
|
||||
argsPtr.Append(currentPipe)
|
||||
}
|
||||
for _, arg := range ast.Args {
|
||||
for _, arg := range ast.InvokeArgs {
|
||||
if ident := arg.Arg.Ident; len(arg.DotSuffix) == 0 && ident != nil && ident.String()[0] == '-' {
|
||||
// Arg switch
|
||||
if kwargs == nil {
|
||||
|
@ -176,6 +184,14 @@ func (e evaluator) evalDot(ctx context.Context, ec *evalCtx, n astDot) (Object,
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (e evaluator) assignDot(ctx context.Context, ec *evalCtx, n *astDot, toVal Object) (Object, error) {
|
||||
if len(n.DotSuffix) == 0 {
|
||||
return e.assignArg(ctx, ec, n.Arg, toVal)
|
||||
}
|
||||
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (Object, error) {
|
||||
switch {
|
||||
case n.Literal != nil:
|
||||
|
@ -211,6 +227,40 @@ func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (Objec
|
|||
return nil, errors.New("unhandled arg type")
|
||||
}
|
||||
|
||||
func (e evaluator) assignArg(ctx context.Context, ec *evalCtx, n astCmdArg, toVal Object) (Object, error) {
|
||||
switch {
|
||||
case n.Literal != nil:
|
||||
// We may use this for variable setting?
|
||||
return nil, errors.New("cannot assign to a literal")
|
||||
case n.Var != nil:
|
||||
ec.setOrDefineVar(*n.Var, toVal)
|
||||
return toVal, nil
|
||||
case n.PseudoVar != nil:
|
||||
pvar, ok := ec.getPseudoVar(*n.PseudoVar)
|
||||
if ok {
|
||||
if err := pvar.set(ctx, *n.PseudoVar, toVal); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toVal, nil
|
||||
}
|
||||
|
||||
if pvar := e.inst.missingPseudoVarHandler; pvar != nil {
|
||||
if err := pvar.set(ctx, *n.PseudoVar, toVal); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toVal, nil
|
||||
}
|
||||
return nil, errors.New("unknown pseudo-variable: " + *n.Var)
|
||||
case n.MaybeSub != nil:
|
||||
return nil, errors.New("cannot assign to a subexpression")
|
||||
case n.ListOrHash != nil:
|
||||
return nil, errors.New("cannot assign to a list or hash")
|
||||
case n.Block != nil:
|
||||
return nil, errors.New("cannot assign to a block")
|
||||
}
|
||||
return nil, errors.New("unhandled arg type")
|
||||
}
|
||||
|
||||
func (e evaluator) evalListOrHash(ctx context.Context, ec *evalCtx, loh *astListOrHash) (Object, error) {
|
||||
if loh.EmptyList {
|
||||
return &ListObject{}, nil
|
||||
|
|
18
ucl/objs.go
18
ucl/objs.go
|
@ -279,7 +279,7 @@ type macroArgs struct {
|
|||
}
|
||||
|
||||
func (ma macroArgs) nargs() int {
|
||||
return len(ma.ast.Args[ma.argShift:])
|
||||
return len(ma.ast.InvokeArgs[ma.argShift:])
|
||||
}
|
||||
|
||||
func (ma *macroArgs) shift(n int) {
|
||||
|
@ -287,15 +287,15 @@ func (ma *macroArgs) shift(n int) {
|
|||
}
|
||||
|
||||
func (ma macroArgs) identIs(ctx context.Context, n int, expectedIdent string) bool {
|
||||
if n >= len(ma.ast.Args[ma.argShift:]) {
|
||||
if n >= len(ma.ast.InvokeArgs[ma.argShift:]) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(ma.ast.Args[ma.argShift+n].DotSuffix) != 0 {
|
||||
if len(ma.ast.InvokeArgs[ma.argShift+n].DotSuffix) != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
lit := ma.ast.Args[ma.argShift+n].Arg.Ident
|
||||
lit := ma.ast.InvokeArgs[ma.argShift+n].Arg.Ident
|
||||
if lit == nil {
|
||||
return false
|
||||
}
|
||||
|
@ -304,15 +304,15 @@ func (ma macroArgs) identIs(ctx context.Context, n int, expectedIdent string) bo
|
|||
}
|
||||
|
||||
func (ma *macroArgs) shiftIdent(ctx context.Context) (string, bool) {
|
||||
if ma.argShift >= len(ma.ast.Args) {
|
||||
if ma.argShift >= len(ma.ast.InvokeArgs) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if len(ma.ast.Args[ma.argShift].DotSuffix) != 0 {
|
||||
if len(ma.ast.InvokeArgs[ma.argShift].DotSuffix) != 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
lit := ma.ast.Args[ma.argShift].Arg.Ident
|
||||
lit := ma.ast.InvokeArgs[ma.argShift].Arg.Ident
|
||||
if lit != nil {
|
||||
ma.argShift += 1
|
||||
return lit.String(), true
|
||||
|
@ -321,11 +321,11 @@ func (ma *macroArgs) shiftIdent(ctx context.Context) (string, bool) {
|
|||
}
|
||||
|
||||
func (ma macroArgs) evalArg(ctx context.Context, n int) (Object, error) {
|
||||
if n >= len(ma.ast.Args[ma.argShift:]) {
|
||||
if n >= len(ma.ast.InvokeArgs[ma.argShift:]) {
|
||||
return nil, errors.New("not enough arguments") // FIX
|
||||
}
|
||||
|
||||
return ma.eval.evalDot(ctx, ma.ec, ma.ast.Args[ma.argShift+n])
|
||||
return ma.eval.evalDot(ctx, ma.ec, ma.ast.InvokeArgs[ma.argShift+n])
|
||||
}
|
||||
|
||||
func (ma macroArgs) evalBlock(ctx context.Context, n int, args []Object, pushScope bool) (Object, error) {
|
||||
|
|
Loading…
Reference in a new issue