-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jkleiser
committed
May 30, 2016
1 parent
70ade1d
commit 6032842
Showing
2 changed files
with
87 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,10 @@ | ||
# toy-forth-in-pony | ||
A rudimentary Forth written in Pony | ||
This will not teach you much about how to implement real Forth. The most interesting part is probably | ||
how one can keep references to Pony functions (the Forth words) in a Map (the `_dict`). | ||
Without the crucial help I got from Chris and Joe, I would have had problems solving that part. | ||
|
||
I more or less ported the Scala code found at [/~https://github.com/joneshf/forla](/~https://github.com/joneshf/forla). | ||
|
||
The readline part is based on the Pony [readline example](/~https://github.com/ponylang/ponyc/tree/master/examples/readline). | ||
|
||
There may of course be things in my Pony code that could be improved. Feel free to file an issue. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use "collections" | ||
use "promises" | ||
use "term" | ||
|
||
type PartialFunRef is ({ref() ?} ref) | ||
type FunBox is ({box()} ref) | ||
type AnyMethod is (PartialFunRef | FunBox) | ||
|
||
class ForthRepl is ReadlineNotify | ||
let _env: Env | ||
let _dict: Map[String, AnyMethod] = _dict.create() | ||
let _stack: Array[I64] = _stack.create() | ||
var _i: U64 = 0 | ||
|
||
new create(env: Env) => | ||
_env = env | ||
_dict("+") = this~_add() | ||
_dict("-") = this~_sub() | ||
_dict("*") = this~_mul() | ||
_dict("/") = this~_div() | ||
_dict(".") = this~_print() | ||
|
||
fun ref apply(line: String, prompt: Promise[String]) => | ||
if line == "bye" then | ||
prompt.reject() | ||
else | ||
_interpret(line) | ||
_i = _i + 1 | ||
prompt(_i.string() + " > ") | ||
end | ||
|
||
fun ref _interpret(line: String) => | ||
for each_token in line.split(" ").values() do | ||
try | ||
_execute(_dict(each_token)) | ||
else | ||
_number(each_token) | ||
end | ||
end | ||
|
||
fun ref _execute(func: AnyMethod) => | ||
match func | ||
| let fun_ref: PartialFunRef => try fun_ref() else _env.out.print("Stack underflow") end | ||
| let fun_box: FunBox => fun_box() | ||
end | ||
|
||
fun ref _number(token: String) => | ||
try | ||
_stack.push(token.i64()) | ||
else | ||
_env.out.print(token + " ?") | ||
end | ||
|
||
fun ref _add() ? => _stack.push(_stack.pop() + _stack.pop()) | ||
fun ref _sub() ? => _stack.push(_stack.pop() - _stack.pop()) | ||
fun ref _mul() ? => _stack.push(_stack.pop() * _stack.pop()) | ||
fun ref _div() ? => _stack.push(_stack.pop() / _stack.pop()) | ||
|
||
fun _print() => | ||
for n in _stack.reverse().values() do | ||
_env.out.write(n.string() + " ") | ||
end | ||
_env.out.write("\n") | ||
|
||
actor Main | ||
new create(env: Env) => | ||
env.out.print("Use 'bye' to exit.") | ||
|
||
let term = ANSITerm(Readline(recover ForthRepl(env) end, env.out), env.input) | ||
term.prompt("0 > ") | ||
|
||
let notify = object iso | ||
let term: ANSITerm = term | ||
fun ref apply(data: Array[U8] iso) => term(consume data) | ||
fun ref dispose() => term.dispose() | ||
end | ||
|
||
env.input(consume notify) |