I'm working through l99 for lisp to learn lisp.
This is from here, and I wish to apply macros just for practice, to write all the ((x) (x (evaluate-boolean left bindings) (evaluate-boolean right bindings)))s with a macro.
(defun evaluate-boolean (expression bindings)
"Evaluates the boolean expression. Returns t or nil
expression := variable
| constant
| '(' operator expression expression ')'
| '(' not expression ')'
.
constant := 'true' | 'fail' .
variable := symbol .
operator := 'and' | 'or' | 'nand' | 'nor' | 'xor' | 'impl' | 'equ' .
bindings is a list of pairs (variable . constant)
"
(cond ((eq expression 'true) t)
((eq expression 'fail) nil)
((symbolp expression)
(let ((pair (assoc expression bindings)))
(if pair
(progn
(assert (member (cdr pair) '(true fail)))
(eql 'true (cdr pair)))
(error "No variable named ~A in the bindings." expression))))
((atom expression) (error "Invalid atom ~A in the expression." expression))
(t (case (length expression)
((2) (destructuring-bind (op subexpression) expression
(case op
((not) (not (evaluate-boolean subexpression bindings)))
(otherwise (error "Invalid operator ~A in ~A" op expression)))))
((3) (destructuring-bind (op left right) expression
(case op
((and) (and (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((or) (or (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((nand) (nand (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((nor) (nor (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((xor) (xor (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((impl) (impl (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
((equ) (equ (evaluate-boolean left bindings) (evaluate-boolean right bindings)))
(otherwise (error "Invalid operator ~A" op)))))
(otherwise (error "Invalid expression ~A" expression))))))
I've tried a few things, but they all seem to give errors reporting missing variables.
How would I implement macros
- as a
defmacro, or - using
macrolet, within theevaluate-booleanfunction?
I usually test stuff out with defun or defmacro first, then replace that with flet. Any advice on this?