Handle more operations and wrap in main function
Add handlers for infix operations (+ - * / %) and assignments. Wrap the resulting code in a main function. Prepare for the lambda-list processing
This commit is contained in:
parent
f8c1db2192
commit
1c1862dd6d
3 changed files with 63 additions and 22 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
(in-package :stoe.shader.compiler)
|
(in-package :stoe.shader.compiler)
|
||||||
|
|
||||||
(defun %defshader (lambda-list body)
|
(defun %defshader (lambda-list body)
|
||||||
(let ((shader (glsl-compile (cons 'newshader (cons lambda-list body)))))
|
(let ((shader (glsl-compile lambda-list body)))
|
||||||
shader))
|
shader))
|
||||||
|
|
||||||
(defmacro defshader (name lambda-list &body body)
|
(defmacro defshader (name lambda-list &body body)
|
||||||
|
|
|
||||||
|
|
@ -24,36 +24,77 @@
|
||||||
(defvar *env* nil
|
(defvar *env* nil
|
||||||
"A special variable used as a container for the macro environment.")
|
"A special variable used as a container for the macro environment.")
|
||||||
|
|
||||||
|
(defvar *verbose* nil
|
||||||
|
"Configure the verbosity of the compiler.
|
||||||
|
if non-nil, the dsl will be printed in comments together with the glsl code.")
|
||||||
|
|
||||||
|
(defmacro noop-handler (body)
|
||||||
|
`(format nil "/* ~((~{~a~^ ~})~) */~%" ,body))
|
||||||
|
|
||||||
|
(defhandler (declare block return-from catch load-time-value
|
||||||
|
macrolet symbol-macrolet flet labels let*
|
||||||
|
eval-when defun lambda tagbody setq function
|
||||||
|
the go unwind-protect progv quote) (&rest body)
|
||||||
|
"Handle the unsupported keywords. For the time being,
|
||||||
|
the forms comprised of these keywords will be printed in comments."
|
||||||
|
(noop-handler body))
|
||||||
|
|
||||||
(defhandler newshader (newshader lambda-list &rest body)
|
(defhandler newshader (newshader lambda-list &rest body)
|
||||||
|
(declare (ignore newshader lambda-list))
|
||||||
(walk-list body))
|
(walk-list body))
|
||||||
|
|
||||||
|
(defhandler (progn locally) (progn &rest body)
|
||||||
|
"Handle the progn special form."
|
||||||
|
(declare (ignore progn))
|
||||||
|
(format nil "~{~a;~%~}" (walk-list body)))
|
||||||
|
|
||||||
(defhandler let (let bindings &rest body)
|
(defhandler let (let bindings &rest body)
|
||||||
(let* ((names (loop for binding in bindings
|
"Handle the variables declaration special form."
|
||||||
collect (safe-first binding)))
|
(declare (ignore let))
|
||||||
(symbol-macrolet-names (loop for name in names
|
(format nil "~{~a;~%~}~%~a"
|
||||||
when (nth-value 1 (macroexpand-1 name *env*))
|
(loop for binding in bindings
|
||||||
collect name)))
|
collect (format nil "~@[~vt~]~(~a~) ~(~a~)~@[ = ~(~a~)~]"
|
||||||
(apply #'concatenate 'string
|
(when (> *current-indent* 0)
|
||||||
(append (loop for binding in bindings
|
*current-indent*)
|
||||||
collect (format nil "~@[~vt~]~(~a ~a~)~@[ = ~a~];~%"
|
(second binding) (first binding)
|
||||||
(when (> *current-indent* 0)
|
(if (and (cddr binding)
|
||||||
*current-indent*)
|
(not (cdddr binding)))
|
||||||
(second binding) (first binding)
|
(walk-1 (third binding))
|
||||||
(if (and (cddr binding)
|
(walk-list (cddr binding)))))
|
||||||
(not (cdddr binding)))
|
(format nil "~{~a;~%~}" (walk-list body))))
|
||||||
(walk-1 (third binding))
|
|
||||||
(walk-list (cddr binding)))))
|
(defhandler setf (setf &rest pairs)
|
||||||
(walk-list body)))))
|
"Handle the assignment special form."
|
||||||
|
(declare (ignore setf))
|
||||||
|
(let ((vars (loop for s in pairs by #'cddr collect s)))
|
||||||
|
(let ((expanded (loop for n in vars
|
||||||
|
for r in (rest pairs) by #'cddr
|
||||||
|
collect n collect (walk-1 r))))
|
||||||
|
(format nil "~@[~vt~]~{~(~a~) = ~(~a~)~^;~%~}"
|
||||||
|
(when (> *current-indent* 0)
|
||||||
|
*current-indent*)
|
||||||
|
expanded))))
|
||||||
|
|
||||||
|
(defhandler (+ - * / %) (op &rest body)
|
||||||
|
"Handle the standard infix operations."
|
||||||
|
(flet ((oper (a b)
|
||||||
|
(format nil "~a ~(~a~) ~a"
|
||||||
|
(if (listp a) (format t "(~a)" (walk-1 a)) a) op
|
||||||
|
(if (listp b) (format nil "(~a)" (walk-1 b)) b))))
|
||||||
|
(reduce #'oper body)))
|
||||||
|
|
||||||
(defun default-handler (first &rest rest)
|
(defun default-handler (first &rest rest)
|
||||||
"Handle a simple function call."
|
"Handle a simple function call."
|
||||||
(format nil "~@[~vt~]~(~a (~{~a~^, ~})~);~%"
|
(format nil "~@[~vt~]~(~a~) (~{~(~a~)~^, ~})"
|
||||||
(when (> *current-indent* 0)
|
(when (> *current-indent* 0)
|
||||||
*current-indent*)
|
*current-indent*)
|
||||||
(if (symbolp first)
|
(if (symbolp first)
|
||||||
first
|
first
|
||||||
(walk-1 first)) (walk-list rest)))
|
(walk-1 first)) (walk-list rest)))
|
||||||
|
|
||||||
(defun glsl-compile (form)
|
(defun glsl-compile (lambda-list body)
|
||||||
(let ((*current-indent* 0))
|
(declare (ignore lambda-list))
|
||||||
(walk form *form-handlers* #'default-handler *env*)))
|
(format nil "~%~a~%void main ()~%{~%~a}~%"
|
||||||
|
|
||||||
|
(let ((*current-indent* 2))
|
||||||
|
(walk `(progn ,body) *form-handlers* #'default-handler *env*))))
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
|
|
||||||
(defmacro defhandler (symbol lambda-list &body body)
|
(defmacro defhandler (symbol lambda-list &body body)
|
||||||
(let ((syms (safe-list symbol)))
|
(let ((syms (safe-list symbol)))
|
||||||
(let ((func (intern (format nil "~A~A" 'handler- (first syms)))))
|
(let ((func (intern (format nil "~a~a" 'handler- (first syms)))))
|
||||||
`(progn
|
`(progn
|
||||||
(defun ,func ,lambda-list
|
(defun ,func ,lambda-list
|
||||||
,@body)
|
,@body)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue