(setf *load-print* T)
(defstruct link (key nil) (sublinks nil))
(defun link-contents (link) (link-sublinks link))
(defsetf link-contents (link) (value)
`(setf (link-sublinks ,link) ,value))
(defun next-link (key link flag)
(cond ( (find key (link-sublinks link) :key #'link-key) )
( flag
(let ((sublink (make-link :key key)))
(push sublink (link-sublinks link))
sublink))
( T NIL)))
(defun query-update (s-expr link flag)
(cond ( (and (not flag) (not (link-p link))) NIL )
( (atom s-expr) (next-link s-expr link flag) )
( T (let* ((A (next-link '*CONS* link flag))
(B (query-update (car s-expr) A flag))
(C (query-update (cdr s-expr) B flag)))
C))))
(defun query (s-expr link)
(let ((result (query-update s-expr link NIL)))
(and (link-p result) (link-contents result))))
(defun update (s-expr link)
(let ((result (query-update s-expr link T)))
(and (link-p result)
(or (link-contents result)
(setf (link-contents result) s-expr)))))
(setf *FOO*
(make-link :key 'FOO :sublinks
(list
(make-link :key '*CONS* :sublinks
(list
(make-link :key 'BOY :sublinks
(list
(make-link :key '*CONS* :sublinks
(list
(make-link :key 'JACK :sublinks
(list
(make-link :key NIL :sublinks '(BOY JACK)))
))
))
)
(make-link :key 'GIRL :sublinks
(list
(make-link :key '*CONS* :sublinks
(list
(make-link :key 'JILL :sublinks
(list
(make-link :key NIL :sublinks '(GIRL JILL)))
))
))
)
(make-link :key 'DOG :sublinks
(list
(make-link :key '*CONS* :sublinks
(list
(make-link :key 'REX :sublinks
(list
(make-link :key NIL :sublinks '(DOG REX)))
)
(make-link :key 'SPOT :sublinks
(list
(make-link :key NIL :sublinks '(DOG SPOT)))
))
))
))
))
)
)
; Loading #p"/h/tas/fischman/h06-solved".
; LINK
; LINK-CONTENTS
; LINK-CONTENTS
; NEXT-LINK
; QUERY-UPDATE
; QUERY
; UPDATE
; (*CONS* *CONS* A B C)
; Warning: Declaring *FOO* special.
; #S(LINK
; etc. etc. etc.
(defun del (s-expr node)
(labels
((del-s (s-expr link cut cp)
(let* ((kid1 (next-link '*CONS* link NIL))
(kid (next-link (car s-expr) kid1 NIL)))
(cond ((or (not link) (not kid) (not cp) (not kid1)) NIL)
((null (link-sublinks link)) NIL)
((null (cdr (link-sublinks kid1))) ;Only one child of link
(cond ((equal (link-key kid)
(car (reverse s-expr))) ;Right above terminal
(setf (link-sublinks cp)
(delete (link-key cut)
(link-sublinks cp) :key #'link-key)
)
T)
(T (del-s (cdr s-expr) kid cut cp)) ;far up
))
(T (cond ((equal (link-key kid)
(car (reverse s-expr))) ;mult. kids/done
(setf (link-sublinks kid1)
(delete (link-key kid)
(link-sublinks kid1) :key #'link-key)
)
)
;mult. kids/not done
(T (del-s (cdr s-expr) kid kid kid1))
)
)
)
)
))
(del-s s-expr node node node)
)
)
(update '(pres bill clinton) *FOO*)
(query '(girl jill) *FOO*)
(query '(dog rex) *FOO*)
(del '(dog rex) *FOO*)
(query '(dog rex) *FOO*)
(query '(girl jill) *FOO*)
(query '(dog spot) *FOO*)
(query '(pres bill clinton) *FOO*)
(del '(pres bill clinton) *FOO*)
(query '(pres bill clinton) *FOO*)
; DEL-S
; DEL
; (PRES BILL CLINTON)
; (GIRL JILL)
; (DOG REX)
; (#S(LINK :KEY SPOT :SUBLINKS (#S(LINK :KEY NIL :SUBLINKS (DOG SPOT)))))
; NIL
; (GIRL JILL)
; (DOG SPOT)
; (PRES BILL CLINTON)
; T
; NIL