package main type PrintValueCommand struct {} func (cmd PrintValueCommand) exec(state *ProgramState) { for _, item := range state.space { state.out <- item } } type ToggleTerminalCommand struct {} func (cmd ToggleTerminalCommand) exec(state *ProgramState) { toggled := map[TerminalValue]TerminalValue { ArrayBegin: MapBegin, ArrayEnd: MapEnd, MapBegin: ArrayBegin, MapEnd: ArrayEnd, } for i := range state.space { terminal, isTerminal := state.space[i].value.(TerminalValue) if !isTerminal { continue } state.space[i].value = toggled[terminal] } } type FilteredCommand struct { filter Filter command Command } func (cmd FilteredCommand) exec(state *ProgramState) { for _, item := range state.space { if cmd.filter.exec(item) { cmd.command.exec(state) return } } } type SequenceCommand struct { commands []Command } func (cmd SequenceCommand) exec(state *ProgramState) { for _, command := range cmd.commands { command.exec(state) } } type AppendLiteralCommand struct { values []WalkValue } func (cmd AppendLiteralCommand) exec(state *ProgramState) { for _, value := range cmd.values { state.space = append(state.space, WalkItem { path: nil, value: value, }) } } type PrependLiteralCommand struct { values []WalkValue } func (cmd PrependLiteralCommand) exec(state *ProgramState) { var newItems []WalkItem for _, value := range cmd.values { newItems = append(newItems, WalkItem { path: nil, value: value, }) } state.space = append(newItems, state.space...) } type NextCommand struct {} func (cmd NextCommand) exec(state *ProgramState) { nextItem := <- state.in state.space = []WalkItem{nextItem} } type AppendNextCommand struct {} func (cmd AppendNextCommand) exec(state *ProgramState) { nextItem := <- state.in state.space = append(state.space, nextItem) } type PrintLiteralsCommand struct { items []WalkItem } func (cmd PrintLiteralsCommand) exec(state *ProgramState) { for _, item := range cmd.items { state.out <- item } } type DeleteAllCommand struct {} func (cmd DeleteAllCommand) exec(state *ProgramState) { state.space = nil } type Command interface { exec(*ProgramState) }