package main import ( "main/walk" "main/subex" ) type Command interface { exec(*ProgramState) } 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 SequenceCommand struct { commands []Command } func (cmd SequenceCommand) exec(state *ProgramState) { for _, command := range cmd.commands { command.exec(state) } } 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 DeleteAllCommand struct {} func (cmd DeleteAllCommand) exec(state *ProgramState) { state.path = nil state.value = nil } func runSubex(state subex.SubexState, in []walk.WalkValue) (out []walk.WalkValue, error bool) { valueStream := make(chan walk.WalkValue) go func(in []walk.WalkValue, out chan<- walk.WalkValue) { for _, value := range in { out <- value } close(out) }(in, valueStream) atomStream := walk.Atomise(valueStream) atomsOut, error := subex.RunTransducer(state, atomStream) if error { return nil, true } valuesOut, err := walk.MemoryCompound(atomsOut) if err != nil { return nil, true } return valuesOut, false } type SubstituteValueCommand struct { subex subex.SubexState next Command } func (cmd SubstituteValueCommand) exec(state *ProgramState) { newValue, err := runSubex(cmd.subex, state.value) if err { return } state.value = newValue cmd.next.exec(state) } type SubstitutePathCommand struct { subex subex.SubexState next Command } func (cmd SubstitutePathCommand) exec(state *ProgramState) { newPath, err := runSubex(cmd.subex, state.path) if err { return } state.path = newPath cmd.next.exec(state) } 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...) }