commit a576400ba980a182fcc44ee23182c8fa1d08b961 Spenser Truex <spensertruexonline@gmail.com> 2018-12-05 19:29:41 -0800 First commit.
README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ eforth.el | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+)
diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0e0a3a --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +eFORTH +=== +# What? +This is an implementation of an elisp-based FORTH. This means that elisp is used to write the function definitions. In fact, no FORTH function definitions are provided at all to the eforth macro from the library. +# How? +Forth code is gone through by the pointer moving through the call stack. When a non-function is found, it is added to the argument stack. When a function is found, it uses up the argument stack if it has arguments, or just runs if it is nullary. Nothing else is provided by the implementation. +# Why? +Needing to simulate a long set of keypresses to create an eight panel frame (37 in total), +the best option seemeed to be obviously to create a miniature language with 1 or 2 letter +abbreviations for each. Any arguments to a function can be passed before it in the list, +and there is no need to define a return stack. +# Usage: +example: + +``` +(require 'eforth) +(defun 8pan () + (interactive) + (eforth ((n . (lambda () (switch-to-buffer nil))) + (d . split-window-below) + (r . split-window-right) + (wr . windmove-right) + (wl . windmove-left) + (wd . windmove-down) + (wu . windmove-up) + (del . delete-other-windows) + (cf . make-frame-command) + (nf . other-frame)) + (cf del r r wr wr r d wr d wl wl d wl d wr n wr n wr n wl wl wl wd n + wr n wr n wr n wl wl wl wu nf))) +``` + +`M-x 8pan` will produce a new frame with eight panels (emacs-speak: "windows"). Here is how it works: + +`eforth` is called with two arguments: the environment, name to function bindings, and the eforth code list. You can see in this example +that there are no arguments used, since all of these are nullary functions. Here is how you might use arguments: + + +``` +(eforth ((ff . find-file)) ("~/some-file" ff)) +``` + +Here we ran `(find-file "~/some-file")`. + diff --git a/eforth.el b/eforth.el new file mode 100644 index 0000000..77adc3a --- /dev/null +++ b/eforth.el @@ -0,0 +1,35 @@ +(defun add-to-each (it list-of-lists) + (let ((l)) + (dolist (i list-of-lists (nreverse l)) + (push (list it i) l)))) +(defmacro eforth (lang list) + "Forth without a return stack." + `(progn ,@(let ((s) (l)) + (dolist (i list (nreverse (add-to-each 'funcall l))) + (if (assoc i lang) + (let ((fn (cdr (assoc i lang)))) + (if s + (progn (push `(lambda () (funcall #',fn ,@s)) l) + (setf s nil)) + (push `(lambda () (,fn)) l))) + (push i s)))))) +;; (defmacro eforth (lang list) +;; `(progn ,@(inner-eforth lang lsit))) +(eforth ((ff . find-file)) ("~/bogus/" ff)) +(eforth ((d . split-window-below)) + (d)) +(defun 8pan () + (interactive) + (eforth ((n . (lambda () (switch-to-buffer nil))) + (d . split-window-below) + (r . split-window-right) + (wr . windmove-right) + (wl . windmove-left) + (wd . windmove-down) + (wu . windmove-up) + (del . delete-other-windows) + (cf . make-frame-command) + (nf . other-frame)) + (cf del r r wr wr r d wr d wl wl d wl d wr n wr n wr n wl wl wl wd n + wr n wr n wr n wl wl wl wu nf))) +(provide 'eforth)