mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
* Update package version * Update makefile targets * Update readme packages * Remaining old packages via rg/sd
75 lines
2.4 KiB
Go
75 lines
2.4 KiB
Go
// ================================================================
|
|
// The other emit variants (emit, emitp, emitf) need to take only oosvars, etc.
|
|
// -- not arbitrary expressions which *evaluate* to map. Emit1, by contrast,
|
|
// takes any expression which evaluates to a map. So you can do 'emit1
|
|
// mapsum({"id": $id}, $some_map_valued_field})'.
|
|
//
|
|
// The reason for this is LR1 shift-reduce conflicts. When I originally
|
|
// implemented emit/emitp/emitf, I permitted a lot of options for lashing
|
|
// together multiple oosvars, indexing, redirection, etc. When we try to let emit (not
|
|
// emit1) take arbitrary Rvalue as argument, we get LR1 conflicts since the
|
|
// parse can't disambiguate between all the possibilities for commas and
|
|
// parentheses for emit-lashing and emit-indexing, and all the possibilities
|
|
// for commas and parentheses for the Rvalue expression itself.
|
|
//
|
|
// So, we have emit/emitp which permit grammatical complexity in the
|
|
// lashing/indexing/redirection, and emit1 which permits grammatical complexity
|
|
// in the emittable.
|
|
// ================================================================
|
|
|
|
package cst
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/johnkerl/miller/v6/pkg/dsl"
|
|
"github.com/johnkerl/miller/v6/pkg/lib"
|
|
"github.com/johnkerl/miller/v6/pkg/runtime"
|
|
"github.com/johnkerl/miller/v6/pkg/types"
|
|
)
|
|
|
|
type Emit1StatementNode struct {
|
|
evaluable IEvaluable
|
|
}
|
|
|
|
func (root *RootNode) BuildEmit1StatementNode(astNode *dsl.ASTNode) (IExecutable, error) {
|
|
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeEmit1Statement)
|
|
return root.buildEmit1StatementNode(astNode, false)
|
|
}
|
|
|
|
func (root *RootNode) buildEmit1StatementNode(
|
|
astNode *dsl.ASTNode,
|
|
isEmitP bool,
|
|
) (IExecutable, error) {
|
|
lib.InternalCodingErrorIf(len(astNode.Children) != 1)
|
|
|
|
evaluable, err := root.BuildEvaluableNode(astNode.Children[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Emit1StatementNode{
|
|
evaluable: evaluable,
|
|
}, nil
|
|
}
|
|
|
|
func (node *Emit1StatementNode) Execute(state *runtime.State) (*BlockExitPayload, error) {
|
|
value := node.evaluable.Evaluate(state)
|
|
if value.IsAbsent() {
|
|
return nil, nil
|
|
}
|
|
|
|
// TODO: in a to-be-developed strict mode, fatal here.
|
|
valueAsMap := value.GetMap() // nil if not a map
|
|
if valueAsMap == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if state.OutputRecordsAndContexts != nil {
|
|
state.OutputRecordsAndContexts.PushBack(types.NewRecordAndContext(valueAsMap, state.Context))
|
|
} else {
|
|
fmt.Println(valueAsMap.String())
|
|
}
|
|
|
|
return nil, nil
|
|
}
|