1 (in-package #:avm2-compiler
)
3 ;;; pieces of sicl/conditionals.lisp that work so far
5 (let ((*symbol-table
* *cl-symbol-table
*))
7 (defun proper-list-p (object)
11 (proper-list-p (cdr object
))
16 (swf-defmacro or
(&rest forms
)
19 (if (not (consp forms
))
20 (error 'malformed-body
:body forms
)
21 (if (null (cdr forms
))
23 (let ((temp-var (gensym)))
24 `(let ((,temp-var
,(car forms
)))
27 (or ,@(cdr forms
)))))))))
29 (swf-defmacro and
(&rest forms
)
32 (if (not (consp forms
))
33 (error 'malformed-body
:body forms
)
34 (if (null (cdr forms
))
41 (swf-defmacro when
(form &body body
)
42 (if (not (proper-list-p body
))
43 (error 'malformed-body
:body body
)
48 (swf-defmacro unless
(form &body body
)
49 (if (not (proper-list-p body
))
50 (error 'malformed-body
:body body
)
56 (swf-defmacro cond
(&rest clauses
)
57 (if (not (proper-list-p clauses
))
58 (error 'malformed-cond-clauses
:clauses clauses
)
61 (let ((clause (car clauses
)))
62 (if (not (and (proper-list-p clause
)
64 (error 'malformed-cond-clause
66 (if (null (cdr clause
))
68 (cond ,@(cdr clauses
)))
70 (progn ,@(cdr clause
))
71 (cond ,@(cdr clauses
)))))))))
73 (defun eql-ify (keys variable
)
76 (cons `(eql ,variable
,(car keys
))
77 (eql-ify (cdr keys
) variable
))))
79 ;;; This function turns a list of CASE clauses into nested IFs. It
80 ;;; checks that the list of clauses is a proper list and that each
81 ;;; clause is also a proper list. It also checks that, if there is an
82 ;;; otherwise clause, it is the last one.
83 (defun expand-case-clauses (clauses variable
)
86 (if (not (consp clauses
))
87 (error 'malformed-case-clauses
89 (let ((clause (car clauses
)))
90 (unless (and (proper-list-p clause
)
92 (error 'malformed-case-clause
94 (if (or (eq (car clause
) 'otherwise
)
96 (if (null (cdr clauses
))
97 `(progn ,@(cdr clause
))
98 (error 'otherwise-clause-not-last
99 :clauses
(cdr clauses
)))
100 ;; it is a normal clause
101 (let ((keys (car clause
))
102 (forms (cdr clause
)))
105 `(if (eql ,variable
,keys
)
107 ,(expand-case-clauses (cdr clauses
) variable
))
108 (if (not (proper-list-p keys
))
109 (error 'malformed-keys
111 `(if (or ,@(eql-ify keys variable
))
113 ,(expand-case-clauses (cdr clauses
) variable
))))))))))
115 (swf-defmacro case
(keyform &rest clauses
)
116 (let ((variable (gensym "CASE-VAR-")))
117 `(let ((,variable
,keyform
))
118 ,(expand-case-clauses clauses variable
))))
120 ;;; Turn a list of TYPECASE clauses into nested IFs. We check that
121 ;;; the list of clauses is a proper list, that each clause is a proper
122 ;;; list as well, and that, if there is an otherwise clause, it is the
124 (defun expand-typecase-clauses (clauses variable
)
127 (if (not (consp clauses
))
128 (error 'malformed-typecase-clauses
130 (let ((clause (car clauses
)))
131 (unless (and (proper-list-p clause
)
133 (error 'malformed-typecase-clause
135 (if (or (eq (car clause
) 'otherwise
)
137 (if (null (cdr clauses
))
138 `(progn ,@(cdr clause
))
139 (error 'otherwise-clause-not-last
140 :clauses
(cdr clauses
)))
141 ;; it is a normal clause
142 (let ((type (car clause
))
143 (forms (cdr clause
)))
144 `(if (%typep
,variable
,type
)
146 ,(expand-typecase-clauses (cdr clauses
) variable
))))))))
147 (swf-defmacro typecase
(keyform &rest clauses
)
148 (let ((variable (gensym)))
149 `(let ((,variable
,keyform
))
150 ,(expand-typecase-clauses clauses variable
))))