From 5b246e6238201125c88ab74e17e46e9aaa9ac70d Mon Sep 17 00:00:00 2001 From: Joop Kiefte Date: Sat, 17 Oct 2020 14:28:34 +0300 Subject: Add newop operator --- main.go | 65 ++++++++++++++++++++++++++++++------------------------------ operators.go | 49 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 33 deletions(-) create mode 100644 operators.go diff --git a/main.go b/main.go index c6d1268..8a65cef 100644 --- a/main.go +++ b/main.go @@ -3,11 +3,15 @@ package main import ( "bufio" "os" - "strings" "strconv" + "strings" ) -type operation func(*[]int, *int) string +type forthfunc func(*[]int, *int, []string) string +type operation struct { + op forthfunc + readuntil string +} type numberError string type bufferError string @@ -16,31 +20,13 @@ func (n bufferError) Error() string { return string(n) } var stack []int var stackpointer int -var dictionary = map[string]operation{ - "base" : func(st *[]int, stp *int) string { - base, _ := getvalue(st, stp) - r, err := getvalue(st, stp) - if err != nil { - return err.Error() - } - return strconv.FormatInt(int64(r), base) - }, - "+" : func(st *[]int, stp *int) string { - n1, _ := getvalue(st, stp) - n2, err := getvalue(st, stp) - if err != nil { - return err.Error() - } - err = putvalue(st, stp, n1+n2) - if err != nil { - return err.Error() - } - return "*" - }, - "quit": func(_ *[]int, _ *int) string { - os.Exit(0) - return "should have quit" - }, +var dictionary = make(map[string]operation) + +func forth(code string) forthfunc { + op := func(st *[]int, stp *int, _ []string) string { + return eval(code, nil) + } + return forthfunc(op) } func getvalue(st *[]int, stp *int) (int, error) { @@ -54,7 +40,7 @@ func getvalue(st *[]int, stp *int) (int, error) { } func putvalue(st *[]int, stp *int, n int) error { - if *stp == int(^uint(0) >> 1) { // check for maxint + if *stp == int(^uint(0)>>1) { // check for maxint return bufferError("buffer overflow") } *st = append(*st, n) @@ -107,13 +93,28 @@ func number(st *[]int, stp *int, cmd string) error { func eval(code string, inerr error) string { if inerr != nil { + if code == "" { + os.Exit(0) + } return "Error before evaluating code: " + inerr.Error() } var value string - for _, cmd := range strings.Split(code, " ") { + cmds := strings.Split(code, " ") + for i := 0; i < len(cmds); i++ { + cmd := cmds[i] op, ok := dictionary[cmd] if ok { - value = op(&stack, &stackpointer) + var read []string + if op.readuntil != "" { + for j, c := range cmds[i+1:] { + if c == op.readuntil { + read = cmds[i+1 : i+j+1] + i += j + 1 + break + } + } + } + value = op.op(&stack, &stackpointer, read) continue } err := number(&stack, &stackpointer, cmd) @@ -126,9 +127,7 @@ func eval(code string, inerr error) string { func main() { stdin := bufio.NewReader(os.Stdin) - dictionary["."] = func(st *[]int, stp *int) string { - return eval("10 base", nil) - } + prelude() for { println(eval(read(stdin))) } diff --git a/operators.go b/operators.go new file mode 100644 index 0000000..9fd3769 --- /dev/null +++ b/operators.go @@ -0,0 +1,49 @@ +package main + +import ( + "strconv" + "os" + "strings" +) + +func prelude() { + dictionary[":"] = operation{op: newop, readuntil: ";"} + dictionary["base"] = operation{op: base} + dictionary["+"] = operation{op: add} + dictionary["quit"] = operation{op: quit} + dictionary["."] = operation{op: forth("10 base")} +} + +func newop(st *[]int, stp *int, code []string) string { + if len(code) > 0 { + dictionary[code[0]] = operation{op: forth(strings.Join(code[1:], " "))} + } + return "" +} + +func base(st *[]int, stp *int, _ []string) string { + base, _ := getvalue(st, stp) + r, err := getvalue(st, stp) + if err != nil { + return err.Error() + } + return strconv.FormatInt(int64(r), base) +} + +func add(st *[]int, stp *int, _ []string) string { + n1, _ := getvalue(st, stp) + n2, err := getvalue(st, stp) + if err != nil { + return err.Error() + } + err = putvalue(st, stp, n1+n2) + if err != nil { + return err.Error() + } + return "*" +} + +func quit(_ *[]int, _ *int, _ []string) string { + os.Exit(0) + return "should have quit" +} -- cgit v1.2.3-70-g09d2