-
Notifications
You must be signed in to change notification settings - Fork 85
/
typecheck.hs
631 lines (573 loc) · 24.9 KB
/
typecheck.hs
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
{-
- Unlike the verified type inferencer, we go top down only unifying at the
- leaves of the AST. This helps the error messages a bit and means that we
- only have to have source location information at the leaves. So instead of
- infer_e returning a type, it takes an extra argument that is the type that
- the expression should have.
-}
module Typecheck where
import Control.Monad.State.Lazy as State
import Data.Map as Map
import Data.List as List
import Data.Set as Set
import Ast
import Unify
import Text.Parsec.Pos (initialPos, SourcePos)
import Data.Maybe
import Parse
getDup :: (Eq a, Ord a) => [a] -> Maybe a
getDup ls = check (sort ls)
where check [] = Nothing
check [x] = Nothing
check (x:y:zs) = if x == y then Just x else check (y:zs)
envAll :: (k -> v -> Bool) -> Map k v -> Bool
envAll f m = List.all (\(x,y) -> f x y) (Map.assocs m)
data Infer_st = Infer_st { next_uvar :: Uvar, subst :: Subst }
type M_st_ex = State.StateT Infer_st (Either (SourcePos, String))
typeError :: SourcePos -> String -> M_st_ex a
typeError pos str = lift (Left (pos,str))
lookup_st_ex :: (HasPos k, Show k, Ord k) => k -> Map.Map k v -> M_st_ex v
lookup_st_ex k env =
case Map.lookup k env of
Nothing -> typeError (getPos k) ("unbound identifier: " ++ (show k))
Just v -> return v
data Tid_or_exn =
TypeId (Id TypeN)
| TypeExn (Id ConN)
instance Show Tid_or_exn where
show (TypeId tid) = show tid
show (TypeExn cid) = show cid
type Tenv = Map VarN (Integer, Infer_t)
type TenvM = Map ModN (Map VarN (Integer, Infer_t))
type TenvC = Map (Id ConN) ([TvarN], [T], Tid_or_exn)
type TenvT = Map (Id TypeN) ([TvarN], T)
type Decls = (Set ModN, Set (Id TypeN), Set (Id ConN))
empty_decls = (Set.empty,Set.empty,Set.empty)
fresh_uvar :: M_st_ex Infer_t
fresh_uvar =
do n <- gets next_uvar;
modify (\x -> x { next_uvar = n + 1 });
return (Infer_Tuvar n)
n_fresh_uvar :: Integral a => a -> M_st_ex [Infer_t]
n_fresh_uvar n =
if n == 0 then
return []
else
do v <- fresh_uvar;
vs <- n_fresh_uvar (n - 1);
return (v:vs)
init_infer_state :: Infer_st
init_infer_state = Infer_st { next_uvar = 0, subst = Map.empty }
add_constraint :: SourcePos -> Infer_t -> Infer_t -> M_st_ex ()
add_constraint pos t1 t2 =
do s <- gets subst;
case t_unify s t1 t2 of
Nothing -> typeError pos ("expected type: " ++ show t2 ++ "\nhad type: " ++ show t1)
Just s -> do modify (\x -> x { subst = s });
return ()
get_next_uvar :: M_st_ex Uvar
get_next_uvar =
do n <- gets next_uvar;
return n
apply_subst :: Infer_t -> M_st_ex Infer_t
apply_subst t =
do s <- gets subst;
return (t_walkstar s t)
apply_subst_list :: [Infer_t] -> M_st_ex [Infer_t]
apply_subst_list ts =
do s <- gets subst;
return (List.map (t_walkstar s) ts)
generalise :: Uvar -> Integer -> Map.Map Uvar Integer -> Infer_t -> (Integer, Map.Map Uvar Integer, Infer_t)
generalise m n s (Infer_Tapp ts tc) =
let (num_gen, s', ts') = generalise_list m n s ts in
(num_gen, s', Infer_Tapp ts' tc)
generalise m n s (Infer_Tuvar uv) =
case Map.lookup uv s of
Just n -> (0, s, Infer_Tvar_db n)
Nothing ->
if m <= uv then
(1, Map.insert uv n s, Infer_Tvar_db n)
else
(0, s, Infer_Tuvar uv)
generalise m n s (Infer_Tvar_db k) =
(0, s, Infer_Tvar_db k)
generalise_list m n s [] =
(0,s,[])
generalise_list m n s (t:ts) =
let (num_gen, s', t') = generalise m n s t in
let (num_gen', s'', ts') = generalise_list m (num_gen + n) s' ts in
(num_gen+num_gen', s'', t':ts')
infer_type_subst :: Map TvarN Infer_t -> T -> Infer_t
infer_type_subst s (Tvar tv) =
case Map.lookup tv s of
Just t -> t
Nothing -> Infer_Tvar_db 0 -- should not happen
infer_type_subst s (Tvar_db n) =
Infer_Tvar_db n
infer_type_subst s (Tapp ts tn) =
Infer_Tapp (List.map (infer_type_subst s) ts) tn
infer_deBruijn_subst :: [Infer_t] -> Infer_t -> Infer_t
infer_deBruijn_subst s (Infer_Tvar_db n) =
if n < toInteger (List.length s) then
s `genericIndex` n
else
Infer_Tvar_db (n - toInteger (List.length s)) -- should not happen
infer_deBruijn_subst s (Infer_Tapp ts tn) =
Infer_Tapp (List.map (infer_deBruijn_subst s) ts) tn
infer_deBruijn_subst s (Infer_Tuvar n) =
Infer_Tuvar n
tid_exn_to_tc :: Tid_or_exn -> Tc
tid_exn_to_tc (TypeId tid) = TC_name tid
tid_exn_to_tc (TypeExn _) = TC_exn
infer_p :: TenvC -> Pat -> Infer_t -> M_st_ex [(VarN,Infer_t)]
infer_p cenv (Pvar n) t =
return [(n,t)]
infer_p cenv (Plit (IntLit i) pos) t =
do add_constraint pos (Infer_Tapp [] TC_int) t;
return []
infer_p cenv (Plit (Char s) pos) t =
do add_constraint pos (Infer_Tapp [] TC_char) t;
return []
infer_p cenv (Plit (StrLit s) pos) t =
do add_constraint pos (Infer_Tapp [] TC_string) t;
return []
infer_p cenv (Plit (Word8 w) pos) t =
do add_constraint pos (Infer_Tapp [] TC_word8) t;
return []
infer_p cenv (Pcon cn_opt ps pos) t =
case cn_opt of
Nothing ->
do ts <- n_fresh_uvar (List.length ps);
add_constraint pos (Infer_Tapp ts TC_tup) t;
infer_ps cenv ps ts;
Just cn ->
do (tvs',ts,tn) <- lookup_st_ex cn cenv;
ts' <- n_fresh_uvar (List.length tvs');
add_constraint pos (Infer_Tapp ts' (tid_exn_to_tc tn)) t;
infer_ps cenv ps (List.map (infer_type_subst (Map.fromList (List.zip tvs' ts'))) ts)
infer_p cenv (Pref p pos) t =
do t1 <- fresh_uvar;
add_constraint pos (Infer_Tapp [t1] TC_ref) t;
tenv <- infer_p cenv p t1;
return tenv
infer_ps cenv [] [] =
return []
infer_ps cenv (p:ps) (t:ts) =
do tenv <- infer_p cenv p t;
tenv' <- infer_ps cenv ps ts;
return (tenv'++tenv)
bool_type = (Infer_Tapp [] (TC_name (Short (TypeN "bool" dummy_pos))))
constrain_op :: Op -> Infer_t -> M_st_ex [Infer_t]
constrain_op op t =
case op of
Opn opn pos ->
do add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [] TC_int, Infer_Tapp [] TC_int]
Opb opb pos ->
do add_constraint pos bool_type t;
return [Infer_Tapp [] TC_int, Infer_Tapp [] TC_int]
Equality pos ->
do add_constraint pos bool_type t;
t1 <- fresh_uvar;
return [t1, t1]
Opapp ->
do uvar <- fresh_uvar;
return [Infer_Tapp [uvar,t] TC_fn, uvar]
Opassign pos ->
do add_constraint pos (Infer_Tapp [] TC_tup) t;
t2 <- fresh_uvar;
return [Infer_Tapp [t2] TC_ref, t2]
Opref pos ->
do uvar <- fresh_uvar;
add_constraint pos (Infer_Tapp [uvar] TC_ref) t;
return [uvar]
Opderef pos -> return [Infer_Tapp [t] TC_ref]
Aw8alloc pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_word8array) t;
return [Infer_Tapp [] TC_int, Infer_Tapp [] TC_word8]
Aw8sub pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_word8) t;
return [Infer_Tapp [] TC_word8array, Infer_Tapp [] TC_int]
Aw8length pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [] TC_word8array]
Aw8update pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_tup) t
return [Infer_Tapp [] TC_word8array, Infer_Tapp [] TC_int, Infer_Tapp [] TC_word8]
Chr pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_char) t;
return [Infer_Tapp [] TC_int]
Ord pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [] TC_char]
Chopb opb pos ->
do add_constraint pos bool_type t;
return [Infer_Tapp [] TC_char, Infer_Tapp [] TC_char]
Explode pos ->
do () <- add_constraint pos (Infer_Tapp [Infer_Tapp [] TC_char] (TC_name (Short (TypeN "list" dummy_pos)))) t;
return [Infer_Tapp [] TC_string]
Implode pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_string) t;
return [Infer_Tapp [Infer_Tapp [] TC_char] (TC_name (Short (TypeN "list" dummy_pos)))]
Strlen pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [] TC_string]
VfromList pos ->
do uvar <- fresh_uvar;
() <- add_constraint pos (Infer_Tapp [uvar] TC_vector) t;
return [Infer_Tapp [uvar] (TC_name (Short (TypeN "list" dummy_pos)))]
Vsub pos ->
return [Infer_Tapp [t] TC_vector, Infer_Tapp [] TC_int]
Vlength pos ->
do uvar <- fresh_uvar;
() <- add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [uvar] TC_vector]
Aalloc pos ->
do uvar <- fresh_uvar;
() <- add_constraint pos (Infer_Tapp [uvar] TC_array) t;
return [Infer_Tapp [] TC_int, uvar]
Asub pos ->
return [Infer_Tapp [t] TC_vector, Infer_Tapp [] TC_int]
Alength pos ->
do uvar <- fresh_uvar;
() <- add_constraint pos (Infer_Tapp [] TC_int) t;
return [Infer_Tapp [uvar] TC_array]
Aupdate pos ->
do uvar <- fresh_uvar;
() <- add_constraint pos (Infer_Tapp [] TC_tup) t
return [Infer_Tapp [uvar] TC_array, Infer_Tapp [] TC_int, uvar]
FFI n pos ->
do () <- add_constraint pos (Infer_Tapp [] TC_tup) t;
return [Infer_Tapp [] TC_word8array]
ensureDistinct msg select l =
case getDup (List.map select l) of
Nothing -> return ()
Just x -> typeError (getPos x) ("duplicate " ++ msg ++ ": " ++ show x)
infer_Texn = Infer_Tapp [] TC_exn
infer_e :: TenvM -> TenvC -> Tenv -> Exp -> Infer_t -> M_st_ex ()
infer_e menv cenv env (Raise e) t =
do infer_e menv cenv env e infer_Texn;
return ()
infer_e menv cenv env (Handle e1 []) t =
error "Impossible empty handler"
infer_e menv cenv env (Handle e1 pes) t =
do infer_e menv cenv env e1 t;
infer_pes menv cenv env pes infer_Texn t
infer_e menv cenv tenv (Lit (IntLit i) pos) t =
add_constraint pos (Infer_Tapp [] TC_int) t
infer_e menv cenv tenv (Lit (Char c) pos) t =
add_constraint pos (Infer_Tapp [] TC_char) t
infer_e menv cenv tenv (Lit (StrLit s) pos) t =
add_constraint pos (Infer_Tapp [] TC_string) t
infer_e menv cenv tenv (Lit (Word8 w) pos) t =
add_constraint pos (Infer_Tapp [] TC_word8) t
infer_e menv cenv env (Var (Short n)) t =
do (tvs,t') <- lookup_st_ex n env;
uvs <- n_fresh_uvar tvs;
add_constraint (getPos n) (infer_deBruijn_subst uvs t') t
infer_e menv cenv env (Var (Long mn n)) t =
do env' <- lookup_st_ex mn menv;
(tvs,t') <- lookup_st_ex n env';
uvs <- n_fresh_uvar tvs;
add_constraint (getPos n) (infer_deBruijn_subst uvs t') t
infer_e menv cenv env (Con cn_opt es pos) t =
case cn_opt of
Nothing ->
do ts <- n_fresh_uvar (List.length es);
add_constraint pos (Infer_Tapp ts TC_tup) t;
infer_es menv cenv env es ts
Just cn ->
do (tvs',ts,tn) <- lookup_st_ex cn cenv;
ts' <- n_fresh_uvar (List.length tvs');
add_constraint pos (Infer_Tapp ts' (tid_exn_to_tc tn)) t;
infer_es menv cenv env es (List.map (infer_type_subst (Map.fromList (List.zip tvs' ts'))) ts)
infer_e menv cenv env (Fun x e pos) t =
do t1 <- fresh_uvar;
t2 <- fresh_uvar;
add_constraint pos (Infer_Tapp [t1,t2] TC_fn) t
infer_e menv cenv (Map.insert x (0,t1) env) e t2;
infer_e menv cenv env (App op es) t =
do ts <- constrain_op op t;
infer_es menv cenv env es ts
infer_e menv cenv env (Log log e1 e2) t =
do add_constraint (getPos log) bool_type t;
infer_e menv cenv env e1 bool_type;
infer_e menv cenv env e2 bool_type
infer_e menv cenv env (If e1 e2 e3) t =
do infer_e menv cenv env e1 bool_type;
infer_e menv cenv env e2 t;
infer_e menv cenv env e3 t
infer_e menv cenv env (Mat e pes) t =
if List.null pes then
error "Empty pattern match"
else
do t' <- fresh_uvar;
infer_e menv cenv env e t';
infer_pes menv cenv env pes t' t
infer_e menv cenv env (Let (Just x) e1 e2) t =
do t1 <- fresh_uvar;
infer_e menv cenv env e1 t1;
infer_e menv cenv (Map.insert x (0,t1) env) e2 t
infer_e menv cenv env (Let Nothing e1 e2) t =
do t1 <- fresh_uvar;
infer_e menv cenv env e1 t1;
infer_e menv cenv env e2 t
infer_e menv cenv env (Letrec funs e) t =
do ensureDistinct "function name" (\(x,y,z) -> x) funs;
uvars <- n_fresh_uvar (List.length funs);
env' <- return (Map.union (Map.fromList (List.map (\((f,x,e), uvar) -> (f,(0,uvar))) (List.zip funs uvars))) env);
infer_funs menv cenv env' funs uvars;
infer_e menv cenv env' e t
infer_es menv cenv env [] [] =
return ()
infer_es menv cenv env (e:es) (t:ts) =
do infer_e menv cenv env e t;
infer_es menv cenv env es ts
infer_pes menv cenv env [] t1 t2 =
return ()
infer_pes menv cenv env ((p,e):pes) t1 t2 =
do env' <- infer_p cenv p t1;
ensureDistinct "pattern variable" fst env';
infer_e menv cenv (Map.union (Map.fromList (List.map (\(n,t) -> (n,(0,t))) env')) env) e t2;
infer_pes menv cenv env pes t1 t2
infer_funs menv cenv env [] [] = return ()
infer_funs menv cenv env ((f, x, e):funs) (t:ts) =
do t1 <- fresh_uvar;
t2 <- fresh_uvar;
add_constraint (getPos f) (Infer_Tapp [t1,t2] TC_fn) t;
infer_e menv cenv (Map.insert x (0,t1) env) e t2;
infer_funs menv cenv env funs ts
init_state :: M_st_ex ()
init_state =
do put init_infer_state;
return ()
is_value :: Exp -> Bool
is_value (Lit _ _) = True
is_value (Con _ es _) = List.all is_value es
is_value (Var _) = True
is_value (Fun _ _ _) = True
is_value _ = False
check_freevars :: Integer -> [TvarN] -> T -> M_st_ex ()
check_freevars dbmax tvs (Tvar tv) =
unless (tv `elem` tvs) (typeError (getPos tv) ("free type variable: " ++ show tv))
check_freevars dbmax tvs (Tapp ts tn) =
mapM_ (check_freevars dbmax tvs) ts
check_freevars dbmax tvs (Tvar_db n) =
unless (n < dbmax) (error "deBruijn type variable in input")
check_dup_ctors :: Maybe ModN -> [([TvarN], TypeN, [(ConN, [T])])] -> M_st_ex ()
check_dup_ctors mn_opt tds =
ensureDistinct "constructor" (\x -> x) (List.foldr (\(tvs, tn, condefs) x2 -> List.foldr (\(n, ts) x2 -> n : x2) x2 condefs) [] tds)
check_type_names :: TenvT -> T -> M_st_ex ()
check_type_names tenvT (Tvar tv) =
return ()
check_type_names tenvT (Tapp ts (TC_name tn)) =
do (tvs,t) <- lookup_st_ex tn tenvT;
unless (List.length tvs == List.length ts) (typeError (getPos tn) ("type constructor " ++ show tn ++ " expected " ++ show (List.length tvs) ++ " arguments, given " ++ show (List.length ts)));
mapM_ (check_type_names tenvT) ts
check_type_names tenvT (Tapp ts _) =
return ()
check_type_names tenvT (Tvar_db n) =
return ()
type_subst :: Map TvarN T -> T -> T
type_subst s (Tvar tv) =
case Map.lookup tv s of
Nothing -> Tvar tv
Just t -> t
type_subst s (Tapp ts tn) =
Tapp (List.map (type_subst s) ts) tn
type_subst s (Tvar_db n) = Tvar_db n
type_name_subst :: TenvT -> T -> T
type_name_subst tenvT (Tvar tv) =
Tvar tv
type_name_subst tenvT (Tapp ts tc) =
let args = List.map (type_name_subst tenvT) ts in
case tc of
TC_name tn ->
case Map.lookup tn tenvT of
Just (tvs, t) -> type_subst (Map.fromList (List.zip tvs args)) t
Nothing -> Tapp args tc
_ -> Tapp args tc
type_name_subst tenvT (Tvar_db n) = Tvar_db n
check_ctor_tenv :: Maybe ModN -> TenvT -> [([TvarN], TypeN, [(ConN, [T])])] -> M_st_ex ()
check_ctor_tenv mn tenvT tds =
do check_dup_ctors mn tds;
mapM_ (\(tvs,tn,ctors) ->
do ensureDistinct "type variable" (\x->x) tvs;
mapM_ (\(cn,ts) -> mapM_ (check_freevars 0 tvs) ts >> mapM_ (check_type_names tenvT) ts) ctors)
tds;
ensureDistinct "type name" (\(_,tn,_) -> tn) tds;
build_ctor_tenv :: Maybe ModN -> TenvT -> [([TvarN], TypeN, [(ConN, [T])])] -> TenvC
build_ctor_tenv mn tenvT tds =
Map.fromList
(List.concat
(List.map
(\(tvs,tn,ctors) ->
List.map (\(cn,ts) -> (Short cn,(tvs,List.map (type_name_subst tenvT) ts, TypeId (mk_id mn tn)))) ctors)
tds))
infer_d :: Maybe ModN -> Decls -> TenvT -> TenvM -> TenvC -> Tenv -> Dec -> M_st_ex (Decls,TenvT,TenvC,Tenv)
infer_d mn decls tenvT menv cenv env (Dlet p e pos) =
do init_state;
n <- get_next_uvar;
t <- fresh_uvar;
infer_e menv cenv env e t;
env' <- infer_p cenv p t;
ensureDistinct "pattern variable" fst env';
ts <- apply_subst_list (List.map (\(x,y) -> y) env');
let (num_tvs, s, ts') = generalise_list n 0 Map.empty ts;
unless (num_tvs == 0 || is_value e)
(typeError pos "Value restriction violated");
return (empty_decls,Map.empty, Map.empty, Map.fromList (List.zip (List.map (\(x,y) -> x) env') (List.map (\t -> (num_tvs, t)) ts')))
infer_d mn decls tenvT menv cenv env (Dletrec funs) =
do ensureDistinct "function name" (\(x,y,z) -> x) funs;
init_state;
next <- get_next_uvar;
uvars <- n_fresh_uvar (List.length funs);
let env' = Map.union (Map.fromList (List.map (\((f,x,e), uvar) -> (f,(0,uvar))) (List.zip funs uvars))) env;
infer_funs menv cenv env' funs uvars;
ts <- apply_subst_list uvars;
let (num_gen,s,ts') = generalise_list next 0 Map.empty ts;
return (empty_decls,Map.empty, Map.empty, Map.fromList (List.map (\((f,x,e), t) -> (f,(num_gen,t))) (List.zip funs ts')))
infer_d mn (mdecls,tdecls,edecls) tenvT menv cenv env (Dtype tdecs) =
do new_tenvT <- return (Map.fromList (List.map (\(tvs,tn,ctors) -> (Short tn, (tvs, Tapp (List.map Tvar tvs) (TC_name (mk_id mn tn))))) tdecs));
tenvT' <- return (Map.union new_tenvT tenvT);
check_ctor_tenv mn tenvT' tdecs;
new_tdecls <- return (List.map (\(tvs,tn,ctors) -> mk_id mn tn) tdecs);
mapM_ (\new_id -> if Set.member new_id tdecls then typeError (getPos new_id) ("Dulicate type definition of: " ++ show new_id) else return ()) new_tdecls;
return ((Set.empty,Set.fromList new_tdecls,Set.empty), new_tenvT, build_ctor_tenv mn tenvT' tdecs, Map.empty)
infer_d mn (mdecls,tdecls,edecls) tenvT menv cenv env (Dtabbrev tvs tn t) =
do ensureDistinct "type variable" (\x->x) tvs;
check_freevars 0 tvs t;
check_type_names tenvT t;
return (empty_decls, Map.insert (Short tn) (tvs,type_name_subst tenvT t) Map.empty, Map.empty, Map.empty)
infer_d mn (mdecls,tdecls,edecls) tenvT menv cenv env (Dexn cn ts) =
do mapM_ (check_freevars 0 []) ts;
mapM_ (check_type_names tenvT) ts;
when (Set.member (mk_id mn cn) edecls) (typeError (getPos cn) ("Duplicate exception definition of" ++ show cn));
return ((Set.empty,Set.empty,Set.singleton (mk_id mn cn)),
Map.empty,
Map.insert (Short cn) ([], List.map (\x -> type_name_subst tenvT x) ts, TypeExn (mk_id mn cn)) Map.empty,
Map.empty)
append_decls (m1,t1,e1) (m2,t2,e2) = (Set.union m1 m2, Set.union t1 t2, Set.union e1 e2)
infer_ds :: Maybe ModN -> Decls -> TenvT -> TenvM -> TenvC -> Tenv -> Decs -> M_st_ex (Decls,TenvT,TenvC,Tenv)
infer_ds mn decls tenvT menv cenv env [] =
return (empty_decls,Map.empty, Map.empty, Map.empty)
infer_ds mn decls tenvT menv cenv env (d:ds) =
do (decls',tenvT',cenv',env') <- infer_d mn decls tenvT menv cenv env d;
(decls'',tenvT'',cenv'',env'') <- infer_ds mn (append_decls decls' decls) (Map.union tenvT' tenvT) menv (Map.union cenv' cenv) (Map.union env' env) ds;
return (append_decls decls'' decls', Map.union tenvT'' tenvT', Map.union cenv'' cenv', Map.union env'' env')
t_to_freevars :: T -> M_st_ex [TvarN]
t_to_freevars (Tvar tn) =
return [tn]
t_to_freevars (Tvar_db _) =
error "deBruijn index in type definition"
t_to_freevars (Tapp ts tc) =
ts_to_freevars ts
ts_to_freevars :: [T] -> M_st_ex [TvarN]
ts_to_freevars [] = return []
ts_to_freevars (t:ts) =
do fvs1 <- t_to_freevars t;
fvs2 <- ts_to_freevars ts;
return (fvs1++fvs2)
{- TODO
check_specs :: Maybe ModN -> TenvC -> Tenv -> Specs -> M_st_ex (TenvC, Tenv)
check_specs mn cenv env [] =
return (cenv,env)
check_specs mn cenv env (Sval x t:specs) =
do fvs <- t_to_freevars t;
fvs' <- return (nub fvs);
check_specs mn cenv (Map.insert x (toInteger (List.length fvs'),
infer_type_subst (Map.fromList (List.zip fvs' (List.map Infer_Tvar_db [0..toInteger (List.length fvs')]))) t) env) specs
check_specs mn cenv env (Stype td : specs) =
do check_ctor_tenv mn cenv td;
check_specs mn (Map.union (build_ctor_tenv mn td) cenv) env specs
check_specs mn cenv env (Sexn cn ts : specs) =
if isJust (Map.lookup (mk_id mn cn) cenv) then
typeError (getPos cn) ("duplicate constructor: " ++ show (mk_id mn cn))
else
do mapM_ (check_freevars 0 []) ts;
check_specs mn (Map.insert (mk_id mn cn) ([], ts, TypeExn) cenv) env specs
check_specs mn cenv env (Stype_opq tvs tn : specs) =
do mapM_ (\(_, (x,y,tn')) ->
unless (TypeId (mk_id mn tn) /= tn')
(typeError (getPos tn) ("duplicate type definition: " ++ show (mk_id mn tn))))
(Map.assocs cenv);
ensureDistinct "type variable" (\x -> x) tvs;
check_specs mn cenv env specs
check_weakC :: TenvC -> TenvC -> M_st_ex ()
check_weakC cenv_impl cenv_spec =
mapM_ (\(cn, (tvs_spec, ts_spec, tn_spec)) ->
case Map.lookup cn cenv_impl of
Nothing -> typeError (getPos cn) ("Missing implementation of " ++ show cn)
Just (tvs_impl,ts_impl,tn_impl) ->
unless (tn_spec == tn_impl && tvs_spec == tvs_impl && ts_spec == ts_impl)
(typeError (getPos cn) "datatype specification and implementation differ"))
(Map.assocs cenv_spec)
check_weakE :: Tenv -> Tenv -> M_st_ex ()
check_weakE env_impl env_spec =
mapM_
(\(n, (tvs_spec, t_spec)) ->
case Map.lookup n env_impl of
Nothing -> typeError (getPos n) ("Missing implementation of " ++ show n)
Just (tvs_impl,t_impl) ->
do init_state;
uvs <- n_fresh_uvar tvs_impl;
let t = (infer_deBruijn_subst uvs t_impl);
add_constraint (getPos n) t t_spec)
(Map.assocs env_spec)
-}
check_signature :: Maybe ModN -> TenvT -> Decls -> Decls -> TenvT -> TenvC -> Tenv -> Maybe Specs -> M_st_ex (Decls, TenvT, TenvC, Tenv)
check_signature mn tenvT init_decls decls tenvT' cenv env Nothing =
return (decls, tenvT', cenv, env)
check_signature mn tenvT init_decls decls tenvT' cenv env (Just specs) =
error "Signatures not yet supported in unverified front end"
{-
do (cenv', env') <- check_specs mn Map.empty Map.empty specs;
check_weakC cenv cenv';
check_weakE env env';
return (cenv',env')
-}
data TypeState = TypeState Decls TenvT TenvM TenvC Tenv
showMap :: (Show k, Show v) => Map k v -> String
showMap m =
show l
where l = Map.toList m
instance Show TypeState where
show (TypeState decls tenvT tenvM tenvC tenv) =
showMap tenvT ++ showMap tenvM ++ showMap tenvC ++ showMap tenv
merge_types :: TypeState -> TypeState -> TypeState
merge_types (TypeState decls' tenvT' menv' cenv' env') (TypeState decls tenvT menv cenv env) =
TypeState (append_decls decls' decls) (Map.union tenvT' tenvT) (Map.union menv' menv)
(Map.union cenv' cenv) (Map.union env' env)
infer_top :: Decls -> TenvT -> TenvM -> TenvC -> Tenv -> Top -> M_st_ex TypeState
infer_top decls tenvT menv cenv env (Tdec d) =
do (decls',tenvT',cenv',env') <- infer_d Nothing decls tenvT menv cenv env d;
return (TypeState decls' tenvT' Map.empty cenv' env')
infer_top (mdecls,tdecls,edecls) tenvT menv cenv env (Tmod mn spec ds1) =
do when (mn `Map.member` menv) (typeError (getPos mn) ("Duplicate module: " ++ show mn));
(decls',tenvT',cenv',env') <- infer_ds (Just mn) (mdecls,tdecls,edecls) tenvT menv cenv env ds1;
((mdecls'',tdecls'',edecls''),tenvT'',cenv'',env'') <-
check_signature (Just mn) tenvT (mdecls,tdecls,edecls) decls' tenvT' cenv' env' spec;
return (TypeState (Set.insert mn mdecls'',tdecls'',edecls'')
(addMod mn tenvT'')
(Map.singleton mn env'')
(addMod mn cenv'')
Map.empty)
where addMod m env =
Map.fromList (List.map (\(k, v) -> (fixKey k, v)) (Map.assocs env))
fixKey (Short k) = Long mn k
fixKey (Long mn k) = error "internal error"
infer_prog :: Decls -> TenvT -> TenvM -> TenvC -> Tenv -> Prog -> M_st_ex TypeState
infer_prog decls tenvT menv cenv env [] =
return (TypeState empty_decls Map.empty Map.empty Map.empty Map.empty)
infer_prog decls tenvT menv cenv env (top:ds) =
do (TypeState decls' tenvT' menv' cenv' env') <- infer_top decls tenvT menv cenv env top;
(TypeState decls'' tenvT'' menv'' cenv'' env'') <-
infer_prog (append_decls decls' decls) (Map.union tenvT' tenvT) (Map.union menv' menv) (Map.union cenv' cenv) (Map.union env' env) ds;
return (TypeState (append_decls decls'' decls') (Map.union tenvT'' tenvT')
(Map.union menv'' menv') (Map.union cenv'' cenv') (Map.union env'' env'))
inferTop :: TypeState -> Top -> Either (SourcePos,String) TypeState
inferTop (TypeState decls tenvT menv cenv env) top =
evalStateT (infer_top decls tenvT menv cenv env top) init_infer_state
inferProg :: TypeState -> Prog -> Either (SourcePos,String) TypeState
inferProg (TypeState decls tenvT menv cenv env) top =
evalStateT (infer_prog decls tenvT menv cenv env top) init_infer_state