Initial commit
commit
f13c785ad7
@ -0,0 +1 @@
|
||||
buforth
|
@ -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…
Reference in New Issue