|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T c ┃
Length: 11988 (0x2ed4) Types: TextFile Names: »compiler.scm«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/gnu-31mar87/scheme/psets/compiler.scm«
;;; Simple SCHEME compiler (define (compile exp) (compile-expression exp '() 'val 'return)) (define (compile-expression exp env target cont) (cond ((self-evaluating? exp) (compile-constant exp target cont)) ((quoted? exp) (compile-constant (text-of-quotation exp) target cont)) ((variable? exp) (compile-variable-access exp env target cont)) ((assignment? exp) (compile-assignment exp env target cont)) ((definition? exp) (compile-definition exp env target cont)) ((lambda? exp) (compile-lambda exp env target cont)) ((conditional? exp) (compile-cond (clauses exp) env target cont)) ((no-args? exp) (compile-no-args exp env target cont)) ((application? exp) (compile-application exp env target cont)) (else (error "Unknown expression type -- compile" exp)))) (define (compile-constant constant target cont) (append-instruction-sequences (make-register-assignment target (make-constant constant)) (continue-at cont))) (define (compile-variable-access var env target cont) (append-instruction-sequences (make-register-assignment target (make-variable-access var env)) (continue-at cont))) (define (compile-assignment exp env target cont) (let ((target (if (null? target) 'val target))) (preserving 'env (compile-expression (assignment-value exp) env target 'next) (append-instruction-sequences (make-variable-assignment (assignment-variable exp) env (make-fetch target)) (continue-at cont))))) (define (compile-definition exp env target cont) (let ((target (if (null? target) 'val target))) (preserving 'env (compile-expression (definition-value exp) (definition-env! (definition-variable exp) env) target 'next) (append-instruction-sequences (make-variable-definition (definition-variable exp) env (make-fetch target)) (continue-at cont))))) \f (define (compile-lambda exp env target cont) (let ((entry (generate-new-name 'entry))) (append-instruction-sequences (make-register-assignment target (make-procedure-maker entry)) (if (eq? cont 'next) (let ((after-lambda (generate-new-name 'after-lambda))) (append-instruction-sequences (continue-at after-lambda) (append-instruction-sequences (compile-lambda-body exp env entry) (make-labeled-point after-lambda)))) (append-instruction-sequences (continue-at cont) (compile-lambda-body exp env entry)))))) (define (compile-lambda-body exp env entry) (safe-instruction-sequence (append-instruction-sequences (make-labeled-point entry) (append-instruction-sequences (make-environment-switch (lambda-parameters exp)) (compile-sequence (lambda-body exp) (extend-compile-time-env (lambda-parameters exp) env) 'val 'return))))) (define (make-environment-switch formals) (append-instruction-sequences (make-register-assignment 'env (make-env-ref (make-fetch 'fun))) (make-register-assignment 'env (make-bindings-maker formals (make-fetch 'argl) (make-fetch 'env))))) (define (compile-cond clauses env target cont) (if (eq? cont 'next) (let ((end-of-cond (generate-new-name 'cond-end))) (append-instruction-sequences (compile-clauses clauses env target end-of-cond) (make-labeled-point end-of-cond))) ;Output label (compile-clauses clauses env target cont))) (define (compile-clauses clauses env target cont) (if (no-clauses? clauses) (continue-at cont) (let ((fc (first-clause clauses))) (if (else-clause? fc) (compile-sequence (action-sequence fc) env target cont) (let ((ift (generate-new-name 'true-branch))) (preserving 'env (compile-expression (predicate fc) env 'val 'next) (append-instruction-sequences (make-branch (make-fetch 'val) ift) (join-instruction-sequences (compile-clauses (rest-clauses clauses) env target cont) (append-instruction-sequences (make-labeled-point ift) (compile-sequence (action-sequence fc) env target cont)))))))))) \f (define (compile-sequence seq env target cont) (if (last-exp? seq) (compile-expression (first-exp seq) env target cont) (preserving 'env (compile-expression (first-exp seq) env 'nil 'next) (compile-sequence (rest-exps seq) env target cont)))) (define (compile-no-args app env target cont) (append-instruction-sequences (compile-expression (operator app) env 'fun 'next) (append-instruction-sequences (make-register-assignment 'argl (make-empty-arglist)) (make-call target cont)))) (define (compile-application app env target cont) (preserving 'env (compile-expression (operator app) env 'fun 'next) (preserving 'fun (compile-operands (operands app) env) (make-call target cont)))) (define (compile-operands rands env) (let ((fo (compile-first-operand rands env))) (if (last-operand? rands) fo (preserving 'env fo (compile-rest-operands (rest-operands rands) env))))) (define (compile-first-operand rands env) (append-instruction-sequences (compile-expression (first-operand rands) env 'val 'next) (make-register-assignment 'argl (make-singleton-arglist (make-fetch 'val))))) (define (compile-rest-operands rands env) (let ((no (compile-next-operand rands env))) (if (last-operand? rands) no (preserving 'env no (compile-rest-operands (rest-operands rands) env))))) (define (compile-next-operand rands env) (preserving 'argl (compile-expression (first-operand rands) env 'val 'next) (make-register-assignment 'argl (make-addition-to-arglist (make-fetch 'val) (make-fetch 'argl))))) \f (define (make-call target cont) (let ((cc (make-call-result-in-val cont))) (if (eq? target 'val) cc (append-instruction-sequences cc (make-register-assignment target (make-fetch 'val)))))) (define (make-call-result-in-val cont) (cond ((eq? cont 'return) (make-transfer-to-procedure-applicator)) ((eq? cont 'next) (let ((after-call (generate-new-name 'after-call))) (append-instruction-sequences (make-call-return-to after-call) (make-labeled-point after-call)))) (else (make-call-return-to cont)))) ;A label (define (make-call-return-to retlabel) (append-instruction-sequences (append-instruction-sequences (make-register-assignment 'continue retlabel) (make-save 'continue)) (make-transfer-to-procedure-applicator))) (define (continue-at continuation) (cond ((eq? continuation 'return) (append-instruction-sequences (make-restore 'continue) (make-goto-instruction (make-fetch 'continue)))) ((eq? continuation 'next) (the-empty-instruction-sequence)) (else (make-goto-instruction continuation)))) (define (append-instruction-sequences s1 s2) (make-seq (set-union (needs-list s1) (set-difference (needs-list s2) (mung-list s1))) (set-union (mung-list s1) (mung-list s2)) (append (statements s1) (statements s2)))) (define (preserving reg seq1 seq2) (if (and (memq reg (needs-list seq2)) (memq reg (mung-list seq1))) (append-instruction-sequences (make-seq (needs-list seq1) (set-difference (mung-list seq1) (list reg)) (append (statements (make-save reg)) (statements seq1) (statements (make-restore reg)))) seq2) (append-instruction-sequences seq1 seq2))) (define (join-instruction-sequences s1 s2) (make-seq (set-union (needs-list s1) (needs-list s2)) (set-union (mung-list s1) (mung-list s2)) (append (statements s1) (statements s2)))) (define (safe-instruction-sequence seq) (make-seq '() '() (statements seq))) \f ;;; Nothing above this line knows the format of ;;; an "assembly-language" instruction. (define (make-goto-instruction continuation) (make-instruction (needs-list continuation) '() (list 'goto (value-of continuation)))) (define (make-branch predicate if-true-label) (make-instruction (needs-list predicate) '() (list 'branch (value-of predicate) if-true-label))) (define (make-transfer-to-procedure-applicator) (make-instruction '(fun argl) all '(goto apply-dispatch))) (define (make-labeled-point label) (make-instruction '() '() label)) (define (make-register-assignment reg val) (cond ((not (null? reg)) (make-instruction (needs-list val) (list reg) (list 'assign reg (value-of val)))) (else (the-empty-instruction-sequence)))) (define (make-fetch reg) (make-value (list reg) (list 'fetch reg))) (define (make-save reg) (make-instruction '() '() (list 'save reg))) (define (make-restore reg) (make-instruction '() '() (list 'restore reg))) (define (make-constant x) (make-value '() (list 'quote x))) (define (make-variable-access var compilation-env) (make-value '(env) (list 'lookup-variable-value (list 'quote var) (value-of (make-fetch 'env))))) (define (make-variable-assignment var compilation-env val) (make-instruction (set-union '(env) (needs-list val)) '() (list 'perform (list 'set-variable-value! (list 'quote var) (value-of val) (value-of (make-fetch 'env)))))) (define (make-variable-definition var compilation-env val) (make-instruction (set-union '(env) (needs-list val)) '() (list 'perform (list 'define-variable! (list 'quote var) (value-of val) (value-of (make-fetch 'env)))))) \f (define (make-bindings-maker vars args env) (make-value (list (needs-list args) (needs-list env)) (list 'extend-environment (list 'quote (reverse vars)) (value-of args) (value-of env)))) (define (make-procedure-maker entry) (make-value '(env) (list 'make-compiled-procedure entry (value-of (make-fetch 'env))))) (define (make-env-ref fun) (make-value (needs-list fun) (list 'env-of-compiled-procedure (value-of fun)))) (define (make-empty-arglist) (make-value '() '())) (define (make-singleton-arglist val) (make-value (needs-list val) (list 'cons (value-of val) '()))) (define (make-addition-to-arglist val args) (make-value (set-union (needs-list val) (needs-list args)) (list 'cons (value-of val) (value-of args)))) ;; From here on down is internal compiler data structure stuff: (define (make-value needed-regs expression) (list needed-regs expression)) (define (needs-list value) (if (symbol? value) ; Label '() (car value))) (define (value-of value) (if (symbol? value) value (cadr value))) (define (make-instruction needs mungs code) (make-seq needs mungs (list code))) (define (make-seq needs mungs seq) (list needs mungs seq)) (define (the-empty-instruction-sequence) (list '() '() '())) ;;;NEEDS-LIST already defined above. (define (mung-list seq) (cadr seq)) (define (statements seq) (caddr seq)) (define (set-union x y) (cond ((null? x) y) ((memq (car x) y) (set-union (cdr x) y)) (else (cons (car x) (set-union (cdr x) y))))) (define (set-difference x y) (cond ((null? x) '()) ((memq (car x) y) (set-difference (cdr x) y)) (else (cons (car x) (set-difference (cdr x) y))))) (define (extend-compile-time-env frame env) (cons (reverse frame) env)) ;;note reversal to match interpreter's ;;make-bindings (define (definition-env! var env) (if (and (not (null? env)) (not (memq var (car env)))) (set-car! env (cons var env))) env) (define (given-new-definition var env) (if (null? env) ;global? env ;no nothing. (cons (cons var (car env)) ;add to top frame (cdr env)))) (sequence (enable-language-features) (define generate-new-name (access generate-uninterned-symbol '())) (disable-language-features)) (define all '(env argl val fun continue)) ;; Syntax extras (define (lambda-parameters exp) (cadr exp)) (define (lambda-body exp) (cddr exp))