(asdf:oos 'asdf:load-op 'ltk) (asdf:oos 'asdf:load-op 'cgn) (use-package :ltk) (use-package :cgn) ;; Inputs is of the form ;; k => name provided by user for input ;; v => the code generated to make an instance ;; ex: (:scale pony 0 10 1) creates an entry ;; where pony=>(make-instance 'scale ...) (defparameter *inputs* (make-hash-table)) ;; The parameters passed to the action function. (defparameter *params* nil) ;; Resets the model (defun reset-inputs () (setf *inputs* (make-hash-table)) (setf *action-function* nil) (setf *params* '())) ;; Converts a keyworded form to the appropriate LTK make-instance. ;; Side-effect: adds all non-:action instances to the *inputs* dictionary (defun convert-to-instance (keyword) (let ((key (car keyword)) (name (second keyword)) (vals (cddr keyword)) tmp) (cond ((equal key :scale) (progn (setf tmp `(make-instance 'scale ,:master main-label ,:label ,(format nil "~A" name) ,:from ,(first vals) ,:to ,(second vals) ,:resolution ,(or (third vals) 1) :orientation 'horizontal)) (setf (gethash name *inputs*) tmp)))) tmp)) (defmacro defmodel (name inputs &body action) (let (lst letz packer l3 model-name function-name function-parameters tp) ; Generates two symbols: NAME-MODEL and NAME-PROCESSOR (setf function-name (intern (format nil "~A-PROCESSOR" name))) (setf model-name (intern (format nil "~A-MODEL" name))) ; Two glorious effects: ; a. Generate a parameter listing for the processor function from the inputs. ; b. Convert the :scale syntax to LTK syntax (dolist (i inputs) (setf function-parameters (append function-parameters (list (second i)))) (setf lst (append lst (list (convert-to-instance i))))) (setf *action-function* (car `(#',name))) ; (format t "Action function: ~A ~%" *action-function*) (setf letz (append letz (list `(main-frame (make-instance 'frame))))) (setf letz (append letz (list `(main-label (make-instance 'labelframe :text "Inputs"))))) (setf letz (append letz (list `(action-frame (make-instance 'frame))))) (setf letz (append letz (list `(action-label (make-instance 'labelframe :text "Action"))))) (maphash #'(lambda (k v) (setf tp (append tp (list `(value ,k))))) *inputs*) (format t "~A ~%" tp) (maphash #'(lambda (k v) (setf letz (append letz (list (list k v))))) *inputs*) (setf letz (append letz (list `(action2 (make-instance 'button :text "Generate" :command #'(lambda () (funcall #',function-name ,@tp))))))) (setf packer (mapcar #'(lambda (l) `(pack ,l)) (mapcar #'first letz))) (maphash #'(lambda (k v) (setf l3 (append l3 (list `(setf (gethash ',k *inputs*) (value ,k)))))) *inputs*) (eval `(defun ,model-name () (with-ltk () (let* ,letz ,@packer ,@l3)))) `(defun ,function-name ,function-parameters (with-gnuplot ('linux) ,@action)))) (defmodel evett ( (:scale lamb 1 10) (:scale fvalue .01 .25 .01) (:scale n 1 5) ) (format t "~A ~A ~A~%" lamb fvalue n) (+ lamb fvalue n))