/[svn]/typing/typer.ml
ViewVC logotype

Contents of /typing/typer.ml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1755 - (hide annotations)
Tue Jul 10 19:20:31 2007 UTC (5 years, 10 months ago) by abate
File size: 35149 byte(s)
[r2005-07-07 15:03:35 by afrisch] open

Original author: afrisch
Date: 2005-07-07 15:03:35+00:00
1 abate 677 open Location
2     open Ast
3     open Ident
4 abate 276
5 abate 1463 let (=) (x:int) y = x = y
6     let (<=) (x:int) y = x <= y
7     let (<) (x:int) y = x < y
8     let (>=) (x:int) y = x >= y
9     let (>) (x:int) y = x > y
10    
11 abate 320 let warning loc msg =
12 abate 1411 let v = Location.get_viewport () in
13 abate 1428 let ppf = if Html.is_html v then Html.ppf v else Format.err_formatter in
14 abate 1411 Format.fprintf ppf "Warning %a:@\n" Location.print_loc (loc,`Full);
15     Location.html_hilight (loc,`Full);
16     Format.fprintf ppf "%s@." msg
17 abate 320
18 abate 1190 exception NonExhaustive of Types.descr
19     exception Constraint of Types.descr * Types.descr
20     exception ShouldHave of Types.descr * string
21     exception ShouldHave2 of Types.descr * string * Types.descr
22     exception WrongLabel of Types.descr * label
23     exception UnboundId of id * bool
24 abate 1746 exception UnboundExtId of Compunit.t * id
25 abate 1190 exception Error of string
26 abate 1238 exception Warning of string * Types.t
27    
28 abate 1190 let raise_loc loc exn = raise (Location (loc,`Full,exn))
29     let raise_loc_str loc ofs exn = raise (Location (loc,`Char ofs,exn))
30     let error loc msg = raise_loc loc (Error msg)
31    
32 abate 1753 type schema = {
33     sch_uri: string;
34     sch_ns: Ns.Uri.t;
35     sch_comps: (Types.t * Schema_validator.t) Ident.Env.t;
36     }
37    
38 abate 686 type item =
39 abate 1753 (* These are really exported by CDuce units: *)
40 abate 686 | Type of Types.t
41 abate 691 | Val of Types.t
42 abate 1753 | ECDuce of Compunit.t
43     | ESchema of schema
44     | ENamespace of Ns.Uri.t
45     (* These are only used internally: *)
46     | EVal of Compunit.t * id * Types.t
47     | EOCaml of string
48     | EOCamlComponent of string
49     | ESchemaComponent of (Types.t * Schema_validator.t)
50 abate 686
51 abate 691 type t = {
52 abate 686 ids : item Env.t;
53 abate 713 ns: Ns.table;
54 abate 1560 keep_ns: bool
55 abate 677 }
56 abate 542
57 abate 1753 (* Namespaces *)
58    
59     let set_ns_table_for_printer env =
60     Ns.InternalPrinter.set_table env.ns
61    
62     let get_ns_table tenv = tenv.ns
63    
64    
65     let type_keep_ns env k =
66     { env with keep_ns = k }
67    
68     let protect_error_ns loc f x =
69     try f x
70     with Ns.UnknownPrefix ns ->
71     raise_loc_generic loc
72     ("Undefined namespace prefix " ^ (U.to_string ns))
73    
74     let qname env loc t =
75     protect_error_ns loc (Ns.map_tag env.ns) t
76    
77     let ident env loc t =
78     protect_error_ns loc (Ns.map_attr env.ns) t
79    
80     let parse_atom env loc t = Atoms.V.mk (qname env loc t)
81    
82     let parse_ns env loc ns =
83     protect_error_ns loc (Ns.map_prefix env.ns) ns
84    
85     let parse_label env loc t =
86     Label.mk (protect_error_ns loc (Ns.map_attr env.ns) t)
87    
88     let parse_record env loc f r =
89     let r = List.map (fun (l,x) -> (parse_label env loc l, f x)) r in
90     LabelMap.from_list (fun _ _ -> raise_loc_generic loc "Duplicated record field") r
91    
92    
93    
94 abate 1552 let load_schema = ref (fun _ _ -> assert false)
95     let from_comp_unit = ref (fun _ -> assert false)
96 abate 1746 let load_comp_unit = ref (fun _ -> assert false)
97 abate 1552 let has_ocaml_unit = ref (fun _ -> false)
98     let has_static_external = ref (fun _ -> assert false)
99 abate 691
100 abate 1753 let type_schema env loc name uri =
101     let x = ident env loc name in
102     let (ns,sch) = !load_schema (U.to_string name) uri in
103     let sch = { sch_uri = uri; sch_comps = sch; sch_ns = ns } in
104     { env with ids = Env.add x (ESchema sch) env.ids }
105 abate 1474
106 abate 686 let empty_env = {
107     ids = Env.empty;
108 abate 1560 ns = Ns.def_table;
109     keep_ns = false
110 abate 686 }
111    
112 abate 1753 let enter_id x i env =
113     { env with ids = Env.add x i env.ids }
114 abate 723
115    
116 abate 1753 let type_using env loc x cu =
117 abate 1496 try
118 abate 1753 let cu = !load_comp_unit cu in
119     enter_id (ident env loc x) (ECDuce cu) env
120     with Not_found ->
121     error loc ("Cannot find external unit " ^ (U.to_string cu))
122 abate 1190
123 abate 1753 let enter_type id t env = enter_id id (Type t) env
124 abate 686 let enter_types l env =
125     { env with ids =
126     List.fold_left (fun accu (id,t) -> Env.add id (Type t) accu) env.ids l }
127    
128 abate 1753 let find_id env0 env loc head x =
129     let id = ident env0 loc x in
130     try Env.find id env.ids
131     with Not_found when head ->
132     try ECDuce (!load_comp_unit x)
133     with Not_found ->
134     if !has_ocaml_unit x then (EOCaml (U.get_str x))
135     else error loc "Cannot resolve this identifier"
136 abate 713
137 abate 686 let enter_value id t env =
138 abate 691 { env with ids = Env.add id (Val t) env.ids }
139 abate 686 let enter_values l env =
140     { env with ids =
141 abate 691 List.fold_left (fun accu (id,t) -> Env.add id (Val t) accu) env.ids l }
142 abate 1238 let enter_values_dummy l env =
143     { env with ids =
144     List.fold_left (fun accu id -> Env.add id (Val Types.empty) accu) env.ids l }
145 abate 1754
146 abate 692 let value_name_ok id env =
147     try match Env.find id env.ids with
148 abate 1755 | Val _ | EVal _ -> true
149 abate 692 | _ -> false
150     with Not_found -> true
151 abate 686
152 abate 695 let iter_values env f =
153     Env.iter (fun x ->
154     function Val t -> f x t;
155     | _ -> ()) env.ids
156 abate 692
157 abate 713
158 abate 956 let register_types cu env =
159 abate 1495 Env.iter (fun x t -> match t with
160     | Type t -> Types.Print.register_global cu (Ident.value x) t
161     | _ -> ()) env.ids
162 abate 713
163 abate 956
164 abate 542
165 abate 677 let rec const env loc = function
166     | LocatedExpr (loc,e) -> const env loc e
167     | Pair (x,y) -> Types.Pair (const env loc x, const env loc y)
168     | Xml (x,y) -> Types.Xml (const env loc x, const env loc y)
169     | RecordLitt x -> Types.Record (parse_record env loc (const env loc) x)
170     | String (i,j,s,c) -> Types.String (i,j,s,const env loc c)
171     | Atom t -> Types.Atom (parse_atom env loc t)
172     | Integer i -> Types.Integer i
173     | Char c -> Types.Char c
174 abate 722 | Const c -> c
175 abate 677 | _ -> raise_loc_generic loc "This should be a scalar or structured constant"
176    
177     (* I. Transform the abstract syntax of types and patterns into
178     the internal form *)
179    
180 abate 5
181 abate 1753 let find_schema_component sch name =
182     try ESchemaComponent (Env.find name sch.sch_comps)
183 abate 1496 with Not_found ->
184     raise (Error (Printf.sprintf "No component named '%s' found in schema '%s'"
185 abate 1753 (Ns.QName.to_string name) sch.sch_uri))
186 abate 786
187 abate 1190
188 abate 1753 let navig loc env0 (env,comp) id =
189     match comp with
190     | ECDuce cu ->
191     let env = !from_comp_unit cu in
192     let c =
193     try find_id env0 env loc false id
194     with Not_found -> error loc "Unbound identifier" in
195     let c = match c with
196     | Val t -> EVal (cu,ident env0 loc id,t)
197     | c -> c in
198     env,c
199     | EOCaml cu ->
200     let s = cu ^ "." ^ (U.get_str id) in
201     (match (U.get_str id).[0] with
202     | 'A'..'Z' -> env,EOCaml s
203     | _ -> env,EOCamlComponent s)
204     | ESchema sch ->
205     env,find_schema_component sch (ident env0 loc id)
206     | _ -> error loc "Invalid dot access"
207 abate 1496
208 abate 1190
209 abate 1753 let rec find_global env loc ids =
210     match ids with
211     | id::rest ->
212     let comp = find_id env env loc true id in
213     snd (List.fold_left (navig loc env) (env,comp) rest)
214     | _ -> assert false
215    
216     let eval_ns env loc = function
217     | `Uri ns -> ns
218     | `Path ids ->
219     match find_global env loc ids with
220     | ENamespace ns -> ns
221     | ESchema sch -> sch.sch_ns
222     | _ -> error loc "This path does not refer to a namespace or schema"
223    
224     let type_ns env loc p ns =
225     (* TODO: check that p has no prefix *)
226     let ns = eval_ns env loc ns in
227     { env with
228     ns = Ns.add_prefix p ns env.ns;
229     ids = Env.add (Ns.empty,p) (ENamespace ns) env.ids }
230    
231    
232    
233     let find_global_type env loc ids =
234     match find_global env loc ids with
235     | Type t | ESchemaComponent (t,_) -> t
236     | _ -> error loc "This path does not refer to a type"
237    
238     let find_global_schema_component env loc ids =
239     match find_global env loc ids with
240     | ESchemaComponent c -> c
241     | _ -> error loc "This path does not refer to a schema component"
242    
243    
244     let find_local_type env loc id =
245     match Env.find id env.ids with
246     | Type t -> t
247 abate 1754 | _ -> raise Not_found
248 abate 1753
249     let find_value id env =
250     try match Env.find id env.ids with
251 abate 1755 | Val t | EVal (_,_,t) -> t
252 abate 1753 | _ -> raise Not_found
253     with Not_found -> assert false
254    
255 abate 1755 let do_open env cu =
256     let env_cu = !from_comp_unit cu in
257     let ids =
258     Env.fold
259     (fun n d ids ->
260     let d = match d with
261     | Val t -> EVal (cu,n,t)
262     | d -> d in
263     Env.add n d ids)
264     env_cu.ids
265     env.ids in
266     { env with
267     ids = ids;
268     ns = Ns.merge_tables env.ns env_cu.ns }
269    
270    
271     let type_open env loc ids =
272     match find_global env loc ids with
273     | ECDuce cu -> do_open env cu
274     | _ -> error loc "This path does not refer to a CDuce unit"
275    
276 abate 1464 module IType = struct
277 abate 1645 open Typepat
278 abate 1464
279     (* From AST to the intermediate representation *)
280    
281     type penv = {
282     penv_tenv : t;
283     penv_derec : node Env.t;
284     }
285    
286     let penv tenv = { penv_tenv = tenv; penv_derec = Env.empty }
287    
288 abate 1465 let all_delayed = ref []
289    
290 abate 1495 let clean_on_err () = all_delayed := []
291    
292 abate 1465 let delayed loc =
293     let s = mk_delayed () in
294     all_delayed := (loc,s) :: !all_delayed;
295     s
296    
297     let check_one_delayed (loc,p) =
298 abate 1645 if not (check_wf p) then error loc "Ill-formed recursion"
299 abate 1465
300     let check_delayed () =
301     let l = !all_delayed in
302     all_delayed := [];
303     List.iter check_one_delayed l
304 abate 1523
305 abate 1464 let rec derecurs env p = match p.descr with
306 abate 1753 | PatVar ids -> derecurs_var env p.loc ids
307 abate 1523 | Recurs (p,b) -> derecurs (fst (derecurs_def env b)) p
308 abate 1645 | Internal t -> mk_type t
309 abate 1464 | NsT ns ->
310 abate 1645 mk_type (Types.atom (Atoms.any_in_ns (parse_ns env.penv_tenv p.loc ns)))
311     | Or (p1,p2) -> mk_or (derecurs env p1) (derecurs env p2)
312     | And (p1,p2) -> mk_and (derecurs env p1) (derecurs env p2)
313     | Diff (p1,p2) -> mk_diff (derecurs env p1) (derecurs env p2)
314     | Prod (p1,p2) -> mk_prod (derecurs env p1) (derecurs env p2)
315     | XmlT (p1,p2) -> mk_xml (derecurs env p1) (derecurs env p2)
316     | Arrow (p1,p2) -> mk_arrow (derecurs env p1) (derecurs env p2)
317     | Optional p -> mk_optional (derecurs env p)
318 abate 1464 | Record (o,r) ->
319     let aux = function
320     | (p,Some e) -> (derecurs env p, Some (derecurs env e))
321     | (p,None) -> derecurs env p, None in
322 abate 1645 mk_record o (parse_record env.penv_tenv p.loc aux r)
323     | Constant (x,c) ->
324     mk_constant (ident env.penv_tenv p.loc x) (const env.penv_tenv p.loc c)
325     | Cst c -> mk_type (Types.constant (const env.penv_tenv p.loc c))
326     | Regexp r -> rexp (derecurs_regexp env r)
327     | Concat (p1,p2) -> mk_concat (derecurs env p1) (derecurs env p2)
328     | Merge (p1,p2) -> mk_merge (derecurs env p1) (derecurs env p2)
329 abate 1464
330 abate 1645 and derecurs_regexp env = function
331     | Epsilon -> mk_epsilon
332     | Elem p -> mk_elem (derecurs env p)
333     | Guard p -> mk_guard (derecurs env p)
334     | Seq (p1,p2) -> mk_seq (derecurs_regexp env p1) (derecurs_regexp env p2)
335     | Alt (p1,p2) -> mk_alt (derecurs_regexp env p1) (derecurs_regexp env p2)
336     | Star p -> mk_star (derecurs_regexp env p)
337     | WeakStar p -> mk_weakstar (derecurs_regexp env p)
338     | SeqCapture (loc,x,p) -> mk_seqcapt (ident env.penv_tenv loc x) (derecurs_regexp env p)
339 abate 1464
340 abate 1753 and derecurs_var env loc ids =
341     match ids with
342     | [v] ->
343     let v = ident env.penv_tenv loc v in
344 abate 1495 (try Env.find v env.penv_derec
345 abate 1464 with Not_found ->
346 abate 1753 try mk_type (find_local_type env.penv_tenv loc v)
347 abate 1645 with Not_found -> mk_capture v)
348 abate 1753 | ids ->
349     mk_type (find_global_type env.penv_tenv loc ids)
350 abate 1464
351     and derecurs_def env b =
352 abate 1495 let seen = ref IdSet.empty in
353     let b =
354     List.map
355     (fun (loc,v,p) ->
356     let v = ident env.penv_tenv loc v in
357     if IdSet.mem !seen v then
358     raise_loc_generic loc
359     ("Multiple definitions for the type identifer " ^
360     (Ident.to_string v));
361     seen := IdSet.add v !seen;
362     (v,p,delayed loc))
363     b in
364    
365 abate 1464 let n =
366     List.fold_left (fun env (v,p,s) -> Env.add v s env) env.penv_derec b in
367     let env = { env with penv_derec = n } in
368 abate 1645 List.iter (fun (v,p,s) -> link s (derecurs env p)) b;
369 abate 1523 (env, b)
370 abate 1464
371 abate 1465 let derec penv p =
372     let d = derecurs penv p in
373 abate 1523 elim_concats ();
374 abate 1465 check_delayed ();
375     internalize d;
376     d
377 abate 1464
378    
379 abate 1465 (* API *)
380 abate 1464
381 abate 1645 let check_no_fv loc n =
382     match peek_fv n with
383     | None -> ()
384     | Some x ->
385     raise_loc_generic loc
386     ("Capture variable not allowed: " ^ (Ident.to_string x))
387    
388 abate 1464 let type_defs env b =
389 abate 1523 let _,b' = derecurs_def (penv env) b in
390     elim_concats ();
391     check_delayed ();
392     let aux loc d =
393     internalize d;
394     check_no_fv loc d;
395 abate 1465 try typ d
396 abate 1523 with Patterns.Error s -> raise_loc_generic loc s
397 abate 1465 in
398 abate 1464 let b =
399 abate 1523 List.map2
400     (fun (loc,v,p) (v',_,d) ->
401     let t = aux loc d in
402 abate 1495 if (loc <> noloc) && (Types.is_empty t) then
403     warning loc
404     ("This definition yields an empty type for " ^ (U.to_string v));
405     let v = ident env loc v in
406 abate 1523 (v',t)) b b' in
407 abate 1746 List.iter (fun (v,t) -> Types.Print.register_global "" v t) b;
408 abate 1551 enter_types b env
409 abate 1464
410 abate 1495 let type_defs env b =
411     try type_defs env b
412     with exn -> clean_on_err (); raise exn
413 abate 1464
414 abate 1465 let typ env t =
415 abate 1495 try
416     let d = derec (penv env) t in
417     check_no_fv t.loc d;
418     try typ_node d
419     with Patterns.Error s -> raise_loc_generic t.loc s
420     with exn -> clean_on_err (); raise exn
421 abate 5
422 abate 1465 let pat env t =
423 abate 1495 try
424     let d = derec (penv env) t in
425     try pat_node d
426     with Patterns.Error s -> raise_loc_generic t.loc s
427     with exn -> clean_on_err (); raise exn
428 abate 1552
429 abate 1465 end
430 abate 677
431 abate 1464 let typ = IType.typ
432     let pat = IType.pat
433     let type_defs = IType.type_defs
434    
435     let dump_types ppf env =
436     Env.iter (fun v ->
437     function
438     (Type _) -> Format.fprintf ppf " %a" Ident.print v
439     | _ -> ()) env.ids
440    
441     let dump_ns ppf env =
442     Ns.dump_table ppf env.ns
443    
444    
445    
446    
447 abate 5 (* II. Build skeleton *)
448    
449 abate 542
450 abate 691 type type_fun = Types.t -> bool -> Types.t
451 abate 542
452 abate 225 module Fv = IdSet
453 abate 6
454 abate 427 type branch = Branch of Typed.branch * branch list
455 abate 314
456 abate 427 let cur_branch : branch list ref = ref []
457    
458 abate 1514 let exp' loc e =
459     { Typed.exp_loc = loc; Typed.exp_typ = Types.empty; Typed.exp_descr = e; }
460 abate 316
461 abate 1514 let exp loc fv e = fv, exp' loc e
462    
463     let exp_nil = exp' noloc (Typed.Cst Sequence.nil_cst)
464    
465     let pat_true =
466     let n = Patterns.make Fv.empty in
467     Patterns.define n (Patterns.constr Builtin_defs.true_type);
468     n
469    
470     let pat_false =
471     let n = Patterns.make Fv.empty in
472     Patterns.define n (Patterns.constr Builtin_defs.false_type);
473     n
474    
475    
476 abate 1237 let ops = Hashtbl.create 13
477 abate 1238 let register_op op arity f = Hashtbl.add ops op (arity,f)
478     let typ_op op = snd (Hashtbl.find ops op)
479 abate 316
480 abate 1495 let fun_name env a =
481     match a.fun_name with
482     | None -> None
483     | Some (loc,s) -> Some (ident env loc s)
484    
485 abate 1238 let is_op env s =
486 abate 1495 if (Env.mem s env.ids) then None
487     else
488 abate 1746 let (ns,s) = s in
489     if Ns.Uri.equal ns Ns.empty then
490 abate 1495 let s = U.get_str s in
491     try
492     let o = Hashtbl.find ops s in
493     Some (s, fst o)
494     with Not_found -> None
495     else None
496 abate 1237
497 abate 686 let rec expr env loc = function
498     | LocatedExpr (loc,e) -> expr env loc e
499 abate 316 | Forget (e,t) ->
500 abate 686 let (fv,e) = expr env loc e and t = typ env t in
501 abate 316 exp loc fv (Typed.Forget (e,t))
502 abate 1398 | Check (e,t) ->
503     let (fv,e) = expr env loc e and t = typ env t in
504 abate 1401 exp loc fv (Typed.Check (ref Types.empty,e,t))
505 abate 1215 | Var s -> var env loc s
506 abate 316 | Apply (e1,e2) ->
507 abate 1238 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
508     let fv = Fv.cup fv1 fv2 in
509     (match e1.Typed.exp_descr with
510     | Typed.Op (op,arity,args) when arity > 0 ->
511     exp loc fv (Typed.Op (op,arity - 1,args @ [e2]))
512     | _ ->
513     exp loc fv (Typed.Apply (e1,e2)))
514     | Abstraction a -> abstraction env loc a
515 abate 722 | (Integer _ | Char _ | Atom _ | Const _) as c ->
516 abate 686 exp loc Fv.empty (Typed.Cst (const env loc c))
517 abate 316 | Pair (e1,e2) ->
518 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
519 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Pair (e1,e2))
520     | Xml (e1,e2) ->
521 abate 686 let (fv1,e1) = expr env loc e1 and (fv2,e2) = expr env loc e2 in
522 abate 1560 let n = if env.keep_ns then Some env.ns else None in
523     exp loc (Fv.cup fv1 fv2) (Typed.Xml (e1,e2,n))
524 abate 1714 | Dot _ as e ->
525 abate 1753 dot loc env e []
526     | TyArgs (Dot _ as e, args) ->
527     dot loc env e args
528     | TyArgs _ ->
529     error loc "Only OCaml external can have type arguments"
530 abate 316 | RemoveField (e,l) ->
531 abate 686 let (fv,e) = expr env loc e in
532     exp loc fv (Typed.RemoveField (e,parse_label env loc l))
533 abate 316 | RecordLitt r ->
534     let fv = ref Fv.empty in
535 abate 686 let r = parse_record env loc
536 abate 316 (fun e ->
537 abate 686 let (fv2,e) = expr env loc e
538 abate 316 in fv := Fv.cup !fv fv2; e)
539     r in
540     exp loc !fv (Typed.RecordLitt r)
541 abate 522 | String (i,j,s,e) ->
542 abate 686 let (fv,e) = expr env loc e in
543 abate 522 exp loc fv (Typed.String (i,j,s,e))
544 abate 316 | Match (e,b) ->
545 abate 686 let (fv1,e) = expr env loc e
546     and (fv2,b) = branches env b in
547 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Match (e, b))
548 abate 421 | Map (e,b) ->
549 abate 686 let (fv1,e) = expr env loc e
550     and (fv2,b) = branches env b in
551 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Map (e, b))
552     | Transform (e,b) ->
553 abate 686 let (fv1,e) = expr env loc e
554     and (fv2,b) = branches env b in
555 abate 421 exp loc (Fv.cup fv1 fv2) (Typed.Transform (e, b))
556 abate 331 | Xtrans (e,b) ->
557 abate 686 let (fv1,e) = expr env loc e
558     and (fv2,b) = branches env b in
559 abate 331 exp loc (Fv.cup fv1 fv2) (Typed.Xtrans (e, b))
560 abate 1753 | Validate (e,ids) ->
561 abate 686 let (fv,e) = expr env loc e in
562 abate 1753 let (t,v) = find_global_schema_component env loc ids in
563 abate 1746 exp loc fv (Typed.Validate (e, t, v))
564 abate 1514 | SelectFW (e,from,where) ->
565     select_from_where env loc e from where
566 abate 316 | Try (e,b) ->
567 abate 686 let (fv1,e) = expr env loc e
568     and (fv2,b) = branches env b in
569 abate 316 exp loc (Fv.cup fv1 fv2) (Typed.Try (e, b))
570 abate 530 | NamespaceIn (pr,ns,e) ->
571 abate 1753 let env = type_ns env loc pr ns in
572 abate 686 expr env loc e
573 abate 1560 | KeepNsIn (k,e) ->
574     expr (type_keep_ns env k) loc e
575 abate 623 | Ref (e,t) ->
576 abate 686 let (fv,e) = expr env loc e and t = typ env t in
577 abate 623 exp loc fv (Typed.Ref (e,t))
578 abate 1514
579     and if_then_else loc cond yes no =
580     let b = {
581     Typed.br_typ = Types.empty;
582     Typed.br_branches = [
583     { Typed.br_loc = yes.Typed.exp_loc;
584     Typed.br_used = false;
585     Typed.br_vars_empty = Fv.empty;
586     Typed.br_pat = pat_true;
587     Typed.br_body = yes };
588     { Typed.br_loc = no.Typed.exp_loc;
589     Typed.br_used = false;
590     Typed.br_vars_empty = Fv.empty;
591     Typed.br_pat = pat_false;
592     Typed.br_body = no } ];
593     Typed.br_accept = Builtin_defs.bool;
594     } in
595     exp' loc (Typed.Match (cond,b))
596 abate 1714
597    
598 abate 1753 and dot loc env0 e args =
599 abate 1714 let dot_access loc (fv,e) l =
600 abate 1753 exp loc fv (Typed.Dot (e,parse_label env0 loc l)) in
601    
602     let no_args () =
603     if args <> [] then
604     error loc "Only OCaml externals can have type arguments" in
605     let rec aux loc = function
606     | LocatedExpr (loc,e) -> aux loc e
607     | Dot (e,id) ->
608     (match aux loc e with
609     | `Val e -> `Val (dot_access loc e id)
610     | `Comp c -> `Comp (navig loc env0 c id))
611     | Var id ->
612     (match find_id env0 env0 loc true id with
613     | Val _ -> `Val (var env0 loc id)
614     | c -> `Comp (env0,c))
615     | e -> `Val (expr env0 loc e)
616     in
617     match aux loc e with
618     | `Val e -> no_args (); e
619     | `Comp (_,EVal (cu,id,t)) ->
620     no_args (); exp loc Fv.empty (Typed.ExtVar (cu,id,t))
621     | `Comp (_,EOCamlComponent s) -> extern loc env0 s args
622     | _ -> error loc "This dot notation does not refer to a value"
623 abate 1238
624     and extern loc env s args =
625     let args = List.map (typ env) args in
626     try
627 abate 1497 let (i,t) =
628     if !has_static_external s then
629     (`Builtin s, Externals.typ s args)
630     else
631     let (i,t) = Externals.resolve s args in
632     (`Ext i, t) in
633 abate 1238 exp loc Fv.empty (Typed.External (t,i))
634     with exn -> raise_loc loc exn
635    
636     and var env loc s =
637 abate 1495 let id = ident env loc s in
638     match is_op env id with
639 abate 1239 | Some (s,arity) ->
640 abate 1560 let e = match s with
641     | "print_xml" | "print_xml_utf8" ->
642     Typed.NsTable (env.ns,Typed.Op (s, arity, []))
643     | "load_xml" when env.keep_ns ->
644     Typed.Op ("!load_xml",arity,[])
645     | _ -> Typed.Op (s, arity, [])
646     in
647 abate 1239 exp loc Fv.empty e
648 abate 1238 | None ->
649 abate 1755 try match Env.find id env.ids with
650     | Val _ -> exp loc (Fv.singleton id) (Typed.Var id)
651     | EVal (cu,id,t) -> exp loc Fv.empty (Typed.ExtVar (cu,id,t))
652     | _ -> error loc "This identifier does not refer to a value"
653     with Not_found -> error loc "Unbound identifier"
654 abate 1178
655 abate 1755
656 abate 1238 and abstraction env loc a =
657     let iface =
658     List.map
659     (fun (t1,t2) -> (typ env t1, typ env t2)) a.fun_iface in
660     let t =
661     List.fold_left
662     (fun accu (t1,t2) -> Types.cap accu (Types.arrow t1 t2))
663     Types.any iface in
664     let iface =
665     List.map
666     (fun (t1,t2) -> (Types.descr t1, Types.descr t2))
667     iface in
668 abate 1495 let fun_name = fun_name env a in
669 abate 1238 let env' =
670 abate 1495 match fun_name with
671 abate 1238 | None -> env
672     | Some f -> enter_values_dummy [ f ] env
673     in
674     let (fv0,body) = branches env' a.fun_body in
675 abate 1495 let fv = match fun_name with
676 abate 1238 | None -> fv0
677     | Some f -> Fv.remove f fv0 in
678     let e = Typed.Abstraction
679 abate 1495 { Typed.fun_name = fun_name;
680 abate 1238 Typed.fun_iface = iface;
681     Typed.fun_body = body;
682     Typed.fun_typ = t;
683     Typed.fun_fv = fv
684     } in
685     exp loc fv e
686    
687     and branches env b =
688     let fv = ref Fv.empty in
689     let accept = ref Types.empty in
690     let branch (p,e) =
691     let cur_br = !cur_branch in
692     cur_branch := [];
693 abate 1514 let ploc = p.loc in
694     let p = pat env p in
695     let fvp = Patterns.fv p in
696     let (fv2,e) = expr (enter_values_dummy fvp env) noloc e in
697     let br_loc = merge_loc ploc e.Typed.exp_loc in
698 abate 1238 (match Fv.pick (Fv.diff fvp fv2) with
699     | None -> ()
700     | Some x ->
701 abate 1495 let x = Ident.to_string x in
702 abate 1238 warning br_loc
703     ("The capture variable " ^ x ^
704     " is declared in the pattern but not used in the body of this branch. It might be a misspelled or undeclared type or name (if it isn't, use _ instead)."));
705     let fv2 = Fv.diff fv2 fvp in
706     fv := Fv.cup !fv fv2;
707 abate 1514 accept := Types.cup !accept (Types.descr (Patterns.accept p));
708 abate 1238 let br =
709     {
710     Typed.br_loc = br_loc;
711 abate 1463 Typed.br_used = br_loc == noloc;
712 abate 1514 Typed.br_vars_empty = fvp;
713     Typed.br_pat = p;
714 abate 1238 Typed.br_body = e } in
715     cur_branch := Branch (br, !cur_branch) :: cur_br;
716     br in
717     let b = List.map branch b in
718     (!fv,
719     {
720     Typed.br_typ = Types.empty;
721     Typed.br_branches = b;
722     Typed.br_accept = !accept;
723     }
724     )
725 abate 1215
726 abate 1514 and select_from_where env loc e from where =
727     let env = ref env in
728     let all_fv = ref Fv.empty in
729     let bound_fv = ref Fv.empty in
730     let clause (p,e) =
731     let ploc = p.loc in
732     let p = pat !env p in
733     let fvp = Patterns.fv p in
734     let (fv2,e) = expr !env noloc e in
735     env := enter_values_dummy fvp !env;
736     all_fv := Fv.cup (Fv.diff fv2 !bound_fv) !all_fv;
737     bound_fv := Fv.cup fvp !bound_fv;
738     (ploc,p,fvp,e) in
739     let from = List.map clause from in
740     let where = List.map (expr !env noloc) where in
741    
742     let put_cond rest (fv,cond) =
743     all_fv := Fv.cup (Fv.diff fv !bound_fv) !all_fv;
744     if_then_else loc cond rest exp_nil in
745     let aux (ploc,p,fvp,e) (where,rest) =
746     (* Put here the conditions that depends on variables in fvp *)
747     let (above,here) = List.partition (fun (v,_) -> Fv.disjoint v fvp) where in
748     (* if cond then ... else [] *)
749     let rest = List.fold_left put_cond rest here in
750     (* transform e with p -> ... *)
751 abate 1713 let br = { Typed.br_loc = ploc;
752 abate 1514 Typed.br_used = false;
753     Typed.br_vars_empty = fvp;
754     Typed.br_pat = p;
755 abate 1713 Typed.br_body = rest } in
756     cur_branch := [ Branch (br, !cur_branch) ];
757     let b = {
758     Typed.br_typ = Types.empty;
759     Typed.br_branches = [ br ];
760 abate 1514 Typed.br_accept = Types.descr (Patterns.accept p);
761     } in
762     let br_loc = merge_loc ploc e.Typed.exp_loc in
763     (above,exp' br_loc (Typed.Transform (e, b)))
764     in
765 abate 1713 let cur_br = !cur_branch in
766     cur_branch := [];
767 abate 1561 let (fv,e) = expr !env noloc (Pair(e,cst_nil)) in
768 abate 1713 cur_branch := !cur_branch @ cur_br;
769 abate 1514 let (where,rest) = List.fold_right aux from (where,e) in
770     (* The remaining conditions are constant. Gives a warning for that. *)
771     (match where with
772     | (_,e) :: _ ->
773     warning e.Typed.exp_loc
774     "This 'where' condition does not depend on any captured variable"
775     | _ -> ());
776     let rest = List.fold_left put_cond rest where in
777     (Fv.cup !all_fv (Fv.diff fv !bound_fv)), rest
778    
779 abate 695 let expr env e = snd (expr env noloc e)
780 abate 122
781 abate 686 let let_decl env p e =
782     { Typed.let_pat = pat env p;
783 abate 1514 Typed.let_body = expr env e }
784 abate 66
785 abate 529
786     (* Hide global "typing/parsing" environment *)
787    
788    
789 abate 66 (* III. Type-checks *)
790    
791 abate 6 open Typed
792    
793 abate 1238 let localize loc f x =
794     try f x
795     with
796     | (Error _ | Constraint (_,_)) as exn -> raise (Location.Location (loc,`Full,exn))
797     | Warning (s,t) -> warning loc s; t
798    
799 abate 421 let require loc t s =
800     if not (Types.subtype t s) then raise_loc loc (Constraint (t, s))
801 abate 17
802 abate 691 let verify loc t s =
803 abate 421 require loc t s; t
804 abate 17
805 abate 1238 let verify_noloc t s =
806     if not (Types.subtype t s) then raise (Constraint (t, s));
807     t
808    
809 abate 522 let check_str loc ofs t s =
810     if not (Types.subtype t s) then raise_loc_str loc ofs (Constraint (t, s));
811     t
812    
813     let should_have loc constr s =
814 abate 421 raise_loc loc (ShouldHave (constr,s))
815    
816 abate 522 let should_have_str loc ofs constr s =
817     raise_loc_str loc ofs (ShouldHave (constr,s))
818    
819 abate 1238 let flatten arg constr precise =
820 abate 421 let constr' = Sequence.star
821     (Sequence.approx (Types.cap Sequence.any constr)) in
822     let sconstr' = Sequence.star constr' in
823     let exact = Types.subtype constr' constr in
824     if exact then
825     let t = arg sconstr' precise in
826     if precise then Sequence.flatten t else constr
827     else
828     let t = arg sconstr' true in
829 abate 1238 verify_noloc (Sequence.flatten t) constr
830 abate 421
831 abate 19 let rec type_check env e constr precise =
832     let d = type_check' e.exp_loc env e.exp_descr constr precise in
833 abate 421 let d = if precise then d else constr in
834 abate 6 e.exp_typ <- Types.cup e.exp_typ d;
835     d
836    
837 abate 19 and type_check' loc env e constr precise = match e with
838 abate 54 | Forget (e,t) ->
839     let t = Types.descr t in
840     ignore (type_check env e t false);
841 abate 691 verify loc t constr
842 abate 421
843 abate 1401 | Check (t0,e,t) ->
844     let te = type_check env e Types.any true in
845     t0 := Types.cup !t0 te;
846 abate 1413 verify loc (Types.cap te (Types.descr t)) constr
847 abate 1398
848 abate 19 | Abstraction a ->
849     let t =
850     try Types.Arrow.check_strenghten a.fun_typ constr
851     with Not_found ->
852 abate 421 should_have loc constr
853     "but the interface of the abstraction is not compatible"
854 abate 19 in
855     let env = match a.fun_name with
856     | None -> env
857 abate 686 | Some f -> enter_value f a.fun_typ env in
858 abate 19 List.iter
859     (fun (t1,t2) ->
860 abate 374 let acc = a.fun_body.br_accept in
861     if not (Types.subtype t1 acc) then
862     raise_loc loc (NonExhaustive (Types.diff t1 acc));
863 abate 65 ignore (type_check_branches loc env t1 a.fun_body t2 false)
864 abate 19 ) a.fun_iface;
865     t
866 abate 64
867 abate 19 | Match (e,b) ->
868     let t = type_check env e b.br_accept true in
869 abate 65 type_check_branches loc env t b constr precise
870 abate 30
871 abate 64 | Try (e,b) ->
872     let te = type_check env e constr precise in
873 abate 65 let tb = type_check_branches loc env Types.any b constr precise in
874 abate 64 Types.cup te tb
875    
876 abate 110 | Pair (e1,e2) ->
877     type_check_pair loc env e1 e2 constr precise
878 abate 421
879 abate 1560 | Xml (e1,e2,_) ->
880 abate 110 type_check_pair ~kind:`XML loc env e1 e2 constr precise
881 abate 159
882 abate 29 | RecordLitt r ->
883 abate 421 type_record loc env r constr precise
884 abate 31
885 abate 421 | Map (e,b) ->
886     type_map loc env false e b constr precise
887    
888     | Transform (e,b) ->
889 abate 1238 localize loc (flatten (type_map loc env true e b) constr) precise
890 abate 421
891 abate 86 | Apply (e1,e2) ->
892     let t1 = type_check env e1 Types.Arrow.any true in
893     let t1 = Types.Arrow.get t1 in
894     let dom = Types.Arrow.domain t1 in
895 abate 110 let res =
896     if Types.Arrow.need_arg t1 then
897     let t2 = type_check env e2 dom true in
898     Types.Arrow.apply t1 t2
899     else
900     (ignore (type_check env e2 dom false); Types.Arrow.apply_noarg t1)
901     in
902 abate 691 verify loc res constr
903 abate 19
904 abate 421 | Var s ->
905 abate 1238 verify loc (find_value s env) constr
906 abate 713
907 abate 1238 | ExtVar (cu,s,t) ->
908 abate 713 verify loc t constr
909 abate 421 | Cst c ->
910 abate 691 verify loc (Types.constant c) constr
911 abate 421
912 abate 522 | String (i,j,s,e) ->
913     type_check_string loc env 0 s i j e constr precise
914    
915 abate 421 | Dot (e,l) ->
916 abate 1698 let expect_rec = Types.record l (Types.cons constr) in
917     let expect_elt =
918     Types.xml
919     Types.any_node
920     (Types.cons (Types.times (Types.cons expect_rec) Types.any_node)) in
921     let t = type_check env e (Types.cup expect_rec expect_elt) precise in
922     let t_elt =
923     let t = Types.Product.pi2 (Types.Product.get ~kind:`XML t) in
924     let t = Types.Product.pi1 (Types.Product.get t) in
925     t in
926     if not precise then constr
927     else
928     (try Types.Record.project (Types.cup t t_elt) l
929     with Not_found -> assert false)
930 abate 421
931     | RemoveField (e,l) ->
932     let t = type_check env e Types.Record.any true in
933     let t = Types.Record.remove_field t l in
934 abate 691 verify loc t constr
935 abate 421
936     | Xtrans (e,b) ->
937     let t = type_check env e Sequence.any true in
938     let t =
939     Sequence.map_tree
940     (fun t ->
941     let resid = Types.diff t b.br_accept in
942     let res = type_check_branches loc env t b Sequence.any true in
943     (res,resid)
944     ) t in
945 abate 691 verify loc t constr
946 abate 421
947 abate 1746 | Validate (e, t, _) ->
948 abate 501 ignore (type_check env e Types.any false);
949 abate 691 verify loc t constr
950 abate 421
951 abate 623 | Ref (e,t) ->
952     ignore (type_check env e (Types.descr t) false);
953 abate 691 verify loc (Builtin_defs.ref_type t) constr
954 abate 623
955 abate 1497 | External (t,_) ->
956 abate 1156 verify loc t constr
957    
958 abate 1238 | Op (op,_,args) ->
959 abate 1237 let args = List.map (type_check env) args in
960 abate 1238 let t = localize loc (typ_op op args constr) precise in
961 abate 1237 verify loc t constr
962    
963 abate 1239 | NsTable (ns,e) ->
964     type_check' loc env e constr precise
965    
966 abate 110 and type_check_pair ?(kind=`Normal) loc env e1 e2 constr precise =
967 abate 361 let rects = Types.Product.normal ~kind constr in
968 abate 110 if Types.Product.is_empty rects then
969     (match kind with
970 abate 421 | `Normal -> should_have loc constr "but it is a pair"
971     | `XML -> should_have loc constr "but it is an XML element");
972 abate 334 let need_s = Types.Product.need_second rects in
973 abate 355 let t1 = type_check env e1 (Types.Product.pi1 rects) (precise || need_s) in
974     let c2 = Types.Product.constraint_on_2 rects t1 in
975     if Types.is_empty c2 then
976     raise_loc loc (ShouldHave2 (constr,"but the first component has type",t1));
977     let t2 = type_check env e2 c2 precise in
978 abate 334
979 abate 110 if precise then
980 abate 355 match kind with
981     | `Normal -> Types.times (Types.cons t1) (Types.cons t2)
982     | `XML -> Types.xml (Types.cons t1) (Types.cons t2)
983 abate 110 else
984     constr
985    
986 abate 522 and type_check_string loc env ofs s i j e constr precise =
987     if U.equal_index i j then type_check env e constr precise
988     else
989     let rects = Types.Product.normal constr in
990     if Types.Product.is_empty rects
991     then should_have_str loc ofs constr "but it is a string"
992     else
993     let need_s = Types.Product.need_second rects in
994     let (ch,i') = U.next s i in
995 abate 656 let ch = Chars.V.mk_int ch in
996 abate 522 let tch = Types.constant (Types.Char ch) in
997     let t1 = check_str loc ofs tch (Types.Product.pi1 rects) in
998     let c2 = Types.Product.constraint_on_2 rects t1 in
999     let t2 = type_check_string loc env (ofs + 1) s i' j e c2 precise in
1000     if precise then Types.times (Types.cons t1) (Types.cons t2)
1001     else constr
1002    
1003 abate 421 and type_record loc env r constr precise =
1004     (* try to get rid of precise = true for values of fields *)
1005     (* also: the use equivalent of need_second to optimize... *)
1006     if not (Types.Record.has_record constr) then
1007     should_have loc constr "but it is a record";
1008     let (rconstr,res) =
1009     List.fold_left
1010     (fun (rconstr,res) (l,e) ->
1011     (* could compute (split l e) once... *)
1012     let pi = Types.Record.project_opt rconstr l in
1013     if Types.is_empty pi then
1014 abate 1746 (let l = Label.string_of_attr l in
1015 abate 421 should_have loc constr
1016     (Printf.sprintf "Field %s is not allowed here." l));
1017     let t = type_check env e pi true in
1018     let rconstr = Types.Record.condition rconstr l t in
1019     let res = (l,Types.cons t) :: res in
1020     (rconstr,res)
1021     ) (constr, []) (LabelMap.get r)
1022     in
1023     if not (Types.Record.has_empty_record rconstr) then
1024     should_have loc constr "More fields should be present";
1025     let t =
1026 abate 1609 Types.record_fields (false, LabelMap.from_list (fun _ _ -> assert false) res)
1027 abate 421 in
1028 abate 691 verify loc t constr
1029 abate 110
1030 abate 19
1031 abate 65 and type_check_branches loc env targ brs constr precise =
1032 abate 374 if Types.is_empty targ then Types.empty
1033 abate 9 else (
1034     brs.br_typ <- Types.cup brs.br_typ targ;
1035 abate 65 branches_aux loc env targ
1036 abate 19 (if precise then Types.empty else constr)
1037     constr precise brs.br_branches
1038 abate 9 )
1039 abate 6
1040 abate 65 and branches_aux loc env targ tres constr precise = function
1041 abate 374 | [] -> tres
1042 abate 6 | b :: rem ->
1043     let p = b.br_pat in
1044     let acc = Types.descr (Patterns.accept p) in
1045    
1046     let targ' = Types.cap targ acc in
1047     if Types.is_empty targ'
1048 abate 65 then branches_aux loc env targ tres constr precise rem
1049 abate 6 else
1050     ( b.br_used <- true;
1051     let res = Patterns.filter targ' p in
1052 abate 1433 let res = IdMap.map Types.descr res in
1053    
1054     b.br_vars_empty <-
1055     IdMap.domain (
1056     IdMap.filter (fun x t -> Types.subtype t Sequence.nil_type)
1057     (IdMap.restrict res b.br_vars_empty));
1058    
1059     let env' = enter_values (IdMap.get res) env in
1060 abate 19 let t = type_check env' b.br_body constr precise in
1061     let tres = if precise then Types.cup t tres else tres in
1062 abate 9 let targ'' = Types.diff targ acc in
1063     if (Types.non_empty targ'') then
1064 abate 65 branches_aux loc env targ'' tres constr precise rem
1065 abate 9 else
1066     tres
1067 abate 6 )
1068 abate 16
1069 abate 421 and type_map loc env def e b constr precise =
1070     let acc = if def then Sequence.any else Sequence.star b.br_accept in
1071     let t = type_check env e acc true in
1072    
1073     let constr' = Sequence.approx (Types.cap Sequence.any constr) in
1074     let exact = Types.subtype (Sequence.star constr') constr in
1075     (* Note:
1076     - could be more precise by integrating the decomposition
1077     of constr inside Sequence.map.
1078     *)
1079     let res =
1080     Sequence.map
1081     (fun t ->
1082     let res =
1083     type_check_branches loc env t b constr' (precise || (not exact)) in
1084     if def && not (Types.subtype t b.br_accept)
1085 abate 969 then (require loc Sequence.nil_type constr'; Types.cup res Sequence.nil_type)
1086 abate 421 else res)
1087     t in
1088 abate 691 if exact then res else verify loc res constr
1089 abate 421
1090 abate 66 and type_let_decl env l =
1091     let acc = Types.descr (Patterns.accept l.let_pat) in
1092     let t = type_check env l.let_body acc true in
1093     let res = Patterns.filter t l.let_pat in
1094 abate 1433 IdMap.mapi_to_list (fun x t -> (x, Types.descr t)) res
1095 abate 66
1096     and type_rec_funs env l =
1097 abate 698 let typs =
1098 abate 66 List.fold_left
1099 abate 431 (fun accu -> function
1100 abate 656 | { exp_descr=Abstraction { fun_typ = t; fun_name = Some f };
1101     exp_loc=loc } ->
1102 abate 692 if not (value_name_ok f env) then
1103 abate 1753 error loc "This function name clashes with another kind of identifier";
1104 abate 698 (f,t)::accu
1105 abate 431 | _ -> assert false
1106     ) [] l
1107 abate 66 in
1108 abate 698 let env = enter_values typs env in
1109     List.iter (fun e -> ignore (type_check env e Types.any false)) l;
1110     typs
1111 abate 66
1112 abate 427 let rec unused_branches b =
1113 abate 314 List.iter
1114 abate 427 (fun (Branch (br,s)) ->
1115     if not br.br_used
1116     then warning br.br_loc "This branch is not used"
1117 abate 1433 else (
1118     if not (IdSet.is_empty br.br_vars_empty)
1119     then (
1120     let msg =
1121     try
1122     let l =
1123     List.map
1124     (fun x ->
1125     let x = Ident.to_string x in
1126 abate 1463 if (String.compare x "$$$" = 0) then raise Exit else x)
1127 abate 1433 (IdSet.get br.br_vars_empty) in
1128     let l = String.concat "," l in
1129     "The following variables always match the empty sequence: " ^
1130     l
1131     with Exit ->
1132     "This projection always returns the empty sequence"
1133     in
1134     warning br.br_loc msg
1135     );
1136     unused_branches s
1137     )
1138 abate 427 )
1139     b
1140 abate 314
1141 abate 427 let report_unused_branches () =
1142     unused_branches !cur_branch;
1143     cur_branch := []
1144 abate 637
1145     let clear_unused_branches () =
1146     cur_branch := []
1147 abate 427
1148 abate 698
1149    
1150     (* API *)
1151    
1152     let type_expr env e =
1153     clear_unused_branches ();
1154     let e = expr env e in
1155     let t = type_check env e Types.any true in
1156     report_unused_branches ();
1157     (e,t)
1158    
1159     let type_let_decl env p e =
1160     clear_unused_branches ();
1161     let decl = let_decl env p e in
1162     let typs = type_let_decl env decl in
1163     report_unused_branches ();
1164     let env = enter_values typs env in
1165     (env,decl,typs)
1166    
1167     let type_let_funs env funs =
1168     clear_unused_branches ();
1169 abate 1238 let rec id = function
1170     | Ast.LocatedExpr (_,e) -> id e
1171 abate 1495 | Ast.Abstraction a -> fun_name env a
1172 abate 1238 | _ -> assert false
1173     in
1174     let ids =
1175     List.fold_left (fun accu f -> match id f with Some x -> x::accu | None -> accu)
1176     [] funs in
1177     let env' = enter_values_dummy ids env in
1178     let funs = List.map (expr env') funs in
1179 abate 698 let typs = type_rec_funs env funs in
1180     report_unused_branches ();
1181     let env = enter_values typs env in
1182     (env,funs,typs)
1183    
1184 abate 1753 (*
1185 abate 1496 let find_cu x env =
1186     match find_cu noloc x env with
1187     | ECDuce cu -> cu
1188     | _ -> raise (Error ("Cannot find external unit " ^ (U.to_string x)))
1189 abate 1753 *)

CVS Admin">CVS Admin
ViewVC Help
Powered by ViewVC 1.1.5