[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
SELECTP -- a useful new utility for pattern-matching (long)
- To: INFO-LISPM at MIT-MC
- Subject: SELECTP -- a useful new utility for pattern-matching (long)
- From: Philip E. Agre <AGRE at MIT-MC>
- Date: Wed ,16 Jun 82 11:52:00 EDT
Living in LMLIB;SELECT is a new macro called SELECTP, which is sort of a
generalization of SELECTQ. I have found it extremely useful in writing
compilers and that sort of thing. Here's an example of its use from the file
AGRE;SCDP, where many more examples can be found:
(defun unary-operation (command)
(selectp command
((#?op #?r) (memq op '(push pop)) t)
((assign #?r1 #?r2) (symbolp r2) (eq r1 r2))
((assign #?r (continuation-pointer #?label)) t t)
((assign #?r1 (#?ignore #?r2 #?r3)) t
(or (and (eq r1 r2) (eq r2 r3))
(and (constant-register-p r2) (constant-register-p r3))
(and (eq r1 r2) (constant-register-p r3))
(and (eq r1 r3) (constant-register-p r2))))
((assign #?r1 (#?ignore #?r2)) t (or (eq r1 r2) (constant-register-p r2)))
((#?ignore #?x #?y) (and (register-p x) (register-p y))
(or (eq x y) (constant-register-p x) (constant-register-p y)))
((#?ignore #?x) (register-p x) t)
(otherwise (ferror nil "Unrecognized command format: ~A" command))))
The syntax is
(SELECTP <object>
(<pattern> <condition> <sexp> ... <sexp>)
(<pattern> <condition> <sexp> ... <sexp>)
...
(<pattern> <condition> <sexp> ... <sexp>)
(OTHERWISE <sexp> <sexp>))
The value of <object> is matched against the <pattern>s one at a time until a
match succeeds and the accompanying <condition> evaluates to something
non-null, at which point the <sexp>'s associated with the <pattern> and
<condition> are evaluated one at a time and the last value is returned. The
<pattern>s can be arbitrary s-expressions, with variables signified by
#?variable. When the pattern is matched against the <object>'s value, the
variables are to bound to their matched values. Different occurences of the
same variable in a given pattern must match to the same thing, so that
(SELECTP '(A B C)
((#?X B #?X) T 'LOSE)
((#?X B #?Y) T 'WIN)
(OTHERWISE 'LOSE-BIG))
returns WIN. The variables mentioned in the <pattern>s need not be bound by
the user; they are bound by the expression resulting from the expansion of the
macro. (The variable #?IGNORE matches everything and doesn't become bound.
Using #?IGNORE for a variable you don't intend to make any use of avoids
"bound but not used" warnings from the compiler.) There is no actual pattern
matcher involved in the matching process; rather, an s-expression is consed up
by the macro which has the same effect. For example, the call to SELECTP just
presented expands to:
((LAMBDA (OBJECT &AUX X Y)
(COND ((AND (LISTP OBJECT) (PROGN (SETQ X (CAR OBJECT)) T)
(LISTP (CDR OBJECT)) (EQ (CAR (CDR OBJECT)) 'B)
(LISTP (CDR (CDR OBJECT))) (EQUAL X (CAR (CDR (CDR OBJECT))))
(NULL (CDR (CDR (CDR OBJECT)))))
'LOSE)
((AND (LISTP OBJECT) (PROGN (SETQ X (CAR OBJECT)) T)
(LISTP (CDR OBJECT)) (EQ (CAR (CDR OBJECT)) 'B)
(LISTP (CDR (CDR OBJECT)))
(PROGN (SETQ Y (CAR (CDR (CDR OBJECT)))) T)
(NULL (CDR (CDR (CDR OBJECT)))))
'WIN)
(T 'LOSE-BIG)))
'(A B C))
(In case your terminal lost, those control characters are greek letters.)
It seems to work in all Lisp Machine systems. Bugs/suggestions to AGRE@MIT-AI.