cduce.ml 7.84 KB
Newer Older
1
open Location
2
open Ident
3

4
let quiet = ref false
5
let toplevel = ref false
6

7
let typing_env = State.ref "Cduce.typing_env" Builtin.env
8 9
let eval_env = State.ref "Cduce.eval_env" Env.empty

10
let enter_global_value x v t =
11
  eval_env := Env.add x v !eval_env;
12
  typing_env := Typer.enter_value x t !typing_env
13

14 15 16 17 18
let rec is_abstraction = function
  | Ast.Abstraction _ -> true
  | Ast.LocatedExpr (_,e) -> is_abstraction e
  | _ -> false

19
let print_norm ppf d = 
20
  Location.protect ppf 
21
    (fun ppf -> Types.Print.print ppf ((*Types.normalize*) d))
22

23 24 25 26
let print_sample ppf s =
  Location.protect ppf
    (fun ppf -> Sample.print ppf s)

27 28 29
let print_protect ppf s =
  Location.protect ppf (fun ppf -> Format.fprintf ppf "%s" s)

30 31
let print_value ppf v =
  Location.protect ppf (fun ppf -> Value.print ppf v)
32

33
let dump_env ppf =
34 35
  Format.fprintf ppf "Types:%a@." Typer.dump_types !typing_env;
  Format.fprintf ppf "Namespace prefixes:@\n%a" Typer.dump_ns !typing_env;
36
  Format.fprintf ppf "Namespace prefixes used for pretty-printing:@.%t"
37 38
    Ns.InternalPrinter.dump;
  Format.fprintf ppf "Values:@\n";
39
  Env.iter 
40
    (fun x v ->
41
       let t = Typer.find_value x !typing_env in
42 43
       Format.fprintf ppf "@[val %a : @[%a = %a@]@]@."
	 U.print (Id.value x) print_norm t print_value v
44
    )
45
    !eval_env
46

47
let rec print_exn ppf = function
48 49
  | Location (loc, w, exn) ->
      Format.fprintf ppf "Error %a:@." Location.print_loc (loc,w);
50
      Format.fprintf ppf "%a" Location.html_hilight (loc,w); 
51
      print_exn ppf exn
52
  | Value.CDuceExn v ->
53
      Format.fprintf ppf "Uncaught CDuce exception: @[%a@]@."
54
        print_value v
55
  | Eval.MultipleDeclaration v ->
56
      Format.fprintf ppf "Multiple declaration for global value %a@." 
57
        U.print (Id.value v)
58
  | Typer.WrongLabel (t,l) ->
59
      Format.fprintf ppf "Wrong record selection; field %a " 
60
        Label.print (LabelPool.value l);
61
      Format.fprintf ppf "not present in an expression of type:@.%a@."
62
        print_norm t
63
  | Typer.ShouldHave (t,msg) ->
64
      Format.fprintf ppf "This expression should have type:@.%a@.%a@." 
65
        print_norm t
66
        print_protect msg
67
  | Typer.ShouldHave2 (t1,msg,t2) ->
68
      Format.fprintf ppf "This expression should have type:@.%a@.%a %a@." 
69
        print_norm t1
70
        print_protect msg
71
        print_norm t2
72
  | Typer.Error s ->
73
      Format.fprintf ppf "%a@." print_protect s
74
  | Typer.Constraint (s,t) ->
75
      Format.fprintf ppf "This expression should have type:@.%a@." 
76
        print_norm t;
77
      Format.fprintf ppf "but its inferred type is:@.%a@." 
78
        print_norm s;
79
      Format.fprintf ppf "which is not a subtype, as shown by the sample:@.%a@." 
80
	print_sample (Sample.get (Types.diff s t))
81
  | Typer.NonExhaustive t ->
82 83
      Format.fprintf ppf "This pattern matching is not exhaustive@.";
      Format.fprintf ppf "Residual type:@.%a@."
84
	print_norm t;
85
      Format.fprintf ppf "Sample:@.%a@." print_sample (Sample.get t)
86 87 88
  | Typer.UnboundId (x,tn) ->
      Format.fprintf ppf "Unbound identifier %a%s@." U.print (Id.value x)
        (if tn then " (it is a type name)" else "")
89 90 91 92
  | Ulexer.Error (i,j,s) ->
      let loc = Location.loc_of_pos (i,j), `Full in
      Format.fprintf ppf "Error %a:@." Location.print_loc loc;
      Format.fprintf ppf "%a%s" Location.html_hilight loc s
93
  | Parser.Error s | Stream.Error s -> 
94
      Format.fprintf ppf "Parsing error: %a@." print_protect s
95
  | Location.Generic s ->
96
      Format.fprintf ppf "%a@." print_protect s
97
  | exn ->
98
(*      raise exn *)
99
      Format.fprintf ppf "%a@." print_protect (Printexc.to_string exn)
100

101
let debug ppf = function
102
  | `Subtype (t1,t2) ->
103
      Format.fprintf ppf "[DEBUG:subtype]@.";
104 105
      let t1 = Types.descr (Typer.typ !typing_env t1)
      and t2 = Types.descr (Typer.typ !typing_env t2) in
106 107
      let s = Types.subtype t1 t2 in
      Format.fprintf ppf "%a %a %a : %b@." print_norm t1 print_protect "<=" print_norm t2 s
108
  | `Sample t ->
109 110
      Format.fprintf ppf "[DEBUG:sample]@.";
      (try
111
	 let t = Types.descr (Typer.typ !typing_env t) in
112 113 114
	 Format.fprintf ppf "%a@." print_sample (Sample.get t)
       with Not_found ->
	 Format.fprintf ppf "Empty type : no sample !@.")
115
  | `Filter (t,p) -> 
116
      Format.fprintf ppf "[DEBUG:filter]@.";
117 118
      let t = Typer.typ !typing_env t
      and p = Typer.pat !typing_env p in
119 120
      let f = Patterns.filter (Types.descr t) p in
      List.iter (fun (x,t) ->
121
		   Format.fprintf ppf " %a:%a@." U.print (Id.value x)
122 123
		     print_norm (Types.descr t)) f
  | `Accept p ->
124
      Format.fprintf ppf "[DEBUG:accept]@.";
125
      let p = Typer.pat !typing_env p in
126
      let t = Patterns.accept p in
127
      Format.fprintf ppf " %a@." Types.Print.print (Types.descr t)
128
  | `Compile (t,pl) ->
129
      Format.fprintf ppf "[DEBUG:compile]@.";
130 131
      let t = Typer.typ !typing_env t
      and pl = List.map (Typer.pat !typing_env) pl in
132
      Patterns.Compile.debug_compile ppf t pl
133

134 135 136 137
let insert_bindings ppf =
  List.iter2 
    (fun (x,t) (y,v) ->
       assert (x = y);
138
       typing_env := Typer.enter_value x t !typing_env;
139 140
       eval_env := Env.add x v !eval_env;
       if not !quiet then
141
	 Format.fprintf ppf "val %a : @[@[%a@] =@ @[%a@]@]@." 
142
	   U.print (Id.value x) print_norm t print_value v)
143
  
144 145
let rec collect_funs ppf accu = function
  | { descr = Ast.FunDecl e } :: rest -> 
146
      let (_,e) = Typer.expr !typing_env e in
147 148
      collect_funs ppf (e::accu) rest
  | rest ->
149
      let typs = Typer.type_rec_funs !typing_env accu in
150
      Typer.report_unused_branches ();
151 152
      let vals = Eval.eval_rec_funs !eval_env accu in
      insert_bindings ppf typs vals;
153 154 155 156 157 158
      rest

let rec collect_types ppf accu = function
  | { descr = Ast.TypeDecl (x,t) } :: rest -> 
      collect_types ppf ((x,t) :: accu) rest
  | rest ->
159 160
      typing_env := 
        Typer.enter_types (Typer.type_defs !typing_env accu) !typing_env;
161 162 163 164 165 166 167
      rest

let rec phrases ppf phs = match phs with
  | { descr = Ast.FunDecl _ } :: _ -> 
      phrases ppf (collect_funs ppf [] phs)
  | { descr = Ast.TypeDecl (_,_) } :: _ ->
      phrases ppf (collect_types ppf [] phs)
168 169 170
  | { descr = Ast.SchemaDecl (name, schema) } :: rest ->
      Typer.register_schema name schema;
      phrases ppf rest
171
  | { descr = Ast.Namespace (pr,ns) } :: rest ->
172
      typing_env := Typer.enter_ns pr ns !typing_env;
173
      phrases ppf rest
174
  | { descr = Ast.EvalStatement e } :: rest ->
175
      let (fv,e) = Typer.expr !typing_env e in
176 177 178
      let t = Typer.type_check !typing_env e Types.any true in
      Typer.report_unused_branches ();
      if not !quiet then
179
	Location.dump_loc ppf (e.Typed.exp_loc,`Full);
180 181
      let v = Eval.eval !eval_env e in
      if not !quiet then
182
	Format.fprintf ppf "- : @[@[%a@] =@ @[%a@]@]@." print_norm t print_value v;
183 184
      phrases ppf rest
  | { descr = Ast.LetDecl (p,e) } :: rest ->
185
      let decl = Typer.let_decl !typing_env p e in
186
      let typs = Typer.type_let_decl !typing_env decl in
187
      Typer.report_unused_branches ();
188 189
      let vals = Eval.eval_let_decl !eval_env decl in
      insert_bindings ppf typs vals;
190 191
      phrases ppf rest
  | { descr = Ast.Debug l } :: rest -> 
192
      debug ppf l; 
193
      phrases ppf rest
194 195 196 197 198 199
  | { descr = Ast.Directive `Quit } :: rest ->
      if !toplevel then raise End_of_file;
      phrases ppf rest
  | { descr = Ast.Directive `Env } :: rest ->
      dump_env ppf;
      phrases ppf rest
200
  | { descr = Ast.Directive `Reinit_ns } :: rest ->
201
      Typer.set_ns_table_for_printer !typing_env;
202
      phrases ppf rest
203 204 205
  | [] -> ()

let run rule ppf ppf_err input =
206
  Typer.clear_unused_branches ();
207
  try 
208
    let p = 
209
      try rule input
210
      with
211
	| Stdpp.Exc_located (_, (Location _ as e)) ->
212
	    Parser.sync (); raise e
213
	| Stdpp.Exc_located ((i,j), e) -> 
214
	    Parser.sync (); raise_loc i j e
215
    in
216
    phrases ppf p;
217
    true
218
  with 
219 220 221
    | (End_of_file | Failure _ | Not_found | Invalid_argument _ | Sys.Break) 
	as e -> 
	raise e
222 223 224 225
    | exn -> 
	print_exn ppf_err exn;
	Format.fprintf ppf_err "@.";
	false
226

227
let script = run Parser.prog
228
let topinput = run Parser.top_phrases