package main import ( "bufio" "errors" "fmt" "os" "strings" ) func main() { stack := Stack{values: []int{}} rstack := Stack{values: []int{}} dict := Dictionary{} c := Context{ Dictionary: dict, Stack: &stack, RStack: &rstack, Flags: Flags{ "Immediate": true, "Comment": false, }, Words: []string{}, } b := &Builtins{} // word definitions dict.AddWord(":", b.Colon(&c), nil, false) dict.AddWord(";", b.Semicolon(&c), nil, true) // comments dict.AddWord("(", b.OpenComment(&c), nil, true) dict.AddWord(")", b.CloseComment(&c), nil, true) // math dict.AddWord("+", b.Add(&stack), nil, false) dict.AddWord("-", b.Sub(&stack), nil, false) dict.AddWord("*", b.Mul(&stack), nil, false) dict.AddWord("/", b.Div(&stack), nil, false) // output dict.AddWord(".", b.Print(os.Stdout, &stack), nil, false) dict.AddWord("EMIT", b.Emit(os.Stdout, &stack), nil, false) dict.AddWord("CR", nil, []string{"10", "EMIT"}, false) // emit a newline // logic dict.AddWord("=", b.Eq(&stack), nil, false) dict.AddWord("0=", nil, []string{"0", "="}, false) dict.AddWord("<>", b.NEq(&stack), nil, false) dict.AddWord(">", b.Gt(&stack), nil, false) dict.AddWord("<", b.Lt(&stack), nil, false) dict.AddWord(">=", b.GtEq(&stack), nil, false) dict.AddWord("<=", b.LtEq(&stack), nil, false) dict.AddWord("0<", nil, []string{"0", "<"}, false) dict.AddWord("0>", nil, []string{"0", ">"}, false) // stack manipulation dict.AddWord("DUP", b.Dup(&stack), nil, false) dict.AddWord("SWAP", b.Swap(&stack), nil, false) dict.AddWord("OVER", b.Over(&stack), nil, false) dict.AddWord("DROP", b.Drop(&stack), nil, false) dict.AddWord("ROT", b.Rot(&stack), nil, false) // debugging dict.AddWord("WORDS", b.Words(dict), nil, false) dict.AddWord("FLAGS", b.Flags(c), nil, false) dict.AddWord(".S", b.Debug(&stack), nil, false) dict.AddWord(".R", b.Debug(&rstack), nil, false) dict.AddWord("R>", b.RFrom(&stack, &rstack), nil, false) dict.AddWord(">R", b.ToR(&stack, &rstack), nil, false) dict.AddWord("R@", b.RFetch(&stack, &rstack), nil, false) // branching dict.AddWord("DO", b.Do(&stack, &rstack), nil, false) dict.AddWord("LOOP", b.Loop(&stack, &rstack), nil, false) dict.AddWord("I", b.I(&stack, &rstack), nil, false) // exit dict.AddWord("BYE", b.Quit(), nil, false) reader := bufio.NewReader(os.Stdin) fmt.Print("prosper\n") // read loop for { if c.Flags["Immediate"] { fmt.Print("> ") } else { fmt.Print(" ") } line, err := reader.ReadString('\n') if err != nil { fmt.Println(err.Error()) os.Exit(1) } line = strings.TrimSpace(line) err = c.Eval(line + " ") // append a space to make sure we always close out our parse loop if errors.Is(err, ErrExit) { fmt.Printf("bye\n") os.Exit(0) } else if err != nil { fmt.Printf("error in evaluation: %v\n", err) } else if c.Flags["Immediate"] { fmt.Print("ok\n") } } }