(in-package "CL-USER") ;; EXPAND: eine vereinfachte macro expansion (defun cons-progn (e) (if (null (cdr e)) (car e) (cons 'progn e))) (defun un-progn (e) (if (and (listp e) (eq (car e) 'progn)) (cdr e) (list e))) ;; ;; an experiment in backquote expansion ;; (defun is-comma-at (e) (and (consp e) (eq (car e) 'comma-at) (null (cddr e)))) (defun is-comma (e) (and (consp e) (eq (car e) 'comma) (null (cddr e)))) (defun is-bq (e) (and (consp e) (eq (car e) 'bq) (null (cddr e)))) ;; (bq-expand-1 e) expresses (bq e) without comma, comma-at and backquote ;; (defun bq-extend-list (el lis) (if (is-comma-at el) (case (car lis) (list (cons 'append (list (bq-expand-1 el) lis))) (append (cons 'append (cons (bq-expand-1 el) (cdr lis))))) (case (car lis) (list (cons 'list (cons (bq-expand-1 el) (cdr lis)))) (append (cons 'append (cons (list 'list (bq-expand-1 el)) (cdr lis))))))) (defun bq-expand-1 (e) (cond ((atom e) (list 'quote e)) ((is-bq e) (bq-expand-1 (bq-expand-1 (cadr e)))) ((is-comma e) (bq-expand (cadr e))) ((is-comma-at e) (bq-expand (cadr e))) ((listp e) (fold #'(lambda (el ll) (bq-extend-list el ll)) '(list) e)) (t (error "bq-expand-1: 000: case not implemented.")))) ;; (bq-expand e) expresses e without comma, comma-at and backquote (defun bq-expand (e) (cond ((atom e) e) (t (cond ((is-bq e) (cond ((is-comma (cadr e)) (bq-expand (cadr (cadr e)))) ((is-comma-at (cadr e)) (bq-expand (cadr (cadr e)))) (t (bq-expand-1 (cadr e))))) (t (cond ((listp e) (mapcar #'bq-expand e)) (t (error "bq-expand: 000: case not implemented.")))))))) (defun expand (e) (labels ((and-expand (e) (cond ((null (cdr e)) t) ((null (cddr e)) (expand (cadr e))) (t (let () (list 'if (expand (cadr e)) (expand (cons 'and (cddr e))) nil))))) (or-expand (e) (cond ((null (cdr e)) nil) ((null (cddr e)) (expand (cadr e))) (t (let ((var (gensym))) (expand (list (make-lambda (list var) (list (list 'if var var (cons 'or (cddr e))))) (cadr e))))))) (let*-expand (e) (let ((vars (let-vars e))) (let ((zz (cond ((null vars) (make-let nil nil (let-body e))) ((null (cdr vars)) (make-let (list (caar vars)) (expand (list (cadar vars))) (let-body e))) (t (make-let (list (caar vars)) (expand (list (cadar vars))) (list (expand (make-let* (mapcar #'car (cdr vars)) (mapcar #'cadr (cdr vars)) (let-body e))))))))) (expand zz)))) (let-expand (e) (cons (make-lambda (mapcar #'car (let-vars e)) (mapcar #'expand (let-body e))) (expand (mapcar #'cadr (let-vars e))))) (cond-expand (e) (let ((rest (cdr e))) (if (null rest) nil (let ((rest-1 (car rest))) (if (null (cdr rest-1)) (let ((tt (gensym))) (expand (make-let (list tt) (list (car rest-1)) (list (list 'if tt tt (cons 'cond (cdr rest))))))) (expand (list 'if (car rest-1) (cons-progn (cdr rest-1)) (cons 'cond (cdr rest))))))))) (when-expand (e) (let ((cnd (cadr e)) (e-lis (cddr e))) (list 'if (expand cnd) (expand (cons 'progn e-lis))))) (defun-expand (e) (list '%set-symbol-function (list 'quote (cadr e)) (expand (make-lambda (caddr e) (cdddr e))))) (do-expand (e) (let ((inits (cadr e)) (test-exit (caddr e)) (body (cdddr e))) (if (null inits) (let () `(do-until ,(expand test-exit) ,@(expand body))) (let* ((vars-init (mapcar #'car inits)) (vals-init (mapcar #'cadr inits)) (steps (mapcar #'caddr inits)) (vars-dummy (mapcar #'(lambda (z) (get-unique-var z)) vars-init))) (expand (make-let vars-init (mapcar #'expand vals-init) (list (append (list 'do-until (expand test-exit)) (append (expand body) (list (make-let vars-dummy (mapcar #'expand steps) (zip #'(lambda (x y) (list 'setq x y)) vars-init vars-dummy)))))))))))) (dolist-expand (e) (let* ((second (cadr e)) (body (cddr e)) (var (car second)) (lis (cadr second)) (auxvar (get-unique-var var))) (expand (append (list 'do (list (list auxvar lis (list 'cdr auxvar))) (list (list 'null auxvar))) (list (make-let (list var) (list (list 'car auxvar)) body)))))) (defconstant-expand (e) (push (cons (cadr e) (caddr e)) *global-const-list*) (caddr e)) (mul-expand (e) (let ((op1 (cadr e)) (op2 (caddr e))) (if (is-power-of-two op1) (let ((m op2)) (setf op2 op1) (setf op1 m))) (if (is-power-of-two op2) (do ((l op2 l) (i 0 i)) ((= l 1) (return-from mul-expand (if (> i 0) `(p-shiftl ,(expand op1) ,i) (expand op1)))) (multiple-value-bind (q r) (floor l 2) (setf i (+ i 1)) (setf l q))) (progn (format t "no strength reduction possible in: ~a~%" e) (let ((res `(mul ,(expand op1) ,(expand op2)))) (format t "res = ~a~%" res) res))))) (atom-expand (e) (if (symbolp e) (let ((val (assoc e *global-const-list*))) (if val (cdr val) e)) e)) (multiple-value-bind-expand (e) (let* ((vars (cadr e)) (fn (caddr e)) (elis (cdddr e)) (nvars (length vars))) (expand (append (list (append (list 'lambda vars) elis) fn) (do ((i 0 (+ i 1)) (res nil res)) ((>= i (- nvars 1)) (reverse res)) (setf res (cons (list '%svref (list '%symbol-value (list 'quote 'valuesq)) (list '%+ (list '%symbol-value (list 'quote 'valuescntq)) (+ i 1))) res))))))) (generic-expand (e) (mapcar #'expand e))) (cond ((atom e) (atom-expand e)) ((stringp e) e) ((listp e) (let ((head (car e))) (cond ((eq head 'backquote) (bq-expand e)) ((eq head 'defstruct) (defstruct-expand e)) ((eq head 'setf) (setf-expand e)) ((eq head 'and) (and-expand e)) ((eq head 'or) (or-expand e)) ((eq head 'let*) (let*-expand e)) ((eq head 'let) (let-expand e)) ((eq head 'cond) (cond-expand e)) ((eq head 'when) (when-expand e)) ((eq head 'defun) (defun-expand e)) ((eq head 'do) (do-expand e)) ((eq head 'dolist) (dolist-expand e)) ((eq head 'defconstant) (defconstant-expand e)) ((eq head '%*) (mul-expand e)) ((eq head 'multiple-value-bind) (multiple-value-bind-expand e)) ((is-struct-accessor head) (rewrite-struct-accessor e)) (t (generic-expand e))))) (t e)))) (defun display (e) (labels ((let-display (e) (cons 'let (cons (zip #'(lambda (x y) (list x y)) (lambda-vars (car e)) (cdr e)) (un-progn (display (lambda-body (car e)))))))) (cond ((atom e) e) ((stringp e) e) ((listp e) (let ((head (car e))) (cond ((is-lambda head) (let-display e)) (t (mapcar #'display e))))) (t e)))) ;; COMP-0: labels substitution, dann alpha substitution (defun access-read-01 (vv) (cadr vv)) (defun access-read-fun-01 (vv) (if (eq (car vv) 'found) (caddr vv) (cadr vv))) (defun comp-01 (e sl) (labels ((comp-01-number (e sl) e) (comp-01-string (e sl) e) (comp-01-character (e sl) e) (comp-01-other (e sl) e)) (cond ((null e) e) ((symbolp e) (access-read-01 (comp-01-symbol e sl))) ((numberp e) (comp-01-number e sl)) ((characterp e) (comp-01-character e sl)) ((stringp e) (comp-01-string e sl)) ((listp e) (cond ((is-quote e) e) ((is-special-form e) (comp-01-nohead e sl)) ((is-primitive e) (comp-01-nohead e sl)) ((is-setq e) (comp-01-setq e sl)) ((is-lambda e) (comp-01-lambda e sl)) ((is-labels e) (comp-01-labels e sl)) ((is-form e) (comp-01-form e sl)) (t (comp-01-generic e sl))))))) (defun comp-01-symbol (e sl) (let ((subs (assoc e sl))) (if subs (list 'found e (cdr subs)) (list 'not-found e e)))) (defun comp-01-setq (e sl) (let ((v (cadr e)) (e1 (caddr e))) (setf v (comp-01 v sl)) (setf e1 (comp-01 e1 sl)) (list 'setq v e1))) (defun comp-01-generic (e sl) (mapcar #'(lambda (z) (comp-01 z sl)) e)) (defun comp-01-nohead (e sl) (let ((head (car e))) (cons head (comp-01-generic (cdr e) sl)))) (defun comp-01-lambda (e sl) (let ((lam-vars (lambda-vars e)) (lam-body (lambda-body e))) (setf lam-body (comp-01 lam-body sl)) (make-lambda lam-vars lam-body))) (defun comp-01-labels (e sl) (let ((e1 (un-annotate e))) (let ((e-body (labels-body e1)) (fn-defs (cadr e1))) (let ((fn-lis (mapcar #'(lambda (z) (list 'lambda (cadr z) (caddr z) (cadddr z))) fn-defs)) (fn-vars (mapcar #'car fn-defs))) (let ((fn-vars-1 (mapcar #'(lambda (z) (get-unique-var z)) fn-vars))) (let ((sl-a (pair fn-vars fn-vars-1))) (let ((sl-1 (append sl-a sl))) (let ((fn-res (mapcar #'(lambda (z) (comp-01 z sl-1)) fn-lis)) (e-body-res (comp-01-generic e-body sl-1))) (make-labels-lambda fn-vars-1 fn-res e-body-res))))))))) (defun comp-01-form (e sl) (let ((head (car e)) (rest (cdr e))) (let ((rest-1 (comp-01-generic rest sl)) (head-1 (access-read-fun-01 (comp-01-symbol head sl)))) (cons head-1 rest-1)))) ;; COMP-1: freie variablen analyse (defun fv-rd (fvl) (car fvl)) (defun fv-wr (fvl) (cadr fvl)) (defun fv-clrd (fvl) (caddr fvl)) (defun fv-clwr (fvl) (cadddr fvl)) (defun fv-empty () (list nil nil nil nil)) (defun add-rd (v fvl) (list (adjoin v (fv-rd fvl)) (fv-wr fvl) (fv-clrd fvl) (fv-clwr fvl))) (defun add-wr (v fvl) (list (fv-rd fvl) (adjoin v (fv-wr fvl)) (fv-clrd fvl) (fv-clwr fvl))) (defun add-clrd (v fvl) (list (fv-rd fvl) (fv-wr fvl) (adjoin v (fv-clrd fvl)) (fv-clwr fvl))) (defun add-clwr (v fvl) (list (fv-rd fvl) (fv-wr fvl) (fv-clrd fvl) (adjoin v (fv-clwr fvl)))) (defun mv-cl (fvl) (list nil nil (union (fv-rd fvl) (fv-clrd fvl)) (union (fv-wr fvl) (fv-clwr fvl)))) (defun add-fv (fvl-1 fvl-2) (zip #'(lambda (x y) (union x y)) fvl-1 fvl-2)) (defun comp-11 (e) (labels ((comp-11-symbol (e) (list e (list (list e) nil nil nil))) (comp-11-number (e) (list e (fv-empty))) (comp-11-string (e) (list e (fv-empty))) (comp-11-other (e) (list e (fv-empty))) (comp-11-setq (e) (let ((v (cadr e)) (e1 (caddr e))) (let ((res (comp-11 e1))) (list (list 'setq v (car res)) (add-wr v (cadr res))))))) (cond ((symbolp e) (comp-11-symbol e)) ((numberp e) (comp-11-number e)) ((characterp e) (comp-11-other e)) ((stringp e) (comp-11-string e)) ((listp e) (cond ((is-quote e) (list e (fv-empty))) ((is-special-form e) (comp-11-nohead e)) ((is-primitive e) (comp-11-nohead e)) ((is-setq e) (comp-11-setq e)) ((is-lambda (car e)) (comp-11-let e)) ((is-lambda e) (comp-11-lambda e :general-form)) ((is-labels e) (comp-11-labels e)) (t (comp-11-generic e))))))) (defun comp-11-generic (e) (let ((res (mapcar #'comp-11 e))) (list (mapcar #'car res) (fold #'(lambda (x y) (add-fv x y)) (list nil nil nil nil) (mapcar #'cadr res))))) (defun comp-11-let (e) (let ((res (comp-11-generic (cdr e))) (res-head (comp-11-lambda (car e) :let-form))) (list (cons (car res-head) (car res)) (add-fv (cadr res) (cadr res-head))))) (defun comp-11-nohead (e) (let ((res (comp-11-generic (cdr e)))) (list (cons (car e) (car res)) (cadr res)))) (defun comp-11-lambda (e mode) (let ((vars (lambda-vars e)) (body (lambda-body e))) (let ((res (comp-11-generic body))) (let ((fvl (cadr res))) (let ((lam (make-lambda vars (car res))) (rds nil) (wrs nil) (wrsx nil) (fvl-1 nil)) (setf fvl-1 (mapcar #'(lambda (z) (set-difference z vars)) fvl)) (cond ((eq mode :general-form) (setf rds (union (fv-rd fvl-1) (fv-clrd fvl-1))) (setf wrs (union (fv-wr fvl-1) (fv-clwr fvl-1))) (setf wrsx (intersection (fv-clwr fvl) vars))) ((eq mode :let-form) (setf rds nil) (setf wrsx (intersection vars (fv-clwr fvl))))) (setf lam (annotate lam (list 'reads rds 'writes wrs 'cl-wrqs wrsx))) (if (eq mode :general-form) (setf fvl-1 (mv-cl fvl-1))) (list lam fvl-1)))))) (defun comp-11-labels (e) (let ((e-body (labels-body e)) (fn-defs (cadr e))) (let ((fn-lis (mapcar #'(lambda (z) (list 'lambda (cadr z) (caddr z))) fn-defs)) (fn-vars (mapcar #'car fn-defs))) (let ((fn-res (mapcar #'comp-11 fn-lis))) (let ((fn-codes (mapcar #'car fn-res)) (fn-fvl-lis (mapcar #'cadr fn-res))) (let ((fn-fvl (fold #'(lambda (x y) (add-fv x y)) (fv-empty) fn-fvl-lis)) (fn-fvl-1 nil) (res-body nil) (code nil) (fvl-b nil)) (setf fn-fvl-1 (mapcar #'(lambda (z) (set-difference z fn-vars)) fn-fvl)) (setf fn-fvl-1 (mv-cl fn-fvl-1)) (format t "e-body = ~A~%" e-body) (setf res-body (comp-11-generic e-body)) (format t "res-body = ~A~%" res-body) (setf fvl-b (cadr res-body)) (setf code (annotate (make-labels-lambda fn-vars fn-codes (car res-body)) (list 'reads (fv-clrd fn-fvl-1) 'writes (fv-clwr fn-fvl-1)))) (setf fvl-b (mapcar #'(lambda (z) (set-difference z fn-vars)) fvl-b)) (setf fvl-b (add-fv fvl-b fn-fvl-1)) (list code fvl-b))))))) ;; NEW-VAR: eindeutige variablen erzeugung (defparameter *unique-var-table* nil) (defun get-unique-var (sym) (let ((sym-name (symbol-name sym)) (u-assoc (assoc sym *unique-var-table*))) (let ((n-id (if u-assoc (cdr u-assoc) 0))) (setf n-id (+ n-id 1)) (let ((usym-name (concatenate 'string sym-name "." (format nil "~A" n-id)))) (let ((usym (make-symbol usym-name))) (if u-assoc (rplacd u-assoc n-id) (push (cons sym n-id) *unique-var-table*)) usym))))) (defun get-closure-write-sl-var () (get-unique-var '&&cv))