reorganized Eval() return errors and call EvalItem() on each item

This commit is contained in:
2023-12-08 18:35:56 +01:00
parent cb774b3b80
commit ac9d08d6fc
3 changed files with 123 additions and 99 deletions

200
calc.go
View File

@@ -222,12 +222,12 @@ func (c *Calc) Prompt() string {
}
// the actual work horse, evaluate a line of calc command[s]
func (c *Calc) Eval(line string) {
func (c *Calc) Eval(line string) error {
// remove surrounding whitespace and comments, if any
line = strings.TrimSpace(c.Comment.ReplaceAllString(line, ""))
if line == "" {
return
return nil
}
items := c.Space.Split(line, -1)
@@ -239,98 +239,8 @@ func (c *Calc) Eval(line string) {
c.notdone = false
}
num, err := strconv.ParseFloat(item, 64)
if err == nil {
c.stack.Backup()
c.stack.Push(num)
} else {
// try hex
var i int
_, err := fmt.Sscanf(item, "0x%x", &i)
if err == nil {
c.stack.Backup()
c.stack.Push(float64(i))
continue
}
if contains(c.Constants, item) {
// put the constant onto the stack
c.stack.Backup()
c.stack.Push(const2num(item))
continue
}
if exists(c.Funcalls, item) {
if err := c.DoFuncall(item); err != nil {
fmt.Println(err)
} else {
c.Result()
}
continue
}
if exists(c.BatchFuncalls, item) {
if !c.batch {
fmt.Println("only supported in batch mode")
continue
}
if err := c.DoFuncall(item); err != nil {
fmt.Println(err)
} else {
c.Result()
}
continue
}
if contains(c.LuaFunctions, item) {
// user provided custom lua functions
c.EvalLuaFunction(item)
continue
}
regmatches := c.Register.FindStringSubmatch(item)
if len(regmatches) == 3 {
switch regmatches[1] {
case ">":
c.PutVar(regmatches[2])
case "<":
c.GetVar(regmatches[2])
}
continue
}
// internal commands
if exists(c.Commands, item) {
c.Commands[item].Func(c)
continue
}
if exists(c.ShowCommands, item) {
c.ShowCommands[item].Func(c)
continue
}
if exists(c.StackCommands, item) {
c.StackCommands[item].Func(c)
continue
}
if exists(c.SettingsCommands, item) {
c.SettingsCommands[item].Func(c)
continue
}
switch item {
case "?":
fallthrough
case "help":
c.PrintHelp()
default:
fmt.Println("unknown command or operator!")
}
if err := c.EvalItem(item); err != nil {
return err
}
}
@@ -343,6 +253,106 @@ func (c *Calc) Eval(line string) {
last := c.stack.Last(5)
fmt.Printf("stack: %s%s\n", dots, list2str(last))
}
return nil
}
func (c *Calc) EvalItem(item string) error {
num, err := strconv.ParseFloat(item, 64)
if err == nil {
c.stack.Backup()
c.stack.Push(num)
} else {
// try hex
var i int
_, err := fmt.Sscanf(item, "0x%x", &i)
if err == nil {
c.stack.Backup()
c.stack.Push(float64(i))
return nil
}
if contains(c.Constants, item) {
// put the constant onto the stack
c.stack.Backup()
c.stack.Push(const2num(item))
return nil
}
if exists(c.Funcalls, item) {
if err := c.DoFuncall(item); err != nil {
return Error(err.Error())
} else {
c.Result()
}
return nil
}
if exists(c.BatchFuncalls, item) {
if !c.batch {
return Error("only supported in batch mode")
}
if err := c.DoFuncall(item); err != nil {
return Error(err.Error())
} else {
c.Result()
}
return nil
}
if contains(c.LuaFunctions, item) {
// user provided custom lua functions
c.EvalLuaFunction(item)
return nil
}
regmatches := c.Register.FindStringSubmatch(item)
if len(regmatches) == 3 {
switch regmatches[1] {
case ">":
c.PutVar(regmatches[2])
case "<":
c.GetVar(regmatches[2])
}
return nil
}
// internal commands
// FIXME: propagate errors
if exists(c.Commands, item) {
c.Commands[item].Func(c)
return nil
}
if exists(c.ShowCommands, item) {
c.ShowCommands[item].Func(c)
return nil
}
if exists(c.StackCommands, item) {
c.StackCommands[item].Func(c)
return nil
}
if exists(c.SettingsCommands, item) {
c.SettingsCommands[item].Func(c)
return nil
}
switch item {
case "?":
fallthrough
case "help":
c.PrintHelp()
default:
return Error("unknown command or operator")
}
}
return nil
}
// Execute a math function, check if it is defined just in case
@@ -355,7 +365,7 @@ func (c *Calc) DoFuncall(funcname string) error {
}
if function == nil {
panic("function not defined but in completion list")
return Error("function not defined but in completion list")
}
var args Numbers

18
main.go
View File

@@ -30,7 +30,7 @@ import (
lua "github.com/yuin/gopher-lua"
)
const VERSION string = "2.0.12"
const VERSION string = "2.0.13"
const Usage string = `This is rpn, a reverse polish notation calculator cli.
@@ -119,7 +119,11 @@ func Main() int {
// commandline calc operation, no readline etc needed
// called like rpn 2 2 +
calc.stdin = true
calc.Eval(strings.Join(flag.Args(), " "))
if err := calc.Eval(strings.Join(flag.Args(), " ")); err != nil {
fmt.Println(err)
return 1
}
return 0
}
@@ -153,7 +157,10 @@ func Main() int {
break
}
calc.Eval(line)
err = calc.Eval(line)
if err != nil {
fmt.Println(err)
}
rl.SetPrompt(calc.Prompt())
}
@@ -162,7 +169,10 @@ func Main() int {
// echo 1 2 3 4 | rpn +
// batch mode enabled automatically
calc.batch = true
calc.Eval(flag.Args()[0])
if err = calc.Eval(flag.Args()[0]); err != nil {
fmt.Println(err)
return 1
}
}
return 0

View File

@@ -71,3 +71,7 @@ func const2num(name string) float64 {
func list2str(list Numbers) string {
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(list)), " "), "[]")
}
func Error(m string) error {
return fmt.Errorf("Error: %s!", m)
}