dbtool mysql adduser working
[hcoop/zz_old/domtool2-proto.git] / src / tycheck.sml
CommitLineData
64014a03 1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
ae3a5b8c 17 *)
64014a03 18
19(* Domtool configuration language type checking *)
20
21structure Tycheck :> TYCHECK = struct
22
add6f172 23open Ast Print Env
64014a03 24
25structure SM = StringMap
26
89c9edc9 27val externFlag = ref false
28fun allowExterns () = externFlag := true
29fun disallowExterns () = externFlag := false
30
64014a03 31local
32 val unifCount = ref 0
33in
34fun resetUnif () = unifCount := 0
35
36fun newUnif () =
37 let
38 val c = !unifCount
39 val name =
40 if c < 26 then
41 str (chr (ord #"A" + c))
42 else
43 "UNIF" ^ Int.toString (c - 26)
44 in
45 unifCount := c + 1;
46 TUnif (name, ref NONE)
47 end
48end
49
50exception UnequalDomains
51
52fun eqRecord f (r1, r2) =
53 (SM.appi (fn (k, v1) =>
54 case SM.find (r2, k) of
55 NONE => raise UnequalDomains
56 | SOME v2 =>
57 if f (v1, v2) then
58 ()
59 else
60 raise UnequalDomains) r1;
61 SM.appi (fn (k, v2) =>
62 case SM.find (r1, k) of
63 NONE => raise UnequalDomains
64 | SOME v1 =>
65 if f (v1, v2) then
66 ()
67 else
68 raise UnequalDomains) r2;
69 true)
70 handle UnequalDomains => false
71
72fun eqPred ((p1, _), (p2, _)) =
73 case (p1, p2) of
74 (CRoot, CRoot) => true
75 | (CConst s1, CConst s2) => s1 = s2
76 | (CPrefix p1, CPrefix p2) => eqPred (p1, p2)
77 | (CNot p1, CNot p2) => eqPred (p1, p2)
78 | (CAnd (p1, q1), CAnd (p2, q2)) =>
79 eqPred (p1, p2) andalso eqPred (q1, q2)
80
81 | _ => false
82
83fun eqTy (t1All as (t1, _), t2All as (t2, _)) =
84 case (t1, t2) of
85 (TBase s1, TBase s2) => s1 = s2
86 | (TList t1, TList t2) => eqTy (t1, t2)
87 | (TArrow (d1, r1), TArrow (d2, r2)) =>
88 eqTy (d1, d2) andalso eqTy (r1, r2)
89
90 | (TAction (p1, d1, r1), TAction (p2, d2, r2)) =>
91 eqPred (p1, p2) andalso eqRecord eqTy (d1, d2)
92 andalso eqRecord eqTy (r1, r2)
93
e680130a 94 | (TNested (p1, q1), TNested (p2, q2)) =>
2dc33fa4 95 eqPred (p1, p2) andalso eqTy (q1, q2)
e680130a 96
64014a03 97 | (TUnif (_, ref (SOME t1)), _) => eqTy (t1, t2All)
98 | (_, TUnif (_, ref (SOME t2))) => eqTy (t1All, t2)
99
100 | (TUnif (_, r1), TUnif (_, r2)) => r1 = r2
101
102 | (TError, TError) => true
103
104 | _ => false
105
106datatype unification_error =
107 UnifyPred of pred * pred
108 | UnifyTyp of typ * typ
109 | UnifyOccurs of string * typ
110
111exception Unify of unification_error
112
113datatype type_error =
114 WrongType of string * exp * typ * typ * unification_error option
115 | WrongForm of string * string * exp * typ * unification_error option
116 | UnboundVariable of string
e680130a 117 | WrongPred of string * pred * pred
64014a03 118
64014a03 119fun describe_unification_error t ue =
120 case ue of
121 UnifyPred (p1, p2) =>
e680130a 122 (print "Reason: Incompatible contexts.\n";
64014a03 123 preface ("Have:", p_pred p1);
124 preface ("Need:", p_pred p2))
125 | UnifyTyp (t1, t2) =>
126 if eqTy (t, t1) then
127 ()
128 else
129 (print "Reason: Incompatible types.\n";
130 preface ("Have:", p_typ t1);
131 preface ("Need:", p_typ t2))
132 | UnifyOccurs (name, t') =>
133 if eqTy (t, t') then
134 ()
135 else
136 (print "Reason: Occurs check failed for ";
137 print name;
138 print " in:\n";
139 printd (p_typ t))
140
141fun describe_type_error loc te =
142 case te of
143 WrongType (place, e, t1, t2, ueo) =>
144 (ErrorMsg.error (SOME loc) (place ^ " has wrong type.");
145 preface (" Expression:", p_exp e);
146 preface ("Actual type:", p_typ t1);
147 preface ("Needed type:", p_typ t2);
148 Option.app (describe_unification_error t1) ueo)
149 | WrongForm (place, form, e, t, ueo) =>
150 (ErrorMsg.error (SOME loc) (place ^ " has a non-" ^ form ^ " type.");
151 preface ("Expression:", p_exp e);
152 preface (" Type:", p_typ t);
153 Option.app (describe_unification_error t) ueo)
154 | UnboundVariable name =>
155 ErrorMsg.error (SOME loc) ("Unbound variable " ^ name ^ ".\n")
e680130a 156 | WrongPred (place, p1, p2) =>
157 (ErrorMsg.error (SOME loc) ("Context incompatibility for " ^ place ^ ".");
158 preface ("Have:", p_pred p1);
159 preface ("Need:", p_pred p2))
64014a03 160
dbd7a7d2 161fun predImplies (p1All as (p1, _), p2All as (p2, _)) =
64014a03 162 case (p1, p2) of
2dc33fa4 163 (_, CAnd (p1, p2)) => predImplies (p1All, p1) andalso predImplies (p1All, p2)
164 | (CAnd (p1, p2), _) => predImplies (p1, p2All) orelse predImplies (p2, p2All)
165
166 | (_, CPrefix (CRoot, _)) => true
dbd7a7d2 167 | (CNot (CPrefix (CRoot, _), _), _) => true
168
169 | (CRoot, CRoot) => true
170
171 | (CConst s1, CConst s2) => s1 = s2
172
173 | (CPrefix p1, CPrefix p2) => predImplies (p1, p2)
e680130a 174 | (_, CPrefix p2) => predImplies (p1All, p2)
dbd7a7d2 175
176 | (CNot p1, CNot p2) => predImplies (p2, p1)
ff2a424a 177 | (CRoot, CNot (CConst _, _)) => true
178 | (CConst s1, CNot (CConst s2, _)) => s1 <> s2
64014a03 179
dbd7a7d2 180 | _ => false
181
182fun predSimpl (pAll as (p, loc)) =
183 case p of
184 CRoot => pAll
185 | CConst _ => pAll
186 | CPrefix p => (CPrefix (predSimpl p), loc)
187 | CNot p => (CNot (predSimpl p), loc)
188 | CAnd (p1, p2) =>
189 let
190 val p1' = predSimpl p1
191 val p2' = predSimpl p2
192 in
193 case p1' of
194 (CAnd (c1, c2), _) => predSimpl (CAnd (c1, (CAnd (c2, p2'), loc)), loc)
195 | _ => if predImplies (p2', p1') then
196 p2'
2dc33fa4 197 else if predImplies (p1', p2') then
198 p1'
dbd7a7d2 199 else
200 (CAnd (p1', p2'), loc)
201 end
202
e680130a 203fun subPred (p1, p2) =
dbd7a7d2 204 if predImplies (p1, p2) then
205 ()
206 else
207 raise (Unify (UnifyPred (p1, p2)))
64014a03 208
e680130a 209fun subRecord f (r1, r2) =
210 SM.appi (fn (k, v2) =>
211 case SM.find (r1, k) of
212 NONE => raise UnequalDomains
213 | SOME v1 => f (v1, v2)) r2
64014a03 214
215fun occurs u (t, _) =
216 case t of
217 TBase _ => false
218 | TList t => occurs u t
219 | TArrow (d, r) => occurs u d orelse occurs u r
220 | TAction (_, d, r) =>
221 List.exists (occurs u) (SM.listItems d)
222 orelse List.exists (occurs u) (SM.listItems r)
2dc33fa4 223 | TNested (_, t) => occurs u t
64014a03 224 | TError => false
225 | TUnif (_, ref (SOME t)) => occurs u t
226 | TUnif (_, u') => u = u'
227
e680130a 228fun subTyp (t1All as (t1, _), t2All as (t2, _)) =
64014a03 229 case (t1, t2) of
230 (TBase s1, TBase s2) =>
231 if s1 = s2 then
232 ()
233 else
234 raise Unify (UnifyTyp (t1All, t2All))
e680130a 235 | (TList t1, TList t2) => subTyp (t1, t2)
64014a03 236 | (TArrow (d1, r1), TArrow (d2, r2)) =>
e680130a 237 (subTyp (d2, d1);
238 subTyp (r1, r2))
64014a03 239
240 | (TAction (p1, d1, r1), TAction (p2, d2, r2)) =>
e680130a 241 ((subPred (p2, p1);
242 subRecord subTyp (d2, d1);
243 subRecord subTyp (r1, r2);
244 subRecord subTyp (r2, r1))
64014a03 245 handle UnequalDomains => raise Unify (UnifyTyp (t1All, t2All)))
246
e680130a 247 | (TNested (d1, r1), TNested (d2, r2)) =>
248 (subPred (d2, d1);
2dc33fa4 249 subTyp (r1, r2))
e680130a 250
251 | (TUnif (_, ref (SOME t1)), _) => subTyp (t1, t2All)
252 | (_, TUnif (_, ref (SOME t2))) => subTyp (t1All, t2)
64014a03 253
254 | (TUnif (_, r1), TUnif (_, r2)) =>
255 if r1 = r2 then
256 ()
257 else
258 r1 := SOME t2All
259
260 | (TUnif (name, r), _) =>
261 if occurs r t2All then
262 raise (Unify (UnifyOccurs (name, t2All)))
263 else
264 r := SOME t2All
265
266 | (_, TUnif (name, r)) =>
267 if occurs r t1All then
268 raise (Unify (UnifyOccurs (name, t1All)))
269 else
270 r := SOME t1All
271
272 | (TError, _) => ()
273 | (_, TError) => ()
274
275 | _ => raise Unify (UnifyTyp (t1All, t2All))
276
277fun isError t =
278 case t of
279 (TError, _) => true
280 | _ => false
281
dbd7a7d2 282fun whnorm (tAll as (t, loc)) =
283 case t of
284 TUnif (_, ref (SOME tAll)) => whnorm tAll
285 | _ => tAll
286
2f68506c 287fun baseCondition t =
288 case whnorm t of
289 (TBase name, _) => typeRule name
290 | (TList t, _) =>
291 (case baseCondition t of
292 NONE => NONE
293 | SOME f => SOME (fn (EList ls, _) => List.all f ls
294 | _ => false))
295 | _ => NONE
296
4264c8ef 297fun hasTyp (e, t1, t2) =
2f68506c 298 if (case baseCondition t2 of
299 NONE => false
300 | SOME rule => rule e) then
301 ()
302 else
303 subTyp (t1, t2)
4264c8ef 304
51c32b45 305fun checkPred G (p, loc) =
306 let
307 val err = ErrorMsg.error (SOME loc)
308 in
309 case p of
310 CRoot => ()
311 | CConst s =>
312 if lookupContext G s then
313 ()
314 else
315 err ("Unbound context " ^ s)
316 | CPrefix p => checkPred G p
317 | CNot p => checkPred G p
318 | CAnd (p1, p2) => (checkPred G p1; checkPred G p2)
319 end
320
e680130a 321fun checkTyp G (tAll as (t, loc)) =
322 let
323 val err = ErrorMsg.error (SOME loc)
324 in
325 case t of
326 TBase name =>
327 if lookupType G name then
328 tAll
329 else
330 (err ("Unbound type name " ^ name);
331 (TError, loc))
332 | TList t => (TList (checkTyp G t), loc)
333 | TArrow (d, r) => (TArrow (checkTyp G d, checkTyp G r), loc)
51c32b45 334 | TAction (p, d, r) => (checkPred G p;
335 (TAction (p, SM.map (checkTyp G) d,
336 SM.map (checkTyp G) r), loc))
337 | TNested (p, t) => (checkPred G p;
338 (TNested (p, checkTyp G t), loc))
e680130a 339 | TError => raise Fail "TError in parser-generated type"
340 | TUnif _ => raise Fail "TUnif in parser-generated type"
341 end
342
d68ab27c 343fun envVarSetFrom v (e, _) =
344 case e of
345 ESet (v', e) =>
346 if v = v' then
347 SOME e
348 else
349 NONE
350 | EGet (_, _, e) => envVarSetFrom v e
351 | ESeq es => foldr (fn (e, found) =>
352 case found of
353 SOME _ => found
354 | NONE => envVarSetFrom v e)
355 NONE es
356 | ELocal (_, e) => envVarSetFrom v e
357
358 | _ => NONE
359
64014a03 360fun checkExp G (eAll as (e, loc)) =
361 let
362 val dte = describe_type_error loc
363 in
364 case e of
365 EInt _ => (TBase "int", loc)
366 | EString _ => (TBase "string", loc)
367 | EList es =>
368 let
369 val t = (newUnif (), loc)
370 in
371 foldl (fn (e', ret) =>
372 let
373 val t' = checkExp G e'
374 in
4264c8ef 375 (hasTyp (eAll, t', t);
64014a03 376 if isError t' then
377 (TList (TError, loc), loc)
378 else
379 ret)
380 handle Unify ue =>
381 (dte (WrongType ("List element",
382 e',
383 t',
384 t,
385 SOME ue));
386 (TError, loc))
387 end) (TList t, loc) es
388 end
389
390 | ELam (x, to, e) =>
391 let
392 val t =
393 case to of
394 NONE => (newUnif (), loc)
e680130a 395 | SOME t => checkTyp G t
64014a03 396
add6f172 397 val G' = bindVal G (x, t, NONE)
64014a03 398 val t' = checkExp G' e
399 in
400 (TArrow (t, t'), loc)
401 end
402 | EVar x =>
e680130a 403 (case lookupVal G x of
64014a03 404 NONE => (dte (UnboundVariable x);
405 (TError, loc))
406 | SOME t => t)
407 | EApp (func, arg) =>
408 let
409 val dom = (newUnif (), loc)
410 val ran = (newUnif (), loc)
411
412 val tf = checkExp G func
413 val ta = checkExp G arg
414 in
4264c8ef 415 (hasTyp (func, tf, (TArrow (dom, ran), loc));
416 hasTyp (arg, ta, dom)
64014a03 417 handle Unify ue =>
418 dte (WrongType ("Function argument",
419 arg,
420 ta,
421 dom,
422 SOME ue));
423 ran)
424 handle Unify ue =>
425 (dte (WrongForm ("Function to be applied",
426 "function",
427 func,
428 tf,
429 SOME ue));
430 (TError, loc))
431 end
dbd7a7d2 432
bf9b0bc3 433 | EALam (x, p, e) =>
434 let
435 val p' = checkPred G p
436
437 val G' = bindVal G (x, (TAction (p, SM.empty, SM.empty), loc), NONE)
c720772b 438 val t' = whnorm (checkExp G' e)
bf9b0bc3 439 in
440 case t' of
441 (TAction _, _) => (TNested (p, t'), loc)
442 | _ => (dte (WrongForm ("Body of nested configuration 'fn'",
443 "action",
444 e,
445 t',
446 NONE));
447 (TError, loc))
448 end
449
dbd7a7d2 450 | ESet (evar, e) =>
451 let
452 val t = checkExp G e
453 in
454 (TAction ((CPrefix (CRoot, loc), loc),
455 SM.empty,
456 SM.insert (SM.empty, evar, t)),
457 loc)
458 end
459 | EGet (x, evar, rest) =>
460 let
461 val xt = (newUnif (), loc)
add6f172 462 val G' = bindVal G (x, xt, NONE)
dbd7a7d2 463
464 val rt = whnorm (checkExp G' rest)
465 in
466 case rt of
467 (TAction (p, d, r), _) =>
468 (case SM.find (d, evar) of
469 NONE => (TAction (p, SM.insert (d, evar, xt), r), loc)
470 | SOME xt' =>
e680130a 471 (subTyp (xt', xt)
dbd7a7d2 472 handle Unify ue =>
473 dte (WrongType ("Retrieved environment variable",
474 (EVar x, loc),
475 xt',
476 xt,
477 SOME ue));
478 rt))
e680130a 479 | (TError, _) => rt
dbd7a7d2 480 | _ => (dte (WrongForm ("Body of environment variable read",
481 "action",
482 rest,
483 rt,
484 NONE));
485 (TError, loc))
486 end
487
488 | ESeq [] => raise Fail "Empty ESeq"
489 | ESeq [e1] => checkExp G e1
490 | ESeq (e1 :: rest) =>
491 let
492 val e2 = (ESeq rest, loc)
493
494 val t1 = whnorm (checkExp G e1)
495 val t2 = whnorm (checkExp G e2)
496 in
497 case t1 of
498 (TAction (p1, d1, r1), _) =>
499 (case t2 of
500 (TAction (p2, d2, r2), _) =>
501 let
502 val p' = predSimpl (CAnd (p1, p2), loc)
503
504 val d' = SM.foldli (fn (name, t, d') =>
505 case SM.find (r1, name) of
506 NONE =>
507 (case SM.find (d', name) of
508 NONE => SM.insert (d', name, t)
509 | SOME t' =>
d68ab27c 510 ((case envVarSetFrom name e1 of
511 NONE => subTyp (t, t')
512 | SOME e => hasTyp (e, t, t'))
dbd7a7d2 513 handle Unify ue =>
514 dte (WrongType ("Shared environment variable",
515 (EVar name, loc),
dbd7a7d2 516 t',
d68ab27c 517 t,
dbd7a7d2 518 SOME ue));
519 d'))
520 | SOME t' =>
d68ab27c 521 ((case envVarSetFrom name e1 of
522 NONE => subTyp (t, t')
523 | SOME e => hasTyp (e, t, t'))
dbd7a7d2 524 handle Unify ue =>
525 dte (WrongType ("Shared environment variable",
526 (EVar name, loc),
dbd7a7d2 527 t',
d68ab27c 528 t,
dbd7a7d2 529 SOME ue));
530 d'))
531 d1 d2
532
533 val r' = SM.foldli (fn (name, t, r') => SM.insert (r', name, t))
534 r1 r2
535 in
536 (TAction (p', d', r'), loc)
537 end
e680130a 538 | (TError, _) => t2
dbd7a7d2 539 | _ => (dte (WrongForm ("Action to be sequenced",
540 "action",
541 e2,
542 t2,
543 NONE));
544 (TError, loc)))
e680130a 545 | (TError, _) => t1
dbd7a7d2 546 | _ => (dte (WrongForm ("Action to be sequenced",
547 "action",
548 e1,
549 t1,
550 NONE));
551 (TError, loc))
552 end
553
2dc33fa4 554 | ELocal (e1, e2) =>
dbd7a7d2 555 let
2dc33fa4 556 val t1 = whnorm (checkExp G e1)
557 val t2 = whnorm (checkExp G e2)
dbd7a7d2 558 in
2dc33fa4 559 case t1 of
560 (TAction (p1, d1, r1), _) =>
561 (case t2 of
562 (TAction (p2, d2, r2), _) =>
563 let
564 val p' = predSimpl (CAnd (p1, p2), loc)
565
566 val d' = SM.foldli (fn (name, t, d') =>
567 case SM.find (r1, name) of
568 NONE =>
569 (case SM.find (d', name) of
570 NONE => SM.insert (d', name, t)
571 | SOME t' =>
d68ab27c 572 ((case envVarSetFrom name e1 of
573 NONE => subTyp (t', t)
574 | SOME e => hasTyp (e, t', t))
2dc33fa4 575 handle Unify ue =>
576 dte (WrongType ("Shared environment variable",
577 (EVar name, loc),
2dc33fa4 578 t',
d68ab27c 579 t,
2dc33fa4 580 SOME ue));
581 d'))
582 | SOME t' =>
d68ab27c 583 ((case envVarSetFrom name e1 of
584 NONE => subTyp (t', t)
585 | SOME e => hasTyp (e, t', t))
2dc33fa4 586 handle Unify ue =>
587 dte (WrongType ("Shared environment variable",
588 (EVar name, loc),
2dc33fa4 589 t',
d68ab27c 590 t,
2dc33fa4 591 SOME ue));
592 d'))
593 d1 d2
594 in
595 (TAction (p', d', r2), loc)
596 end
597 | (TError, _) => t2
598 | _ => (dte (WrongForm ("Action to be sequenced",
599 "action",
600 e2,
601 t2,
602 NONE));
603 (TError, loc)))
604 | (TError, _) => t1
605 | _ => (dte (WrongForm ("Action to be sequenced",
dbd7a7d2 606 "action",
2dc33fa4 607 e1,
608 t1,
dbd7a7d2 609 NONE));
610 (TError, loc))
611 end
e680130a 612
2dc33fa4 613
e680130a 614 | EWith (e1, e2) =>
615 let
616 val t1 = whnorm (checkExp G e1)
617 val t2 = whnorm (checkExp G e2)
618 in
619 case t1 of
2dc33fa4 620 (TNested (pd, (TAction (pr, d1, r1), _)), _) =>
e680130a 621 (case t2 of
622 (TAction (p, d, r), _) =>
623 if predImplies (pd, p) then
2dc33fa4 624 let
625 val combineRecs =
626 SM.unionWithi (fn (name, t1, t2) =>
627 (subTyp (t1, t2)
628 handle Unify ue =>
629 dte (WrongType ("Environment variable",
630 (EVar name, loc),
631 t1,
632 t2,
633 SOME ue));
634 t2))
635 in
636 (TAction (pr, combineRecs (d, d1),
637 combineRecs (r, r1)), loc)
638 end
e680130a 639 else
640 (dte (WrongPred ("nested action",
641 pd,
642 p));
643 (TError, loc))
644 | (TError, _) => t2
645 | _ =>
646 (dte (WrongForm ("Body of nested action",
647 "action",
648 e2,
649 t2,
650 NONE));
651 (TError, loc)))
652 | (TError, _) => t1
653 | _ =>
654 (dte (WrongForm ("Container of nested action",
655 "action",
656 e1,
657 t1,
658 NONE));
659 (TError, loc))
660 end
661
662 | ESkip => (TAction ((CPrefix (CRoot, loc), loc),
663 SM.empty, SM.empty), loc)
64014a03 664 end
665
666exception Ununif
667
668fun ununif (tAll as (t, loc)) =
669 case t of
670 TBase _ => tAll
671 | TList t => (TList (ununif t), loc)
672 | TArrow (d, r) => (TArrow (ununif d, ununif r), loc)
673 | TAction (p, d, r) => (TAction (p, SM.map ununif d, SM.map ununif r), loc)
674 | TUnif (_, ref (SOME t)) => ununif t
e680130a 675 | TNested _ => tAll
64014a03 676 | TError => tAll
677
678 | TUnif (_, ref NONE) => raise Ununif
679
680fun hasError (t, _) =
681 case t of
682 TBase _ => false
683 | TList t => hasError t
684 | TArrow (d, r) => hasError d orelse hasError r
685 | TAction (p, d, r) => List.exists hasError (SM.listItems d)
686 orelse List.exists hasError (SM.listItems r)
e680130a 687 | TNested _ => false
64014a03 688 | TError => false
689 | TUnif (_, ref (SOME t)) => hasError t
690 | TUnif (_, ref NONE) => false
691
692
693fun checkUnit G (eAll as (_, loc)) =
694 let
695 val _ = resetUnif ()
696 val t = checkExp G eAll
697 in
698 if hasError t then
699 t
700 else
701 ununif t
702 handle Ununif =>
703 (ErrorMsg.error (SOME loc) "Unification variables remain in type:";
704 printd (p_typ t);
705 t)
706 end
707
e680130a 708fun checkDecl G (d, _, loc) =
709 case d of
89c9edc9 710 DExternType name =>
711 if !externFlag then
712 bindType G name
713 else
714 (ErrorMsg.error (SOME loc) "'extern type' not allowed in untrusted code";
715 G)
716 | DExternVal (name, t) =>
717 if !externFlag then
718 bindVal G (name, checkTyp G t, NONE)
719 else
720 (ErrorMsg.error (SOME loc) "'extern val' not allowed in untrusted code";
721 G)
add6f172 722 | DVal (name, to, e) =>
723 let
724 val to =
725 case to of
726 NONE => (newUnif (), loc)
727 | SOME to => checkTyp G to
728
729 val t = checkExp G e
730 in
4264c8ef 731 hasTyp (e, t, to)
add6f172 732 handle Unify ue =>
733 describe_type_error loc
734 (WrongType ("Bound value",
735 e,
736 t,
737 to,
738 SOME ue));
739 bindVal G (name, to, SOME e)
740 end
51c32b45 741 | DContext name => bindContext G name
e680130a 742
51c32b45 743fun checkFile G tInit (_, ds, eo) =
e680130a 744 let
745 val G' = foldl (fn (d, G) => checkDecl G d) G ds
746 in
747 case eo of
748 NONE => ()
749 | SOME (e as (_, loc)) =>
750 let
751 val t = checkExp G' e
752 in
4264c8ef 753 hasTyp (e, t, tInit)
e680130a 754 handle Unify ue =>
755 (ErrorMsg.error (SOME loc) "Bad type for final expression of source file.";
756 preface ("Actual:", p_typ t);
757 preface ("Needed:", p_typ tInit))
758 end;
759 G'
760 end
761
64014a03 762end