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

4
5
let quiet = ref false

6
let typing_env = State.ref "Cduce.typing_env" Env.empty
7

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 := Env.add 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
27
let print_sample ppf s =
  Location.protect ppf
    (fun ppf -> Sample.print ppf s)


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

31
let dump_env ppf =
32
33
  Format.fprintf ppf "Global types:";
  Typer.dump_global_types ppf;
34
  Format.fprintf ppf ".@.";
35
  Env.iter 
36
    (fun x v ->
37
       let t = Env.find x !typing_env in
38
39
       Format.fprintf ppf "@[val %a : @[%a = %a@]@]@."
	 U.print (Id.value x) print_norm t print_value v
40
    )
41
    !eval_env
42
43
  

44
let rec print_exn ppf = function
45
  | Location (loc, exn) ->
46
      Format.fprintf ppf "Error %a:@." Location.print_loc loc;
47
      Format.fprintf ppf "%a" Location.html_hilight loc;
48
      print_exn ppf exn
49
  | Value.CDuceExn v ->
50
      Format.fprintf ppf "Uncaught CDuce exception: @[%a@]@."
51
        print_value v
52
  | Eval.MultipleDeclaration v ->
53
      Format.fprintf ppf "Multiple declaration for global value %a@." 
54
        U.print (Id.value v)
55
  | Typer.WrongLabel (t,l) ->
56
      Format.fprintf ppf "Wrong record selection: the label %a@." 
57
        U.print (LabelPool.value l);
58
      Format.fprintf ppf "applied to an expression of type:@.%a@."
59
        print_norm t
60
  | Typer.ShouldHave (t,msg) ->
61
      Format.fprintf ppf "This expression should have type:@.%a@.%s@." 
62
        print_norm t
63
        msg
64
  | Typer.ShouldHave2 (t1,msg,t2) ->
65
      Format.fprintf ppf "This expression should have type:@.%a@.%s %a@." 
66
67
68
        print_norm t1
        msg
        print_norm t2
69
  | Typer.Error s ->
70
      Format.fprintf ppf "%s@." s
71
  | Typer.Constraint (s,t) ->
72
      Format.fprintf ppf "This expression should have type:@.%a@." 
73
        print_norm t;
74
      Format.fprintf ppf "but its inferred type is:@.%a@." 
75
        print_norm s;
76
      Format.fprintf ppf "which is not a subtype, as shown by the sample:@.%a@." 
77
	print_sample (Sample.get (Types.diff s t))
78
  | Typer.NonExhaustive t ->
79
80
      Format.fprintf ppf "This pattern matching is not exhaustive@.";
      Format.fprintf ppf "Residual type:@.%a@."
81
	print_norm t;
82
      Format.fprintf ppf "Sample:@.%a@." print_sample (Sample.get t)
83
  | Typer.UnboundId x ->
84
      Format.fprintf ppf "Unbound identifier %a@." U.print (Id.value x)
85
  | Wlexer.Illegal_character c ->
86
      Format.fprintf ppf "Illegal character (%s)@." (Char.escaped c)
87
  | Wlexer.Unterminated_comment ->
88
      Format.fprintf ppf "Comment not terminated@."
89
  | Wlexer.Unterminated_string ->
90
      Format.fprintf ppf "String literal not terminated@."
91
  | Wlexer.Unterminated_string_in_comment ->
92
      Format.fprintf ppf "This comment contains an unterminated string literal@."
93
  | Parser.Error s | Stream.Error s -> 
94
      Format.fprintf ppf "Parsing error: %s@." s
95
  | Location.Generic s ->
96
      Format.fprintf ppf "%s@." s
97
  | exn ->
98
(*      raise exn *)
99
      Format.fprintf ppf "%s@." (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 t1)
      and t2 = Types.descr (Typer.typ t2) in
106
      Format.fprintf ppf "%a <= %a : %b@." print_norm t1 print_norm t2
107
	(Types.subtype t1 t2)
108
  | `Sample t ->
109
110
111
112
113
114
      Format.fprintf ppf "[DEBUG:sample]@.";
      (try
	 let t = Types.descr (Typer.typ t) in
	 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 t
      and p = Typer.pat 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 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 t
      and pl = List.map Typer.pat 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
139
140
       typing_env := Env.add x t !typing_env;
       eval_env := Env.add x v !eval_env;
       if not !quiet then
141
142
	 Format.fprintf ppf "val %a : @[%a@] = @[%a@]@." 
	   U.print (Id.value x) print_norm t print_value v)
143
  
144
145
146
147
148
let rec collect_funs ppf accu = function
  | { descr = Ast.FunDecl e } :: rest -> 
      let (_,e) = Typer.expr e in
      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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
      rest

let rec collect_types ppf accu = function
  | { descr = Ast.TypeDecl (x,t) } :: rest -> 
      collect_types ppf ((x,t) :: accu) rest
  | rest ->
      Typer.register_global_types accu;
      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)
  | { descr = Ast.EvalStatement e } :: rest ->
      let (fv,e) = Typer.expr e in
      let t = Typer.type_check !typing_env e Types.any true in
      Typer.report_unused_branches ();
      if not !quiet then
	Location.dump_loc ppf e.Typed.exp_loc;
      let v = Eval.eval !eval_env e in
      if not !quiet then
175
	Format.fprintf ppf "- : @[%a@] = @[%a@]@." print_norm t print_value v;
176
177
178
      phrases ppf rest
  | { descr = Ast.LetDecl (p,e) } :: rest ->
      let decl = Typer.let_decl p e in
179
      let typs = Typer.type_let_decl !typing_env decl in
180
      Typer.report_unused_branches ();
181
182
      let vals = Eval.eval_let_decl !eval_env decl in
      insert_bindings ppf typs vals;
183
184
185
186
187
188
189
      phrases ppf rest
  | { descr = Ast.Debug l } :: rest -> 
      debug ppf l;
      phrases ppf rest
  | [] -> ()

let run rule ppf ppf_err input =
190
  try 
191
    let p = 
192
      try rule input
193
      with
194
195
196
197
	| Stdpp.Exc_located (_, (Location _ as e)) ->
	    Parser.sync input; raise e
	| Stdpp.Exc_located ((i,j), e) -> 
	    Parser.sync input; raise_loc i j e
198
    in
199
    phrases ppf p;
200
    true
201
  with 
202
    | (End_of_file | Failure _ | Not_found | Invalid_argument _) as e -> 
203
	raise e  (* To get ocamlrun stack trace *)
204
205
206
207
    | exn -> 
	print_exn ppf_err exn;
	Format.fprintf ppf_err "@.";
	false
208

209
210
let script = run Parser.prog
let toplevel = run Parser.top_phrases