lisp-random / forth.lisp

;;;; forth.lisp
;;;; Copyright (c) 2013 Robert Smith

;;;; Experiments with a Forth-like language.

(defstruct forth
  (stack nil)
  (dict (make-hash-table)))

(defun lookup-word (word state)
  (gethash word (forth-dict state)))

(defun execute-word (word state)
  (let ((code (lookup-word word state)))
    (cond
      ((functionp code) (funcall code state))
      ((consp code) (interpret code state))
      ((null code) (error "Undefined word: ~A" word))
      (t (error "Invalid word: ~A" word)))))

(defun install-primitive (state word fn)
  (setf (gethash word (forth-dict state))
        fn))

(defun primordial-forth ()
  (let ((state (make-forth)))
    (macrolet ((defprim (name stuff &body body)
                 (declare (ignore stuff))
                 `(install-primitive state ',name
                                     (lambda (state)
                                       ,@body))))
      (defprim call ()
        (let ((f (pop (forth-stack state))))
          (interpret f state)))
      
      (defprim print ()
        (let ((x (pop (forth-stack state))))
          (format t "~A" x)))
      
      (defprim + ()
        (let* ((a (pop (forth-stack state)))
               (b (pop (forth-stack state))))
          (push (+ a b) (forth-stack state)))))
    
    ;; Return the state.
    state))

(defun interpret (words state)
  (dolist (word words state)
    (cond
      ((or (numberp word)
           (consp word)
           (stringp word)) (push word (forth-stack state)))
      ((symbolp word) (execute-word word state))
      (t (error "Unrecognized token: ~S" word)))))
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.