cduce.ml 6.74 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 enter_global_value x v t =
  Eval.enter_global x v;
10
  typing_env := Env.add x t !typing_env
11

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

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

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


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

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

44
let rec print_exn ppf = function
45
  | Location (loc, exn) ->
46
      Format.fprintf ppf "Error %a:@\n" Location.print_loc loc;
47
      Format.fprintf ppf "%a" Location.html_hilight loc;
48
      print_exn ppf exn
49 50
  | Value.CDuceExn v ->
      Format.fprintf ppf "Uncaught CDuce exception: @[%a@]@\n"
51
        print_value v
52
  | Eval.MultipleDeclaration v ->
53 54
      Format.fprintf ppf "Multiple declaration for global value %a@\n" 
        U.print (Id.value v)
55
  | Typer.WrongLabel (t,l) ->
56 57
      Format.fprintf ppf "Wrong record selection: the label %a@\n" 
        U.print (LabelPool.value l);
58
      Format.fprintf ppf "applied to an expression of type:@\n%a@\n"
59
        print_norm t
60
  | Typer.ShouldHave (t,msg) ->
61
      Format.fprintf ppf "This expression should have type:@\n%a@\n%s@\n" 
62
        print_norm t
63
        msg
64
  | Typer.ShouldHave2 (t1,msg,t2) ->
65
      Format.fprintf ppf "This expression should have type:@\n%a@\n%s %a@\n" 
66 67 68
        print_norm t1
        msg
        print_norm t2
69 70 71
  | Typer.Error s ->
      Format.fprintf ppf "%s@\n" s
  | Typer.Constraint (s,t) ->
72
      Format.fprintf ppf "This expression should have type:@\n%a@\n" 
73
        print_norm t;
74
      Format.fprintf ppf "but its inferred type is:@\n%a@\n" 
75
        print_norm s;
76 77
      Format.fprintf ppf "which is not a subtype, as shown by the sample:@\n%a@\n" 
	print_sample (Sample.get (Types.diff s t))
78 79
  | Typer.NonExhaustive t ->
      Format.fprintf ppf "This pattern matching is not exhaustive@\n";
80
      Format.fprintf ppf "Residual type:@\n%a@\n"
81
	print_norm t;
82
      Format.fprintf ppf "Sample:@\n%a@\n" print_sample (Sample.get t)
83
  | Typer.UnboundId x ->
84
      Format.fprintf ppf "Unbound identifier %a@\n" U.print (Id.value x)
85 86 87 88 89 90 91 92
  | Wlexer.Illegal_character c ->
      Format.fprintf ppf "Illegal character (%s)@\n" (Char.escaped c)
  | Wlexer.Unterminated_comment ->
      Format.fprintf ppf "Comment not terminated@\n"
  | Wlexer.Unterminated_string ->
      Format.fprintf ppf "String literal not terminated@\n"
  | Wlexer.Unterminated_string_in_comment ->
      Format.fprintf ppf "This comment contains an unterminated string literal@\n"
93
  | Parser.Error s | Stream.Error s -> 
94
      Format.fprintf ppf "Parsing error: %s@\n" s
95 96
  | Location.Generic s ->
      Format.fprintf ppf "%s@\n" s
97
  | exn ->
98
(*      raise exn *)
99 100
      Format.fprintf ppf "%s@\n" (Printexc.to_string exn)

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


132

133 134


135
let run ppf ppf_err input =
136 137
  let insert_type_bindings = 
    List.iter (fun (x,t) ->
138
		 typing_env := Env.add x t !typing_env;
139
		 if not !quiet then
140
		   Format.fprintf ppf "|- %a : %a@\n@." U.print (Id.value x) print_norm t) 
141 142 143
  in
  
  let type_decl decl =
144 145
    insert_type_bindings (Typer.type_let_decl !typing_env decl);
    Typer.report_unused_branches ()
146 147 148
  in

  let eval_decl decl =
149
    let bindings = Eval.eval_let_decl Env.empty decl in
150 151 152
    List.iter 
      (fun (x,v) ->
	 Eval.enter_global x v;
153
	 if not !quiet then
154
	   Format.fprintf ppf "=> %a : @[%a@]@\n@." U.print (Id.value x) print_value v
155 156 157
      ) bindings
  in

158
  let phrase ph = 
159 160
    match ph.descr with
      | Ast.EvalStatement e ->
161
	  let (fv,e) = Typer.expr e in
162
	  let t = Typer.type_check !typing_env e Types.any true in
163
	  Typer.report_unused_branches ();
164
	  Location.dump_loc ppf e.Typed.exp_loc;
165 166
	  if not !quiet then
	    Format.fprintf ppf "|- %a@\n@." print_norm t;
167
	  let v = Eval.eval Env.empty e in
168 169
	  if not !quiet then
	    Format.fprintf ppf "=> @[%a@]@\n@." print_value v
170
      | Ast.LetDecl (p,e) when is_abstraction e -> ()
171
      | Ast.LetDecl (p,e) ->
172
	  let decl = Typer.let_decl p e in
173
	  type_decl decl;
174
	  Typer.report_unused_branches ();
175 176 177 178 179 180 181
	  eval_decl decl
      | Ast.TypeDecl _ -> ()
      | Ast.Debug l -> debug ppf l
      | _ -> assert false
  in

  let do_fun_decls decls =
182
    let decls = List.map (fun (p,e) -> Typer.let_decl p e) decls in
183
    insert_type_bindings (Typer.type_rec_funs !typing_env decls);
184
    Typer.report_unused_branches ();
185 186
    List.iter eval_decl decls
  in
187
  let rec phrases funs = function
188
    | { descr = Ast.LetDecl (p,e) } :: phs when is_abstraction e -> 
189 190 191 192 193 194 195 196
	phrases ((p,e)::funs) phs
    | ph :: phs ->
	do_fun_decls funs;
	phrase ph;
	phrases [] phs
    | _ ->
	do_fun_decls funs
  in
197
  try 
198 199 200 201
    let p = 
      try Parser.prog input
      with
	| Stdpp.Exc_located (_, (Location _ as e)) -> raise e
202
	| Stdpp.Exc_located ((i,j), e) -> raise_loc i j e
203
    in
204
    let (type_decls,fun_decls) = 
205
      List.fold_left
206 207
	(fun ((typs,funs) as accu) ph -> match ph.descr with
	   | Ast.TypeDecl (x,t) -> ((x,t) :: typs,funs)
208
	   | Ast.LetDecl (p,e) when is_abstraction e -> 
209
	       (typs, (p,e)::funs)
210
	   | _ -> accu
211
	) ([],[]) p in
212
    Typer.register_global_types type_decls;
213
    phrases [] p;
214
    true
215
  with 
216
    | (Failure _ | Not_found | Invalid_argument _) as e -> 
217
	raise e  (* To get ocamlrun stack trace *)
218
    | exn -> print_exn ppf_err exn; false
219
	
220