This commit is contained in:
parent
0f1ceba090
commit
51e35aa9a6
|
@ -105,7 +105,8 @@ type astDot struct {
|
||||||
type astCmd struct {
|
type astCmd struct {
|
||||||
Pos lexer.Position
|
Pos lexer.Position
|
||||||
Name astDot `parser:"@@"`
|
Name astDot `parser:"@@"`
|
||||||
Args []astDot `parser:"@@*"`
|
Assign *astDot `parser:"( EQ @@"`
|
||||||
|
InvokeArgs []astDot `parser:" | @@+ )?"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type astPipeline struct {
|
type astPipeline struct {
|
||||||
|
@ -141,6 +142,7 @@ var scanner = lexer.MustStateful(lexer.Rules{
|
||||||
{"RC", `\}`, nil},
|
{"RC", `\}`, nil},
|
||||||
{"NL", `[;\n][; \n\t]*`, nil},
|
{"NL", `[;\n][; \n\t]*`, nil},
|
||||||
{"PIPE", `\|`, nil},
|
{"PIPE", `\|`, nil},
|
||||||
|
{"EQ", `=`, nil},
|
||||||
{"Ident", `[-]*[a-zA-Z_][\w-!?]*`, nil},
|
{"Ident", `[-]*[a-zA-Z_][\w-!?]*`, nil},
|
||||||
},
|
},
|
||||||
"String": {
|
"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) {
|
func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe Object, ast *astCmd) (Object, error) {
|
||||||
switch {
|
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:
|
case (ast.Name.Arg.Ident != nil) && len(ast.Name.DotSuffix) == 0:
|
||||||
name := ast.Name.Arg.Ident.String()
|
name := ast.Name.Arg.Ident.String()
|
||||||
|
|
||||||
|
@ -85,7 +93,7 @@ func (e evaluator) evalCmd(ctx context.Context, ec *evalCtx, currentPipe Object,
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New("unknown command: " + name)
|
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)
|
nameElem, err := e.evalDot(ctx, ec, ast.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -117,7 +125,7 @@ func (e evaluator) evalInvokable(ctx context.Context, ec *evalCtx, currentPipe O
|
||||||
if currentPipe != nil {
|
if currentPipe != nil {
|
||||||
argsPtr.Append(currentPipe)
|
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] == '-' {
|
if ident := arg.Arg.Ident; len(arg.DotSuffix) == 0 && ident != nil && ident.String()[0] == '-' {
|
||||||
// Arg switch
|
// Arg switch
|
||||||
if kwargs == nil {
|
if kwargs == nil {
|
||||||
|
@ -176,6 +184,14 @@ func (e evaluator) evalDot(ctx context.Context, ec *evalCtx, n astDot) (Object,
|
||||||
return res, nil
|
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) {
|
func (e evaluator) evalArg(ctx context.Context, ec *evalCtx, n astCmdArg) (Object, error) {
|
||||||
switch {
|
switch {
|
||||||
case n.Literal != nil:
|
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")
|
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) {
|
func (e evaluator) evalListOrHash(ctx context.Context, ec *evalCtx, loh *astListOrHash) (Object, error) {
|
||||||
if loh.EmptyList {
|
if loh.EmptyList {
|
||||||
return &ListObject{}, nil
|
return &ListObject{}, nil
|
||||||
|
|
18
ucl/objs.go
18
ucl/objs.go
|
@ -279,7 +279,7 @@ type macroArgs struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ma macroArgs) nargs() int {
|
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) {
|
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 {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ma.ast.Args[ma.argShift+n].DotSuffix) != 0 {
|
if len(ma.ast.InvokeArgs[ma.argShift+n].DotSuffix) != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
lit := ma.ast.Args[ma.argShift+n].Arg.Ident
|
lit := ma.ast.InvokeArgs[ma.argShift+n].Arg.Ident
|
||||||
if lit == nil {
|
if lit == nil {
|
||||||
return false
|
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) {
|
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
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ma.ast.Args[ma.argShift].DotSuffix) != 0 {
|
if len(ma.ast.InvokeArgs[ma.argShift].DotSuffix) != 0 {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
lit := ma.ast.Args[ma.argShift].Arg.Ident
|
lit := ma.ast.InvokeArgs[ma.argShift].Arg.Ident
|
||||||
if lit != nil {
|
if lit != nil {
|
||||||
ma.argShift += 1
|
ma.argShift += 1
|
||||||
return lit.String(), true
|
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) {
|
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 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) {
|
func (ma macroArgs) evalBlock(ctx context.Context, n int, args []Object, pushScope bool) (Object, error) {
|
||||||
|
|
Loading…
Reference in a new issue