open Location open Ident let quiet = ref false let toplevel = ref false let typing_env = State.ref "Cduce.typing_env" Env.empty let eval_env = State.ref "Cduce.eval_env" Env.empty let enter_global_value x v t = eval_env := Env.add x v !eval_env; typing_env := Env.add x t !typing_env let rec is_abstraction = function | Ast.Abstraction _ -> true | Ast.LocatedExpr (_,e) -> is_abstraction e | _ -> false let print_norm ppf d = Location.protect ppf (fun ppf -> Types.Print.print ppf ((*Types.normalize*) d)) let print_sample ppf s = Location.protect ppf (fun ppf -> Sample.print ppf s) let print_value ppf v = Location.protect ppf (fun ppf -> Value.print ppf v) let dump_env ppf = Format.fprintf ppf "Global types:"; Typer.dump_global_types ppf; Format.fprintf ppf ".@."; Env.iter (fun x v -> let t = Env.find x !typing_env in Format.fprintf ppf "@[val %a : @[%a = %a@]@]@." U.print (Id.value x) print_norm t print_value v ) !eval_env; Format.fprintf ppf "Namespaces:@."; Atoms.Ns.dump_prefix_table ppf let rec print_exn ppf = function | Location (loc, w, exn) -> Format.fprintf ppf "Error %a:@." Location.print_loc (loc,w); Format.fprintf ppf "%a" Location.html_hilight (loc,w); print_exn ppf exn | Value.CDuceExn v -> Format.fprintf ppf "Uncaught CDuce exception: @[%a@]@." print_value v | Eval.MultipleDeclaration v -> Format.fprintf ppf "Multiple declaration for global value %a@." U.print (Id.value v) | Typer.WrongLabel (t,l) -> Format.fprintf ppf "Wrong record selection; field %a " U.print (LabelPool.value l); Format.fprintf ppf "not present in an expression of type:@.%a@." print_norm t | Typer.ShouldHave (t,msg) -> Format.fprintf ppf "This expression should have type:@.%a@.%s@." print_norm t msg | Typer.ShouldHave2 (t1,msg,t2) -> Format.fprintf ppf "This expression should have type:@.%a@.%s %a@." print_norm t1 msg print_norm t2 | Typer.Error s -> Format.fprintf ppf "%s@." s | Typer.Constraint (s,t) -> Format.fprintf ppf "This expression should have type:@.%a@." print_norm t; Format.fprintf ppf "but its inferred type is:@.%a@." print_norm s; Format.fprintf ppf "which is not a subtype, as shown by the sample:@.%a@." print_sample (Sample.get (Types.diff s t)) | Typer.NonExhaustive t -> Format.fprintf ppf "This pattern matching is not exhaustive@."; Format.fprintf ppf "Residual type:@.%a@." print_norm t; Format.fprintf ppf "Sample:@.%a@." print_sample (Sample.get t) | Typer.UnboundId x -> Format.fprintf ppf "Unbound identifier %a@." U.print (Id.value x) | Wlexer.Illegal_character c -> Format.fprintf ppf "Illegal character (%s)@." (Char.escaped c) | Wlexer.Unterminated_comment -> Format.fprintf ppf "Comment not terminated@." | Wlexer.Unterminated_string -> Format.fprintf ppf "String literal not terminated@." | Wlexer.Unterminated_string_in_comment -> Format.fprintf ppf "This comment contains an unterminated string literal@." | Parser.Error s | Stream.Error s -> Format.fprintf ppf "Parsing error: %s@." s | Location.Generic s -> Format.fprintf ppf "%s@." s | exn -> (* raise exn *) Format.fprintf ppf "%s@." (Printexc.to_string exn) let debug ppf = function | `Subtype (t1,t2) -> Format.fprintf ppf "[DEBUG:subtype]@."; let t1 = Types.descr (Typer.typ t1) and t2 = Types.descr (Typer.typ t2) in Format.fprintf ppf "%a <= %a : %b@." print_norm t1 print_norm t2 (Types.subtype t1 t2) | `Sample t -> 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 !@.") | `Filter (t,p) -> Format.fprintf ppf "[DEBUG:filter]@."; let t = Typer.typ t and p = Typer.pat p in let f = Patterns.filter (Types.descr t) p in List.iter (fun (x,t) -> Format.fprintf ppf " %a:%a@." U.print (Id.value x) print_norm (Types.descr t)) f | `Accept p -> Format.fprintf ppf "[DEBUG:accept]@."; let p = Typer.pat p in let t = Patterns.accept p in Format.fprintf ppf " %a@." Types.Print.print (Types.descr t) | `Compile (t,pl) -> Format.fprintf ppf "[DEBUG:compile]@."; let t = Typer.typ t and pl = List.map Typer.pat pl in Patterns.Compile.debug_compile ppf t pl let insert_bindings ppf = List.iter2 (fun (x,t) (y,v) -> assert (x = y); typing_env := Env.add x t !typing_env; eval_env := Env.add x v !eval_env; if not !quiet then Format.fprintf ppf "val %a : @[@[%a@] =@ @[%a@]@]@." U.print (Id.value x) print_norm t print_value v) 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 -> let typs = Typer.type_rec_funs !typing_env accu in Typer.report_unused_branches (); let vals = Eval.eval_rec_funs !eval_env accu in insert_bindings ppf typs vals; 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.SchemaDecl (name, schema) } :: rest -> Typer.register_schema name schema; phrases ppf rest | { descr = Ast.Namespace (pr,ns) } :: rest -> Typer.register_ns_prefix pr ns; phrases ppf rest | { 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,`Full); let v = Eval.eval !eval_env e in if not !quiet then Format.fprintf ppf "- : @[@[%a@] =@ @[%a@]@]@." print_norm t print_value v; phrases ppf rest | { descr = Ast.LetDecl (p,e) } :: rest -> let decl = Typer.let_decl p e in let typs = Typer.type_let_decl !typing_env decl in Typer.report_unused_branches (); let vals = Eval.eval_let_decl !eval_env decl in insert_bindings ppf typs vals; phrases ppf rest | { descr = Ast.Debug l } :: rest -> debug ppf l; phrases ppf rest | { 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 | [] -> () let run rule ppf ppf_err input = try let p = try rule input with | Stdpp.Exc_located (_, (Location _ as e)) -> Parser.sync (); raise e | Stdpp.Exc_located ((i,j), e) -> Parser.sync (); raise_loc i j e in phrases ppf p; true with | (End_of_file | Failure _ | Not_found | Invalid_argument _ | Sys.Break) as e -> raise e | exn -> print_exn ppf_err exn; Format.fprintf ppf_err "@."; false let script = run Parser.prog let topinput = run Parser.top_phrases