From c6905e06ba73f47495ba86cebe1cb42f141f308d Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Wed, 19 Apr 2023 09:48:04 +0100 Subject: Adds casting strings to numbers in the sum operator --- subex/subexstate.go | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'subex/subexstate.go') diff --git a/subex/subexstate.go b/subex/subexstate.go index 62e9d1a..855d44a 100644 --- a/subex/subexstate.go +++ b/subex/subexstate.go @@ -2,6 +2,8 @@ package subex import ( "main/walk" + "strconv" + "errors" ) // A state of execution for the transducer @@ -236,41 +238,54 @@ func (state SubexRangeState) accepting(store Store) [][]walk.Atom { return nil } -func sumValues(values []walk.Atom) walk.ValueNumber { +func sumValues(atoms []walk.Atom) (walk.ValueNumber, error) { var sum float64 = 0 + values, err := walk.MemoryCompound(atoms) + if err != nil { + return 0, err + } for _, value := range values { switch v := value.(type) { + case walk.ValueNull: case walk.ValueBool: if (bool(v)) { sum += 1 } case walk.ValueNumber: sum += float64(v) - case rune: - if '0' <= v && v <= '9' { - sum += float64(v - '0') + case walk.ValueString: + num, err := strconv.ParseFloat(string(v), 64) + if err == nil { + sum += num + } else { + return 0, errors.New("Tried to sum non-castable string") } default: + return 0, errors.New("Tried to sum non-number") } } - return walk.ValueNumber(sum) + return walk.ValueNumber(sum), nil } // Run the inputState machine and sum any values output, output the sum -// Cast non numbers into numbers, ignore anything uncastable +// Cast non numbers into numbers, branch dies if it is not castable type SubexSumState struct { inputState SubexState next SubexState - sum walk.ValueNumber + acc []walk.Atom } func (state SubexSumState) child() SubexState { return state.inputState } func (state SubexSumState) nextAcc(output []walk.Atom) interface{} { - return sumValues(append(output, state.sum)) + return walk.ConcatData(state.acc, output) } func (state SubexSumState) feedNext(acc interface{}, store Store, char walk.Atom) []SubexBranch { - total := acc.(walk.ValueNumber) + childOutput := acc.([]walk.Atom) + total, err := sumValues(childOutput) + if err != nil { + return nil + } output := []walk.Atom{total} nextStates := state.next.eat(store.clone(), char) for i := range nextStates { @@ -279,7 +294,11 @@ func (state SubexSumState) feedNext(acc interface{}, store Store, char walk.Atom return nextStates } func (state SubexSumState) acceptNext(acc interface{}, store Store) [][]walk.Atom { - total := acc.(walk.ValueNumber) + childOutput := acc.([]walk.Atom) + total, err := sumValues(childOutput) + if err != nil { + return nil + } output := []walk.Atom{total} outputs := state.next.accepting(store.clone()) for i := range outputs { @@ -288,11 +307,11 @@ func (state SubexSumState) acceptNext(acc interface{}, store Store) [][]walk.Ato return outputs } func (state SubexSumState) nextParent(child SubexState, acc interface{}) SubexState { - sum := acc.(walk.ValueNumber) + childOutput := acc.([]walk.Atom) return &SubexSumState { inputState: child, next: state.next, - sum: sum, + acc: childOutput, } } func (state SubexSumState) eat(store Store, char walk.Atom) (nextStates []SubexBranch) { -- cgit v1.2.3