From 080a24e894f125d4f1741cfdcba7cb722304d209 Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Fri, 29 Mar 2024 09:49:26 +0000 Subject: Completely remove the path space The new design uses deeply nested values in the value space instead. --- subex/subexast.go | 287 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 160 insertions(+), 127 deletions(-) (limited to 'subex/subexast.go') diff --git a/subex/subexast.go b/subex/subexast.go index e02091d..cc7313b 100644 --- a/subex/subexast.go +++ b/subex/subexast.go @@ -7,43 +7,42 @@ import ( // A node in the AST of a subex type SubexAST interface { - compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState + compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState } // Process the first subex, then the second, splitting the input text in two type SubexASTConcat struct { First, Second SubexAST } -func (ast SubexASTConcat) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { - return ast.First.compileWith(ast.Second.compileWith(next, slotMap, runic), slotMap, runic) +func (ast SubexASTConcat) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + return ast.First.compileWith( + ast.Second.compileWith(next, slotMap, inType, outType), + slotMap, + inType, + outType, + ) } func (ast SubexASTConcat) String() string { return fmt.Sprintf("(%v)(%v)", ast.First, ast.Second) } // Processing a subex and storing the output in a slot instead of outputting it -type SubexASTStore struct { +type SubexASTStoreValues struct { Match SubexAST Slot rune } -func (ast SubexASTStore) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTStoreValues) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { id := slotMap.getId(ast.Slot) newNext := ast.Match.compileWith(&SubexStoreEndState { slot: id, next: next, - }, slotMap, runic) + }, slotMap, inType, ValueType) - if !runic { - return &SubexCaptureBeginState { - next: newNext, - } - } else { - return &SubexCaptureRunesBeginState { - next: newNext, - } + return &SubexCaptureBeginState { + next: newNext, } } -func (ast SubexASTStore) String() string { +func (ast SubexASTStoreValues) String() string { return fmt.Sprintf("$%c(%v)", ast.Slot, ast.Match) } @@ -51,10 +50,10 @@ func (ast SubexASTStore) String() string { type SubexASTOr struct { First, Second SubexAST } -func (ast SubexASTOr) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTOr) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { return &SubexGroupState { - ast.First.compileWith(next, slotMap, runic), - ast.Second.compileWith(next, slotMap, runic), + ast.First.compileWith(next, slotMap, inType, outType), + ast.Second.compileWith(next, slotMap, inType, outType), } } func (ast SubexASTOr) String() string { @@ -84,19 +83,24 @@ func (cr ConvexRange) decrement() ConvexRange { return ConvexRange{cr.Start - 1, cr.End - 1} } } -func (cr ConvexRange) compile(content SubexAST, next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (cr ConvexRange) compile(content SubexAST, next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { min, _ := cr.minmax() if min != 0 { - return content.compileWith(cr.decrement().compile(content, next, slotMap, runic), slotMap, runic) + return content.compileWith( + cr.decrement().compile(content, next, slotMap, inType, outType), + slotMap, + inType, + outType, + ) } if cr.Start == -1 { state := &SubexGroupState {nil, next} - state.first = content.compileWith(state, slotMap, runic) + state.first = content.compileWith(state, slotMap, inType, outType) return state } if cr.End == -1 { state := &SubexGroupState {next, nil} - state.second = content.compileWith(state, slotMap, runic) + state.second = content.compileWith(state, slotMap, inType, outType) return state } @@ -104,7 +108,7 @@ func (cr ConvexRange) compile(content SubexAST, next SubexState, slotMap *SlotMa state := next; for i := 0; i < cr.Start; i += 1 { state = &SubexGroupState { - content.compileWith(state, slotMap, runic), + content.compileWith(state, slotMap, inType, outType), next, } } @@ -114,7 +118,7 @@ func (cr ConvexRange) compile(content SubexAST, next SubexState, slotMap *SlotMa for i := 0; i < cr.End; i += 1 { state = &SubexGroupState { next, - content.compileWith(state, slotMap, runic), + content.compileWith(state, slotMap, inType, outType), } } return state @@ -127,10 +131,13 @@ type SubexASTRepeat struct { Content SubexAST Acceptable []ConvexRange } -func (ast SubexASTRepeat) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTRepeat) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != outType { + panic("Invalid types") + } var state SubexState = &SubexDeadState{} for _, convex := range ast.Acceptable { - state = &SubexGroupState {state, convex.compile(ast.Content, next, slotMap, runic)} + state = &SubexGroupState {state, convex.compile(ast.Content, next, slotMap, inType, outType)} } return state } @@ -142,7 +149,10 @@ func (ast SubexASTRepeat) String() string { type SubexASTCopyScalar struct { Scalar walk.Scalar } -func (ast SubexASTCopyScalar) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTCopyScalar) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyState{ filter: selectScalarFilter {ast.Scalar}, next: next, @@ -153,17 +163,26 @@ func (ast SubexASTCopyScalar) String() string { } type SubexASTCopyAnyRune struct {} -func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTCopyAnyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != RuneType || outType != RuneType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyRuneState { next: next, filter: anyRuneFilter{}, } } +func (ast SubexASTCopyAnyRune) String() string { + return "." +} type SubexASTCopyRune struct { rune rune } -func (ast SubexASTCopyRune) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTCopyRune) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != RuneType || outType != RuneType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyRuneState { next: next, filter: selectRuneFilter {ast.rune}, @@ -172,7 +191,10 @@ func (ast SubexASTCopyRune) compileWith(next SubexState, slotMap *SlotMap, runic // 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, runic bool) SubexState { +func (ast SubexASTCopyBool) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyState { next: next, filter: anyBoolFilter{}, @@ -184,7 +206,10 @@ func (ast SubexASTCopyBool) String() string { // Read in a single atom that must be a number and output it unchanged type SubexASTCopyNumber struct {} -func (ast SubexASTCopyNumber) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTCopyNumber) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyState { next: next, filter: anyNumberFilter{}, @@ -194,34 +219,12 @@ func (ast SubexASTCopyNumber) String() string { return "%" } -// Read in a full string value and copy it out unchanged -// # is equivalent to "_{-0}" -// TODO -// type SubexASTCopyString struct {} -// func (ast SubexASTCopyString) compileWith(next SubexState, slotMap *SlotMap) SubexState { -// stringAtomState := &SubexCopyStringAtomState { -// next: nil, -// } -// stringContentState := &SubexGroupState { -// &SubexCopyScalarState { -// scalar: walk.NewAtomStringTerminal(), -// next: next, -// }, -// stringAtomState, -// } -// stringAtomState.next = stringContentState -// return &SubexCopyScalarState { -// scalar: walk.NewAtomStringTerminal(), -// next: stringContentState, -// } -// } -// func (ast SubexASTCopyString) String() string { -// return "#" -// } - // Read in any single Atom and output it unchanged type SubexASTCopyAnyValue struct {} -func (ast SubexASTCopyAnyValue) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTCopyAnyValue) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCopyState { next: next, filter: anyValueFilter{}, @@ -231,6 +234,7 @@ func (ast SubexASTCopyAnyValue) String() string { return "." } +/* type OutputContentAST interface { compile(slotMap *SlotMap) OutputContent } @@ -273,25 +277,66 @@ func (ast SubexASTOutput) compileWith(next SubexState, slotMap *SlotMap, runic b func (ast SubexASTOutput) String() string { return "=...=" } +*/ -// Read in a repeated subex separated by a delimiter. Greedy -type SubexASTJoin struct { - Content, Delimiter SubexAST +type OutputValueAST interface { + compile(slotMap *SlotMap) OutputValue +} + +type OutputValueLoadAST struct { + slot rune } -func (ast SubexASTJoin) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { - afterContentState := &SubexGroupState { - nil, - next, +func (ast OutputValueLoadAST) compile(slotMap *SlotMap) OutputValue { + return OutputValueLoad { + slotMap.getId(ast.slot), } - manyContentsState := ast.Content.compileWith(afterContentState, slotMap, runic) - afterContentState.first = ast.Delimiter.compileWith(manyContentsState, slotMap, runic) - return &SubexGroupState { - manyContentsState, - next, +} + +type OutputValueLiteralAST struct { + scalar walk.Scalar +} +func (ast OutputValueLiteralAST) compile(slotMap *SlotMap) OutputValue { + return OutputValueLiteral { + ast.scalar, + } +} + +type SubexASTOutputValues struct { + Replacement []OutputValueAST +} +func (ast SubexASTOutputValues) 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)) + } + return &SubexOutputValuesState { + content: content, + next: next, } } -func (ast SubexASTJoin) String() string { - return fmt.Sprintf("(%v);(%v)", ast.Content, ast.Delimiter) + +type OutputRuneAST interface { + compile(slotMap *SlotMap) OutputRune +} + +type OutputRuneLoadAST struct { + slot rune +} +func (ast OutputRuneLoadAST) compile(slotMap *SlotMap) OutputRune { + return OutputRuneLoad {slotMap.getRuneId(ast.slot)} +} + +type OutputRuneLiteralAST struct { + r rune +} +func (ast OutputRuneLiteralAST) compile (slotMap *SlotMap) OutputRune { + return OutputRuneLiteral {ast.r} +} + +type SubexASTOutputRunes struct { } // Run each input Atom through a map to produce an output Atom @@ -314,12 +359,15 @@ func (ast SubexASTJoin) String() string { type SubexASTSum struct { Content SubexAST } -func (ast SubexASTSum) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTSum) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCaptureBeginState { next: ast.Content.compileWith(&SubexArithmeticEndState { next: next, calculate: sumValues, - }, slotMap, runic), + }, slotMap, inType, outType), } } func (ast SubexASTSum) String() string { @@ -330,12 +378,15 @@ func (ast SubexASTSum) String() string { type SubexASTProduct struct { Content SubexAST } -func (ast SubexASTProduct) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTProduct) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCaptureBeginState { next: ast.Content.compileWith(&SubexArithmeticEndState { next: next, calculate: multiplyValues, - }, slotMap, runic), + }, slotMap, inType, outType), } } func (ast SubexASTProduct) String() string { @@ -347,71 +398,45 @@ func (ast SubexASTProduct) String() string { type SubexASTNegate struct { Content SubexAST } -func (ast SubexASTNegate) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTNegate) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCaptureBeginState { next: ast.Content.compileWith(&SubexArithmeticEndState { next: next, calculate: negateValues, - }, slotMap, runic), + }, slotMap, inType, outType), } } func (ast SubexASTNegate) String() string { return fmt.Sprintf("(%v)-", ast.Content) } -// Runs the content Subex and collects the output -// If it is a list of atoms castable to numbers, it takes the reciprocal of them all and outputs them -// Else it rejects -type SubexASTReciprocal struct { - Content SubexAST -} -func (ast SubexASTReciprocal) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { - return &SubexCaptureBeginState { - next: ast.Content.compileWith(&SubexArithmeticEndState { - next: next, - calculate: reciprocalValues, - }, slotMap, runic), - } -} -func (ast SubexASTReciprocal) String() string { - return fmt.Sprintf("(%v)/", ast.Content) -} - // Runs the content Subex and collects the output // Maps over the values in the output, casting each to a boolean, notting each and then outputs them // Rejects if it cannot cast to boolean type SubexASTNot struct { Content SubexAST } -func (ast SubexASTNot) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTNot) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTNot") + } return &SubexCaptureBeginState { next: ast.Content.compileWith(&SubexArithmeticEndState { next: next, calculate: notValues, - }, slotMap, runic), + }, slotMap, ValueType, ValueType), } } func (ast SubexASTNot) String() string { return fmt.Sprintf("(%v)!", ast.Content) } -// Runs the content Subex and collects the output -// Replaces it with true if all output values are equal and false otherwise -type SubexASTEqual struct { - Content SubexAST -} -func (ast SubexASTEqual) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { - return &SubexCaptureBeginState { - next: ast.Content.compileWith(&SubexArithmeticEndState { - next: next, - calculate: equalValues, - }, slotMap, runic), - } -} - // Does nothing type SubexASTEmpty struct {} -func (ast SubexASTEmpty) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTEmpty) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { return next } func (ast SubexASTEmpty) String() string { @@ -422,9 +447,9 @@ func (ast SubexASTEmpty) String() string { type SubexASTDiscard struct { Content SubexAST } -func (ast SubexASTDiscard) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { - newNext := ast.Content.compileWith(&SubexDiscardState {next}, slotMap, runic) - if !runic { +func (ast SubexASTDiscard) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + newNext := ast.Content.compileWith(&SubexDiscardState {next}, slotMap, inType, outType) + if inType == ValueType { return &SubexCaptureBeginState { next: newNext, } @@ -442,7 +467,10 @@ func (ast SubexASTDiscard) String() string { type SubexASTEnterArray struct { Content SubexAST } -func (ast SubexASTEnterArray) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTEnterArray) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTEnterArray") + } return &SubexCaptureBeginState { next: &SubexIncrementNestState { next: &SubexCopyState { @@ -451,13 +479,14 @@ func (ast SubexASTEnterArray) compileWith(next SubexState, slotMap *SlotMap, run next: &SubexCaptureBeginState { next: ast.Content.compileWith( &SubexDiscardTerminalState { - terminal: walk.ArrayEndTerminal{}, + terminal: walk.ArrayEnd, next: &SubexDecrementNestState { next: &SubexConstructArrayState {next: next}, }, }, slotMap, - runic, + ValueType, + ValueType, ), }, }, @@ -469,22 +498,26 @@ func (ast SubexASTEnterArray) compileWith(next SubexState, slotMap *SlotMap, run type SubexASTEnterString struct { Content SubexAST } -func (ast SubexASTEnterString) compileWith(next SubexState, slotMap *SlotMap, runic bool) SubexState { +func (ast SubexASTEnterString) compileWith(next SubexState, slotMap *SlotMap, inType Type, outType Type) SubexState { + if inType != ValueType || outType != ValueType { + panic("Invalid types for SubexASTEnterString") + } return &SubexCaptureBeginState { - next: &SubexIncrementNestState { - next: &SubexCopyState { - filter: anyStringFilter{}, - next: &SubexDiscardState { + next: &SubexCopyState { + filter: anyStringFilter{}, + next: &SubexDiscardState { + next: &SubexIncrementNestState { next: &SubexCaptureRunesBeginState { next: ast.Content.compileWith( - &SubexDecrementNestState { - next: &SubexDiscardTerminalState { - terminal: walk.StringEndTerminal{}, + &SubexDiscardTerminalState { + terminal: walk.StringEnd, + next: &SubexDecrementNestState { next: &SubexConstructStringState {next: next}, }, }, slotMap, - true, + RuneType, + RuneType, ), }, }, -- cgit v1.2.3