001  (ns beowulf.reader.macros
002    "Can I implement reader macros? let's see!
003     
004     We don't need (at least, in the Clojure reader) to rewrite forms like
005     `'FOO`, because that's handled by the parser. But we do need to rewrite
006     things which don't evaluate their arguments, like `SETQ`, because (unless
007     LABEL does it, which I'm not yet sure of) we're not yet able to implement
008     things which don't evaluate arguments.
009  
010     TODO: at this stage, the following should probably also be read macros:
011     DEFINE"
012    (:require [beowulf.cons-cell :refer [make-beowulf-list]]
013              [beowulf.host :refer [CONS LIST]]
014              [clojure.string :refer [join]]))
015  
016  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
017  ;;;
018  ;;; We don't need (at least, in the Clojure reader) to rewrite forms like
019  ;;; "'FOO", because that's handled by the parser. But we do need to rewrite
020  ;;; things which don't evaluate their arguments, like `SETQ`, because (unless
021  ;;; LABEL does it, which I'm not yet sure of) we're not yet able to implement
022  ;;; things which don't evaluate arguments.
023  ;;;
024  ;;; TODO: at this stage, the following should probably also be read macros:
025  ;;; DEFINE
026  ;;;
027  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
028  ;;;
029  ;;; Copyright (C) 2022-2023 Simon Brooke
030  ;;;
031  ;;; This program is free software; you can redistribute it and/or
032  ;;; modify it under the terms of the GNU General Public License
033  ;;; as published by the Free Software Foundation; either version 2
034  ;;; of the License, or (at your option) any later version.
035  ;;; 
036  ;;; This program is distributed in the hope that it will be useful,
037  ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
038  ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
039  ;;; GNU General Public License for more details.
040  ;;; 
041  ;;; You should have received a copy of the GNU General Public License
042  ;;; along with this program; if not, write to the Free Software
043  ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
044  ;;;
045  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
046  
047  (def ^:dynamic *readmacros*
048    {:car {'DEFUN (fn [f]
049                    (LIST 'SET (LIST 'QUOTE (second f))
050                          (LIST 'QUOTE (CONS 'LAMBDA (rest (rest f))))))
051           'SETQ (fn [f] (LIST 'SET (LIST 'QUOTE (second f)) (nth f 2)))}})
052  
053  (defn expand-macros
054    [form]
055    (try
056      (if-let [car (when (and (coll? form) (symbol? (first form))) 
057                     (first form))]
058        (if-let [macro (-> *readmacros* :car car)]
059          (make-beowulf-list (apply macro (list form)))
060          form)
061        form)
062      (catch Exception any
063        (println (join "\n"
064                       ["# ERROR while expanding macro:"
065                        (str "# Form: " form)
066                        (str "# Error class: " (.getName (.getClass any)))
067                        (str "# Message: " (.getMessage any))]))
068        form)))