(read-sections))))
(make-model
:code (nth 0 sections)
- :interface (nth 1 sections)
+ :interface (parse-interface (nth 1 sections))
:info (nth 2 sections)
:turtle-shapes (nth 3 sections)
:version (nth 4 sections)
:link-shapes (nth 9 sections)
:model-settings (nth 10 sections)
:delta-tick (nth 11 sections))))
+
+;;; INTERFACE PARSER
+
+(defparameter *widget-parsers* nil)
+
+(defmacro defwidget-definition (type &rest definitions)
+ (let
+ ((lines (gensym)))
+ `(progn
+ (defstruct ,type
+ ,@(remove nil
+ (mapcar
+ (lambda (def) (when (find (car def) (list :int :double :boolean :choice :string)) (second def)))
+ definitions)))
+ (push
+ (list
+ (lambda (,lines)
+ (and
+ ,@(remove nil
+ (mapcar
+ (lambda (def n)
+ (let
+ ((line `(nth ,n ,lines)))
+ (case (car def)
+ (:specified `(string= ,(second def) ,line))
+ (:int `(parse-integer ,line :junk-allowed t))
+ (:double `(ignore-errors (coerce (read-from-string ,line) 'double-float)))
+ (:boolean `(or (string= "1" ,line) (string= "0" ,line)))
+ (:choice `(find ,line ',(mapcar #'car (third def)) :test #'string=)))))
+ definitions
+ (loop for i to (length definitions) collect i)))))
+ (lambda (,lines)
+ (,(read-from-string (format nil "make-~A" type))
+ ,@(apply #'append
+ (mapcar
+ (lambda (def n)
+ (let*
+ ((line `(nth ,n ,lines))
+ (val-getter
+ (case (car def)
+ (:int `(parse-integer ,line))
+ (:double `(coerce (read-from-string ,line) 'double-float))
+ (:boolean `(string= "1" ,line))
+ (:choice `(cadr (find ,line ',(third def) :key #'car :test #'string=)))
+ (:string line))))
+ (when val-getter (list (intern (symbol-name (cadr def)) :keyword) val-getter))))
+ definitions
+ (loop for i to (length definitions) collect i))))))
+ *widget-parsers*))))
+
+(defwidget-definition view
+ (:specified "GRAPHICS-WINDOW")
+ (:int left)
+ (:int top)
+ (:int right)
+ (:int bottom)
+ (:reserved "-1")
+ (:reserved "-1")
+ (:double patch-size)
+ (:reserved)
+ (:int font-size)
+ (:reserved)
+ (:reserved)
+ (:reserved)
+ (:reserved)
+ (:boolean wrapping-allowed-in-x)
+ (:boolean wrapping-allowed-in-y)
+ (:reserved)
+ (:int min-pxcor)
+ (:int max-pxcor)
+ (:int min-pycor)
+ (:int max-pycor)
+ (:choice update-mode (("0" :continuous) ("1" :tick-based)))
+ (:dump update-mode)
+ (:boolean show-tick-counter)
+ (:string tick-counter-label)
+ (:double frame-rate 30))
+
+(defun parse-interface (interface-as-strings)
+ (let
+ ((widgets-as-strings
+ (labels
+ ((separate-widgets-as-strings (lines &optional widget-as-strings)
+ (when lines
+ (if (string= "" (car lines))
+ (cons widget-as-strings (separate-widgets-as-strings (cdr lines)))
+ (separate-widgets-as-strings (cdr lines) (append widget-as-strings (list (car lines))))))))
+ (separate-widgets-as-strings interface-as-strings))))
+ (remove
+ nil
+ (mapcar
+ (lambda (widget-as-strings)
+ (let
+ ((parser (find-if (lambda (validator) (funcall validator widget-as-strings)) *widget-parsers* :key #'car)))
+ (when parser (funcall (cadr parser) widget-as-strings))))
+ widgets-as-strings))))
(defpackage #:clnl (:use :common-lisp)
- (:export :run :boot :run-commands :run-reporter)
+ (:export #:run #:boot #:run-commands #:run-reporter)
(:documentation
"Main CLNL package
(defpackage #:clnl-parser
(:use :common-lisp)
- (:export :parse)
+ (:export #:parse)
(:documentation
"CLNL Parser
(defpackage #:clnl-transpiler
(:use :common-lisp)
- (:export :transpile-commands :transpile-reporter)
+ (:export #:transpile-commands #:transpile-reporter)
(:documentation
"CLNL Transpiler
(defpackage #:clnl-nvm
(:use :common-lisp)
- (:export :export-world :create-world :current-state
+ (:export #:export-world #:create-world #:current-state
; API as used by transpiled NetLogo programs
#:ask
#:create-turtles
(defpackage #:clnl-lexer
(:use :common-lisp)
- (:export :lex)
+ (:export #:lex)
(:documentation
"CLNL Lexer
(defpackage #:clnl-interface
(:use :common-lisp)
- (:export :run :export-view)
+ (:export #:run #:export-view)
(:documentation
"CLNL Interface
(defpackage #:clnl-cli
(:use :common-lisp :cl-charms/low-level)
- (:export :run)
+ (:export #:run)
(:documentation
"CLNL CLI
(defpackage #:clnl-model
(:use :common-lisp :cl-charms/low-level)
- (:export :read-from-nlogo)
+ (:export #:read-from-nlogo)
(:documentation
"CLNL Model