\section{Read-Eval-Print Loop} I am loathe to create a REPL for Max, because it's completely against the Max architecture. REPL is not data flow, and using a REPL does not encourage data flow design. But for now, some better interface than the menu is needed, so here it is. <>= (in-package max) (defun repl () (loop (catch 'end-menu (max-print (catch 'eval (max-eval (max-read))))))) @ Evaluate a max expression. This REPL evaluation is unrelated to the data flow evaluator in the eval module. <>= (defun max-eval (expression) (cond ((listp expression) (max-eval-list expression)) ((stringp expression) (make-string-address expression)) ((symbolp expression) (max-eval-symbol expression)) (t (throw 'eval (format nil "Syntax error: ~A" expression))) ) ) (defun singleton-item (set) (let (addr) (mapset #'(lambda (item) (setq addr (addr-value item))) set) addr ) ) (defun max-eval-symbol (expression) (let* ((set (lookup (make-string-address (string-downcase expression)))) (n (set-count set))) (cond ((= 0 n) (throw 'eval (format nil "No Max objects found for symbol: ~A" expression))) ((= 1 n) (singleton-item set)) (t (catch 'selectobject (call-menu (make-menu (format nil "Choose object for symbol: ~A" expression) (menu-items-from-set set #'(lambda (item) (throw 'selectobject (addr-value item))) )) :submenup nil ))) ) ) ) @ Evaluate each item in a list: The first item should evaluate to a function address, and the other items are the arguments. Form the type product of the arguments and then apply the function to the product. <>= (defun max-eval-list (expression) (let* ((evallist (map 'list #'max-eval expression)) (argtype (apply #'type-product (map 'list #'(lambda (item) (make-address-form (addr-value *types*) (addr-type item))) (cdr evallist) ) )) (arg (make-product-addr argtype (cdr evallist)))) (function-apply (car evallist) arg) ) ) @ Display a prompt and get an S-exp. <>= (defun max-read () (format t "~%Max> ") (read) ) @ Display a Max address. Sets are shown in { item1, item2 } notation. Tuples are shown in < item1, item2 > notation. Strings are shown in double-quotes. Other addresses are shown as [type:value]. <>= (defun max-print (address) (if (not (listp address)) (format t "~A~%" address) ;else (let ((f (factors (addr-type address)))) (cond ((addr-type-equals *string-type* address) (print-string address)) ((addr-type-equals *set-type* address) ;(max-print (set-type address)) (format t "{") (let* ((n (set-count address)) (i 0)) (mapset #'(lambda (item) (max-print item) (incf i) (if (< i n) (format t ",~%") ) ) address ) ) (format t "}") ) ((> (length f) 1) ; tuple (format t "<") (let ((n (length f)) (i 0)) (map nil #'(lambda (item) (max-print item) (incf i) (if (< i n) (format t ", ") ) ) (product-values address) ) ) (format t ">") ) ((addr-type-equals *functions* address) (cond ((eq (class-of (function-implementation address)) (find-class 'enumerated-function)) (format t "[enumerated function]")) ((eq (class-of (function-implementation address)) (find-class 'builtin-function)) (format t "[builtin function]")) ) ) ; ((addr-type-equals *types* address) ; (format t "[type]")) (t (format t "[~A:~A]" (addr-type address) (addr-value address))) ) ) ) )