📄 dynamic.scm
字号:
;;; DYNAMIC -- Obtained from Andrew Wright.;; 08/06/01 (felix): renamed "null" to "null2" because stupid MZC can't; handle redefinitions of primitives.;;;; Fritz's dynamic type inferencer, set up to run on itself;; (see the end of this file).;----------------------------------------------------------------------------; Environment management;----------------------------------------------------------------------------;; environments are lists of pairs, the first component being the key;; general environment operations;;;; empty-env: Env;; gen-binding: Key x Value -> Binding;; binding-key: Binding -> Key;; binding-value: Binding -> Value;; binding-show: Binding -> Symbol*;; extend-env-with-binding: Env x Binding -> Env;; extend-env-with-env: Env x Env -> Env;; lookup: Key x Env -> (Binding + False);; env->list: Env -> Binding*;; env-show: Env -> Symbol*; bindings(define gen-binding cons); generates a type binding, binding a symbol to a type variable(define binding-key car); returns the key of a type binding(define binding-value cdr); returns the tvariable of a type binding(define (key-show key) ; default show procedure for keys key)(define (value-show value) ; default show procedure for values value)(define (binding-show binding) ; returns a printable representation of a type binding (cons (key-show (binding-key binding)) (cons ': (value-show (binding-value binding))))); environments(define dynamic-empty-env '()); returns the empty environment(define (extend-env-with-binding env binding) ; extends env with a binding, which hides any other binding in env ; for the same key (see dynamic-lookup) ; returns the extended environment (cons binding env))(define (extend-env-with-env env ext-env) ; extends environment env with environment ext-env ; a binding for a key in ext-env hides any binding in env for ; the same key (see dynamic-lookup) ; returns the extended environment (append ext-env env))(define dynamic-lookup (lambda (x l) (assv x l))); returns the first pair in env that matches the key; returns #f; if no such pair exists(define (env->list e) ; converts an environment to a list of bindings e)(define (env-show env) ; returns a printable list representation of a type environment (map binding-show env));----------------------------------------------------------------------------; Parsing for Scheme;----------------------------------------------------------------------------;; Needed packages: environment management;(load "env-mgmt.ss");(load "pars-act.ss");; Lexical notions(define syntactic-keywords ;; source: IEEE Scheme, 7.1, <expression keyword>, <syntactic keyword> '(lambda if set! begin cond and or case let let* letrec do quasiquote else => define unquote unquote-splicing));; Parse routines; Datum; dynamic-parse-datum: parses nonterminal <datum>(define (dynamic-parse-datum e) ;; Source: IEEE Scheme, sect. 7.2, <datum> ;; Note: "'" is parsed as 'quote, "`" as 'quasiquote, "," as ;; 'unquote, ",@" as 'unquote-splicing (see sect. 4.2.5, p. 18) ;; ***Note***: quasi-quotations are not permitted! (It would be ;; necessary to pass the environment to dynamic-parse-datum.) (cond ((null? e) (dynamic-parse-action-null-const)) ((boolean? e) (dynamic-parse-action-boolean-const e)) ((char? e) (dynamic-parse-action-char-const e)) ((number? e) (dynamic-parse-action-number-const e)) ((string? e) (dynamic-parse-action-string-const e)) ((symbol? e) (dynamic-parse-action-symbol-const e)) ((vector? e) (dynamic-parse-action-vector-const (map dynamic-parse-datum (vector->list e)))) ((pair? e) (dynamic-parse-action-pair-const (dynamic-parse-datum (car e)) (dynamic-parse-datum (cdr e)))) (else (error 'dynamic-parse-datum "Unknown datum: ~s" e)))); VarDef; dynamic-parse-formal: parses nonterminal <variable> in defining occurrence position(define (dynamic-parse-formal f-env e) ; e is an arbitrary object, f-env is a forbidden environment; ; returns: a variable definition (a binding for the symbol), plus ; the value of the binding as a result (if (symbol? e) (cond ((memq e syntactic-keywords) (error 'dynamic-parse-formal "Illegal identifier (keyword): ~s" e)) ((dynamic-lookup e f-env) (error 'dynamic-parse-formal "Duplicate variable definition: ~s" e)) (else (let ((dynamic-parse-action-result (dynamic-parse-action-var-def e))) (cons (gen-binding e dynamic-parse-action-result) dynamic-parse-action-result)))) (error 'dynamic-parse-formal "Not an identifier: ~s" e))); dynamic-parse-formal*(define (dynamic-parse-formal* formals) ;; parses a list of formals and returns a pair consisting of generated ;; environment and list of parsing action results (letrec ((pf* (lambda (f-env results formals) ;; f-env: "forbidden" environment (to avoid duplicate defs) ;; results: the results of the parsing actions ;; formals: the unprocessed formals ;; Note: generates the results of formals in reverse order! (cond ((null? formals) (cons f-env results)) ((pair? formals) (let* ((fst-formal (car formals)) (binding-result (dynamic-parse-formal f-env fst-formal)) (binding (car binding-result)) (var-result (cdr binding-result))) (pf* (extend-env-with-binding f-env binding) (cons var-result results) (cdr formals)))) (else (error 'dynamic-parse-formal* "Illegal formals: ~s" formals)))))) (let ((renv-rres (pf* dynamic-empty-env '() formals))) (cons (car renv-rres) (reverse (cdr renv-rres)))))); dynamic-parse-formals: parses <formals>(define (dynamic-parse-formals formals) ;; parses <formals>; see IEEE Scheme, sect. 7.3 ;; returns a pair: env and result (letrec ((pfs (lambda (f-env formals) (cond ((null? formals) (cons dynamic-empty-env (dynamic-parse-action-null-formal))) ((pair? formals) (let* ((fst-formal (car formals)) (rem-formals (cdr formals)) (bind-res (dynamic-parse-formal f-env fst-formal)) (bind (car bind-res)) (res (cdr bind-res)) (nf-env (extend-env-with-binding f-env bind)) (renv-res* (pfs nf-env rem-formals)) (renv (car renv-res*)) (res* (cdr renv-res*))) (cons (extend-env-with-binding renv bind) (dynamic-parse-action-pair-formal res res*)))) (else (let* ((bind-res (dynamic-parse-formal f-env formals)) (bind (car bind-res)) (res (cdr bind-res))) (cons (extend-env-with-binding dynamic-empty-env bind) res))))))) (pfs dynamic-empty-env formals))); Expr; dynamic-parse-expression: parses nonterminal <expression>(define (dynamic-parse-expression env e) (cond ((symbol? e) (dynamic-parse-variable env e)) ((pair? e) (let ((op (car e)) (args (cdr e))) (case op ((quote) (dynamic-parse-quote env args)) ((lambda) (dynamic-parse-lambda env args)) ((if) (dynamic-parse-if env args)) ((set!) (dynamic-parse-set env args)) ((begin) (dynamic-parse-begin env args)) ((cond) (dynamic-parse-cond env args)) ((case) (dynamic-parse-case env args)) ((and) (dynamic-parse-and env args)) ((or) (dynamic-parse-or env args)) ((let) (dynamic-parse-let env args)) ((let*) (dynamic-parse-let* env args)) ((letrec) (dynamic-parse-letrec env args)) ((do) (dynamic-parse-do env args)) ((quasiquote) (dynamic-parse-quasiquote env args)) (else (dynamic-parse-procedure-call env op args))))) (else (dynamic-parse-datum e)))); dynamic-parse-expression*(define (dynamic-parse-expression* env exprs) ;; Parses lists of expressions (returns them in the right order!) (letrec ((pe* (lambda (results es) (cond ((null? es) results) ((pair? es) (pe* (cons (dynamic-parse-expression env (car es)) results) (cdr es))) (else (error 'dynamic-parse-expression* "Not a list of expressions: ~s" es)))))) (reverse (pe* '() exprs)))); dynamic-parse-expressions(define (dynamic-parse-expressions env exprs) ;; parses lists of arguments of a procedure call (cond ((null? exprs) (dynamic-parse-action-null-arg)) ((pair? exprs) (let* ((fst-expr (car exprs)) (rem-exprs (cdr exprs)) (fst-res (dynamic-parse-expression env fst-expr)) (rem-res (dynamic-parse-expressions env rem-exprs))) (dynamic-parse-action-pair-arg fst-res rem-res))) (else (error 'dynamic-parse-expressions "Illegal expression list: ~s" exprs)))); dynamic-parse-variable: parses variables (applied occurrences)(define (dynamic-parse-variable env e) (if (symbol? e) (if (memq e syntactic-keywords) (error 'dynamic-parse-variable "Illegal identifier (keyword): ~s" e) (let ((assoc-var-def (dynamic-lookup e env))) (if assoc-var-def (dynamic-parse-action-variable (binding-value assoc-var-def)) (dynamic-parse-action-identifier e)))) (error 'dynamic-parse-variable "Not an identifier: ~s" e))); dynamic-parse-procedure-call(define (dynamic-parse-procedure-call env op args) (dynamic-parse-action-procedure-call (dynamic-parse-expression env op) (dynamic-parse-expressions env args))); dynamic-parse-quote(define (dynamic-parse-quote env args) (if (list-of-1? args) (dynamic-parse-datum (car args)) (error 'dynamic-parse-quote "Not a datum (multiple arguments): ~s" args))); dynamic-parse-lambda(define (dynamic-parse-lambda env args) (if (pair? args) (let* ((formals (car args)) (body (cdr args)) (nenv-fresults (dynamic-parse-formals formals)) (nenv (car nenv-fresults)) (fresults (cdr nenv-fresults))) (dynamic-parse-action-lambda-expression fresults (dynamic-parse-body (extend-env-with-env env nenv) body))) (error 'dynamic-parse-lambda "Illegal formals/body: ~s" args))); dynamic-parse-body(define (dynamic-parse-body env body) ; <body> = <definition>* <expression>+ (define (def-var* f-env body) ; finds the defined variables in a body and returns an ; environment containing them (if (pair? body) (let ((n-env (def-var f-env (car body)))) (if n-env (def-var* n-env (cdr body)) f-env)) f-env)) (define (def-var f-env clause) ; finds the defined variables in a single clause and extends ; f-env accordingly; returns false if it's not a definition (if (pair? clause) (case (car clause) ((define) (if (pair? (cdr clause)) (let ((pattern (cadr clause))) (cond ((symbol? pattern) (extend-env-with-binding f-env (gen-binding pattern (dynamic-parse-action-var-def pattern)))) ((and (pair? pattern) (symbol? (car pattern))) (extend-env-with-binding f-env (gen-binding (car pattern) (dynamic-parse-action-var-def (car pattern))))) (else f-env))) f-env)) ((begin) (def-var* f-env (cdr clause))) (else #f)) #f)) (if (pair? body) (dynamic-parse-command* (def-var* env body) body) (error 'dynamic-parse-body "Illegal body: ~s" body))); dynamic-parse-if(define (dynamic-parse-if env args) (cond ((list-of-3? args) (dynamic-parse-action-conditional (dynamic-parse-expression env (car args)) (dynamic-parse-expression env (cadr args)) (dynamic-parse-expression env (caddr args)))) ((list-of-2? args) (dynamic-parse-action-conditional (dynamic-parse-expression env (car args)) (dynamic-parse-expression env (cadr args)) (dynamic-parse-action-empty))) (else (error 'dynamic-parse-if "Not an if-expression: ~s" args)))); dynamic-parse-set(define (dynamic-parse-set env args) (if (list-of-2? args) (dynamic-parse-action-assignment (dynamic-parse-variable env (car args)) (dynamic-parse-expression env (cadr args))) (error 'dynamic-parse-set "Not a variable/expression pair: ~s" args)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -