Recently Written · git

Forthe

Forth-like DSL.

git clone https://github.com/equwal/Forthe

Log | Files | Refs


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)