From 31a0ddd547f2ef6e3288080db458baf28deb40bb Mon Sep 17 00:00:00 2001 From: "T.v.Dein" Date: Wed, 8 Nov 2023 14:47:15 +0100 Subject: [PATCH] add variable support, implements #10 (#14) --- README.md | 1 + calc.go | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++----- rpn.go | 14 ++++++++++++ rpn.pod | 14 ++++++++++++ 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index db8c4e7..0904e76 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Features: - completion - history - comments (comment character is `#`) +- variables ## Demo diff --git a/calc.go b/calc.go index 77dc9ff..dedc461 100644 --- a/calc.go +++ b/calc.go @@ -41,11 +41,14 @@ type Calc struct { interpreter *Interpreter Space *regexp.Regexp Comment *regexp.Regexp + Register *regexp.Regexp Constants []string LuaFunctions []string Funcalls Funcalls BatchFuncalls Funcalls + + Vars map[string]float64 } // help for lua functions will be added dynamically @@ -58,6 +61,7 @@ clear clear the whole stack shift remove the last element of the stack reverse reverse the stack elements swap exchange the last two elements +vars show list of variables history display calculation history help|? show this message quit|exit|c-d|c-c exit program @@ -81,12 +85,16 @@ sum sum of all values (alias: +) max max of all values min min of all values mean mean of all values (alias: avg) -median median of all values` +median median of all values + +Register variables: +>NAME Put last stack element into variable NAME +])([A-Z][A-Z0-9]*)`) // pre-calculate mode switching arrays c.Constants = strings.Split(Constants, " ") @@ -253,15 +263,28 @@ func (c *Calc) Eval(line string) { continue } + regmatches := c.Register.FindStringSubmatch(item) + if len(regmatches) == 3 { + switch regmatches[1] { + case ">": + c.PutVar(regmatches[2]) + case "<": + c.GetVar(regmatches[2]) + } + continue + } + // management commands switch item { case "?": fallthrough case "help": fmt.Println(Help) - fmt.Println("Lua functions:") - for name, function := range LuaFuncs { - fmt.Printf("%-20s %s\n", name, function.help) + if len(LuaFuncs) > 0 { + fmt.Println("Lua functions:") + for name, function := range LuaFuncs { + fmt.Printf("%-20s %s\n", name, function.help) + } } case "dump": c.stack.Dump() @@ -301,6 +324,16 @@ func (c *Calc) Eval(line string) { os.Exit(0) case "manual": man() + case "vars": + if len(c.Vars) > 0 { + fmt.Printf("%-20s %s\n", "VARIABLE", "VALUE") + for k, v := range c.Vars { + fmt.Printf("%-20s -> %.2f\n", k, v) + } + } else { + fmt.Println("no vars registered") + } + default: fmt.Println("unknown command or operator!") } @@ -449,3 +482,24 @@ func (c *Calc) luafunc(funcname string) { c.Result() } + +func (c *Calc) PutVar(name string) { + last := c.stack.Last() + + if len(last) == 1 { + c.Debug(fmt.Sprintf("register %.2f in %s", last[0], name)) + c.Vars[name] = last[0] + } else { + fmt.Println("empty stack") + } +} + +func (c *Calc) GetVar(name string) { + if _, ok := c.Vars[name]; ok { + c.Debug(fmt.Sprintf("retrieve %.2f from %s", c.Vars[name], name)) + c.stack.Backup() + c.stack.Push(c.Vars[name]) + } else { + fmt.Println("variable doesn't exist") + } +} diff --git a/rpn.go b/rpn.go index ef4b85f..4b6bee6 100644 --- a/rpn.go +++ b/rpn.go @@ -164,6 +164,11 @@ DESCRIPTION help|? show this message quit|exit|c-d|c-c exit program + Register variables: + + >NAME Put last stack element into variable NAME + NAME" command to put a value into + variable "NAME". Use "NAME Put last stack element into variable NAME + NAME" command to put a value into +variable "NAME". Use " can be used to get a list of all variables. + =head1 EXTENDING RPN USING LUA You can use a lua script with lua functions to extend the