home *** CD-ROM | disk | FTP | other *** search
- ; LED.L - UNXLISP structure editor
- ;
- ; Copyright (c) 1985 by David Morein
- ; You can do anything you like with this file,
- ; as long as you aren't trying to put me out of
- ; business.
- ;
- ; Similar to, but rather simple-minded by comparison with,
- ; the BBN Interlisp editor.
- ;
- ; note - edit this file with tabs set to 4
- ;
- ; summary of LED commands:
- ;
- ; n, where n is an integer:
- ;
- ; n > 0 ==> make the current expression
- ; the nth element of the current expression
- ;
- ; n < 0 ==> make the current expression
- ; the nth from the last element of the
- ; current expression. (i.e., -1 selects
- ; the last element, -2 the second from
- ; the last, etc.)
- ;
- ; n = 0 => pops the thread one level.
- ;
- ; ^ pops the thread all the way back to the top.
- ; OK ends the edit and accepts the altered expression.
- ; Q ends the edit with no changes.
- ; E evaluates an expression and prints its value.
- ; P prints the current expression.
- ; PP pretty-prints the current expression
- ; COPY copies the entire thread to a safe place.
- ; RESTORE restores the thread to the value which
- ; was saved by copy.
- ; MARK sets a mark in the mark list
- ; < goes back 1 place in the mark list, but does not pop the mark list.
- ; << goes back 1 place in the mark list, and pops the mark list.
- ; POFF turns off the print flag.
- ; PON turns on the print flag.
- ;
- ; find command:
- ; (f e) searches for the expression e in the current expression.
- ; if found, the found expression becomes the new current expression.
- ;
- ; structure modification commands:
- ;
- ; (n e), n>1 replaces the nth element of the current expression with e
- ; (n e1 e2 ... em), n,m > 1 replaces the nth element of the
- ; current expression with e1 e2 ... em.
- ; (-n e), n > 1 inserts e before the nth element of the current expression.
- ; (-n e1 e2 ... em), n,m > 1 inserts e1 ... em before the nth element
- ; of the current expression.
- ; (r x y) "Replace" - replaces all occurrences of x in the
- ; current expression by y. The replacement is done
- ; throughout the current expression, and not just
- ; at the top-most level. For example, if the current
- ; expression were (LAMBDA (X Y) (+ X Y)), then
- ; typing (r y z) would change the current expression
- ; to (LAMBDA (X Z) (+ X Z)).
- ;
- ; parenthesis moving commands:
- ; (bi m n) "Both In" - inserts parenthesis before the mth element and
- ; after the nth element of the current expression.
- ; For example, if the current expression were (a b c d e),
- ; then executing (bi 3 4) would change it to (a b (c d) e).
- ;
- ; (bo n) "Both Out" - removes both parenthesis from the nth
- ; element of the current expression, and splices
- ; its elements into the current expression.
- ; For example, if the current expression were
- ; (a b (c d) e f), then executing (bo 3) would
- ; result in (a b c d e f).
- ;
- ; (li n) "Left In" - inserts a left parenthesis before the
- ; nth element, and a matching right parenthesis
- ; at the end of the current expression. For example,
- ; if (a b c d e) were the current expression, then
- ; executing (li 2) would result in (a (b c d e)).
- ;
- ; (lo n) "Left Out" - removes a left parenthesis from the
- ; nth element of the current expression, and
- ; deletes all elements after the nth element.
- ; For example, if the current expression were
- ; (a b (c d) e f), then executing (lo 3) would
- ; result in (a b c d).
- ;
- ; (ri m n) "Right In" - moves the right paren at the end of
- ; the mth element inward until it is after the nth
- ; element of the mth element of the current expression.
- ; The remainder of the mth element is elevated to
- ; the top-most level of the current expression.
- ; For example, if the current expression were
- ; (a b (c d e) f g), then executing (ri 3 2) would
- ; change it to (a b (c d) e f g).
- ;
- ; (ro n) "Right Out" - moves the right parenthesis at
- ; the end of the nth element out to the end of
- ; the current expression. The rest of the elements
- ; following the nth are moved inside of the
- ; nth element. For example, if the current expression
- ; were (a b (c d) e f) then executing (ro 3)
- ; would change it to (a b (c d e f)).
- ;
- ; note - all of the above parenthesis moving commands take
- ; negative arguments, which are processed in the same
- ; way as simple numerical commands. That is, -1
- ; refers to the last element of the current expression,
- ; -2 to the second to the last element, and so on.
- ;
- ;
- (pdq /sys/cmd) ;start at /sys/cmd.
- (mcdq led) ;make /sys/cmd/led
- (add-to-path '/sys/cmd/led) ;put editor on reader-search-path.
- ;
- ; global symbols:
- ;
- ; global functions:
- (global 'ledfq 'ledeq 'ledpq 'ledvq)
- ;
- ; editor commands:
- (global
- 'ok
- 'q
- 'e
- 'p
- 'pp
- 'mark
- '^
- '<<
- 'poff
- 'pon
- 'r
- 'i
- 'n
- 'p
- 'f
- 'ednth
- 'ri
- 'ro
- 'li
- 'lo
- 'bi
- 'bo
- 'm
- 'd)
- ;
- ;
- ; explanation of variables global to this file:
- ; thread - list of expressions being edited.
- ; (car thread) is the current expression.
- ;
- (setq printflag t)
- ; print on by default
- ;
- (setq printlevel 3)
- (setq maxlevel 100)
- ;
- ; ledeq - edits an arbitrary s-expression
- ;
- (def ledeq (nlambda (x)
- (progn (setq thread nil)
- (setq m nil)
- (lede1 x))))
- ;
- ;
- ; ledfq - edits the function definition cell of a symbol.
- ;
- (def ledfq (nlambda (fn)
- (prog ()
- (pushpath '/sys/cmd/led) ;put editor on reader-search-path.
- (setq thread nil) ;initialize the thread
- ;
- ; filter out symbols which do not have an editable fn def
- ;
- (cond
- ((or (null (getd fn)) (compiled-function-p fn))
- (return '(not editable))))
- ;
- ; edit the fn def
- ;
- (putd fn (lede1 (getd fn)))
- ;
- ; pop editor off search-path
- ;
- (poppath)
- (return fn))))
- ;
- ; ledvq - edits the variable binding of a symbol
- ;
- (def ledvq (nlambda (someatom)
- (progn
- (setq thread nil)
- (cond ((not (boundp someatom))
- (err "***> LEDV: symbol not bound as a variable.")))
- (set someatom (lede1 (eval someatom)))
- someatom)))
- ;
- ;
- ; ledpq - edits the property list of an atom.
- ;
- (def ledpq (nlambda (someatom)
- (progn
- (setq thread nil)
- (setplist someatom (lede1 (symbol-plist someatom)))
- someatom)))
- ;
- ; lede1 - edits an arbitrary s-expression
- ; x - expression to be edited
- ;
- ; if the user accepts the changes via the OK command,
- ; then this function returns the edited expression;
- ; otherwise, it returns the original expression.
- ;
- (defun lede1 (x)
- (prog (c copied) ;prog variables
- (setq old_value (copy-tree x)) ;save old value of x
- ;
- ; start the thread, if necessary
- ;
- (cond ((null thread) (setq thread (list x))))
- ;
- ; initialize some variables, output 'LED', and print current expression:
- ;
- (princ "LED")
- (setq edok nil) ;initialize editor accept flag
- (setq edquit nil) ;initialize editor quit flag
- ;
- ; enter main editing loop:
- ;
- editloop
- ;
- ; if the editor accept flag is set, then return the altered expression:
- ;
- (cond (edok (return (car (last thread)))))
- ;
- ; if the editor quit flag is set, then return the original value:
- ;
- (cond (edquit (return old_value)))
- ;
- ; if the printflag is set, then print the current expression:
- ;
- (cond (printflag (terpri) (editcom 'p)))
- ;
- ; display the editor's prompt:
- ;
- outprompt
- (terpri)
- (princ '*)
- ;
- ; read a command:
- ;
- (cond ((null (errset (setq c (read)))) (go editloop)))
- ;
- ; process the command:
- ;
- ; if the command was p or pp, output the current expression and loop back:
- ;
- (cond ((eq c 'p) (editcom 'p) (go outprompt))
- ((eq c 'pp) (editcom 'pp) (go outprompt)))
- ;
- ; otherwise, process the command normally:
- ;
- (cond ((errset (editcom c)) t)
- (t (qmark c)))
- (go editloop)))
- ;
- ; qmark - outputs a suspect command followed by a question mark.
- ;
- (def qmark (lambda (c)
- (progn
- (terpri)
- (print c)
- (princ '?)
- (terpri))))
- ;
- ;
- ; editcom - processes an editor command.
- ;
- (defun editcom (c)
- (progn
- (cond
- ;
- ; integer - changes the current expression to be the nth
- ; element of the current expression.
- ;
- ; this call to numberp should be replaced by integerp
- ;
- ((numberp c) (simpnum c) t)
- ;
- ; if c is atomic, then process an atomic command:
- ;
- ((atom c) (atomcom c) t)
- ;
- ; otherwise, process a list command:
- ;
- (t (listcom c) t))))
- ;
- ; atomcom - processes an atomic editor command
- ;
- (def atomcom (lambda (c)
- (cond
- ;
- ; ok - sets the variable edok to t.
- ;
- ((eq c 'ok)
- (setq edok t))
- ;
- ; q - quits the edit with no changes
- ;
- ((eq c 'q)
- (setq edquit t))
- ;
- ; e - evaluates an expression & prints its value.
- ;
- ((eq c 'e)
- (errset (print (eval (read))))
- (terpri))
- ;
- ; p - prints the current expression.
- ;
- ((eq c 'p)
- (eprint (car thread)))
- ;
- ; pp - pretty-prints the current expression.
- ;
- ((eq c 'pp)
- (terpri)
- (errset (pp (car thread)))
- (terpri))
- ;
- ; mark - sets a mark
- ;
- ((eq c 'mark)
- (setq m (cons thread m)))
- ;
- ; ^ - pop the thread back to the top
- ;
- ((eq c '^)
- ; (setq thread (list (last thread))))
- (setq thread (last thread)));
- ;
- ; copy - copies current expression to a safe place
- ;
- ((eq c 'copy)
- (setq copied (copy-tree thread)))
- ;
- ; restore - restores current expression to value
- ; which was saved by copy.
- ;
- ((eq c 'restore)
- (setq thread copied))
- ;
- ; < - goes back 1 place in the mark list
- ;
- ((eq c '<)
- (cond (m (setq thread (car m)))
- (t (err "***> LED: no marks"))))
- ;
- ; << - same as < except pops the mark list
- ;
- ((eq c '<<)
- (cond (m (setq thread (car m))
- (setq m (cdr m)))
- (t (err "***> LED: no marks"))))
- ;
- ; poff - turn off the print flag:
- ;
- ((eq c 'poff)
- (setq printflag nil))
- ;
- ; pon - turn on the print flag:
- ;
- ((eq c 'pon)
- (setq printflag t))
- ;
- ; otherwise, indicate that we couldn't parse the command:
- ;
- (t (err nil)))))
- ;
- ; listcom - this function processes a list command if it can,
- ; otherwise signals an error with ERR.
- ;
- (def listcom (lambda (c)
- (prog (c1 c2 c3)
- (setq ce (car thread)) ; ce := current expression
- (setq c1 (car c)) ; c1 := 1st element of command list
- (setq c2 (cadr c)) ; c2 := 2nd element of command list
- (setq c3 (caddr c)) ; c3 := 3rd element of command list
- ;
- ; dispatch on c1, the 1st element of the command list:
- ;
- (return
- (cond
- ((numberp c1)
- (compnum c)) ;complex # command
-
- ((eq c1 'd) ;delete command
- (leddelete c2))
-
- ((eq c1 'i) ;insert command
- (ledinsert c2 c3))
-
- ((eq c1 'r) ;replace command
- (dsubst c2 c3 ce))
-
- ((eq c1 'f) ;find command
- (ledfind c2))
-
- ((eq c1 'nth)
- (setq thread (cons (lednthcdr c3 c2) thread)))
-
- ((member c1 '(ri ro li lo bi bo)) ;paren move command
- (apply1 c1 (append (cdr c) (list ce))))
- ;
- ; failure to parse command.
- ;
- (t (err nil)))))))
- ;
- ; printlevel - swaps the current printlevel with x
- ;
- (def printlevel (lambda (x)
- (prog (a)
- (setq a printlevel)
- (setq printlevel x)
- (return a))))
- ;
- ; simpnum - processes simple numeric commands
- ; n = 0 ==> go up 1 level in the thread
- ; n > 0 ==> go to the nth element of current expression
- ; (expression # 1 is the left-most expression)
- ; n < 0 ==> go to the nth from the last element of the
- ; current expression
- ;
- (def simpnum (lambda (n)
- (cond
- ;
- ; n = 0 => up 1 level in thread
- ;
- ((equal n 0)
- (cond
- ((null (cdr thread))
- (err "***> LED: already at top of thread"))
- (t (setq thread (cdr thread)))))
- ;
- ; n > 0 => go to nth element of current expression
- ;
- ((> n 0)
- (cond ((> n (length (car thread)))
- (err "***> LED: numeric arg larger than list size"))
- (t (setq thread
- (cons
- (nth (sub1 n) (car thread))
- thread)))))
- ;
- ; check for negative number too big:
- ;
- ((> (* n -1) (length (car thread)))
- (err "***> LED: numeric arg larger than list size"))
- ;
- ; n < 0 => go to nth element from end of current expr
- ;
- (t (setq thread
- (cons
- (nth
- (+ (length (car thread)) n)
- (car thread))
- thread))))))
- ;
- ; compnum - processes a numeric list command
- ;
- (def compnum (lambda (c)
- (cond ((> (car c) 0)
- (cond ((> (car c) (length (car thread)))
- (err nil))
- (t (rplaca
- thread
- (linkbend
- (sub1 (car c))
- (car thread)
- (cdr c)
- nil)))))
- ((or (equal (car c) 0)
- (null (cdr c))
- (> (* -1 (car c)) (length (car thread))))
- (err nil))
- (t (rplaca
- thread
- (linkbend
- (sub1 (* -1 (car c)))
- (car thread)
- (cdr c)
- t))))))
- ;
- ; linkbend - handy dandy link bending routine.
- ; Handles the dirty work for (# ...) commands.
- ;
- (def linkbend (lambda (n x r d)
- (prog ()
- (cond ((not (equal n 0))
- (rplacd (nthcdr (sub1 n) x)
- (nconc r
- (cond (d (nthcdr n x))
- (t (nthcdr (add1 n) x))))))
- (d (attach (car r) x)
- (rplacd x (nconc (cdr r) (cdr x))))
- (r (rplaca x (car r))
- (rplacd x (nconc (cdr r) (cdr x))))
- (t (print (list 'aha x)) ;from BBN editor.
- (rplaca x (cadr x))
- (rplacd x (cddr x))))
- (return x))))
- ;
- ;
- ; attach - auxilliary function for linkbend
- ;
- (def attach (lambda (x y)
- (prog (a)
- (setq a (cons (car y) (cdr y)))
- (rplaca y x)
- (rplacd y a)
- (return y))) )
- ;
- ;
- ; ledmatch - pattern match routine for LED
- ; returns T iff x matches y
- ;
- ; notes:
- ; (1) if the second element of x is eq to '-, then
- ; T is returned if x and y are both lists and the first
- ; element of each matches.
- ; (2) if x is eq to '&, then it matches anything.
- ;
- (def ledmatch (lambda (x y srchlevel)
- (cond ((eql maxlevel srchlevel)
- (err "***> LED: max search level exceeded."))
- ((equal x y) t)
- ((atom x) (eq x '&))
- ((atom y) nil)
- ((ledmatch (car x) (car y) (+ srchlevel 1))
- (or (eq (cadr x) '-)
- (ledmatch (cdr x) (cdr y) (+ srchlevel 1)))))))
- ;
- ; lednthcdr - special nthcdr function which takes negative arguments:
- ;
- (def lednthcdr (lambda (n x)
- (cond
- ((< n 0)
- (cond ((> (* n -1) (length x))
- (err "***> LED: numeric arg larger than list size."))
- (t (nthcdr (+ n (length x)) x))))
- ((> n 0)
- (cond ((> n (length x))
- (err "***> LED: numeric arg larger than list size."))
- (t (nthcdr (sub1 n) x))))
- ((equal n 0)
- (err "***> LED: invalid arg.")))))
- ;
- ;
- ; ro - "right out" command, moves right parenthesis out.
- ;
- (def ro (lambda (n x)
- (prog (a)
- (setq a (lednthcdr n x))
- (cond ((or (null a) (atom (car a))) (err nil)))
- (rplacd (last (car a)) (cdr a))
- (rplacd a nil))) )
- ;
- ;
- ; ri - "right in" command, moves right parenthesis in.
- ;
- (def ri (lambda (m n x)
- (prog (a b)
- (setq a (lednthcdr m x))
- (setq b (lednthcdr n (car a)))
- (cond ((or (null a) (null b)) (err nil)))
- (rplacd a (nconc (cdr b) (cdr a)))
- (rplacd b nil))) )
- ;
- ;
- ; li - "left in" command, moves left parenthesis in.
- ;
- (def li (lambda (n x)
- (prog (a)
- (setq a (lednthcdr n x))
- (cond ((null a) (err nil)))
- (rplaca a (cons (car a) (cdr a)))
- (rplacd a nil))) )
- ;
- ;
- ; lo - "left out" command, moves left parenthesis out.
- ;
- (def lo (lambda (n x)
- (prog (a)
- (setq a (lednthcdr n x))
- (cond ((or (null a) (atom (car a))) (err nil)))
- (rplacd a (cdar a))
- (rplaca a (caar a))) ))
- ;
- ;
- ; bi - "both in" command, moves both parenthesis in.
- ;
- (def bi (lambda (m n x)
- (prog (a b)
- (setq b (cdr (setq a (lednthcdr n x))) )
- (setq x (lednthcdr m x))
- (cond ((and a (null (> (length x))) )
- (rplacd a nil)
- (rplaca x (cons (car x) (cdr x)))
- (rplacd x b))
- (t (err nil))) )))
- ;
- ;
- ; bo - "both out" command, moves both parenthesis out.
- ;
- (def bo (lambda (n x)
- (progn
- (setq x (lednthcdr n x))
- (cond ((atom (car x)) (err nil)))
- (rplacd x (nconc (cdar x) (cdr x)))
- (return (rplaca x (caar x))) )))
- ;
- ;
- ; dsubst - destructive substitution function;
- ; x - oldval
- ; y - newval
- ; z - s-expression being altered.
- ;
- ; Substitutes y for x in z.
- ; Uses rplaca and permanently alters z.
- ;
- (def dsubst (lambda (x y z)
- (progn
- (cond
- ((consp z)
- (progn
- (cond
- ((equal x (car z)) (rplaca z y))
- (t (dsubst x y (car z))) )
- (cond ((cdr z) (dsubst x y (cdr z))) )))
- (t z)) ;if z is not a cons, do nothing.
- z)))
- ;
- ;
- ; eprint - "safe" editor print function
- ; prints x to a maximum depth of printlevel.
- ;
- (defun eprint (x) (print (sprint x printlevel)))
- ;
- (defun apply1 (f l)
- (eval (cons f (mapcar '(lambda (z) (list 'quote z)) l))))
- ;
- ;
- ; leddelete - deletes element N from the current expression
- ;
- (def leddelete (lambda (n)
- (prog (a)
- (if (equal n 1)
- (progn
- (setq ce (cdr ce))
- (rplaca thread ce))
- (progn
- (rplacd
- (lednthcdr (- n 1) ce)
- (lednthcdr (+ n 1) ce)))))))
- ;
- ;
- ; ledinsert - inserts X before position N in CE
- ;
- (def ledinsert (lambda (n x)
- (prog (a b)
- (if (equal n 1)
- (progn
- (setq ce (cons x ce))
- (rplaca thread ce))
- (progn
- (setq a (lednthcdr n ce))
- (setq b (lednthcdr (sub1 n) ce))
- (rplacd b (cons x a))
- (rplaca thread ce)
- (return ce))))))
- ;
- ;
- ; ledfind - general purpose find routine.
- ; finds expression S in THREAD.
- ; The search proceeds downwards
- ; from the current expression,
- ; left recursively.
- ;
- (def ledfind (lambda (target)
- (cond
- ((setq result (ledfind1 target (car thread) 1))
- (setq thread (cons result thread)))
- (t (princ "***> FIND: could not find target in current exp")))))
- ;
- ;
- ;
- ; ledfind1 - finds first match of X in Y.
- ; srchlevel is the current search level,
- ; and is not permitted to exceed maxlevel.
- ;
- (def ledfind1 (lambda (x y srchlevel &aux result)
- (cond ((eql srchlevel maxlevel)
- (err "***> LED: max search level exceeded in LEDFIND"))
- ((ledmatch x y srchlevel) y)
- ((atom y) nil)
- ((setq result (ledfind1 x (car y) (+ srchlevel 1))) result)
- ((setq result (ledfind1 x (cdr y) (+ srchlevel 1))) result)
- (t nil))))
- ;
- (popd) ;return to entry directory
-