Initial commit

master
Joop Kiefte 3 years ago
commit f13c785ad7

1
.gitignore vendored

@ -0,0 +1 @@
buforth

@ -0,0 +1,3 @@
module git.kiefte.eu/lapingvino/buforth
go 1.15

@ -0,0 +1,135 @@
package main
import (
"bufio"
"os"
"strings"
"strconv"
)
type operation func(*[]int, *int) string
type numberError string
type bufferError string
func (n numberError) Error() string { return string(n) }
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"
},
}
func getvalue(st *[]int, stp *int) (int, error) {
if *stp < 1 {
return 0, bufferError("buffer underflow")
}
r := (*st)[*stp-1]
*st = (*st)[:len(*st)-1]
*stp--
return r, nil
}
func putvalue(st *[]int, stp *int, n int) error {
if *stp == int(^uint(0) >> 1) { // check for maxint
return bufferError("buffer overflow")
}
*st = append(*st, n)
*stp++
return nil
}
func read(r *bufio.Reader) (string, error) {
s, err := r.ReadString('\n')
if err != nil {
return "", err
}
return s[:len(s)-1], err
}
func pow(n, p int) int {
r := 1
for i := 0; i < p; i++ {
r *= n
}
return r
}
func number(st *[]int, stp *int, cmd string) error {
base := 6
if len(cmd) < 1 {
return numberError("tried parsing empty value")
}
switch {
case cmd[0] == 'd':
base = 10
case cmd[0] == 'x':
base = 16
case cmd[0] == '0':
base = 8
case cmd[0] == 'b':
base = 2
case cmd[0] == '#':
base = 36
}
if base != 6 {
cmd = cmd[1:]
}
val, err := strconv.ParseInt(cmd, base, 0)
if err != nil {
return err
}
return putvalue(st, stp, int(val))
}
func eval(code string, inerr error) string {
if inerr != nil {
return "Error before evaluating code: " + inerr.Error()
}
var value string
for _, cmd := range strings.Split(code, " ") {
op, ok := dictionary[cmd]
if ok {
value = op(&stack, &stackpointer)
continue
}
err := number(&stack, &stackpointer, cmd)
if err != nil {
return "Error reading value: " + err.Error()
}
}
return value
}
func main() {
stdin := bufio.NewReader(os.Stdin)
dictionary["."] = func(st *[]int, stp *int) string {
return eval("10 base", nil)
}
for {
println(eval(read(stdin)))
}
}
Loading…
Cancel
Save