;;;; sam-d.lisp
(defpackage sam-d (:use cl cl-user))
(in-package sam-d)
(defclass ext-proc ()
((2way :accessor 2way)
(proc :accessor proc)))
(defclass sam-d (ext-proc)
((2sam :initform (list '|:-(|) :accessor 2sam)
(fsam :initform (list '|:-)|) :accessor fsam)
(dirty :initform nil :accessor dirty)))
(defmethod shared-initialize :after ((obj sam-d) names &rest args)
(declare (ignore unused names args))
(multiple-value-bind (2way unused proc)
(ext:run-program "9" '("sam" "-d") :wait nil)
(setf (slot-value obj '2way) 2way
(slot-value obj 'proc) proc)))
(defmethod wstrm ((obj sam-d))
(two-way-stream-output-stream (2way obj)))
(defmethod rstrm ((obj sam-d))
(two-way-stream-input-stream (2way obj)))
(defvar *sam-d* (make-instance 'sam-d))
(defun fin ()
(format (wstrm *sam-d*) "=~%")
(force-output (wstrm *sam-d*))
(loop for line = (read-line (rstrm *sam-d*))
do (format t "~a~%" line) while (not (search "; #" line)))
(when (listen (rstrm *sam-d*))
(loop for ch = (read-char-no-hang (rstrm *sam-d*))
while ch do (princ ch))))
(define-symbol-macro % (fin))
(defun sam (say)
(format (wstrm *sam-d*) "~a~%" say)
(force-output (wstrm *sam-d*)))
(defun sam-reader (s c n)
(declare (ignore c n))
`(progn (sam (coerce
',(loop
for ch = (read-char s)
while (not (and (char= ch #\#)
(char= (peek-char nil s) #\])))
collecting ch
finally (read-char-no-hang s))
'string))
(fin)))
(set-dispatch-macro-character #\# #\[ #'sam-reader)
(defmacro 2s (&body body)
`(with-input-from-string (s (format nil "#[~@{~a~^ ~}#]" ,@body))
(eval (read s))))
(defun rs (start end)
(with-output-to-string (*standard-output*)
(sam (format nil "~a,~a" start end))))