diff options
-rw-r--r-- | subex/main.go | 92 | ||||
-rw-r--r-- | walk/walk.go | 79 |
2 files changed, 98 insertions, 73 deletions
diff --git a/subex/main.go b/subex/main.go index 0b87dc9..593dbbd 100644 --- a/subex/main.go +++ b/subex/main.go @@ -5,7 +5,6 @@ import ( "fmt" "bufio" "main/walk" - "strings" ) // Where slots are stored @@ -97,83 +96,30 @@ func Main() { if len(os.Args) != 2 { panic("Expected: program [subex]") } - stdin := bufio.NewReader(os.Stdin); - jsonStream := walk.Json(stdin); - var tokens []walk.WalkValue; - for token := range jsonStream { - tokens = append(tokens, token.Value); - } program := os.Args[1] ast := Parse(program) transducer := CompileTransducer(ast) - pieces := make(chan walk.Atom) - go func(out chan<- walk.Atom, input []walk.WalkValue) { - for _, value := range input { - value.Pieces(out) + + stdin := bufio.NewReader(os.Stdin); + jsonStream := walk.Json(stdin); + tokenStream := make(chan walk.WalkValue) + go func(in <-chan walk.WalkItem, out chan<- walk.WalkValue) { + for item := range in { + out<-item.Value } close(out) - }(pieces, tokens) - output, err := RunTransducer(transducer, pieces) - if !err { - dataIn := make(chan walk.Atom) - go func(out chan<- walk.Atom, in []walk.Atom) { - for _, atom := range in { - out<-atom - } - close(out) - }(dataIn, output) - valueOut := make(chan walk.WalkValue) - go func(out chan<- walk.WalkValue, in <-chan walk.Atom) { - for { - atom, hasAtom := <-in - if !hasAtom { - break - } - switch v := atom.(type) { - case walk.TerminalValue: - out<-v - continue - case walk.ValueNull: - out<-v - continue - case walk.ValueBool: - out<-v - continue - case walk.ValueNumber: - out<-v - continue - case rune: - panic("Error! Rune output by subex but not in a string") - case walk.EndString: - panic("Error! subex output an EndString before BeginString") - case walk.StartString: - default: - panic("Unknown atom type") - } - // Handle string start - var builder strings.Builder - loop: for { - atom, hasAtom := <-in - if !hasAtom { - panic("Missing EndString") - } - switch v := atom.(type) { - case walk.EndString: - break loop - case rune: - builder.WriteRune(v) - default: - panic("Invalid atom in string") - } - } - out<-walk.ValueString(builder.String()) - } - close(out) - }(valueOut, dataIn) - for value := range valueOut { - fmt.Println(value) - } - } else { + }(jsonStream, tokenStream) + + atoms := walk.Atomise(tokenStream) + + output, err := RunTransducer(transducer, atoms) + if err { fmt.Println("Error") + return + } + + valueOut := walk.MemoryCompound(output) + for _, value := range valueOut { + fmt.Println(value) } } diff --git a/walk/walk.go b/walk/walk.go index 33e5554..4da8040 100644 --- a/walk/walk.go +++ b/walk/walk.go @@ -4,6 +4,7 @@ import ( "io" "encoding/json" "fmt" + "strings" ) type PathSegment interface {} @@ -377,3 +378,81 @@ func JsonOut(in chan WalkItem) { func ConcatData(first []Atom, second []Atom) []Atom { return append(append([]Atom(nil), first...), second...) } + +func Atomise(in <-chan WalkValue) <-chan Atom { + out := make(chan Atom) + go func(out chan<- Atom, input <-chan WalkValue) { + for value := range input { + value.Pieces(out) + } + close(out) + }(out, in) + return out +} + +func Compound(in <-chan Atom) <-chan WalkValue { + out := make(chan WalkValue) + go func(out chan<- WalkValue, in <-chan Atom) { + for { + atom, hasAtom := <-in + if !hasAtom { + break + } + switch v := atom.(type) { + case TerminalValue: + out<-v + continue + case ValueNull: + out<-v + continue + case ValueBool: + out<-v + continue + case ValueNumber: + out<-v + continue + case rune: + panic("Error! Rune output by subex but not in a string") + case EndString: + panic("Error! subex output an EndString before BeginString") + case StartString: + default: + panic("Unknown atom type") + } + // Handle string start + var builder strings.Builder + loop: for { + atom, hasAtom := <-in + if !hasAtom { + panic("Missing EndString") + } + switch v := atom.(type) { + case EndString: + break loop + case rune: + builder.WriteRune(v) + default: + panic("Invalid atom in string") + } + } + out<-ValueString(builder.String()) + } + close(out) + }(out, in) + return out +} + +func MemoryCompound(in []Atom) (out []WalkValue) { + inChan := make(chan Atom) + go func(in []Atom, out chan<- Atom) { + for _, atom := range in { + out<-atom + } + close(out) + }(in, inChan) + outChan := Compound(inChan) + for value := range outChan { + out = append(out, value) + } + return out +}
\ No newline at end of file |