diff --git a/internal/pkg/dsl/cst/exit.go b/internal/pkg/dsl/cst/exit.go new file mode 100644 index 000000000..c4138e739 --- /dev/null +++ b/internal/pkg/dsl/cst/exit.go @@ -0,0 +1,52 @@ +// ================================================================ +// This handles exit statements. +// ================================================================ + +package cst + +import ( + "fmt" + + "github.com/johnkerl/miller/internal/pkg/dsl" + "github.com/johnkerl/miller/internal/pkg/lib" + "github.com/johnkerl/miller/internal/pkg/runtime" +) + +// ================================================================ +type ExitStatementNode struct { + exitCodeEvaluable IEvaluable +} + +func (root *RootNode) BuildExitStatementNode( + astNode *dsl.ASTNode, +) (IExecutable, error) { + lib.InternalCodingErrorIf(len(astNode.Children) != 1) + exitCodeNode := astNode.Children[0] + + exitCodeEvaluable, err := root.BuildEvaluableNode(exitCodeNode) + if err != nil { + return nil, err + } + + retval := &ExitStatementNode{ + exitCodeEvaluable: exitCodeEvaluable, + } + + return retval, nil +} + +// ---------------------------------------------------------------- +func (node *ExitStatementNode) Execute(state *runtime.State) (*BlockExitPayload, error) { + exitCodeMlrval := node.exitCodeEvaluable.Evaluate(state) + + intValue, isInt := exitCodeMlrval.GetIntValue() + if !isInt { + return nil, fmt.Errorf("expected exit statement int argument; got %d", exitCodeMlrval.GetTypeName()) + } + + state.ExitInfo.HasExitCode = true + state.ExitInfo.ExitCode = int(intValue) + + return nil, nil +} + diff --git a/internal/pkg/dsl/cst/statements.go b/internal/pkg/dsl/cst/statements.go index 1ea5ca026..9f3c58421 100644 --- a/internal/pkg/dsl/cst/statements.go +++ b/internal/pkg/dsl/cst/statements.go @@ -66,6 +66,9 @@ func (root *RootNode) BuildStatementNode( case dsl.NodeTypeEmitPStatement: return root.BuildEmitPStatementNode(astNode) + case dsl.NodeTypeExitStatement: + return root.BuildExitStatementNode(astNode) + case dsl.NodeTypeBeginBlock: return nil, fmt.Errorf("mlr: begin blocks may only be declared at top level.") case dsl.NodeTypeEndBlock: diff --git a/internal/pkg/runtime/state.go b/internal/pkg/runtime/state.go index 7df865705..c18943f2a 100644 --- a/internal/pkg/runtime/state.go +++ b/internal/pkg/runtime/state.go @@ -18,6 +18,7 @@ import ( type State struct { Inrec *mlrval.Mlrmap Context *types.Context + ExitInfo *types.ExitInfo Oosvars *mlrval.Mlrmap FilterExpression *mlrval.Mlrval Stack *Stack @@ -34,6 +35,7 @@ func NewEmptyState(options *cli.TOptions) *State { return &State{ Inrec: nil, Context: nil, + ExitInfo: types.NewExitInfo(), Oosvars: oosvars, FilterExpression: mlrval.TRUE, Stack: NewStack(),