diff options
Diffstat (limited to 'subex/arithmetic.go')
-rw-r--r-- | subex/arithmetic.go | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/subex/arithmetic.go b/subex/arithmetic.go new file mode 100644 index 0000000..7200ac7 --- /dev/null +++ b/subex/arithmetic.go @@ -0,0 +1,87 @@ +package subex + +import ( + "main/walk" + "errors" + "strconv" +) + +func sumValues(atoms []walk.Atom) ([]walk.Atom, error) { + allBools := true + var sum float64 = 0 + var any bool = false + values, err := walk.MemoryCompound(atoms) + if err != nil { + return nil, err + } + for _, value := range values { + switch v := value.(type) { + case walk.ValueNull: + allBools = false + case walk.ValueBool: + if bool(v) { + sum += 1 + any = true + } + case walk.ValueNumber: + allBools = false + sum += float64(v) + case walk.ValueString: + allBools = false + num, err := strconv.ParseFloat(string(v), 64) + if err == nil { + sum += num + } else { + return nil, errors.New("Tried to sum non-castable string") + } + default: + return nil, errors.New("Tried to sum non-number") + } + } + if allBools { + return []walk.Atom{walk.ValueBool(any)}, nil + } else { + return []walk.Atom{walk.ValueNumber(sum)}, nil + } +} + +// Compounds atoms into values, if all values are booleans, does AND, if not, tries to cast to numbers and multiply +func multiplyValues(atoms []walk.Atom) ([]walk.Atom, error) { + allBools := true + var product float64 = 1 + var all bool = false + values, err := walk.MemoryCompound(atoms) + if err != nil { + return nil, err + } + for _, value := range values { + switch v := value.(type) { + case walk.ValueNull: + allBools = false + product *= 0 + case walk.ValueBool: + if !bool(v) { + product *= 0 + all = false + } + case walk.ValueNumber: + allBools = false + product *= float64(v) + case walk.ValueString: + allBools = false + num, err := strconv.ParseFloat(string(v), 64) + if err == nil { + product *= num + } else { + return nil, errors.New("Tried to sum non-castable string") + } + default: + return nil, errors.New("Tried to sum non-number") + } + } + if allBools { + return []walk.Atom{walk.ValueBool(all)}, nil + } else { + return []walk.Atom{walk.ValueNumber(product)}, nil + } +} |