home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacHaskell 2.2 / prec / scope.scm < prev   
Encoding:
Text File  |  1994-09-27  |  13.8 KB  |  430 lines  |  [TEXT/CCL2]

  1. ;;; scope.scm -- variable scoping and precedence parsing phase
  2. ;;; 
  3. ;;; author :  John & Sandra
  4. ;;; date   :  11 Feb 1992
  5. ;;;
  6. ;;;
  7.  
  8.  
  9. ;;;===================================================================
  10. ;;; Basic support
  11. ;;;===================================================================
  12.  
  13. (define (scope-modules modules)
  14.   (watch-for-undefined-symbols)
  15.   (walk-modules
  16.     modules
  17.     (lambda ()
  18.       (setf (module-decls *module*) (scope-ast-decls (module-decls *module*)))
  19.       (dolist (a (module-annotations *module*))
  20.     ;; This is currently bogus since it assumes only vars are annotated.
  21.     (when (annotation-decl? a)
  22.       (dolist (n (annotation-decl-names a))
  23.         (let ((v (table-entry *symbol-table* n)))
  24.           (cond ((or (eq? v '#f) (not (var? v)))
  25.              (signal-undefined-annotated-var n a))
  26.             ((not (eq? (def-module v) *module-name*))
  27.              (signal-bad-annotated-var v a))
  28.             (else
  29.              (setf (var-annotations v)
  30.                (append (var-annotations v)
  31.                    (annotation-decl-annotations a)))
  32.              (do-specialize-annotation-magic
  33.               v (annotation-decl-annotations a) '#t)
  34.              ))))))))
  35.   (show-undefined-symbols))
  36.  
  37. ;;; Define the basic walker and some helper functions.
  38.  
  39. (define-walker scope ast-td-scope-walker)
  40.  
  41. (define (scope-ast-1 x env)
  42.   (remember-context x
  43.     (call-walker scope x env)))
  44.  
  45.  
  46. (define (scope-ast/list l env)
  47.   (scope-ast/list-aux l env)
  48.   l)
  49.  
  50. (define (scope-ast/list-aux l env)
  51.   (when (not (null? l))
  52.     (setf (car l) (scope-ast-1 (car l) env))
  53.     (scope-ast/list-aux (cdr l) env)))
  54.  
  55.  
  56.  
  57. ;;; This filters out signdecls from decl lists.  These declarations are moved
  58. ;;; into the var definitions.
  59.  
  60. (define (scope-ast/decl-list l env)
  61.   (if (null? l)
  62.       '()
  63.       (let ((x (scope-ast-1 (car l) env))
  64.         (rest (scope-ast/decl-list (cdr l) env)))
  65.     (if (or (annotation-decls? x)
  66.         (and (signdecl? x)
  67.              (not (eq? (module-type *module*) 'interface))))
  68.         rest
  69.         (begin
  70.           (setf (car l) x)
  71.           (setf (cdr l) rest)
  72.           l)))))
  73.  
  74.  
  75.  
  76. ;;; Magic to cons up and collect decls for defs introduced by
  77. ;;; "Specialize" annotations.  These decls are added to the same group
  78. ;;; where the var being specialized is bound.  Attach the specified
  79. ;;; signature to the new var, and store a pointer to it on the def
  80. ;;; for the original var.
  81.  
  82. (define *specializer-decls* '())
  83. (define *specializer-count* 0)
  84.  
  85. (define (scope-ast/decl-list/inner l env)
  86.   (dynamic-let ((*specializer-decls* '()))
  87.     (let ((list  (scope-ast/decl-list l env)))
  88.       (nconc (dynamic *specializer-decls*) list))))
  89.  
  90. (define (do-specialize-annotation-magic var annotation-values toplevel?)
  91.   (dolist (val annotation-values)
  92.     (when (eq? (annotation-value-name val) '|Specialize|)
  93.       (let* ((sig    (car (annotation-value-args val)))
  94.          (gtype  (begin
  95.                (resolve-signature sig)
  96.                (ast->gtype (signature-context sig)
  97.                     (signature-type sig))))
  98.          (name   (format '#f "~a-specialized-~a"
  99.                  var (incf (dynamic *specializer-count*))))
  100.          (svar   (if toplevel?
  101.              (create-top-definition (string->symbol name) 'var)
  102.              (create-local-definition (gensym name))))
  103.          (decl   (**valdef/def svar (**var/def var))))
  104.     (setf (var-signature svar) gtype)
  105.     (setf (var-specializers var)
  106.           (nconc (var-specializers var) (list (list svar))))
  107.     (if toplevel?
  108.         (push decl (module-decls *module*))
  109.         (push decl (dynamic *specializer-decls*)))
  110.     ))))
  111.  
  112.  
  113.  
  114. ;;; This is the main entry point.  It is called by the driver
  115. ;;; on each top-level decl in the module.
  116.  
  117. (define (scope-ast-decls x)
  118.   (let ((result  (scope-ast/decl-list x '())))
  119.     result))
  120.  
  121.  
  122. ;;; All top-level names are entered in the *symbol-table* hash table.
  123. ;;; This is done by the import/export phase of the compiler before
  124. ;;; we get here.
  125. ;;; The env is a list of a-lists that associates locally-defined names with
  126. ;;; their definitions.  Each nested a-list corresponds to a "level" or
  127. ;;; scope.
  128. ;;; *** If many variables are being added in each scope, it might be
  129. ;;; *** better to use a table instead of an alist to represent each contour.
  130.  
  131. (define (lookup-name name env)
  132.   (if (null? env)
  133.       (lookup-toplevel-name name)
  134.       (let ((info  (assq name (car env))))
  135.     (if info
  136.         (cdr info)
  137.         (lookup-name name (cdr env))))))
  138.  
  139.  
  140. ;;; Some kinds of names (e.g. type definitions) appear only at top-level,
  141. ;;; so use this to look for them directly.
  142.  
  143. (define (lookup-toplevel-name name)
  144.   (or (resolve-toplevel-name name)
  145.       (begin
  146.         (signal-undefined-symbol name 'var)
  147.     *undefined-def*)))
  148.  
  149.  
  150. ;;; Some kinds of lookups (e.g., matching a signature declaration)
  151. ;;; require that the name be defined in the current scope and not
  152. ;;; an outer one.  Use this function.
  153.  
  154. (define (lookup-local-name name env place)
  155.   (if (null? env)
  156.       (lookup-toplevel-name name)
  157.       (let ((info  (assq name (car env))))
  158.     (if info
  159.         (cdr info)
  160.         (begin
  161.           (signal-undefined-local-symbol name place)
  162.           *undefined-def*)))))
  163.  
  164.  
  165. ;;; Add local declarations to the environment, returning a new env.
  166. ;;; Do not actually walk the local declarations here.
  167.  
  168. (define *scope-info* '())
  169.  
  170. (define (add-local-declarations decls env)
  171.   (if (null? decls)
  172.       env
  173.       (let ((contour   '()))
  174.     (dolist (d decls)
  175.       (if (is-type? 'valdef d)
  176.           (setf contour
  177.             (add-bindings (collect-pattern-vars (valdef-lhs d))
  178.                   contour d))))
  179.     (cons contour env))))
  180.  
  181.  
  182. ;;; Similar, but for adding lambda and function argument bindings to the
  183. ;;; environment.
  184.  
  185. (define (add-pattern-variables patterns env place)
  186.   (if (null? patterns)
  187.       env
  188.       (let ((contour   '()))
  189.     (dolist (p patterns)
  190.       (setf contour (add-bindings (collect-pattern-vars p) contour place)))
  191.     (cons contour env))))
  192.  
  193.  
  194. ;;; Given a list of var-refs, create defs for them and add them to
  195. ;;; the local environment.
  196. ;;; Also check to see that there are no duplicates.
  197.  
  198. (define (add-bindings var-refs contour place)
  199.   (dolist (v var-refs)
  200.    (when (eq? (var-ref-var v) *undefined-def*)
  201.     (let* ((name     (var-ref-name v))
  202.        (def      (create-local-definition name)))
  203.       (setf (var-ref-var v) def)
  204.       (setf (def-where-defined def) 
  205.         (ast-node-line-number place))
  206.       (let ((old (assq name contour)))
  207.     (if old
  208.         (signal-multiple-bindings name place def (tuple-2-2 old))
  209.         (push (cons name def) contour))))))
  210.   contour)
  211.  
  212.  
  213. ;;; Error signalling utilities.
  214.  
  215. (define (signal-undefined-local-symbol name place)
  216.   (phase-error 'undefined-local-symbol
  217.     "In declaration ~A~%The name ~a is not defined by this declaration group."
  218.     place name))
  219.  
  220. (define (signal-multiple-signatures name)
  221.   (phase-error 'multiple-signatures
  222.     "There is more than one type signature for ~a."
  223.     name))
  224.  
  225. (define (signal-multiple-bindings name place def1 def2)
  226.   (if (and (def-where-defined def1)
  227.        (not (eq? (def-where-defined def1) (def-where-defined def2))))
  228.       (phase-error/objs 'multiple-bindings (list def1 def2)
  229.         "The name `~A' is defined twice in the same scope." name)
  230.       (phase-error 'multiple-bindings
  231.         "There is more than one binding of ~A in ~A"
  232.     name (sz place 40))))
  233.   
  234. (define (signal-undefined-annotated-var n a)
  235.   (recoverable-error 'undefined-annotated-var
  236.        "The variable ~A in annotation ~%~A~%is undefined" n a))
  237.  
  238. ;;;===================================================================
  239. ;;; Default traversal methods
  240. ;;;===================================================================
  241.  
  242.  
  243. (define-local-syntax (make-scope-code slot type)
  244.   (let ((stype  (sd-type slot))
  245.     (sname  (sd-name slot)))
  246.     (cond ((and (symbol? stype)
  247.         (or (eq? stype 'exp)
  248.             (subtype? stype 'exp)))
  249.        `(setf (struct-slot ',type ',sname object)
  250.           (scope-ast-1 (struct-slot ',type ',sname object) env)))
  251.       ((and (pair? stype)
  252.         (eq? (car stype) 'list)
  253.         (symbol? (cadr stype))
  254.         (or (eq? (cadr stype) 'exp)
  255.             (subtype? (cadr stype) 'exp)))
  256.        `(setf (struct-slot ',type ',sname object)
  257.           (scope-ast/list (struct-slot ',type ',sname object) env)))
  258.       (else
  259. ;       (format '#t "Scope: skipping slot ~A in ~A~%"
  260. ;           (sd-name slot)
  261. ;           type)
  262.        '#f))))
  263.  
  264.  
  265. (define-modify-walker-methods scope
  266.   (guarded-rhs  ; exp slots
  267.    if           ; exp slots
  268.    app          ; exp slots
  269.    integer-const float-const char-const string-const  ; no slots
  270.    list-exp     ; (list exp) slot
  271.    sequence sequence-to sequence-then sequence-then-to ; exp slots
  272.    section-l section-r ; exp slots
  273.    omitted-guard overloaded-var-ref bottom ; no slots
  274.    negate ; no slots
  275.    sel
  276.    con-number cast
  277.    is-constructor
  278.    )
  279.   (object env)
  280.   make-scope-code)
  281.  
  282.  
  283. ;;;===================================================================
  284. ;;; valdef-structs
  285. ;;;===================================================================
  286.  
  287.  
  288. ;;; Signature declarations must appear at the same level as the names
  289. ;;; they apply to.  There must not be more than one signature declaration
  290. ;;; applying to a given name.
  291.  
  292. (define-walker-method scope signdecl (object env)
  293.   (let ((signature  (signdecl-signature object)))
  294.     (resolve-signature signature)
  295.     (let ((gtype (ast->gtype (signature-context signature)
  296.                  (signature-type signature))))
  297.       (dolist (v (signdecl-vars object))
  298.     (when (eq? (var-ref-var v) *undefined-def*)
  299.           (setf (var-ref-var v)
  300.             (lookup-local-name (var-ref-name v) env object)))
  301.     (let ((def  (var-ref-var v)))
  302.       (when (not (eq? def *undefined-def*))
  303.         ;; The lookup-local-name may fail if there is a program error.
  304.         ;; In that case, skip this.
  305.         (if (var-signature def)
  306.         (signal-multiple-signatures (var-ref-name v))
  307.         (setf (var-signature def) gtype))))))
  308.     object))
  309.  
  310. ;;; This attaches annotations to locally defined vars in the same
  311. ;;; manner as signdecl annotations.
  312.  
  313. (define-walker-method scope annotation-decls (object env)
  314.   (let ((anns (annotation-decls-annotations object)))
  315.     (dolist (a anns)
  316.       (cond ((annotation-value? a)
  317.          (recoverable-error 'unknown-annotation
  318.                 "Unknown annotation: ~A" a))
  319.         ((annotation-decl? a)
  320.          (dolist (v (annotation-decl-names a))
  321.            (let ((name (lookup-local-name v env a)))
  322.          (cond ((eq? name *undefined-def*)
  323.             (signal-bad-annotated-var v a))
  324.                (else
  325.             (setf (var-annotations name)
  326.                   (append (var-annotations name)
  327.                       (annotation-decl-annotations a)))
  328.             (do-specialize-annotation-magic
  329.              name (annotation-decl-annotations a) '#f)))))))))
  330.   object)
  331.  
  332. (define-walker-method scope exp-sign (object env)
  333.   (resolve-signature (exp-sign-signature object))
  334.   (setf (exp-sign-exp object) (scope-ast-1 (exp-sign-exp object) env))
  335.   object)
  336.  
  337. ;;; By the time we get to walking a valdef, all the variables it
  338. ;;; declares have been entered into the environment.  All we need to
  339. ;;; do is massage the pattern and recursively walk the definitions.
  340.  
  341. (define-walker-method scope valdef (object env)
  342.   (setf (valdef-module object) *module-name*)
  343.   (setf (valdef-lhs object) (massage-pattern (valdef-lhs object)))
  344.   (dolist (sfd (valdef-definitions object))
  345.     (scope-single-fun-def sfd env (valdef-lhs object)))
  346.   object)
  347.  
  348.  
  349. ;;; For a single-fun-def, do the where-decls first, and then walk the
  350. ;;; rhs in an env that includes both the where-decls and the args.
  351.  
  352. (define (scope-single-fun-def object env lhs)
  353.   (setf env (add-pattern-variables
  354.          (single-fun-def-args object)
  355.          env 
  356.          ;; This is just for the error message
  357.          (make valdef (lhs lhs) (definitions (list object)))))
  358.   (setf env (add-local-declarations (single-fun-def-where-decls object) env))
  359.   (setf (single-fun-def-where-decls object)
  360.     (scope-ast/decl-list/inner (single-fun-def-where-decls object) env))
  361.   (setf (single-fun-def-args object)
  362.     (massage-pattern-list (single-fun-def-args object)))
  363.   (setf (single-fun-def-rhs-list object)
  364.     (scope-ast/list (single-fun-def-rhs-list object) env)))
  365.  
  366. ;;;===================================================================
  367. ;;; exp-structs
  368. ;;;===================================================================
  369.  
  370. (define-walker-method scope lambda (object env)
  371.   (setf env (add-pattern-variables (lambda-pats object) env object))
  372.   (setf (lambda-pats object) (massage-pattern-list (lambda-pats object)))
  373.   (setf (lambda-body object) (scope-ast-1 (lambda-body object) env))
  374.   object)
  375.  
  376. (define-walker-method scope let (object env)
  377.   (setf env (add-local-declarations (let-decls object) env))
  378.   (setf (let-decls object) (scope-ast/decl-list/inner (let-decls object) env))
  379.   (setf (let-body object) (scope-ast-1 (let-body object) env))
  380.   object)
  381.  
  382.  
  383. ;;; Case alts are treated very much like single-fun-defs.
  384.  
  385. (define-walker-method scope case (object env)
  386.   (setf (case-exp object) (scope-ast-1 (case-exp object) env))
  387.   (dolist (a (case-alts object))
  388.     (let ((env  (add-pattern-variables (list (alt-pat a)) env (alt-pat a))))
  389.       (setf env (add-local-declarations (alt-where-decls a) env))
  390.       (setf (alt-where-decls a)
  391.         (scope-ast/decl-list/inner (alt-where-decls a) env))
  392.       (setf (alt-pat a) (massage-pattern (alt-pat a)))
  393.       (setf (alt-rhs-list a)
  394.         (scope-ast/list (alt-rhs-list a) env))))
  395.   object)
  396.  
  397.  
  398. (define-walker-method scope var-ref (object env)
  399.   (when (eq? (var-ref-var object) *undefined-def*)
  400.     (setf (var-ref-var object)
  401.           (lookup-name (var-ref-name object) env)))
  402.   object)
  403.  
  404. (define-walker-method scope con-ref (object env)
  405.   (declare (ignore env))
  406.   (when (eq? (con-ref-con object) *undefined-def*)
  407.     (setf (con-ref-con object)
  408.           (lookup-toplevel-name (con-ref-name object))))
  409.   object)
  410.  
  411. (define-walker-method scope list-comp (object env)
  412.   (dolist (q (list-comp-quals object))
  413.     (cond ((is-type? 'qual-generator q)
  414.        (setf (qual-generator-exp q)
  415.          (scope-ast-1 (qual-generator-exp q) env))
  416.        (setf env
  417.          (add-pattern-variables
  418.           (list (qual-generator-pat q)) env (qual-generator-pat q)))
  419.        (setf (qual-generator-pat q)
  420.          (massage-pattern (qual-generator-pat q))))
  421.       ((is-type? 'qual-filter q)
  422.        (setf (qual-filter-exp q)
  423.          (scope-ast-1 (qual-filter-exp q) env)))))
  424.   (setf (list-comp-exp object) (scope-ast-1 (list-comp-exp object) env))
  425.   object)
  426.  
  427. (define-walker-method scope pp-exp-list (object env)
  428.   (massage-pp-exp-list (scope-ast/list (pp-exp-list-exps object) env)))
  429.  
  430.