jaoswald / cl-comfy-6502

Baker's COMFY compiler for the 6502 ported to Common Lisp

This URL has Read+Write access

cl-comfy-6502 / macro-test.lisp
100644 74 lines (61 sloc) 1.951 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
;;; macro-test.lisp
 
(defun match-variable-p (thing)
  (and (symbolp thing) (char= (char (symbol-name thing) 0) #\?)))
 
(defun match-predicate (x)
  (and (consp x) (eq (car x) :in)))
 
(defun bindings-created (pattern &optional existing)
  (cond
    ((null pattern) nil)
    ((match-variable-p pattern)
     (if (member pattern existing)
nil
(list pattern)))
    ((atom pattern) nil)
    ((eq (car pattern) 'quote) nil)
    ((match-predicate pattern)
     (if (endp (cddr pattern))
(let ((var (caddr pattern)))
(if (member var existing)
nil
(list var)))))
    (t ; pattern is a CONS
     (let ((car-bindings (bindings-created (car pattern)
existing)))
       (append car-bindings (bindings-created (cdr pattern)
(append car-bindings
existing)))))))
    
 
(defun rr-expander (form)
  "Returns two values, the first is T if a match was achieved,
the second is then the expansion.
If no match was possible, the first value is NIL and the
second is the original form"
  (multiple-value-bind (match-1 expansion-1)
      (let ((car-var (car form))
(cdr-var (cdr form)))
(if (eql car-var 'rr-example)
(if (null cdr-var)
(values t '(8 rl))
(values nil form))
(values nil form)))
    (if match-1 (values match-1 expansion-1)
(multiple-value-bind (match-2 expansion-2)
(let ((car-var (car form))
(cdr-var (cdr form)))
(if (eql car-var 'rr-example)
(let ((?place (car cdr-var))
(cddr-var (cdr cdr-var)))
(if (null cddr-var)
(values t `(seq push (l ,@?place)
rr-example (st ,@?place)
pop))
(values nil form)))
(values nil form)))
(if match-2
(values match-2 expansion-2)
(values nil form))))))
 
(rr-expander '(rr-example))
 
;; --> T, (8 RL)
 
(rr-expander '(rr-example (loc)))
 
;; --> T, (SEQ PUSH (L LOC) RR-EXAMPLE (ST LOC) POP)
 
(rr-expander '(rr-mismatch))
 
;; --> NIL, (RR-MISMATCH)