home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / MacHaskell 2.2 / type / dictionary.scm < prev    next >
Encoding:
Text File  |  1994-09-27  |  12.0 KB  |  323 lines  |  [TEXT/CCL2]

  1.  
  2. ;;; type/dictionary.scm
  3.  
  4. ;;; This function supports dictionary conversion.  It creates lambda
  5. ;;; variables to bind to the dictionary args needed by the context.
  6. ;;; The actual conversion to lambda is done in the cfn.  Each tyvar in
  7. ;;; the context has an associated mapping from class to dictionary
  8. ;;; variable.  This mapping depends on the decl containing the placeholder
  9. ;;; since different recursive decls share common tyvars.  The mapping is
  10. ;;; two levels: decl -> class -> var.
  11.  
  12. ;;; Due to language restrictions this valdef must be a simple variable
  13. ;;; definition.
  14.  
  15. (define (dictionary-conversion/definition valdef tyvars)
  16.   (let* ((var (decl-var valdef))
  17.      (type (var-type var))
  18.      (context (gtype-context type))
  19.      (dict-param-vars '()))
  20.     (dolist (c context)
  21.       (let ((tyvar (car tyvars))
  22.         (dparams '()))
  23.        (when (not (null? c))
  24.     (dolist (class c)
  25.           (let ((var (create-temp-var
  26.               (string-append "d_"
  27.                      (symbol->string (def-name class))))))
  28.         (setf (var-force-strict? var) '#t)
  29.         (push (tuple class var) dparams)
  30.         (push var dict-param-vars)))
  31.     (push (tuple valdef dparams) (ntyvar-dict-params tyvar)))
  32.        (setf tyvars (cdr tyvars))))
  33.     (setf (valdef-dictionary-args valdef) (nreverse dict-param-vars))))
  34.  
  35. ;;; These routines deal with dict-var processing.
  36.  
  37. ;;; This discharges the tyvars associated with dictionaries.  The dict-vars
  38. ;;; to be processed at the next level are returned.
  39.  
  40. (define (process-placeholders placeholders deferred decls)
  41.  (mlet (((ps dps)
  42.      (process-placeholders-1 placeholders deferred '() decls))
  43.     ((deferred-1 _)
  44.      (process-dtype-placeholders dps ps '() (car decls))))
  45.     deferred-1))
  46.        
  47. (define (process-placeholders-1 placeholders deferred dps decls)
  48.   (cond ((null? placeholders)
  49.      (values deferred dps))
  50.     ((dtype-placeholder? (car placeholders))
  51.      (process-placeholders-1
  52.       (cdr placeholders) deferred (cons (car placeholders) dps) decls))
  53.     (else
  54.      (let ((d1 (process-placeholder (car placeholders) deferred decls)))
  55.        (process-placeholders-1 (cdr placeholders) d1 dps decls)))))
  56.  
  57. ;;; This processes a placeholder.  The following cases arise:
  58. ;;;  a) the variable has already been processed (no placeholders remain) -
  59. ;;;     ignore it.  placeholders may contain duplicates so this is likely.
  60. ;;;  b) the type variable is from an outer type environment (in ng-list)
  61. ;;;     and should just be passed up to the next level (added to old-placeholders)
  62. ;;;  c) the type variable is associated with a dictionary parameter
  63. ;;;  d) the type variable is instantiated to a type constructor
  64. ;;;  e) the type variable is ambiguous (none of the above)
  65.  
  66. (define (process-placeholder p deferred decls)
  67.   (let* ((tyvar (placeholder-tyvar p))
  68.      (type (prune tyvar)))
  69.     (cond ((ntycon? type)
  70.        (process-instantiated-tyvar
  71.         (expand-ntype-synonym type) p deferred decls))
  72.       ((non-generic? type)
  73.        (cons p deferred))
  74.       ((not (null? (ntyvar-dict-params type)))
  75.        (if (dict-placeholder? p)
  76.            (placeholder->dict-param p (ntyvar-dict-params type) decls)
  77.            (placeholder->method p (ntyvar-dict-params type) decls))
  78.        deferred)
  79.       (else
  80.        ;; Since default types are monotypes, no new vars will
  81.        ;; be added to old-placeholders
  82.        (when (maybe-default-ambiguous-tyvar
  83.           type (placeholder-overloaded-var p)
  84.           (valdef-module (car (placeholder-enclosing-decls p))))
  85.           (process-placeholder p deferred decls))
  86.        deferred))))
  87.            
  88. ;;; The type variable is associated with a dictionary parameter.  The only
  89. ;;; complication here is that the class needed may not be directly available -
  90. ;;; it may need to be obtained from the super classes of the parameter
  91. ;;; dictionaries.
  92.  
  93. (define (placeholder->dict-param p param-vars decls)
  94.   (let ((class (dict-placeholder-class p))
  95.     (edecls (dict-placeholder-enclosing-decls p)))
  96.     (setf (placeholder-exp p)
  97.       (dict-reference-code class (locate-params param-vars edecls decls)))))
  98.  
  99. (define (dict-reference-code class param-vars)
  100.   (let ((var (assoc-def class param-vars)))
  101.     (if (not (eq? var '#f))
  102.     (**var/def var)
  103.     (search-superclasses class param-vars))))
  104.  
  105. (define (locate-params param-vars enclosing-decls decls)
  106.   (if (null? (cdr param-vars))
  107.       (tuple-2-2 (car param-vars))
  108.       (let ((decl (search-enclosing-decls enclosing-decls decls)))
  109.     (tuple-2-2 (assq decl param-vars)))))
  110.  
  111. ;;; This finds the first dictionary containing the needed class in its
  112. ;;; super classes and generates a selector to get the needed dictionary.
  113.  
  114. (define (search-superclasses class param-vars)
  115.   (let ((pclass (tuple-2-1 (car param-vars))))
  116.     (if (memq class (class-super* pclass))
  117.     (**dsel/dict pclass class (**var/def (tuple-2-2 (car param-vars))))
  118.     (search-superclasses class (cdr param-vars)))))
  119.  
  120. (define (placeholder->method p param-vars decls)
  121.   (let* ((method (method-placeholder-method p))
  122.      (class (method-var-class method))
  123.      (edecls (placeholder-enclosing-decls p))
  124.      (params (locate-params param-vars edecls decls)))
  125.     (setf (placeholder-exp p)
  126.       (method-reference-code method class params))))
  127.  
  128. (define (method-reference-code m c param-vars)
  129.  (let ((pclass (tuple-2-1 (car param-vars))))
  130.   (if (or (eq? c pclass)
  131.       (memq c (class-super* pclass)))
  132.       (let ((mvar (assoc-def m (class-selectors pclass))))
  133.     (**app (**var/def mvar) (**var/def (tuple-2-2 (car param-vars)))))
  134.       (method-reference-code m c (cdr param-vars)))))
  135.  
  136. ;;; This is for tyvars instantiated to a tycon.  A reference to the
  137. ;;; appropriate dictionary is generated.  This reference must be recursively
  138. ;;; dictionary converted since dictionaries may need subdictionaries
  139. ;;; when referenced.
  140.  
  141. (define (process-instantiated-tyvar tycon p deferred decls)
  142.   (let* ((alg (ntycon-tycon tycon))
  143.      (edecls (placeholder-enclosing-decls p))
  144.      (var (placeholder-overloaded-var p))
  145.      (class (if (dict-placeholder? p)
  146.             (dict-placeholder-class p)
  147.             (method-var-class (method-placeholder-method p))))
  148.      (instance (lookup-instance alg class)))
  149.     (if (dict-placeholder? p)
  150.     (mlet (((code def1)
  151.         (generate-dict-ref instance tycon deferred decls edecls var)))
  152.        (setf (placeholder-exp p) code)
  153.        (setf deferred def1))
  154.     (let ((method (method-placeholder-method p)))
  155.       (if (and (not (instance-skolem-inst? instance))
  156.            (every (function null?) (instance-gcontext instance))
  157.            (instance-methods instance))
  158.           (let ((mvar (assoc-def method (instance-methods instance))))
  159.         (setf (placeholder-exp p) (**var/def mvar)))
  160.           (mlet (((code def1)
  161.               (generate-dict-ref
  162.                  instance tycon deferred decls edecls var))
  163.              (sel (assoc-def method (class-selectors class))))
  164.         (setf (method-placeholder-exp p) (**app (**var/def sel) code))
  165.         (setf deferred def1)))))
  166.     deferred))
  167.  
  168. ;;; This generates a reference to a specific dictionary and binds
  169. ;;; needed subdictionaries.  Since subdictionaries may be part of the outer
  170. ;;; type environment new placeholders may be generated for later resolution.
  171.  
  172. (define (generate-dict-ref instance type deferred decls edecls var)
  173.   (let* ((ctxt (instance-gcontext instance))
  174.      (dict (dict-ref-code instance)))
  175.     (do-contexts (class ctxt) (ty (ntycon-args type))
  176.       (let ((ntype (prune ty)))
  177.     (cond
  178.      ((ntycon? ntype)
  179.       (mlet ((ntype (expand-ntype-synonym ntype))
  180.          (alg (ntycon-tycon ntype))
  181.          (instance (lookup-instance alg class))
  182.          ((code dv1)
  183.           (generate-dict-ref
  184.             instance ntype deferred decls edecls var)))
  185.           (setf dict (**app dict code))
  186.           (setf deferred dv1)))
  187.      ((non-generic? ntype)
  188.       (let ((p (**dict-placeholder
  189.             class ntype edecls var)))
  190.         (setf dict (**app dict p))
  191.         (push p deferred)))
  192.      ((null? (ntyvar-dict-params ntype))
  193.       (let ((ref-code (**dict-placeholder
  194.                class ntype edecls var)))
  195.          (when (maybe-default-ambiguous-tyvar
  196.             ntype var (valdef-module (car edecls)))
  197.         (process-placeholder ref-code '() decls))
  198.          (setf dict (**app dict ref-code))))
  199.      (else
  200.       (let ((p (locate-params (ntyvar-dict-params ntype) edecls decls)))
  201.         (setf dict (**app dict (dict-reference-code class p))))))))
  202.     (values dict deferred)))
  203.  
  204. ;;; The following routines deal with recursive placeholders.  The basic
  205. ;;; strategy is to pass the entire context as a parameter with each
  206. ;;; recursive call (this could be optimized later to make use of an
  207. ;;; internal entry point).  The basic complication is that the context
  208. ;;; of each function in a letrec may be arranged differently.
  209.  
  210. ;;; This generates a call inside decl 'from' to the var 'to'.  Vmap is an
  211. ;;; alist from vars to a list of vars corresponding to the gtyvars of
  212. ;;; the decl signature.
  213.  
  214. (define (recursive-call-code from to vmap)
  215.   (let ((exp (**var/def to))
  216.     (tyvars (tuple-2-2 (assq to vmap)))
  217.     (contexts (gtype-context (var-type to))))
  218.     (do-contexts (class contexts) (tyvar tyvars)
  219.        (setf exp (**app exp (locate-param-var tyvar class from))))
  220.     exp))
  221.  
  222. (define (locate-param-var tyvar class decl)
  223.   (let ((vmap (tuple-2-2 (assq decl (ntyvar-dict-params tyvar)))))
  224.     (**var/def (assoc-def class vmap))))
  225.  
  226. ;;; This is used to get the code for a specific dictionary reference.
  227.  
  228. (define (dict-ref-code instance)
  229.   (if (instance-skolem-inst? instance)
  230.       (**app (**var/def (core-symbol "fetchDict"))
  231.          (**var/def (algdata-runtime-var (instance-algdata instance)))
  232.          (**var/def (class-runtime-var (instance-class instance))))
  233.       (**var/def (instance-dictionary instance))))
  234.  
  235. ;;; This is used to locate the correct enclosing decl.
  236.  
  237. (define (search-enclosing-decls decl-list decls)
  238.   (cond ((null? decl-list)
  239.      (error "Lost decl in search-enclosing-decls!"))
  240.     ((memq (car decl-list) decls)
  241.      (car decl-list))
  242.     (else
  243.      (search-enclosing-decls (cdr decl-list) decls))))
  244.  
  245. ;;; Dynamic typing stuff
  246.  
  247. (define (process-dtype-placeholders dps r env decl)
  248.   (if (null? dps)
  249.       (values r env)
  250.       (mlet (((r1 env1) (process-dtype-placeholder (car dps) r env decl)))
  251.     (process-dtype-placeholders (cdr dps) r1 env1 decl))))
  252.  
  253. (define (process-dtype-placeholder p r env decl)
  254.   (let ((ty (prune (dtype-placeholder-tyvar p))))
  255.     (cond ((and (ntyvar? ty) (non-generic? ty))
  256.        (values (cons p r) env))
  257.       (else
  258.        (mlet (((code r1 env1) (process-dtype-type ty r env decl)))
  259.           (setf (dtype-placeholder-exp p) code)
  260.           (values r1 env1))))))
  261.  
  262. (define (process-dtype-type ty r env decl)
  263.   (setf ty (prune ty))
  264.   (if (ntyvar? ty)
  265.       (if (non-generic? ty)
  266.       (let ((p (**dtype-placeholder ty)))
  267.         (values p (cons p r) env))
  268.       (let ((v (assq ty env)))
  269.         (if v 
  270.         (values (**var/def (tuple-2-2 v)) r env)
  271.         (let ((new-var (create-temp-var "dynamic-")))
  272.           (install-dtype-decl decl new-var ty)
  273.           (values (**var/def new-var) r
  274.               (cons (tuple ty new-var) env))))))
  275.       ;; Existential types are slightly different here - their runtime
  276.       ;; type var is bound to a Type instead of a DataType.
  277.       (let ((tycon (ntycon-tycon ty)))
  278.     (if (synonym? tycon)
  279.         (process-dtype-type (expand-ntype-synonym ty) r env decl)
  280.         (mlet 
  281.              (((args r1 env1)
  282.            (process-dtype-type/l (ntycon-args ty) r env decl))
  283.           (code (if (algdata-skolem-type? tycon)
  284.             (rconvert-tycon tycon)
  285.             (**app (**con/def (core-symbol "Tycon"))
  286.                    (rconvert-tycon tycon)
  287.                    (**list/l args)))))
  288.          (values code r1 env1))))))
  289.  
  290. (define (process-dtype-type/l types r env decl)
  291.   (if (null? types)
  292.       (values '() r env)
  293.       (mlet (((ty r1 env1) (process-dtype-type (car types) r env decl))
  294.          ((tys r2 env2) (process-dtype-type/l (cdr types) r1 env1 decl)))
  295.      (values (cons ty tys) r2 env2))))
  296.  
  297. (define (install-dtype-decl decl var ty)
  298.   (let* ((dicts (concat
  299.          (map (lambda (v-c-v)
  300.             (map (lambda (c-v)
  301.                    (let ((class (tuple-2-1 c-v))
  302.                      (dict (tuple-2-2 c-v)))
  303.                  (**tuple (**var/def (class-runtime-var class))
  304.                       (**var/def dict))))
  305.                  (tuple-2-2 v-c-v)))
  306.              (ntyvar-dict-params ty))))
  307.      (skolem-type (**app (**var/def (core-symbol "buildSkolem"))
  308.                  (**list/l dicts)))
  309.      (code (**valdef/def var skolem-type)))
  310.     (setf (valdef-extra-decls decl)
  311.       (cons code (valdef-extra-decls decl)))))
  312.  
  313.  
  314. (define (assoc-def def alist)
  315.   (assoc-def-1 (forward-def def) alist))
  316.  
  317. (define (assoc-def-1 def alist)
  318.   (if (null? alist)
  319.       '#f
  320.       (if (eq? def (forward-def (tuple-2-1 (car alist))))
  321.       (tuple-2-2 (car alist))
  322.       (assoc-def-1 def (cdr alist)))))
  323.