aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/analyser/inference.lux
blob: 824071ab3008f0a7c64797fd12d02c25402cd7b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
(;module:
  lux
  (lux (control monad)
       (data text/format
             (coll [list "L/" Functor<List>]))
       [macro #+ Monad<Lux>]
       [type]
       (type ["TC" check]))
  (luxc ["&" base]
        (lang ["la" analysis #+ Analysis])
        (analyser ["&;" common])))

(def: #export (bind-var var-id bound-idx type)
  (-> Nat Nat Type Type)
  (case type
    (#;Host name params)
    (#;Host name (L/map (bind-var var-id bound-idx) params))

    (^template [<tag>]
      (<tag> left right)
      (<tag> (bind-var var-id bound-idx left)
             (bind-var var-id bound-idx right)))
    ([#;Sum]
     [#;Product]
     [#;Function]
     [#;App])
    
    (#;Var id)
    (if (n.= var-id id)
      (#;Bound bound-idx)
      type)

    (^template [<tag>]
      (<tag> env quantified)
      (<tag> (L/map (bind-var var-id bound-idx) env)
             (bind-var var-id (n.+ +2 bound-idx) quantified)))
    ([#;UnivQ]
     [#;ExQ])
    
    (#;Named name unnamedT)
    (#;Named name
             (bind-var var-id bound-idx unnamedT))

    _
    type))

(def: #export (apply-function analyse funcT args)
  (-> &;Analyser Type (List Code) (Lux [Type (List Analysis)]))
  (case args
    #;Nil
    (:: Monad<Lux> wrap [funcT (list)])
    
    (#;Cons arg args')
    (case funcT
      (#;Named name unnamedT)
      (apply-function analyse unnamedT args)

      (#;UnivQ _)
      (&common;with-var
        (function [[var-id varT]]
          (do Monad<Lux>
            [[outputT argsA] (apply-function analyse (assume (type;apply-type funcT varT)) args)]
            (do @
              [? (&;within-type-env
                  (TC;bound? var-id))
               outputT' (if ?
                          (&;within-type-env
                           (TC;clean var-id outputT))
                          (wrap (#;UnivQ (list) (bind-var var-id +1 outputT))))]
              (wrap [outputT' argsA])))))

      (#;ExQ _)
      (do Monad<Lux>
        [[ex-id exT] (&;within-type-env
                      TC;existential)]
        (apply-function analyse (assume (type;apply-type funcT exT)) args))

      (#;Function inputT outputT)
      (do Monad<Lux>
        [[outputT' args'A] (apply-function analyse outputT args')
         argA (&;with-stacked-errors
                (function [_] (format "Expected type: " (%type inputT) "\n"
                                      " For argument: " (%code arg)))
                (&;with-expected-type inputT
                  (analyse arg)))]
        (wrap [outputT' (list& argA args'A)]))

      _
      (&;fail (format "Cannot apply a non-function: " (%type funcT))))
    ))