home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / LISP / PDLISP.ZIP / LED.L < prev    next >
Encoding:
Text File  |  1986-02-13  |  21.1 KB  |  714 lines

  1. ; LED.L - UNXLISP structure editor
  2. ;
  3. ; Copyright (c) 1985 by David Morein
  4. ; You can do anything you like with this file,
  5. ; as long as you aren't trying to put me out of
  6. ; business.
  7. ;
  8. ; Similar to, but rather simple-minded by comparison with,
  9. ; the BBN Interlisp editor.
  10. ;
  11. ; note - edit this file with tabs set to 4
  12. ;
  13. ; summary of LED commands:
  14. ;
  15. ; n, where n is an integer:
  16. ;
  17. ;   n > 0 ==> make the current expression
  18. ;   the nth element of the current expression
  19. ;
  20. ;   n < 0 ==> make the current expression
  21. ;   the nth from the last element of the 
  22. ;   current expression. (i.e., -1 selects
  23. ;   the last element, -2 the second from
  24. ;   the last, etc.)
  25. ;
  26. ;   n = 0 => pops the thread one level.
  27. ;
  28. ; ^ pops the thread all the way back to the top.
  29. ; OK ends the edit and accepts the altered expression.
  30. ; Q ends the edit with no changes.
  31. ; E evaluates an expression and prints its value.
  32. ; P prints the current expression.
  33. ; PP pretty-prints the current expression
  34. ; COPY copies the entire thread to a safe place.
  35. ; RESTORE restores the thread to the value which
  36. ;   was saved by copy.
  37. ; MARK sets a mark in the mark list
  38. ; < goes back 1 place in the mark list, but does not pop the mark list.
  39. ; << goes back 1 place in the mark list, and pops the mark list.
  40. ; POFF turns off the print flag.
  41. ; PON turns on the print flag.
  42. ;
  43. ; find command:
  44. ; (f e) searches for the expression e in the current expression.
  45. ; if found, the found expression becomes the new current expression.
  46. ;
  47. ; structure modification commands:
  48. ;
  49. ; (n e), n>1 replaces the nth element of the current expression with e
  50. ; (n e1 e2 ... em), n,m > 1 replaces the nth element of the
  51. ;   current expression with e1 e2 ... em.
  52. ; (-n e), n > 1 inserts e before the nth element of the current expression.
  53. ; (-n e1 e2 ... em), n,m > 1 inserts e1 ... em before the nth element
  54. ;   of the current expression.
  55. ; (r x y) "Replace" - replaces all occurrences of x in the
  56. ;          current expression by y. The replacement is done
  57. ;          throughout the current expression, and not just
  58. ;          at the top-most level. For example, if the current
  59. ;          expression were (LAMBDA (X Y) (+ X Y)), then
  60. ;          typing (r y z) would change the current expression
  61. ;          to (LAMBDA (X Z) (+ X Z)).
  62. ;
  63. ; parenthesis moving commands:
  64. ; (bi m n)  "Both In" - inserts parenthesis before the mth element and
  65. ;            after the nth element of the current expression.
  66. ;            For example, if the current expression were (a b c d e),
  67. ;            then executing (bi 3 4) would change it to (a b (c d) e).
  68. ;
  69. ; (bo n)    "Both Out" - removes both parenthesis from the nth
  70. ;            element of the current expression, and splices
  71. ;            its elements into the current expression. 
  72. ;            For example, if the current expression were
  73. ;            (a b (c d) e f), then executing (bo 3) would
  74. ;            result in (a b c d e f).
  75. ;
  76. ; (li n)    "Left In" - inserts a left parenthesis before the
  77. ;            nth element, and a matching right parenthesis
  78. ;            at the end of the current expression. For example,
  79. ;            if (a b c d e) were the current expression, then
  80. ;            executing (li 2) would result in (a (b c d e)).
  81. ;
  82. ; (lo n)    "Left Out" - removes a left parenthesis from the
  83. ;            nth element of the current expression, and
  84. ;            deletes all elements after the nth element.
  85. ;            For example, if the current expression were
  86. ;            (a b (c d) e f), then executing (lo 3) would
  87. ;            result in (a b c d).
  88. ;
  89. ; (ri m n)  "Right In" - moves the right paren at the end of
  90. ;            the mth element inward until it is after the nth
  91. ;            element of the mth element of the current expression.
  92. ;            The remainder of the mth element is elevated to
  93. ;            the top-most level of the current expression.
  94. ;            For example, if the current expression were
  95. ;            (a b (c d e) f g), then executing (ri 3 2) would
  96. ;            change it to (a b (c d) e f g).
  97. ;
  98. ; (ro n)    "Right Out" - moves the right parenthesis at
  99. ;            the end of the nth element out to the end of
  100. ;            the current expression. The rest of the elements
  101. ;            following the nth are moved inside of the
  102. ;            nth element. For example, if the current expression
  103. ;            were (a b (c d) e f) then executing (ro 3)
  104. ;            would change it to (a b (c d e f)).
  105. ;
  106. ; note - all of the above parenthesis moving commands take
  107. ;        negative arguments, which are processed in the same
  108. ;        way as simple numerical commands. That is, -1
  109. ;        refers to the last element of the current expression,
  110. ;        -2 to the second to the last element, and so on.
  111. ;
  112. ;
  113. (pdq /sys/cmd)              ;start at /sys/cmd.
  114. (mcdq led)                  ;make /sys/cmd/led
  115. (add-to-path '/sys/cmd/led)    ;put editor on reader-search-path.
  116. ;
  117. ; global symbols:
  118. ;
  119. ; global functions:
  120. (global 'ledfq 'ledeq 'ledpq 'ledvq)
  121. ;               
  122. ; editor commands:
  123. (global
  124. 'ok
  125. 'q
  126. 'e
  127. 'p
  128. 'pp
  129. 'mark
  130. '^
  131. '<<
  132. 'poff
  133. 'pon
  134. 'r
  135. 'i
  136. 'n
  137. 'p
  138. 'f
  139. 'ednth
  140. 'ri
  141. 'ro
  142. 'li
  143. 'lo
  144. 'bi
  145. 'bo
  146. 'm
  147. 'd)
  148. ;
  149. ; explanation of variables global to this file:
  150. ;   thread - list of expressions being edited.
  151. ;            (car thread) is the current expression.
  152. ;
  153. (setq printflag t)
  154. ; print on by default
  155. ;
  156. (setq printlevel 3)
  157. (setq maxlevel 100)
  158. ;
  159. ; ledeq - edits an arbitrary s-expression
  160. ;
  161. (def ledeq (nlambda (x)
  162.     (progn  (setq thread nil)
  163.             (setq m nil)
  164.             (lede1 x))))
  165. ;
  166. ;
  167. ; ledfq - edits the function definition cell of a symbol.
  168. ;
  169. (def ledfq (nlambda (fn)
  170.     (prog   ()
  171.             (pushpath '/sys/cmd/led)    ;put editor on reader-search-path.
  172.             (setq thread nil)           ;initialize the thread
  173. ;
  174. ; filter out symbols which do not have an editable fn def
  175. ;
  176.             (cond
  177.             ((or (null (getd fn)) (compiled-function-p fn))
  178.                     (return '(not editable))))
  179. ;
  180. ; edit the fn def
  181. ;
  182.             (putd fn (lede1 (getd fn)))
  183. ;
  184. ; pop editor off search-path
  185. ;
  186.             (poppath)
  187.             (return fn))))
  188. ;
  189. ; ledvq - edits the variable binding of a symbol
  190. ;
  191. (def ledvq (nlambda (someatom)
  192.     (progn
  193.             (setq thread nil)
  194.             (cond ((not (boundp someatom))
  195.                    (err "***> LEDV: symbol not bound as a variable.")))
  196.             (set someatom (lede1 (eval someatom)))
  197.             someatom)))
  198. ;
  199. ;
  200. ; ledpq - edits the property list of an atom.
  201. ;
  202. (def ledpq (nlambda (someatom)
  203.     (progn
  204.             (setq thread nil)
  205.             (setplist someatom (lede1 (symbol-plist someatom)))
  206.             someatom)))
  207. ;
  208. ; lede1 - edits an arbitrary s-expression
  209. ;   x   - expression to be edited
  210. ;   
  211. ; if the user accepts the changes via the OK command,
  212. ; then this function returns the edited expression;
  213. ; otherwise, it returns the original expression.
  214. ;
  215. (defun lede1 (x)
  216.     (prog   (c copied)                      ;prog variables
  217.             (setq old_value (copy-tree x))  ;save old value of x
  218. ;
  219. ; start the thread, if necessary
  220. ;
  221.             (cond ((null thread) (setq thread (list x))))
  222. ;
  223. ; initialize some variables, output 'LED', and print current expression:
  224. ;
  225.             (princ "LED")
  226.             (setq edok nil)         ;initialize editor accept flag
  227.             (setq edquit nil)       ;initialize editor quit flag
  228. ;
  229. ; enter main editing loop:
  230. ;
  231. editloop
  232. ;
  233. ; if the editor accept flag is set, then return the altered expression:
  234. ;
  235.             (cond (edok (return (car (last thread)))))
  236. ;
  237. ; if the editor quit flag is set, then return the original value:
  238. ;
  239.             (cond (edquit (return old_value)))
  240. ;
  241. ; if the printflag is set, then print the current expression:
  242. ;
  243.             (cond (printflag (terpri) (editcom 'p)))
  244. ;
  245. ; display the editor's prompt:
  246. ;
  247. outprompt
  248.             (terpri)
  249.             (princ '*)
  250. ;
  251. ; read a command:
  252. ;
  253.             (cond ((null (errset (setq c (read)))) (go editloop)))
  254. ;
  255. ; process the command:
  256. ;
  257. ; if the command was p or pp, output the current expression and loop back:
  258. ;
  259.             (cond   ((eq c 'p) (editcom 'p) (go outprompt))
  260.                     ((eq c 'pp) (editcom 'pp) (go outprompt)))
  261. ;
  262. ; otherwise, process the command normally:
  263. ;
  264.             (cond ((errset (editcom c)) t)
  265.                    (t (qmark c)))
  266.             (go editloop)))
  267. ;
  268. ; qmark - outputs a suspect command followed by a question mark.
  269. ;
  270. (def qmark (lambda (c)
  271.     (progn
  272.         (terpri)
  273.         (print c)
  274.         (princ '?)
  275.         (terpri))))
  276. ;
  277. ;
  278. ; editcom - processes an editor command.
  279. ;
  280. (defun editcom (c)
  281.     (progn
  282.             (cond
  283. ;
  284. ; integer - changes the current expression to be the nth
  285. ;           element of the current expression.
  286. ;
  287. ; this call to numberp should be replaced by integerp
  288. ;
  289.                 ((numberp c) (simpnum c) t)
  290. ;
  291. ; if c is atomic, then process an atomic command:
  292. ;
  293.                 ((atom c) (atomcom c) t)
  294. ;
  295. ; otherwise, process a list command:
  296. ;
  297.                 (t (listcom c) t))))
  298. ;
  299. ; atomcom - processes an atomic editor command
  300. ;
  301. (def atomcom (lambda (c)
  302.      (cond
  303. ;
  304. ; ok - sets the variable edok to t.
  305. ;
  306.             ((eq c 'ok)
  307.              (setq edok t))
  308. ;
  309. ; q - quits the edit with no changes
  310. ;
  311.             ((eq c 'q)
  312.              (setq edquit t))
  313. ;
  314. ; e - evaluates an expression & prints its value.
  315. ;
  316.             ((eq c 'e)
  317.              (errset (print (eval (read))))
  318.              (terpri))
  319. ;
  320. ; p - prints the current expression.
  321. ;
  322.             ((eq c 'p)
  323.              (eprint (car thread)))
  324. ;
  325. ; pp - pretty-prints the current expression.
  326. ;
  327.             ((eq c 'pp)
  328.              (terpri)
  329.              (errset (pp (car thread)))
  330.              (terpri))
  331. ;
  332. ; mark - sets a mark
  333. ;
  334.             ((eq c 'mark)
  335.              (setq m (cons thread m)))
  336. ;
  337. ; ^ - pop the thread back to the top
  338. ;
  339.             ((eq c '^)
  340. ;            (setq thread (list (last thread))))
  341.              (setq thread (last thread)));
  342. ;
  343. ; copy - copies current expression to a safe place
  344. ;
  345.             ((eq c 'copy)
  346.              (setq copied (copy-tree thread)))
  347. ;
  348. ; restore - restores current expression to value
  349. ;           which was saved by copy.
  350. ;
  351.             ((eq c 'restore)
  352.              (setq thread copied))
  353. ;
  354. ; < - goes back 1 place in the mark list
  355. ;
  356.             ((eq c '<)
  357.              (cond  (m (setq thread (car m)))
  358.                     (t (err "***> LED: no marks"))))
  359. ;
  360. ; << - same as < except pops the mark list
  361. ;
  362.             ((eq c '<<)
  363.              (cond  (m (setq thread (car m))
  364.                        (setq m (cdr m)))
  365.                     (t (err "***> LED: no marks"))))
  366. ;
  367. ; poff - turn off the print flag:
  368. ;
  369.             ((eq c 'poff)
  370.              (setq printflag nil))
  371. ;
  372. ; pon - turn on the print flag:
  373. ;
  374.             ((eq c 'pon)
  375.              (setq printflag t))
  376. ;
  377. ; otherwise, indicate that we couldn't parse the command:
  378. ;
  379.             (t (err nil)))))
  380. ;
  381. ; listcom - this function processes a list command if it can,
  382. ;           otherwise signals an error with ERR.
  383. ;
  384. (def listcom (lambda (c)
  385.     (prog   (c1 c2 c3)
  386.             (setq ce (car thread))          ; ce := current expression
  387.             (setq c1 (car c))               ; c1 := 1st element of command list
  388.             (setq c2 (cadr c))              ; c2 := 2nd element of command list
  389.             (setq c3 (caddr c))             ; c3 := 3rd element of command list
  390. ;
  391. ; dispatch on c1, the 1st element of the command list:
  392. ;
  393.             (return
  394.             (cond   
  395.                 ((numberp c1)
  396.                  (compnum c))               ;complex # command
  397.  
  398.         ((eq c1 'd)                 ;delete command
  399.          (leddelete c2))
  400.  
  401.         ((eq c1 'i)                 ;insert command
  402.          (ledinsert c2 c3))
  403.  
  404.                 ((eq c1 'r)                 ;replace command
  405.                  (dsubst c2 c3 ce))
  406.  
  407.                 ((eq c1 'f)                 ;find command
  408.                  (ledfind c2))
  409.  
  410.                 ((eq c1 'nth)   
  411.                  (setq thread (cons (lednthcdr c3 c2) thread)))
  412.  
  413.                 ((member c1 '(ri ro li lo bi bo))           ;paren move command
  414.                  (apply1 c1 (append (cdr c) (list ce))))
  415. ;
  416. ; failure to parse command.
  417. ;
  418.                 (t (err nil)))))))
  419. ;
  420. ; printlevel - swaps the current printlevel with x
  421. ;
  422. (def printlevel (lambda (x)
  423.     (prog   (a)
  424.             (setq a printlevel)
  425.             (setq printlevel x)
  426.             (return a))))
  427. ;
  428. ; simpnum - processes simple numeric commands
  429. ;   n = 0 ==> go up 1 level in the thread
  430. ;   n > 0 ==> go to the nth element of current expression
  431. ;             (expression # 1 is the left-most expression)
  432. ;   n < 0 ==> go to the nth from the last element of the
  433. ;             current expression
  434. ;
  435. (def simpnum (lambda (n)
  436.     (cond   
  437. ;
  438. ; n = 0 => up 1 level in thread
  439. ;
  440.             ((equal n 0)
  441.         (cond
  442.             ((null (cdr thread))
  443.                 (err "***> LED: already at top of thread"))
  444.             (t (setq thread (cdr thread)))))
  445. ;
  446. ; n > 0 => go to nth element of current expression
  447. ;
  448.             ((> n 0)
  449.                  (cond ((> n (length (car thread)))
  450.                          (err "***> LED: numeric arg larger than list size"))
  451.                         (t (setq thread
  452.                                 (cons
  453.                                     (nth (sub1 n) (car thread))
  454.                                     thread)))))
  455. ;
  456. ; check for negative number too big:
  457. ;
  458.             ((> (* n -1) (length (car thread)))
  459.                 (err "***> LED: numeric arg larger than list size"))
  460. ;
  461. ; n < 0 => go to nth element from end of current expr
  462. ;
  463.             (t (setq thread
  464.                     (cons
  465.                         (nth
  466.                             (+ (length (car thread)) n)
  467.                             (car thread))
  468.                         thread))))))
  469. ;
  470. ; compnum - processes a numeric list command
  471. ;
  472. (def compnum (lambda (c)
  473.     (cond   ((> (car c) 0)
  474.                  (cond  ((> (car c) (length (car thread)))
  475.                          (err nil))
  476.                         (t  (rplaca
  477.                                 thread
  478.                                 (linkbend
  479.                                     (sub1 (car c))
  480.                                     (car thread)
  481.                                     (cdr c)
  482.                                     nil)))))
  483.             ((or    (equal (car c) 0)
  484.                     (null (cdr c))
  485.                     (> (* -1 (car c)) (length (car thread))))
  486.              (err nil))
  487.             (t (rplaca
  488.                     thread
  489.                     (linkbend
  490.                         (sub1 (* -1 (car c)))
  491.                         (car thread)
  492.                         (cdr c)
  493.                         t))))))
  494. ;
  495. ; linkbend - handy dandy link bending routine.
  496. ;            Handles the dirty work for (# ...) commands.
  497. ;
  498. (def linkbend (lambda (n x r d)
  499.     (prog ()
  500.         (cond   ((not (equal n 0))
  501.                  (rplacd (nthcdr (sub1 n) x)
  502.                          (nconc r
  503.                                 (cond   (d (nthcdr n x))
  504.                                         (t (nthcdr (add1 n) x))))))
  505.                 (d  (attach (car r) x)
  506.                     (rplacd x (nconc (cdr r) (cdr x))))
  507.                 (r  (rplaca x (car r))
  508.                     (rplacd x (nconc (cdr r) (cdr x))))
  509.                 (t  (print (list 'aha x))       ;from BBN editor.
  510.                     (rplaca x (cadr x))
  511.                     (rplacd x (cddr x))))
  512.             (return x))))
  513. ;
  514. ;
  515. ; attach - auxilliary function for linkbend
  516. ;
  517. (def attach (lambda (x y)
  518.     (prog   (a)
  519.             (setq a (cons (car y) (cdr y)))
  520.             (rplaca y x)
  521.             (rplacd y a)
  522.             (return y))) )
  523. ;
  524. ;
  525. ; ledmatch - pattern match routine for LED
  526. ;            returns T iff x matches y
  527. ;
  528. ; notes:
  529. ; (1) if the second element of x is eq to '-, then
  530. ;     T is returned if x and y are both lists and the first
  531. ;     element of each matches.
  532. ; (2) if x is eq to '&, then it matches anything.
  533. ;
  534. (def ledmatch (lambda (x y srchlevel)
  535.     (cond   ((eql maxlevel srchlevel)
  536.                 (err "***> LED: max search level exceeded."))
  537.             ((equal x y) t)
  538.             ((atom x) (eq x '&))
  539.             ((atom y) nil)
  540.             ((ledmatch (car x) (car y) (+ srchlevel 1))
  541.              (or    (eq (cadr x) '-)
  542.                     (ledmatch (cdr x) (cdr y) (+ srchlevel 1)))))))
  543. ;
  544. ; lednthcdr - special nthcdr function which takes negative arguments:
  545. ;
  546. (def lednthcdr (lambda (n x)
  547.     (cond
  548.         ((< n 0)
  549.             (cond   ((> (* n -1) (length x))
  550.                         (err "***> LED: numeric arg larger than list size."))
  551.                     (t (nthcdr (+ n (length x)) x))))
  552.         ((> n 0)
  553.             (cond   ((> n (length x))
  554.                         (err "***> LED: numeric arg larger than list size."))
  555.                     (t (nthcdr (sub1 n) x))))
  556.         ((equal n 0)
  557.             (err "***> LED: invalid arg.")))))
  558. ;
  559. ;                                               
  560. ; ro - "right out" command, moves right parenthesis out.
  561. ;
  562. (def ro (lambda (n x)
  563.     (prog   (a)
  564.             (setq a (lednthcdr n x))
  565.             (cond ((or (null a) (atom (car a))) (err nil)))
  566.             (rplacd (last (car a)) (cdr a))
  567.             (rplacd a nil))) )
  568. ;
  569. ;
  570. ; ri - "right in" command, moves right parenthesis in.
  571. ;
  572. (def ri (lambda (m n x)
  573.     (prog   (a b)
  574.             (setq a (lednthcdr m x))
  575.             (setq b (lednthcdr n (car a)))
  576.             (cond ((or (null a) (null b)) (err nil)))
  577.             (rplacd a (nconc (cdr b) (cdr a)))
  578.             (rplacd b nil))) )
  579. ;
  580. ;
  581. ; li - "left in" command, moves left parenthesis in.
  582. ;
  583. (def li (lambda (n x)
  584.     (prog   (a)
  585.             (setq a (lednthcdr n x))
  586.             (cond ((null a) (err nil)))
  587.             (rplaca a (cons (car a) (cdr a)))
  588.             (rplacd a nil))) )
  589. ;
  590. ;
  591. ; lo - "left out" command, moves left parenthesis out.
  592. ;
  593. (def lo (lambda (n x)
  594.     (prog   (a)
  595.             (setq a (lednthcdr n x))
  596.             (cond ((or (null a) (atom (car a))) (err nil)))
  597.             (rplacd a (cdar a))
  598.             (rplaca a (caar a))) ))
  599. ;
  600. ;
  601. ; bi - "both in" command, moves both parenthesis in.
  602. ;
  603. (def bi (lambda (m n x)
  604.     (prog   (a b)
  605.             (setq b (cdr (setq a (lednthcdr n x))) )
  606.             (setq x (lednthcdr m x))
  607.             (cond ((and a (null (> (length x))) )
  608.                    (rplacd a nil)
  609.                    (rplaca x (cons (car x) (cdr x)))
  610.                    (rplacd x b))
  611.                   (t  (err nil))) )))
  612. ;
  613. ;
  614. ; bo - "both out" command, moves both parenthesis out.
  615. ;
  616. (def bo (lambda (n x)
  617.     (progn
  618.         (setq x (lednthcdr n x))
  619.         (cond ((atom (car x)) (err nil)))
  620.         (rplacd x (nconc (cdar x) (cdr x)))
  621.         (return (rplaca x (caar x))) )))
  622. ;
  623. ;
  624. ; dsubst - destructive substitution function;
  625. ;   x - oldval
  626. ;   y - newval
  627. ;   z - s-expression being altered.
  628. ;
  629. ; Substitutes y for x in z.
  630. ; Uses rplaca and permanently alters z.
  631. ;
  632. (def dsubst (lambda (x y z)
  633.     (progn
  634.     (cond
  635.         ((consp z)
  636.             (progn
  637.                 (cond
  638.                     ((equal x (car z))  (rplaca z y))
  639.                     (t                  (dsubst x y (car z))) )
  640.                 (cond ((cdr z)  (dsubst x y (cdr z))) )))
  641.         (t z))  ;if z is not a cons, do nothing.
  642.     z)))
  643. ;
  644. ;
  645. ; eprint - "safe" editor print function
  646. ; prints x to a maximum depth of printlevel.
  647. (defun eprint (x) (print (sprint x printlevel)))
  648. ;
  649. (defun apply1 (f l)
  650.     (eval (cons f (mapcar '(lambda (z) (list 'quote z)) l))))
  651. ;
  652. ;
  653. ; leddelete - deletes element N from the current expression
  654. ;
  655. (def leddelete (lambda (n)
  656.     (prog   (a)
  657.         (if (equal n 1)
  658.         (progn
  659.             (setq ce (cdr ce))
  660.             (rplaca thread ce))
  661.         (progn
  662.             (rplacd
  663.                 (lednthcdr (- n 1) ce)
  664.                 (lednthcdr (+ n 1) ce)))))))
  665. ;
  666. ;
  667. ; ledinsert - inserts X before position N in CE
  668. ;
  669. (def ledinsert (lambda (n x)
  670.     (prog   (a b)
  671.         (if (equal n 1)
  672.         (progn
  673.             (setq ce (cons x ce))
  674.             (rplaca thread ce))
  675.         (progn
  676.             (setq a (lednthcdr n ce))
  677.             (setq b (lednthcdr (sub1 n) ce))
  678.             (rplacd b (cons x a))
  679.             (rplaca thread ce)
  680.             (return ce))))))
  681. ;
  682. ;
  683. ; ledfind - general purpose find routine.
  684. ;           finds expression S in THREAD.
  685. ;           The search proceeds downwards
  686. ;           from the current expression,
  687. ;           left recursively.
  688. ;
  689. (def ledfind (lambda (target)
  690.     (cond
  691.         ((setq result (ledfind1 target (car thread) 1))
  692.             (setq thread (cons result thread)))
  693.         (t  (princ "***> FIND: could not find target in current exp")))))
  694. ;       
  695. ;           
  696. ;
  697. ; ledfind1 - finds first match of X in Y.
  698. ; srchlevel is the current search level,
  699. ; and is not permitted to exceed maxlevel.
  700. ;
  701. (def ledfind1 (lambda (x y srchlevel &aux result)
  702.     (cond   ((eql srchlevel maxlevel)
  703.                 (err "***> LED: max search level exceeded in LEDFIND"))
  704.             ((ledmatch x y srchlevel) y)
  705.             ((atom y) nil)
  706.             ((setq result (ledfind1 x (car y) (+ srchlevel 1))) result)
  707.             ((setq result (ledfind1 x (cdr y) (+ srchlevel 1))) result)
  708.             (t nil))))
  709. ;
  710. (popd)      ;return to entry directory
  711.  
  712.