Add the first part of a code walker for the shader dsl
This commit is contained in:
parent
d8df41dbe4
commit
64a7d83e80
1 changed files with 67 additions and 0 deletions
67
src/render/shader/walker.lisp
Normal file
67
src/render/shader/walker.lisp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#|
|
||||
This file is a part of stoe project.
|
||||
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||
|#
|
||||
|
||||
(in-package :cl-user)
|
||||
(defpackage stoe.shader.walker
|
||||
(:nickname :walker)
|
||||
(:use :cl :utils))
|
||||
(in-package :stoe.shader.walker)
|
||||
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defvar *form-handlers* (make-hash-table)))
|
||||
|
||||
(defun e-list (list)
|
||||
"Apply `e' to all members of LIST."
|
||||
(mapcar #'e list))
|
||||
|
||||
(defmacro defhandler (symbol lambda-list &body body)
|
||||
(let ((syms (safe-list symbol)))
|
||||
(let ((func (intern (format nil "~A~A" 'handler- (first syms)))))
|
||||
`(progn
|
||||
(defun ,func ,lambda-list
|
||||
,@body)
|
||||
(setf ,@(loop for sym in syms
|
||||
collect `(gethash sym *form-handlers*)
|
||||
collect `',func))))))
|
||||
|
||||
(defun default-form-handler (first &rest form)
|
||||
"Handle FORM when FIRST is not a special form."
|
||||
`(list ,(if (symbolp first)
|
||||
`',first
|
||||
(e first)) ,@(e-list rest)))
|
||||
|
||||
(defun form-handler (first)
|
||||
"Retreive the handler for the symbol FIRST."
|
||||
(gethash first *form-handlers* 'default-form-handler))
|
||||
|
||||
(defun compiler-macroexpand-1 (form &optional env)
|
||||
"Try and expand the compiler macro defined for the first element of FORM if it exists."
|
||||
(let ((cm (and (listp form) (function-name-p (first form))
|
||||
(compiler-macro-function (first form) env))))
|
||||
(if cm
|
||||
(funcall *macroexpand-hook* cm form env)
|
||||
form)))
|
||||
|
||||
(defun e (form)
|
||||
"Walk across the specified form."
|
||||
(flet ((handle (form)
|
||||
(apply (form-handler (first form)) form)))
|
||||
(cond ((and (listp form) (gethash (first form) *form-handlers*))
|
||||
(handle form))
|
||||
(t
|
||||
(multiple-value-bind (form expanded)
|
||||
(macroexpand-1 form *env*)
|
||||
(cond (expanded
|
||||
(e form))
|
||||
(t
|
||||
(typecase form
|
||||
(null nil)
|
||||
(list
|
||||
(let ((next (compiler-macroexpand-1 form)))
|
||||
(if (eq form next)
|
||||
(handle form)
|
||||
(e next))))
|
||||
(t
|
||||
`',form)))))))))
|
||||
Loading…
Add table
Reference in a new issue