package main import ( "main/walk" "main/subex" ) type PrintValueCommand struct {} func (cmd PrintValueCommand) exec(state *ProgramState) { path := walk.PathFromWalkValues(state.path) for _, value := range state.value { state.out <- walk.WalkItem { Value: value, Path: path, } } } type ToggleTerminalCommand struct {} func (cmd ToggleTerminalCommand) exec(state *ProgramState) { toggled := map[walk.TerminalValue]walk.TerminalValue { walk.ArrayBegin: walk.MapBegin, walk.ArrayEnd: walk.MapEnd, walk.MapBegin: walk.ArrayBegin, walk.MapEnd: walk.ArrayEnd, } for i := range state.value { terminal, isTerminal := state.value[i].(walk.TerminalValue) if !isTerminal { continue } state.value[i] = toggled[terminal] } } type FilteredCommand struct { filter Filter command Command } func (cmd FilteredCommand) exec(state *ProgramState) { path := walk.PathFromWalkValues(state.path) for _, value := range state.value { if cmd.filter.exec(walk.WalkItem { Value: value, Path: path, }) { 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 []walk.WalkValue } func (cmd AppendLiteralCommand) exec(state *ProgramState) { state.value = append(state.value, cmd.values...) } type PrependLiteralCommand struct { values []walk.WalkValue } func (cmd PrependLiteralCommand) exec(state *ProgramState) { var newItems []walk.WalkValue newItems = append(newItems, cmd.values...) state.value = append(newItems, state.value...) } type NextCommand struct {} func (cmd NextCommand) exec(state *ProgramState) { nextItem := <- state.in state.value = []walk.WalkValue{nextItem.Value} state.path = nextItem.Path.ToWalkValues() } type AppendNextCommand struct {} func (cmd AppendNextCommand) exec(state *ProgramState) { nextItem := <- state.in state.value = append(state.value, nextItem.Value) state.path = nextItem.Path.ToWalkValues() } type PrintLiteralsCommand struct { items []walk.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.path = nil state.value = nil } type SubstituteCommand struct { subex subex.SubexState next Command } func (cmd SubstituteCommand) exec(state *ProgramState) { valueStream := make(chan walk.WalkValue) go func(in []walk.WalkValue, out chan<- walk.WalkValue) { for _, value := range in { out <- value } close(out) }(state.value, valueStream) atomStream := walk.Atomise(valueStream) atomsOut, error := subex.RunTransducer(cmd.subex, atomStream) if error { return } valuesOut, err := walk.MemoryCompound(atomsOut) if err != nil { return } state.value = valuesOut cmd.next.exec(state) } type Command interface { exec(*ProgramState) } type NoopCommand struct {} func (cmd NoopCommand) exec(state *ProgramState) {} type SwapXRegCommand struct {} func (cmd SwapXRegCommand) exec(state *ProgramState) { v := state.value state.value = state.xreg state.xreg = v } type AppendXRegCommand struct {} func (cmd AppendXRegCommand) exec(state *ProgramState) { state.xreg = append(state.xreg, state.value...) } type SwapPathCommand struct {} func (cmd SwapPathCommand) exec(state *ProgramState) { v := state.value state.value = state.path state.path = v } type AppendPathCommand struct {} func (cmd AppendPathCommand) exec(state *ProgramState) { state.path = append(state.path, state.value...) }