<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-19 13:23:47 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-19 13:27:38 +0100
commitaea1a08d6a9d378137d467d3e1f1ccc40232b725 (patch)
tree680e7c913b3ea782557d51968e24d7fa5c4d450a /subex
parentb48dcb0d37bd3db854927df25e6ff41d07501026 (diff)
downloadstred-go-aea1a08d6a9d378137d467d3e1f1ccc40232b725.tar
Adds the negate operator
Negates all of the numbers produced by its content subex
Diffstat (limited to 'subex')
-rw-r--r--subex/arithmetic.go33
-rw-r--r--subex/parse.go2
-rw-r--r--subex/subexast.go14
3 files changed, 49 insertions, 0 deletions
diff --git a/subex/arithmetic.go b/subex/arithmetic.go
index 7200ac7..5497a68 100644
--- a/subex/arithmetic.go
+++ b/subex/arithmetic.go
@@ -85,3 +85,36 @@ func multiplyValues(atoms []walk.Atom) ([]walk.Atom, error) {
return []walk.Atom{walk.ValueNumber(product)}, nil
}
}
+
+// Does tries to cast all to numbers and negates them
+func negateValues(atoms []walk.Atom) ([]walk.Atom, error) {
+ var negatedNumbers []walk.Atom
+ values, err := walk.MemoryCompound(atoms)
+ if err != nil {
+ return nil, err
+ }
+ for _, value := range values {
+ switch v := value.(type) {
+ case walk.ValueNull:
+ negatedNumbers = append(negatedNumbers, walk.ValueNumber(0))
+ case walk.ValueBool:
+ if bool(v) {
+ negatedNumbers = append(negatedNumbers, walk.ValueNumber(-1))
+ } else {
+ negatedNumbers = append(negatedNumbers, walk.ValueNumber(0))
+ }
+ case walk.ValueNumber:
+ negatedNumbers = append(negatedNumbers, walk.ValueNumber(-v))
+ case walk.ValueString:
+ num, err := strconv.ParseFloat(string(v), 64)
+ if err == nil {
+ negatedNumbers = append(negatedNumbers, walk.ValueNumber(-num))
+ } else {
+ return nil, errors.New("Tried to sum non-castable string")
+ }
+ default:
+ return nil, errors.New("Tried to sum non-number")
+ }
+ }
+ return negatedNumbers, nil
+}
diff --git a/subex/parse.go b/subex/parse.go
index f73d060..8635186 100644
--- a/subex/parse.go
+++ b/subex/parse.go
@@ -238,6 +238,8 @@ func parseSubex(l *RuneReader, minPower int) SubexAST {
lhs = SubexASTSum {lhs}
case r == '*' && minPower <= 8:
lhs = SubexASTProduct {lhs}
+ case r == '-' && minPower <= 8:
+ lhs = SubexASTNegate {lhs}
case r == '$' && minPower <= 8:
slot := l.next()
if slot == eof {
diff --git a/subex/subexast.go b/subex/subexast.go
index abf0ca6..3c807ee 100644
--- a/subex/subexast.go
+++ b/subex/subexast.go
@@ -209,3 +209,17 @@ func (ast SubexASTProduct) compileWith(next SubexState) SubexState {
}),
}
}
+
+// Runs the content Subex, if all outputted atoms can be cast to numbers, outputs them all negated
+// Rejects if this fails
+type SubexASTNegate struct {
+ content SubexAST
+}
+func (ast SubexASTNegate) compileWith(next SubexState) SubexState {
+ return &SubexCaptureBeginState {
+ next: ast.content.compileWith(&SubexArithmeticEndState {
+ next: next,
+ calculate: negateValues,
+ }),
+ }
+}