blob: 829f837135e810db1786d3bd04a81d38653cabcb (
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
(.module:
[lux #*
[control
[monad (#+ do)]
pipe]
[data
["." error]
["." maybe]
["." product]
["." text ("#/." equivalence)
format]
[collection
["." list ("#/." functor)]]]
[math
["r" random]]
["." type]
["." macro
["." code]]
[compiler
[default
["." reference]
["." init]
["." phase
["." analysis (#+ Analysis Operation)
[".A" type]
["." expression]
["/" function]]
[extension
[".E" analysis]]]]]
test]
[//
["_." primitive]
["_." structure]])
(def: (check-apply expectedT num-args analysis)
(-> Type Nat (Operation Analysis) Bit)
(|> analysis
(typeA.with-type expectedT)
(phase.run _primitive.state)
(case> (#error.Success applyA)
(let [[funcA argsA] (analysis.application applyA)]
(n/= num-args (list.size argsA)))
(#error.Failure error)
#0)))
(context: "Function definition."
(<| (times 100)
(do @
[func-name (r.unicode 5)
arg-name (|> (r.unicode 5) (r.filter (|>> (text/= func-name) not)))
[outputT outputC] _primitive.primitive
[inputT _] _primitive.primitive
#let [g!arg (code.local-identifier arg-name)]]
($_ seq
(test "Can analyse function."
(and (|> (typeA.with-type (All [a] (-> a outputT))
(/.function _primitive.phase func-name arg-name outputC))
_structure.check-succeeds)
(|> (typeA.with-type (All [a] (-> a a))
(/.function _primitive.phase func-name arg-name g!arg))
_structure.check-succeeds)))
(test "Generic functions can always be specialized."
(and (|> (typeA.with-type (-> inputT outputT)
(/.function _primitive.phase func-name arg-name outputC))
_structure.check-succeeds)
(|> (typeA.with-type (-> inputT inputT)
(/.function _primitive.phase func-name arg-name g!arg))
_structure.check-succeeds)))
(test "The function's name is bound to the function's type."
(|> (typeA.with-type (Rec self (-> inputT self))
(/.function _primitive.phase func-name arg-name (code.local-identifier func-name)))
_structure.check-succeeds))
))))
(context: "Function application."
(<| (times 100)
(do @
[full-args (|> r.nat (:: @ map (|>> (n/% 10) (n/max 2))))
partial-args (|> r.nat (:: @ map (n/% full-args)))
var-idx (|> r.nat (:: @ map (|>> (n/% full-args) (n/max 1))))
inputsTC (r.list full-args _primitive.primitive)
#let [inputsT (list/map product.left inputsTC)
inputsC (list/map product.right inputsTC)]
[outputT outputC] _primitive.primitive
#let [funcT (type.function inputsT outputT)
partialT (type.function (list.drop partial-args inputsT) outputT)
varT (#.Parameter 1)
polyT (<| (type.univ-q 1)
(type.function (list.concat (list (list.take var-idx inputsT)
(list varT)
(list.drop (inc var-idx) inputsT))))
varT)
poly-inputT (maybe.assume (list.nth var-idx inputsT))
partial-poly-inputsT (list.drop (inc var-idx) inputsT)
partial-polyT1 (<| (type.function partial-poly-inputsT)
poly-inputT)
partial-polyT2 (<| (type.univ-q 1)
(type.function (#.Cons varT partial-poly-inputsT))
varT)
dummy-function (#analysis.Function (list) (#analysis.Reference (reference.local 1)))]]
($_ seq
(test "Can analyse monomorphic type application."
(|> (/.apply _primitive.phase funcT dummy-function inputsC)
(check-apply outputT full-args)))
(test "Can partially apply functions."
(|> (/.apply _primitive.phase funcT dummy-function (list.take partial-args inputsC))
(check-apply partialT partial-args)))
(test "Can apply polymorphic functions."
(|> (/.apply _primitive.phase polyT dummy-function inputsC)
(check-apply poly-inputT full-args)))
(test "Polymorphic partial application propagates found type-vars."
(|> (/.apply _primitive.phase polyT dummy-function (list.take (inc var-idx) inputsC))
(check-apply partial-polyT1 (inc var-idx))))
(test "Polymorphic partial application preserves quantification for type-vars."
(|> (/.apply _primitive.phase polyT dummy-function (list.take var-idx inputsC))
(check-apply partial-polyT2 var-idx)))
))))
|