Add newop operator

master
Joop Kiefte 3 years ago
parent f13c785ad7
commit 5b246e6238

@ -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)))
}

@ -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"
}
Loading…
Cancel
Save