open Location exception Usage let () = List.iter (fun (n,t) -> Typer.register_global_types [n, mk noloc (Ast.Internal t)]) Builtin.types let (source,input_channel) = match Array.length Sys.argv with | 1 -> ("",stdin) | 2 -> let s = Sys.argv.(1) in (s, open_in s) | _ -> raise Usage let () = Location.set_source source let input = Stream.of_channel input_channel let ppf = Format.std_formatter let prog () = try Parser.prog input with | Stdpp.Exc_located (loc, e) -> raise (Location (loc, e)) let print_norm ppf d = Types.Print.print_descr ppf ((*Types.normalize*) d) let rec print_exn ppf = function | Location (loc, exn) -> Format.fprintf ppf "Error %a:@\n%a" Location.print_loc loc print_exn exn | Value.CDuceExn v -> Format.fprintf ppf "Uncaught CDuce exception: @[%a@]@\n" Value.print v | Typer.WrongLabel (t,l) -> Format.fprintf ppf "Wrong record selection: the label %s@\n" (Types.label_name l); Format.fprintf ppf "applied to an expression of type %a@\n" print_norm t | Typer.MultipleLabel l -> Format.fprintf ppf "Multiple occurences for the record label %s@\n" (Types.label_name l); | Typer.ShouldHave (t,msg) -> Format.fprintf ppf "This expression should have type %a@\n%s@\n" print_norm t msg | Typer.Constraint (s,t,msg) -> Format.fprintf ppf "This expression should have type %a@\n" print_norm t; Format.fprintf ppf "but its infered type is: %a@\n" print_norm s; Format.fprintf ppf "which is not a subtype, as shown by the value %a@\n" Types.Sample.print (Types.Sample.get (Types.diff s t)); Format.fprintf ppf "%s@\n" msg | Typer.NonExhaustive t -> Format.fprintf ppf "This pattern matching is not exhaustive@\n"; Format.fprintf ppf "Residual type: %a@\n" print_norm t; Format.fprintf ppf "Sample value: %a@\n" Types.Sample.print (Types.Sample.get t) | Typer.UnboundId x -> Format.fprintf ppf "Unbound identifier %s@\n" x | exn -> Format.fprintf ppf "%s@\n" (Printexc.to_string exn) let debug = function | `Filter (t,p) -> Format.fprintf ppf "[DEBUG:filter]@\n"; 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 " x:%a@\n" print_norm (Types.descr t)) f | `Accept p -> Format.fprintf ppf "[DEBUG:accept]@\n"; let p = Typer.pat p in let t = Patterns.accept p in Format.fprintf ppf " %a@\n" Types.Print.print t | `Compile (t,pl) -> Format.fprintf ppf "[DEBUG:compile]@\n"; let t = Typer.typ t and pl = List.map Typer.pat pl in let pl = Array.of_list (List.map (fun p -> Patterns.Compile.normal (Patterns.descr p)) pl) in Patterns.Compile.show ppf (Types.descr t) pl | _ -> Format.fprintf ppf "Unknown or ill-formed debugging directive !! @\n" let typing_env = ref Typer.Env.empty let eval_env = ref Eval.Env.empty let insert_type_bindings = List.iter (fun (x,t) -> typing_env := Typer.Env.add x t !typing_env; Format.fprintf ppf "|- %s : %a@\n@." x print_norm t) let type_decl decl = insert_type_bindings (Typer.type_let_decl !typing_env decl) let eval_decl decl = let bindings = Eval.eval_let_decl !eval_env decl in List.iter (fun (x,v) -> Eval.enter_global x v; Format.fprintf ppf "=> %s : @[%a@]@\n@." x Value.print v ) bindings let phrase ph = match ph.descr with | Ast.EvalStatement e -> let (fv,e) = Typer.expr e in let t = Typer.type_check !typing_env e Types.any true in Format.fprintf ppf "|- %a@\n@." print_norm t; let v = Eval.eval !eval_env e in Format.fprintf ppf "=> @[%a@]@\n@." Value.print v | Ast.LetDecl (p,{descr=Ast.Abstraction _}) -> () | Ast.LetDecl (p,e) -> let decl = Typer.let_decl p e in type_decl decl; eval_decl decl | Ast.TypeDecl _ -> () | Ast.Debug l -> debug l | _ -> assert false let do_fun_decls decls = let decls = List.map (fun (p,e) -> Typer.let_decl p e) decls in insert_type_bindings (Typer.type_rec_funs !typing_env decls); List.iter eval_decl decls let () = try let p = prog () in let (type_decls,fun_decls) = List.fold_left (fun ((typs,funs) as accu) ph -> match ph.descr with | Ast.TypeDecl (x,t) -> ((x,t) :: typs,funs) | Ast.LetDecl (p,({descr=Ast.Abstraction _} as e)) -> (typs, (p,e)::funs) | _ -> accu ) ([],[]) p in Typer.register_global_types type_decls; do_fun_decls fun_decls; List.iter phrase p with | (Failure _ | Not_found | Invalid_argument _) as e -> raise e (* To get the ocamlrun stack trace *) | exn -> print_exn ppf exn