git.fiddlerwoaroof.com
Raw Blame History
(defpackage :fwoar.lisp-sandbox.eclector-test
  (:use :cl )
  (:export ))
(in-package :fwoar.lisp-sandbox.eclector-test)

(defvar *verbose* nil)

(defclass my-reader ()
  ())
(defvar *eclector-client*
  (make-instance 'my-reader))

(fw.lu:defclass+ fw-package ()
  ((%name :initarg :name :reader fw-name)
   (%symbols :reader fw-symbols :initform (make-hash-table :test 'equal))))


(defvar *fw-packages*
  (alexandria:alist-hash-table (list (cons "KEYWORD" (fw-package "KEYWORD")))
                               :test 'equal))

(defmethod print-object ((o fw-package) s)
  (print-unreadable-object (o s :type t :identity t)
    (format s "~s with ~d symbols"
            (fw-name o)
            (hash-table-count (fw-symbols o)))))

(defgeneric my-intern (symbol package)
  (:method ((symbol string) (package package))
    (intern symbol package))
  (:method ((symbol string) (package fw-package))
    (when *verbose*
      (:printv symbol package))
    (if (eql package (ensure-package "KEYWORD"))
        (intern symbol (find-package "KEYWORD"))
        (fw.lu:if-let* ((s-p (find-package (fw-name package)))
                        (s-s (and s-p (find-symbol symbol s-p)))
                        (_ (not (eql s-p (symbol-package s-s)))))
          (my-intern symbol
                     (ensure-package
                      (package-name
                       (symbol-package s-s))))
          (alexandria:ensure-gethash symbol
                                     (fw-symbols package)
                                     (make-symbol symbol))))))

(defgeneric my-find-symbol (symbol package)
  (:method ((symbol string) (package package))
    (find-symbol symbol package))
  (:method ((symbol string) (package fw-package))
    (gethash symbol (fw-symbols package))))

(defun my-find-package (package)
  (gethash package *fw-packages*))

(defun ensure-package (package)
  (etypecase package
    (fw-package package)
    (package (ensure-package (package-name package)))
    (symbol (ensure-package (symbol-name package)))
    (string (alexandria:ensure-gethash package *fw-packages*
                                       (fw-package package)))))

(defmethod eclector.reader:interpret-symbol
    ((client my-reader) input-stream package-indicator symbol-name internp)
  (let ((package (case package-indicator
                   (:current (ensure-package *package*))
                   (:keyword (ensure-package "KEYWORD"))
                   (t        (or (ensure-package package-indicator))))))
    (if *verbose*
        (:printv package-indicator package symbol-name (my-intern symbol-name package))
        (my-intern symbol-name package))))

(defparameter *my-readtable*
  (let ((readtable (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
    (eclector.readtable:set-dispatch-macro-character
     readtable #\# #\+
     (lambda (stream char parameter)
       parameter
       char
       (:printv
        eclector.reader:*client*
        (let ((*verbose* t))
          (cons 'when-feature
                (eclector.reader:read stream t
                                      nil t))))))
    (eclector.readtable:set-dispatch-macro-character
     readtable #\# #\-
     (lambda (stream char parameter)
       parameter
       char
       (:printv
        eclector.reader:*client*
        (let ((*verbose* t))
          (cons 'unless-feature
                (eclector.reader:read stream t
                                      nil t))))))
    readtable))

(defun my-read-from-string (string)
  (let ((eclector.reader:*client* *eclector-client*)
        (eclector.reader:*readtable* *my-readtable*))
    (eclector.reader:read-from-string string)))