summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoop Kiefte <ikojba@gmail.com>2020-10-17 14:28:34 +0300
committerJoop Kiefte <ikojba@gmail.com>2020-10-17 14:28:34 +0300
commit5b246e6238201125c88ab74e17e46e9aaa9ac70d (patch)
tree69ff8528e548b352a06f268a19348f7a3bcaa260
parentf13c785ad79cc993582b61c7b84260bbf91e9fe3 (diff)
Add newop operatorHEADmaster
-rw-r--r--main.go65
-rw-r--r--operators.go49
2 files changed, 81 insertions, 33 deletions
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"
+}