|
@@ -32,6 +32,8 @@ type ctx = {
|
|
mutable tabs : string;
|
|
mutable tabs : string;
|
|
mutable separator : bool;
|
|
mutable separator : bool;
|
|
dirs : (string list, bool) Hashtbl.t;
|
|
dirs : (string list, bool) Hashtbl.t;
|
|
|
|
+ mutable vars : (int, bool) Hashtbl.t;
|
|
|
|
+ mutable current_module : path;
|
|
}
|
|
}
|
|
|
|
|
|
type ml_type =
|
|
type ml_type =
|
|
@@ -76,7 +78,8 @@ let begin_module ctx (path,name) =
|
|
Hashtbl.add ctx.dirs path true;
|
|
Hashtbl.add ctx.dirs path true;
|
|
end;
|
|
end;
|
|
let file = ctx.com.file ^ (match path with [] -> "" | _ -> "/" ^ String.concat "/" path) ^ "/" ^ name ^ ".ml" in
|
|
let file = ctx.com.file ^ (match path with [] -> "" | _ -> "/" ^ String.concat "/" path) ^ "/" ^ name ^ ".ml" in
|
|
- ctx.ch <- open_out_bin file
|
|
|
|
|
|
+ ctx.ch <- open_out_bin file;
|
|
|
|
+ ctx.current_module <- (path,name)
|
|
|
|
|
|
let flush ctx =
|
|
let flush ctx =
|
|
Rbuffer.output_buffer ctx.ch ctx.buf;
|
|
Rbuffer.output_buffer ctx.ch ctx.buf;
|
|
@@ -110,6 +113,10 @@ let rec to_type ctx t p =
|
|
MInst c.cl_path
|
|
MInst c.cl_path
|
|
| TInst (c,pl) ->
|
|
| TInst (c,pl) ->
|
|
MParams (MInst c.cl_path, List.map (fun t -> to_type ctx t p) pl)
|
|
MParams (MInst c.cl_path, List.map (fun t -> to_type ctx t p) pl)
|
|
|
|
+ | TEnum (e,[]) ->
|
|
|
|
+ MInst e.e_path
|
|
|
|
+ | TEnum (e,pl) ->
|
|
|
|
+ MParams (MInst e.e_path, List.map (fun t -> to_type ctx t p) pl)
|
|
| TAbstract (a,pl) ->
|
|
| TAbstract (a,pl) ->
|
|
if Meta.has Meta.CoreType a.a_meta then
|
|
if Meta.has Meta.CoreType a.a_meta then
|
|
(match a.a_path with
|
|
(match a.a_path with
|
|
@@ -125,7 +132,10 @@ let rec to_type ctx t p =
|
|
|
|
|
|
|
|
|
|
let module_path ctx path =
|
|
let module_path ctx path =
|
|
- snd path
|
|
|
|
|
|
+ if path = ctx.current_module then
|
|
|
|
+ ""
|
|
|
|
+ else
|
|
|
|
+ snd path ^ "."
|
|
|
|
|
|
let rec type_str ctx = function
|
|
let rec type_str ctx = function
|
|
| MUnit -> "unit"
|
|
| MUnit -> "unit"
|
|
@@ -135,14 +145,44 @@ let rec type_str ctx = function
|
|
| MString -> "string"
|
|
| MString -> "string"
|
|
| MOption t -> type_str ctx t ^ " option"
|
|
| MOption t -> type_str ctx t ^ " option"
|
|
| MFun tl -> String.concat " -> " (List.map (type_str ctx) tl)
|
|
| MFun tl -> String.concat " -> " (List.map (type_str ctx) tl)
|
|
- | MInst path -> module_path ctx path ^ ".t"
|
|
|
|
|
|
+ | MInst path -> module_path ctx path ^ "t"
|
|
| MParams (t,[]) -> type_str ctx t
|
|
| MParams (t,[]) -> type_str ctx t
|
|
| MParams (t,[p]) -> type_str ctx p ^ " " ^ type_str ctx p
|
|
| MParams (t,[p]) -> type_str ctx p ^ " " ^ type_str ctx p
|
|
- | MParams (t,pl) -> "(" ^ String.concat " * " (List.map (type_str ctx) pl) ^ ") " ^ type_str ctx t
|
|
|
|
|
|
+ | MParams (t,pl) -> "(" ^ String.concat ", " (List.map (type_str ctx) pl) ^ ") " ^ type_str ctx t
|
|
|
|
+
|
|
|
|
+let rec def_value ctx = function
|
|
|
|
+ | MUnit -> "()"
|
|
|
|
+ | MInt -> "0"
|
|
|
|
+ | MFloat -> "0."
|
|
|
|
+ | MBool -> "false"
|
|
|
|
+ | MString -> "\"\""
|
|
|
|
+ | MOption t -> "None"
|
|
|
|
+ | MFun tl -> "(fun " ^ String.concat " " (List.map (fun _ -> "_") tl) ^ " -> assert false)"
|
|
|
|
+ | MParams (t,_) -> def_value ctx t
|
|
|
|
+ | MInst path -> "Obj.magic 0"
|
|
|
|
|
|
let s_type ctx t p = type_str ctx (to_type ctx t p)
|
|
let s_type ctx t p = type_str ctx (to_type ctx t p)
|
|
|
|
|
|
-let rec gen_expr ctx e =
|
|
|
|
|
|
+let scan_vars ctx e =
|
|
|
|
+ let old = ctx.vars in
|
|
|
|
+ ctx.vars <- Hashtbl.create 0;
|
|
|
|
+ let rec loop e =
|
|
|
|
+ (match e.eexpr with
|
|
|
|
+ | TBinop ((OpAssign | OpAssignOp _), { eexpr = TLocal v },_) -> Hashtbl.replace ctx.vars v.v_id true
|
|
|
|
+ | _ -> ());
|
|
|
|
+ Type.iter loop e
|
|
|
|
+ in
|
|
|
|
+ loop e;
|
|
|
|
+ (fun() -> ctx.vars <- old)
|
|
|
|
+
|
|
|
|
+let gen_list ctx sep f list =
|
|
|
|
+ let first = ref true in
|
|
|
|
+ List.iter (fun e ->
|
|
|
|
+ if !first then first := false else spr ctx sep;
|
|
|
|
+ f ctx e
|
|
|
|
+ ) list
|
|
|
|
+
|
|
|
|
+let rec gen_expr ctx e is_final =
|
|
match e.eexpr with
|
|
match e.eexpr with
|
|
| TConst c ->
|
|
| TConst c ->
|
|
(match c with
|
|
(match c with
|
|
@@ -154,42 +194,71 @@ let rec gen_expr ctx e =
|
|
| TThis -> spr ctx "this"
|
|
| TThis -> spr ctx "this"
|
|
| TSuper -> assert false)
|
|
| TSuper -> assert false)
|
|
| TLocal v ->
|
|
| TLocal v ->
|
|
- spr ctx (ident v.v_name)
|
|
|
|
|
|
+ let vid = ident v.v_name in
|
|
|
|
+ if Hashtbl.mem ctx.vars v.v_id then print ctx "!%s" vid else spr ctx vid
|
|
|
|
+ | TVar (v,init) ->
|
|
|
|
+ let mut = Hashtbl.mem ctx.vars v.v_id in
|
|
|
|
+ let t = to_type ctx v.v_type e.epos in
|
|
|
|
+ print ctx "let %s : %s = %s" (ident v.v_name) (type_str ctx t) (if mut then "ref " else "");
|
|
|
|
+ (match init with None -> spr ctx (def_value ctx t) | Some e -> gen_expr ctx e false);
|
|
|
|
+ spr ctx " in ";
|
|
|
|
+ ctx.separator <- true;
|
|
| TBlock [] ->
|
|
| TBlock [] ->
|
|
spr ctx "()"
|
|
spr ctx "()"
|
|
| TBlock el ->
|
|
| TBlock el ->
|
|
spr ctx "begin";
|
|
spr ctx "begin";
|
|
ctx.separator <- true;
|
|
ctx.separator <- true;
|
|
let b = open_block ctx in
|
|
let b = open_block ctx in
|
|
- List.iter (fun e ->
|
|
|
|
- newline ctx;
|
|
|
|
- gen_expr ctx e
|
|
|
|
- ) el;
|
|
|
|
|
|
+ let rec loop = function
|
|
|
|
+ | [] -> assert false
|
|
|
|
+ | [e] ->
|
|
|
|
+ newline ctx;
|
|
|
|
+ gen_expr ctx e is_final
|
|
|
|
+ | e :: el ->
|
|
|
|
+ newline ctx;
|
|
|
|
+ (match follow e.etype with TAbstract ({ a_path = [],"Void" },_) -> () | _ -> spr ctx "ignore ");
|
|
|
|
+ gen_expr ctx e false;
|
|
|
|
+ loop el
|
|
|
|
+ in
|
|
|
|
+ loop el;
|
|
b();
|
|
b();
|
|
newline ctx;
|
|
newline ctx;
|
|
spr ctx "end";
|
|
spr ctx "end";
|
|
|
|
+ | TCall ({ eexpr = TField (_,FEnum _) } as e, (_ :: _ :: _ as pl)) ->
|
|
|
|
+ gen_expr ctx e false;
|
|
|
|
+ spr ctx "(";
|
|
|
|
+ gen_list ctx ", " (fun ctx e -> gen_expr ctx e false) pl;
|
|
|
|
+ spr ctx ")"
|
|
| TCall (e, pl) ->
|
|
| TCall (e, pl) ->
|
|
- gen_expr ctx e;
|
|
|
|
|
|
+ gen_expr ctx e false;
|
|
|
|
+ if pl = [] then spr ctx "()";
|
|
List.iter (fun e ->
|
|
List.iter (fun e ->
|
|
spr ctx " ";
|
|
spr ctx " ";
|
|
- gen_expr ctx e;
|
|
|
|
|
|
+ gen_expr ctx e false;
|
|
) pl;
|
|
) pl;
|
|
| TField (e, ft) ->
|
|
| TField (e, ft) ->
|
|
(match ft with
|
|
(match ft with
|
|
| FInstance _ -> assert false
|
|
| FInstance _ -> assert false
|
|
|
|
+ | FEnum (e,ef) ->
|
|
|
|
+ print ctx "%s%s" (module_path ctx e.e_path) (ident ef.ef_name)
|
|
| FStatic (c,cf) ->
|
|
| FStatic (c,cf) ->
|
|
let rec loop = function
|
|
let rec loop = function
|
|
| (Meta.Custom ":mlNative",[EConst (String s),_],_) :: _ ->
|
|
| (Meta.Custom ":mlNative",[EConst (String s),_],_) :: _ ->
|
|
spr ctx s
|
|
spr ctx s
|
|
| _ :: l -> loop l
|
|
| _ :: l -> loop l
|
|
| [] ->
|
|
| [] ->
|
|
- print ctx "%s.%s" (module_path ctx c.cl_path) (ident cf.cf_name)
|
|
|
|
|
|
+ print ctx "%s%s" (module_path ctx c.cl_path) (ident cf.cf_name)
|
|
in
|
|
in
|
|
loop cf.cf_meta
|
|
loop cf.cf_meta
|
|
| FAnon f -> assert false
|
|
| FAnon f -> assert false
|
|
| FDynamic _ -> assert false
|
|
| FDynamic _ -> assert false
|
|
- | FClosure _ -> assert false
|
|
|
|
- | FEnum _ -> assert false);
|
|
|
|
|
|
+ | FClosure _ -> assert false);
|
|
|
|
+ | TReturn _ when not is_final ->
|
|
|
|
+ abort "Unallowed not final return" e.epos
|
|
|
|
+ | TReturn None ->
|
|
|
|
+ spr ctx "()"
|
|
|
|
+ | TReturn (Some e) ->
|
|
|
|
+ gen_expr ctx e is_final
|
|
| _ ->
|
|
| _ ->
|
|
abort ("Unsupported expr " ^ s_expr_kind e) e.epos
|
|
abort ("Unsupported expr " ^ s_expr_kind e) e.epos
|
|
|
|
|
|
@@ -220,16 +289,33 @@ let generate_class ctx c =
|
|
| Var v -> assert false
|
|
| Var v -> assert false
|
|
| Method _ ->
|
|
| Method _ ->
|
|
let args, ret = (match follow f.cf_type with TFun (args, ret) -> args, ret | _ -> assert false) in
|
|
let args, ret = (match follow f.cf_type with TFun (args, ret) -> args, ret | _ -> assert false) in
|
|
|
|
+ let tret = to_type ctx ret f.cf_pos in
|
|
print ctx "let %s %s : %s = " (ident f.cf_name) (if args = [] then "()" else String.concat " " (List.map (fun (n,o,t) ->
|
|
print ctx "let %s %s : %s = " (ident f.cf_name) (if args = [] then "()" else String.concat " " (List.map (fun (n,o,t) ->
|
|
if o then abort "Unsupported optional arg" f.cf_pos;
|
|
if o then abort "Unsupported optional arg" f.cf_pos;
|
|
sprintf "(%s:%s)" (ident n) (s_type ctx t f.cf_pos)
|
|
sprintf "(%s:%s)" (ident n) (s_type ctx t f.cf_pos)
|
|
- ) args)) (s_type ctx ret f.cf_pos);
|
|
|
|
|
|
+ ) args)) (type_str ctx tret);
|
|
(match f.cf_expr with
|
|
(match f.cf_expr with
|
|
- | Some { eexpr = TFunction f } -> gen_expr ctx f.tf_expr
|
|
|
|
|
|
+ | Some { eexpr = TFunction f } ->
|
|
|
|
+ let e = f.tf_expr in
|
|
|
|
+ let old = scan_vars ctx e in
|
|
|
|
+ if tret = MUnit && to_type ctx e.etype e.epos <> MUnit then spr ctx "ignore ";
|
|
|
|
+ gen_expr ctx e true;
|
|
|
|
+ old()
|
|
| _ -> assert false);
|
|
| _ -> assert false);
|
|
spr ctx "\n"
|
|
spr ctx "\n"
|
|
) c.cl_ordered_statics
|
|
) c.cl_ordered_statics
|
|
|
|
|
|
|
|
+let generate_enum ctx e =
|
|
|
|
+ print ctx "type t =";
|
|
|
|
+ List.iter (fun n ->
|
|
|
|
+ let c = PMap.find n e.e_constrs in
|
|
|
|
+ print ctx "\n\t| %s" (ident n);
|
|
|
|
+ (match follow c.ef_type with
|
|
|
|
+ | TFun (args,_) -> print ctx " of %s" (String.concat " * " (List.map (fun (n,o,t) -> s_type ctx t c.ef_pos) args))
|
|
|
|
+ | _ -> ())
|
|
|
|
+ ) e.e_names;
|
|
|
|
+ spr ctx "\n\n"
|
|
|
|
+
|
|
let generate_type ctx t =
|
|
let generate_type ctx t =
|
|
match t with
|
|
match t with
|
|
| TClassDecl { cl_extern = true } ->
|
|
| TClassDecl { cl_extern = true } ->
|
|
@@ -242,6 +328,11 @@ let generate_type ctx t =
|
|
() (* core type *)
|
|
() (* core type *)
|
|
| TTypeDecl td ->
|
|
| TTypeDecl td ->
|
|
begin_module ctx td.t_path;
|
|
begin_module ctx td.t_path;
|
|
|
|
+ spr ctx "TODO";
|
|
|
|
+ end_module ctx;
|
|
|
|
+ | TEnumDecl e ->
|
|
|
|
+ begin_module ctx e.e_path;
|
|
|
|
+ generate_enum ctx e;
|
|
end_module ctx;
|
|
end_module ctx;
|
|
| _ ->
|
|
| _ ->
|
|
abort "Unsupported module type" (t_infos t).mt_pos
|
|
abort "Unsupported module type" (t_infos t).mt_pos
|
|
@@ -254,6 +345,8 @@ let generate com =
|
|
separator = false;
|
|
separator = false;
|
|
dirs = Hashtbl.create 0;
|
|
dirs = Hashtbl.create 0;
|
|
buf = Rbuffer.create 65536;
|
|
buf = Rbuffer.create 65536;
|
|
|
|
+ vars = Hashtbl.create 0;
|
|
|
|
+ current_module = [],"";
|
|
} in
|
|
} in
|
|
(try Unix.mkdir ctx.com.file 0o755 with _ -> ());
|
|
(try Unix.mkdir ctx.com.file 0o755 with _ -> ());
|
|
List.iter (generate_type ctx) com.types;
|
|
List.iter (generate_type ctx) com.types;
|
|
@@ -261,7 +354,6 @@ let generate com =
|
|
| None -> ()
|
|
| None -> ()
|
|
| Some e ->
|
|
| Some e ->
|
|
begin_module ctx ([],"MLBoot");
|
|
begin_module ctx ([],"MLBoot");
|
|
- gen_expr ctx e;
|
|
|
|
- spr ctx "()";
|
|
|
|
|
|
+ gen_expr ctx e true;
|
|
newline ctx;
|
|
newline ctx;
|
|
end_module ctx)
|
|
end_module ctx)
|