<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2024-04-07 15:27:36 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2024-04-07 15:27:36 +0100
commit658900fcae610caace83a112ac0ee865108ebc92 (patch)
tree4d7b6bebe0d192abf62970ca4324ef1ff274e3c8
parent81925b6ad5212512d27365b8224b76095191431f (diff)
downloadstred-go-658900fcae610caace83a112ac0ee865108ebc92.tar
Change output subex internals to allow structures
Also add substitute register syntactic sugar
-rw-r--r--main/command.go144
-rw-r--r--main/lex.go35
-rw-r--r--main/main.go5
-rw-r--r--main/main_test.go46
-rw-r--r--main/parse.go56
-rw-r--r--subex/main_test.go12
-rw-r--r--subex/parse.go82
-rw-r--r--subex/subexast.go117
-rw-r--r--subex/subexstate.go67
9 files changed, 442 insertions, 122 deletions
diff --git a/main/command.go b/main/command.go
index 1d089ee..3f22821 100644
--- a/main/command.go
+++ b/main/command.go
@@ -84,6 +84,54 @@ func (cmd SubstituteValueCommand) String() string {
return "s/.../"
}
+type IsStartCommand struct {}
+func (cmd IsStartCommand) exec(state *ProgramState) {
+ if state.start {
+ state.pc += 2
+ } else {
+ state.pc += 1
+ }
+}
+func (cmd IsStartCommand) String() string {
+ return "a"
+}
+
+type IsPrevStartCommand struct {}
+func (cmd IsPrevStartCommand) exec(state *ProgramState) {
+ if state.prevStart {
+ state.pc += 2
+ } else {
+ state.pc += 1
+ }
+}
+func (cmd IsPrevStartCommand) String() string {
+ return "A"
+}
+
+type IsEndCommand struct {}
+func (cmd IsEndCommand) exec(state *ProgramState) {
+ if state.end {
+ state.pc += 2
+ } else {
+ state.pc += 1
+ }
+}
+func (cmd IsEndCommand) String() string {
+ return "e"
+}
+
+type IsNextEndCommand struct {}
+func (cmd IsNextEndCommand) exec(state *ProgramState) {
+ if state.nextEnd {
+ state.pc += 2
+ } else {
+ state.pc += 1
+ }
+}
+func (cmd IsNextEndCommand) String() string {
+ return "E"
+}
+
type NoopCommand struct {}
func (cmd NoopCommand) exec(state *ProgramState) {
state.pc++
@@ -112,6 +160,38 @@ func (cmd AppendXRegCommand) String() string {
return "X"
}
+type SubstituteToXRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteToXRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.xreg = newValue
+ }
+}
+func (cmd SubstituteToXRegCommand) String() string {
+ return "x/.../"
+}
+
+type SubstituteAppendXRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteAppendXRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.xreg = append(state.xreg, newValue...)
+ }
+}
+func (cmd SubstituteAppendXRegCommand) String() string {
+ return "X/.../"
+}
+
type SwapYRegCommand struct {}
func (cmd SwapYRegCommand) exec(state *ProgramState) {
v := state.value
@@ -132,6 +212,38 @@ func (cmd AppendYRegCommand) String() string {
return "Y"
}
+type SubstituteToYRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteToYRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.yreg = newValue
+ }
+}
+func (cmd SubstituteToYRegCommand) String() string {
+ return "y/.../"
+}
+
+type SubstituteAppendYRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteAppendYRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.yreg = append(state.xreg, newValue...)
+ }
+}
+func (cmd SubstituteAppendYRegCommand) String() string {
+ return "Y/.../"
+}
+
type SwapZRegCommand struct {}
func (cmd SwapZRegCommand) exec(state *ProgramState) {
v := state.value
@@ -152,6 +264,38 @@ func (cmd AppendZRegCommand) String() string {
return "Z"
}
+type SubstituteToZRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteToZRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.zreg = newValue
+ }
+}
+func (cmd SubstituteToZRegCommand) String() string {
+ return "z/.../"
+}
+
+type SubstituteAppendZRegCommand struct {
+ subex subex.Transducer
+}
+func (cmd SubstituteAppendZRegCommand) exec(state *ProgramState) {
+ newValue, err := runSubex(cmd.subex, state.value)
+ if err {
+ state.pc++
+ } else {
+ state.pc += 2
+ state.zreg = append(state.xreg, newValue...)
+ }
+}
+func (cmd SubstituteAppendZRegCommand) String() string {
+ return "Z/.../"
+}
+
type JumpCommand struct {
destination int
}
diff --git a/main/lex.go b/main/lex.go
index 496abd0..a28975f 100644
--- a/main/lex.go
+++ b/main/lex.go
@@ -171,21 +171,28 @@ func lexCommand(l *lexer) stateFunc {
l.ignore()
r := l.next()
switch r {
- case eof:
- l.emit(TokenEOF)
- return nil
- case '{':
- l.emit(TokenLBrace)
- return lexCommand
- case '}':
- l.emit(TokenRBrace)
- return lexCommand
- case 's', 'S':
- l.emit(TokenCommand)
+ case eof:
+ l.emit(TokenEOF)
+ return nil
+ case '{':
+ l.emit(TokenLBrace)
+ return lexCommand
+ case '}':
+ l.emit(TokenRBrace)
+ return lexCommand
+ case 's', 'S':
+ l.emit(TokenCommand)
+ return lexSubstitution
+ case 'x', 'X', 'y', 'Y', 'z', 'Z':
+ l.emit(TokenCommand)
+ if l.peek() == '/' {
return lexSubstitution
- case ':', 'b':
- l.emit(TokenCommand)
- return lexLabel
+ } else {
+ return lexCommand
+ }
+ case ':', 'b':
+ l.emit(TokenCommand)
+ return lexLabel
}
if isAlpha(r) {
l.emit(TokenCommand)
diff --git a/main/main.go b/main/main.go
index 3a864ad..3fb1cbf 100644
--- a/main/main.go
+++ b/main/main.go
@@ -10,6 +10,7 @@ import (
type ProgramState struct {
value, xreg, yreg, zreg []walk.Value
+ start, prevStart, end, nextEnd bool
in walk.StredReader
out walk.StredWriter
program []Command
@@ -42,6 +43,10 @@ func run(config config) {
break
}
state.value = []walk.Value{walkItem.Value}
+ state.start = walkItem.Start
+ state.prevStart = walkItem.PrevStart
+ state.end = walkItem.End
+ state.nextEnd = walkItem.NextEnd
state.pc = 0
for state.pc < len(state.program) {
state.program[state.pc].exec(&state)
diff --git a/main/main_test.go b/main/main_test.go
index a7a7795..7aa90aa 100644
--- a/main/main_test.go
+++ b/main/main_test.go
@@ -5,6 +5,8 @@ import (
"testing"
)
+var miscInput string = `{"something":{"nested":"Here is my test value"},"array":["Hello","world","these","are","values"],"people":[{"first_name":"Charlie","last_name":"Johnson","age":22},{"first_name":"Tom","last_name":"Johnson","age":18},{"first_name":"Charlie","last_name":"Chaplin","age":122},{"first_name":"John","last_name":"Johnson","age":48}]}`
+
func TestMain(t *testing.T) {
type test struct {
program string
@@ -17,9 +19,51 @@ func TestMain(t *testing.T) {
{
program: `s/#(~(people)~$_@(1$_#(~(first_name)~$_.|(..$_){-0})-|(..$_){-0})-|(..$_){-0})-/p`,
quiet: true,
- input: `{"something":{"nested":"Here is my test value"},"array":["Hello","world","these","are","values"],"people":[{"first_name":"Charlie","last_name":"Johnson","age":22},{"first_name":"Tom","last_name":"Johnson","age":18},{"first_name":"Charlie","last_name":"Chaplin","age":122},{"first_name":"John","last_name":"Johnson","age":48}]}`,
+ input: miscInput,
+ expected: `"Tom"`,
+ },
+ {
+ program: `s/#("people"$_ @(1 $_#("first_name"$_ .)-)-)-/p`,
+ quiet: true,
+ input: miscInput,
+ expected: `"Tom"`,
+ },
+ {
+ program: "s/#(\"people\" @(1 #(\"first_name\" (.$a))-)-)-$_ `$a`/p",
+ quiet: true,
+ input: miscInput,
expected: `"Tom"`,
},
+ {
+ program: "s/#(\"people\" @(2 (.$a))-)-$_ `$a`/p",
+ quiet: true,
+ input: miscInput,
+ expected: `{"first_name":"Charlie","last_name":"Chaplin","age":122}`,
+ },
+ {
+ program: "s/#(\"people\"$_ :(#(\"age\"$_ .)-):)-/p",
+ quiet: true,
+ input: miscInput,
+ expected: `[22,18,122,48]`,
+ },
+ {
+ program: "aX/#(\"people\" :(#()#):)#$_ `1`/o es/#()#/{ xs/.{-0}+/p }",
+ quiet: true,
+ input: miscInput,
+ expected: "4",
+ },
+ {
+ program: "s/#(\"people\"$_ .)-/{ s/:():/p as/:(#()#):/{ xdx } s/:(#((\"first_name\" | \"last_name\") .)#)-/X es/@(.#()-)-/{ xs/(#(\"first_name\" \".{-0}$a\")# | #(\"last_name\" \".{-0}$b\")# | .){-0}$_ `\"$a $b\"`/Xxs/-(..)@/p } }",
+ quiet: true,
+ input: miscInput,
+ expected: `["Charlie Johnson","Tom Johnson","Charlie Chaplin","John Johnson"]`,
+ },
+ {
+ program: "s/#(\"people\"$_ .)-/{ s/:():/p as/:(#()#):/{ xdx } X/:(#((\"first_name\" | \"last_name\") .)#)-/o es/@(.#()-)-/{ xX/(#(\"first_name\" \".{-0}$a\")# | #(\"last_name\" \".{-0}$b\")# | .){-0}$_ `\"$a $b\"`/xs/-(..)@/p } }",
+ quiet: true,
+ input: miscInput,
+ expected: `["Charlie Johnson","Tom Johnson","Charlie Chaplin","John Johnson"]`,
+ },
}
for i, test := range tests {
diff --git a/main/parse.go b/main/parse.go
index 9c7a437..3e0e80b 100644
--- a/main/parse.go
+++ b/main/parse.go
@@ -76,17 +76,61 @@ func (p *parser) parseBasicCommand(commands []Command, commandChar rune) []Comma
case 'o':
return append(commands, NoopCommand{})
case 'x':
- return append(commands, SwapXRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, SwapXRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteToXRegCommand {subex}, JumpCommand {len(commands) + 3})
case 'X':
- return append(commands, AppendXRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, AppendXRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteAppendXRegCommand {subex}, JumpCommand {len(commands) + 3})
case 'y':
- return append(commands, SwapYRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, SwapYRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteToYRegCommand {subex}, JumpCommand {len(commands) + 3})
case 'Y':
- return append(commands, AppendYRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, AppendYRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteAppendYRegCommand {subex}, JumpCommand {len(commands) + 3})
case 'z':
- return append(commands, SwapZRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, SwapZRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteToZRegCommand {subex}, JumpCommand {len(commands) + 3})
case 'Z':
- return append(commands, AppendZRegCommand{})
+ delim := p.peek()
+ if delim.typ != TokenSubstituteDelimiter {
+ return append(commands, AppendZRegCommand{})
+ }
+ ast := p.parseSubex()
+ subex := subex.CompileTransducer(ast)
+ return append(commands, SubstituteAppendZRegCommand {subex}, JumpCommand {len(commands) + 3})
+ case 'a':
+ return append(commands, IsStartCommand{}, JumpCommand {len(commands) + 3})
+ case 'A':
+ return append(commands, IsPrevStartCommand{}, JumpCommand {len(commands) + 3})
+ case 'e':
+ return append(commands, IsEndCommand{}, JumpCommand {len(commands) + 3})
+ case 'E':
+ return append(commands, IsNextEndCommand{}, JumpCommand {len(commands) + 3})
case ':':
labelToken := p.next()
if labelToken.typ != TokenLabel {
diff --git a/subex/main_test.go b/subex/main_test.go
index 8e98798..fb6f152 100644
--- a/subex/main_test.go
+++ b/subex/main_test.go
@@ -405,6 +405,18 @@ func TestSubexMain(t *testing.T) {
},
},
},
+ {
+ subex: ".{-0}`\"hello\"`",
+ input: []walk.Value {
+ walk.NumberValue(1),
+ walk.NumberValue(2),
+ },
+ expected: []walk.Value {
+ walk.NumberValue(1),
+ walk.NumberValue(2),
+ walk.StringValue("hello"),
+ },
+ },
}
for i, test := range tests {
diff --git a/subex/parse.go b/subex/parse.go
index d7fe243..619c1c3 100644
--- a/subex/parse.go
+++ b/subex/parse.go
@@ -1,6 +1,7 @@
package subex
import (
+ "fmt"
"main/walk"
"strconv"
"strings"
@@ -115,6 +116,7 @@ func parseScalarLiteral(l RuneReader) (walk.Scalar, bool) {
panic("Invalid literal")
}
default:
+ fmt.Printf("%c\n", r)
panic("Invalid literal")
}
}
@@ -181,7 +183,8 @@ func parseRepeatRange(l RuneReader) (output []ConvexRange) {
return output
}
-func parseValueReplacement(l RuneReader) (output []OutputValueAST) {
+func parseValueReplacement(l RuneReader) (output SubexAST) {
+ output = SubexASTEmpty{}
// TODO escaping
// TODO add arrays, maps and strings
loop: for {
@@ -197,37 +200,67 @@ func parseValueReplacement(l RuneReader) (output []OutputValueAST) {
if slot == eof {
panic("Missing slot character")
}
- output = append(output, OutputValueLoadAST {slot: slot})
+ output = SubexASTConcat {
+ First: output,
+ Second: SubexASTOutputValueLoad {
+ slot: slot,
+ },
+ }
+ // TODO: destructures
+ case '"':
+ output = SubexASTConcat {
+ First: output,
+ Second: SubexASTDestructure {
+ Destructure: NoneStructure,
+ Structure: StringStructure,
+ Content: parseRuneReplacement(l, '"'),
+ },
+ }
default:
l.Rewind()
scalar, ok := parseScalarLiteral(l)
if !ok {
panic("Invalid scalar literal")
}
- output = append(output, OutputValueLiteralAST {scalar})
+ output = SubexASTConcat {
+ First: output,
+ Second: SubexASTOutputValueLiteral {
+ literal: scalar,
+ },
+ }
}
}
return output
}
-func parseRuneReplacement(l RuneReader) (output []OutputRuneAST) {
+func parseRuneReplacement(l RuneReader, end rune) (output SubexAST) {
+ output = SubexASTEmpty{}
// TODO escaping
- // TODO add arrays, maps and strings
loop: for {
r := l.Next()
switch r {
case eof:
panic("Missing closing `")
- case '`':
+ case end:
break loop
case '$':
slot := l.Next()
if slot == eof {
panic("Missing slot character")
}
- output = append(output, OutputRuneLoadAST {slot: slot})
+ output = SubexASTConcat {
+ First: output,
+ Second: SubexASTOutputRuneLoad {
+ slot: slot,
+ },
+ }
default:
- output = append(output, OutputRuneLiteralAST {r})
+ output = SubexASTConcat {
+ First: output,
+ Second: SubexASTOutputRuneLiteral {
+ literal: r,
+ },
+ }
}
}
return output
@@ -394,6 +427,7 @@ func parseDestructure(l RuneReader, destructure Structure, inType Type) (lhs Sub
}
func parseSubex(l RuneReader, minPower int, inType Type) (lhs SubexAST, outType Type) {
+ start:
r := l.Next()
switch r {
case eof:
@@ -467,16 +501,14 @@ func parseSubex(l RuneReader, minPower int, inType Type) (lhs SubexAST, outType
lhs = SubexASTCopyNumber{}
case '`':
outType = inType
- lhs = SubexASTOutputValues {parseValueReplacement(l)}
- // TODO
- // case '_':
- // lhs = SubexASTCopyStringAtom{}
- // case '#':
- // lhs = SubexASTCopyString{}
- // case ',':
- // lhs = SubexASTCopyValue{}
- // case '"':
- // lhs = SubexASTCopyScalar {walk.NewAtomStringTerminal()}
+ lhs = parseValueReplacement(l)
+ case ' ':
+ if inType == RuneType {
+ outType = RuneType
+ lhs = SubexASTCopyRune {' '}
+ } else {
+ goto start
+ }
default:
outType = inType
if inType == RuneType {
@@ -533,10 +565,16 @@ func parseSubex(l RuneReader, minPower int, inType Type) (lhs SubexAST, outType
InnerOutType: outType,
}
} else {
- resolveTypes(inType, ValueType)
- lhs = SubexASTStoreValues {
- Match: lhs,
- Slot: slot,
+ if inType == ValueType {
+ lhs = SubexASTStoreValues {
+ Match: lhs,
+ Slot: slot,
+ }
+ } else {
+ lhs = SubexASTStoreRunes {
+ Match: lhs,
+ Slot: slot,
+ }
}
}
outType = AnyType
diff --git a/subex/subexast.go b/subex/subexast.go
index 2685925..d08ddac 100644
--- a/subex/subexast.go
+++ b/subex/subexast.go
@@ -46,6 +46,25 @@ func (ast SubexASTStoreValues) String() string {
return fmt.Sprintf("$%c(%v)", ast.Slot, ast.Match)
}
+type SubexASTStoreRunes struct {
+ Match SubexAST
+ Slot rune
+}
+func (ast SubexASTStoreRunes) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ id := slotMap.getRuneId(ast.Slot)
+ newNext := ast.Match.compileWith(&SubexStoreRunesEndState {
+ slot: id,
+ next: next,
+ }, slotMap, inType, RuneType)
+
+ return &SubexCaptureRunesBeginState {
+ next: newNext,
+ }
+}
+func (ast SubexASTStoreRunes) String() string {
+ return fmt.Sprintf("(%v)$%c", ast.Match, ast.Slot)
+}
+
// Try to run the first subex, if it fails then backtrack and use the second
type SubexASTOr struct {
First, Second SubexAST
@@ -148,7 +167,7 @@ type SubexASTCopyScalar struct {
}
func (ast SubexASTCopyScalar) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyScalar")
}
return &SubexCopyState{
filter: selectScalarFilter {ast.Scalar},
@@ -162,7 +181,7 @@ func (ast SubexASTCopyScalar) String() string {
type SubexASTCopyAnyRune struct {}
func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != RuneType || outType != RuneType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyAnyRune")
}
return &SubexCopyRuneState {
next: next,
@@ -170,7 +189,7 @@ func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, in
}
}
func (ast SubexASTCopyAnyRune) String() string {
- return "."
+ return ".RUNE"
}
type SubexASTCopyRune struct {
@@ -178,19 +197,22 @@ type SubexASTCopyRune struct {
}
func (ast SubexASTCopyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != RuneType || outType != RuneType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyRune")
}
return &SubexCopyRuneState {
next: next,
filter: selectRuneFilter {ast.rune},
}
}
+func (ast SubexASTCopyRune) String() string {
+ return string(ast.rune)
+}
// Read in a single atom that must be a boolean and output it unchanged
type SubexASTCopyBool struct {}
func (ast SubexASTCopyBool) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyBool")
}
return &SubexCopyState {
next: next,
@@ -205,7 +227,7 @@ func (ast SubexASTCopyBool) String() string {
type SubexASTCopyNumber struct {}
func (ast SubexASTCopyNumber) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTCopyNumber")
}
return &SubexCopyState {
next: next,
@@ -220,7 +242,6 @@ func (ast SubexASTCopyNumber) String() string {
type SubexASTCopyAnyValue struct {}
func (ast SubexASTCopyAnyValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- fmt.Printf("%v, %v", inType, outType)
panic("Invalid types for SubexASTCopyAnyValue")
}
return &SubexCopyState {
@@ -277,64 +298,56 @@ func (ast SubexASTOutput) String() string {
}
*/
-type OutputValueAST interface {
- compile(slotMap *SlotMap) OutputValue
+type SubexASTOutputValueLiteral struct {
+ literal walk.Scalar
}
-
-type OutputValueLoadAST struct {
- slot rune
-}
-func (ast OutputValueLoadAST) compile(slotMap *SlotMap) OutputValue {
- return OutputValueLoad {
- slotMap.getId(ast.slot),
+func (ast SubexASTOutputValueLiteral) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != ValueType {
+ panic("Invalid outType for SubexASTOutputValueLiteral")
}
-}
-
-type OutputValueLiteralAST struct {
- scalar walk.Scalar
-}
-func (ast OutputValueLiteralAST) compile(slotMap *SlotMap) OutputValue {
- return OutputValueLiteral {
- ast.scalar,
+ return &SubexOutputValueLiteralState {
+ literal: ast.literal,
+ next: next,
}
}
-type SubexASTOutputValues struct {
- Replacement []OutputValueAST
+type SubexASTOutputValueLoad struct {
+ slot rune
}
-func (ast SubexASTOutputValues) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+func (ast SubexASTOutputValueLoad) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if outType != ValueType {
- panic("Invalid outType")
- }
- var content []OutputValue
- for _, el := range ast.Replacement {
- content = append(content, el.compile(slotMap))
+ panic("Invalid outType for SubexASTOutputValueLoad")
}
- return &SubexOutputValuesState {
- content: content,
+ return &SubexOutputValueLoadState {
+ slot: slotMap.getId(ast.slot),
next: next,
}
}
-type OutputRuneAST interface {
- compile(slotMap *SlotMap) OutputRune
-}
-
-type OutputRuneLoadAST struct {
- slot rune
+type SubexASTOutputRuneLiteral struct {
+ literal rune
}
-func (ast OutputRuneLoadAST) compile(slotMap *SlotMap) OutputRune {
- return OutputRuneLoad {slotMap.getRuneId(ast.slot)}
+func (ast SubexASTOutputRuneLiteral) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != RuneType {
+ panic("Invalid outType for SubexASTOutputRuneLiteral")
+ }
+ return &SubexOutputRuneLiteralState {
+ literal: ast.literal,
+ next: next,
+ }
}
-type OutputRuneLiteralAST struct {
- r rune
-}
-func (ast OutputRuneLiteralAST) compile (slotMap *SlotMap) OutputRune {
- return OutputRuneLiteral {ast.r}
+type SubexASTOutputRuneLoad struct {
+ slot rune
}
-
-type SubexASTOutputRunes struct {
+func (ast SubexASTOutputRuneLoad) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
+ if outType != RuneType {
+ panic("Invalid outType for SubexASTOutputRuneLoad")
+ }
+ return &SubexOutputRuneLoadState {
+ slot: slotMap.getRuneId(ast.slot),
+ next: next,
+ }
}
// Run each input Atom through a map to produce an output Atom
@@ -359,7 +372,7 @@ type SubexASTSum struct {
}
func (ast SubexASTSum) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTSum")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
@@ -378,7 +391,7 @@ type SubexASTProduct struct {
}
func (ast SubexASTProduct) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTProduct")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
@@ -398,7 +411,7 @@ type SubexASTNegate struct {
}
func (ast SubexASTNegate) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState {
if inType != ValueType || outType != ValueType {
- panic("Invalid types for SubexASTNot")
+ panic("Invalid types for SubexASTNegate")
}
return &SubexCaptureBeginState {
next: ast.Content.compileWith(&SubexArithmeticEndState {
diff --git a/subex/subexstate.go b/subex/subexstate.go
index 4f5dc19..1e1e94e 100644
--- a/subex/subexstate.go
+++ b/subex/subexstate.go
@@ -133,6 +133,19 @@ func (state SubexStoreEndState) epsilon(aux auxiliaryState) []SubexBranch {
}}
}
+type SubexStoreRunesEndState struct {
+ slot int
+ next SubexState
+}
+func (state SubexStoreRunesEndState) epsilon(aux auxiliaryState) []SubexBranch {
+ toStore, aux := aux.popOutputRunes()
+ aux.store = aux.store.withRunes(state.slot, toStore)
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux,
+ }}
+}
+
/*
// A part of an output literal, either an Atom or a slot from which to load
type OutputContent interface {
@@ -211,48 +224,48 @@ func (state SubexOutputState) accepting(aux auxiliaryState) []OutputStack {
}
*/
-type OutputValue interface {
- build(store Store) []walk.Value
-}
-
-type OutputValueLoad struct {
- slot int
+type SubexOutputValueLiteralState struct {
+ literal walk.Scalar
+ next SubexState
}
-func (ov OutputValueLoad) build(store Store) []walk.Value {
- return store.values[ov.slot]
+func (state SubexOutputValueLiteralState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend([]walk.Value {state.literal}),
+ }}
}
-type OutputValueLiteral struct {
- scalar walk.Scalar
+type SubexOutputValueLoadState struct {
+ slot int
+ next SubexState
}
-func (ov OutputValueLiteral) build(store Store) []walk.Value {
- return []walk.Value{ov.scalar}
+func (state SubexOutputValueLoadState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend(aux.store.values[state.slot]),
+ }}
}
-type SubexOutputValuesState struct {
- content []OutputValue
+type SubexOutputRuneLiteralState struct {
+ literal rune
next SubexState
}
-func (state SubexOutputValuesState) epsilon(aux auxiliaryState) []SubexBranch {
- var content []walk.Value
- for _, el := range state.content {
- content = append(content, el.build(aux.store)...)
- }
+func (state SubexOutputRuneLiteralState) epsilon(aux auxiliaryState) []SubexBranch {
return []SubexBranch {{
state: state.next,
- aux: aux.topAppend(content),
+ aux: aux.topAppendRune([]rune {state.literal}),
}}
}
-type OutputRune interface {
-}
-
-type OutputRuneLoad struct {
+type SubexOutputRuneLoadState struct {
slot int
+ next SubexState
}
-
-type OutputRuneLiteral struct {
- r rune
+func (state SubexOutputRuneLoadState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppendRune(aux.store.runes[state.slot]),
+ }}
}
// A final state, transitions to nothing but is accepting