commit
f13c785ad7
3 changed files with 139 additions and 0 deletions
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
module git.kiefte.eu/lapingvino/buforth |
||||
|
||||
go 1.15 |
@ -0,0 +1,135 @@
@@ -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