Merge branch 'java'
Conflicts: .gitignore compiler/global/global_printer.ml compiler/main/mls2obc.mlmaster
commit
6b720e6c23
@ -0,0 +1,6 @@
|
||||
- Ne plus forcer l'ordre constantes puis types puis definitions de noeud. Il
|
||||
faudra mettre à jour les phases du compilateur et modifier l'ast.
|
||||
- Ajouter des constantes locales
|
||||
|
||||
- supprimer pinst dans minils
|
||||
- heptcheck
|
@ -1 +1 @@
|
||||
<c> or <java>:include
|
||||
<transformations> or <c> or <java>:include
|
||||
|
@ -0,0 +1,69 @@
|
||||
open Misc
|
||||
open Java
|
||||
open Java_printer
|
||||
|
||||
(** returns the vd and the pat of a fresh ident from [name] *)
|
||||
let mk_var ty name =
|
||||
let id = Idents.gen_var "java_main" name in
|
||||
mk_var_dec id ty, Pvar id
|
||||
|
||||
let program p =
|
||||
let p_java = Obc2java.program p in
|
||||
let dir = Compiler_utils.build_path "java" in
|
||||
Compiler_utils.ensure_dir dir;
|
||||
|
||||
(* Compile and output the nodes *)
|
||||
output_program dir p_java;
|
||||
|
||||
(* Create a runnable main simulation *)
|
||||
if !Compiler_options.simulation
|
||||
then (
|
||||
let class_name = Obc2java.fresh_classe (!Compiler_options.simulation_node ^ "_sim") in
|
||||
Idents.enter_node class_name;
|
||||
let field_step_dnb, id_step_dnb =
|
||||
let id = Idents.gen_var "java_main" "default_step_nb" in
|
||||
mk_field ~static:true ~final:true ~value:(Some (Sint 30000)) Tint id, id
|
||||
in
|
||||
let main_methode =
|
||||
let vd_step, pat_step = mk_var Tint "step" in
|
||||
let vd_args, pat_args = mk_var (Tarray (Tclass (Names.pervasives_qn "String"), (Sint 0))) "args" in
|
||||
let body =
|
||||
let vd_main, e_main, q_main =
|
||||
let q_main = !Compiler_options.simulation_node |> Modules.qualify_value |> Obc2java.qualname_to_package_classe
|
||||
in let id = Idents.gen_var "java_main" "main" in
|
||||
mk_var_dec id (Tclass q_main), Eval (Pvar id), q_main
|
||||
in
|
||||
let acts =
|
||||
let integer = Eval(Pclass(Names.pervasives_qn "Integer")) in
|
||||
let args1 = Eval(Parray_elem(pat_args, Sint 1)) in
|
||||
let out = Eval(Pclass(Names.qualname_of_string "java.lang.System.out")) in
|
||||
let vd_r, pat_r = mk_var Tint "r" in
|
||||
let step_call = Anewvar(vd_r, Emethod_call(e_main, "step", [])) in
|
||||
[ Anewvar(vd_main, Enew (Tclass q_main, []));
|
||||
Aifelse( Efun(Names.pervasives_qn ">", [Eval (Pfield (pat_args, "length")); Sint 1])
|
||||
, mk_block [Aassgn(pat_step, Emethod_call(integer, "parseInt", [args1]))]
|
||||
, mk_block [Aassgn(pat_step, Eval (Pvar id_step_dnb))]);
|
||||
Obc2java.fresh_for (Eval pat_step)
|
||||
(fun i ->
|
||||
let printing =
|
||||
if !Compiler_options.verbose
|
||||
then [Amethod_call(out, "printf", [Sstring "%d => %d\\n"; Eval (Pvar i); Eval pat_r])]
|
||||
else []
|
||||
in step_call::printing )
|
||||
]
|
||||
in
|
||||
mk_block ~locals:[vd_step] acts
|
||||
in
|
||||
mk_methode ~static:true ~args:[vd_args] body "main"
|
||||
in
|
||||
let c = mk_classe ~fields:[field_step_dnb] ~methodes:[main_methode] class_name in
|
||||
output_program dir [c]
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,233 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Heptagon *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* Java printer *)
|
||||
|
||||
open Java
|
||||
open Pp_tools
|
||||
open Format
|
||||
open Misc
|
||||
|
||||
let class_name = Global_printer.print_qualname
|
||||
let bare_class_name = Global_printer.print_shortname
|
||||
let obj_ident = Global_printer.print_ident
|
||||
let constructor_name = Global_printer.print_qualname
|
||||
let bare_constructor_name = Global_printer.print_shortname
|
||||
let method_name = pp_print_string
|
||||
let field_name = pp_print_string
|
||||
let field_ident = Global_printer.print_ident
|
||||
let var_ident = Global_printer.print_ident
|
||||
let const_name = Global_printer.print_qualname
|
||||
|
||||
let protection ff = function
|
||||
| Ppublic -> fprintf ff "public "
|
||||
| Pprotected -> fprintf ff "protected "
|
||||
| Pprivate -> fprintf ff "private "
|
||||
| Ppackage -> ()
|
||||
|
||||
let static ff s = if s then fprintf ff "static " else ()
|
||||
|
||||
let final ff f = if f then fprintf ff "final " else ()
|
||||
|
||||
let rec _ty size ff t = match t with
|
||||
| Tbool -> fprintf ff "boolean"
|
||||
| Tint -> fprintf ff "int"
|
||||
| Tfloat -> fprintf ff "float"
|
||||
| Tclass n -> class_name ff n
|
||||
| Tgeneric (n, ty_l) -> fprintf ff "%a<@[%a@]>" class_name n (print_list_r ty """,""") ty_l
|
||||
| Tarray (t,s) -> if size then fprintf ff "%a[%a]" full_ty t exp s else fprintf ff "%a[]" ty t
|
||||
| Tref t -> ty ff t
|
||||
| Tunit -> pp_print_string ff "void"
|
||||
|
||||
and full_ty ff t = _ty true ff t
|
||||
|
||||
and ty ff t = _ty false ff t
|
||||
|
||||
and var_dec init ff vd =
|
||||
if init then
|
||||
fprintf ff "%a %a = %a" ty vd.vd_type var_ident vd.vd_ident exp (Java.default_value vd.vd_type)
|
||||
else
|
||||
fprintf ff "%a %a" ty vd.vd_type var_ident vd.vd_ident
|
||||
|
||||
and vd_list s1 s2 s3 ff vd_l = match vd_l with
|
||||
| [] -> ()
|
||||
| _ -> fprintf ff "@[<v>%a@]@\n" (print_list_r (var_dec true) s1 s2 s3) vd_l
|
||||
|
||||
and field ff f =
|
||||
fprintf ff "@[<2>%a%a%a%a %a%a@]"
|
||||
protection f.f_protection
|
||||
static f.f_static
|
||||
final f.f_final
|
||||
ty f.f_type
|
||||
field_ident f.f_ident
|
||||
(print_opt2 exp " = ") f.f_value
|
||||
|
||||
and exp ff = function
|
||||
| Ethis -> fprintf ff "this"
|
||||
| Eval p -> pattern ff p
|
||||
| Efun (f,e_l) -> op ff (f, e_l)
|
||||
| Emethod_call (o,m,e_l) -> fprintf ff "%a.%a%a" exp o method_name m args e_l
|
||||
| Enew (c,e_l) -> fprintf ff "new %a%a" full_ty c args e_l
|
||||
| Enew_array (t,e_l) ->
|
||||
(match e_l with
|
||||
| [] -> fprintf ff "new %a" full_ty t
|
||||
| _ -> fprintf ff "new %a@[<2>%a@]" ty t (print_list_r exp "{"",""}") e_l )
|
||||
| Evoid -> ()
|
||||
| Ecast (t,e) -> fprintf ff "(%a)(%a)" ty t exp e
|
||||
| Svar c -> const_name ff c
|
||||
| Sint i -> pp_print_int ff i
|
||||
| Sfloat f -> pp_print_float ff f
|
||||
| Sbool b -> pp_print_bool ff b
|
||||
| Sconstructor c -> constructor_name ff c
|
||||
| Sstring s -> fprintf ff "\"%s\"" s
|
||||
| Snull -> fprintf ff "null"
|
||||
|
||||
and op ff (f, e_l) =
|
||||
let javaop = function
|
||||
| "=" -> "=="
|
||||
| "<>" -> "!="
|
||||
| "or" -> "||"
|
||||
| "&" -> "&&"
|
||||
| "*." -> "*"
|
||||
| "/." -> "/"
|
||||
| "+." -> "+"
|
||||
| "-." -> "-"
|
||||
| op -> op
|
||||
in
|
||||
match Names.modul f with
|
||||
| Names.Pervasives ->
|
||||
(match Names.shortname f with
|
||||
|("+" | "-" | "*" | "/"
|
||||
|"+." | "-." | "*." | "/."
|
||||
| "=" | "<>" | "<" | "<="
|
||||
| ">" | ">=" | "&" | "or") as n ->
|
||||
let e1,e2 = Misc.assert_2 e_l in
|
||||
fprintf ff "(@[%a@ %s %a@])" exp e1 (javaop n) exp e2
|
||||
| "not" ->
|
||||
let e = Misc.assert_1 e_l in
|
||||
fprintf ff "!%a" exp e
|
||||
| "~-" ->
|
||||
let e = Misc.assert_1 e_l in
|
||||
fprintf ff "-%a" exp e
|
||||
| s -> fprintf ff "jeptagon.Pervasives.%s%a" s args e_l) (* TODO java deal with this correctly
|
||||
bug when using Pervasives.ggg in the code but works when using ggg directly *)
|
||||
| _ -> fprintf ff "%a%a" Global_printer.print_qualname f args e_l
|
||||
|
||||
and args ff e_l = fprintf ff "@[(%a)@]" (print_list_r exp """,""") e_l
|
||||
|
||||
and pattern ff = function
|
||||
| Pfield (p,f) -> fprintf ff "%a.%a" pattern p field_name f
|
||||
| Pvar v -> var_ident ff v
|
||||
| Pclass c -> class_name ff c
|
||||
| Parray_elem (p,e) -> fprintf ff "%a[%a]" pattern p exp e
|
||||
| Pthis f -> fprintf ff "this.%a" field_ident f
|
||||
|
||||
let rec block ff b =
|
||||
fprintf ff "%a%a"
|
||||
(vd_list """;"";") b.b_locals
|
||||
(print_list_r act """""") b.b_body
|
||||
|
||||
(*
|
||||
and switch_hack ff c_b_l =
|
||||
fprintf ff "@[<hv 2> default :\\Dead code. Hack to prevent \"may not be initialized\" java error.@ %a@ break;@]"
|
||||
block (c_b_l |> List.hd |> snd)
|
||||
*)
|
||||
|
||||
and act ff = function
|
||||
| Anewvar (vd,e) -> fprintf ff "@[<4>%a =@ %a;@]" (var_dec false) vd exp e
|
||||
| Aassgn (p,e) -> fprintf ff "@[<4>%a =@ %a;@]" pattern p exp e
|
||||
| Amethod_call (o,m,e_l) -> fprintf ff "@[%a.%a%a;@]" exp o method_name m args e_l
|
||||
| Aswitch (e, c_b_l) ->
|
||||
let pcb ff (c,b) = fprintf ff "@[<v4>case %a:@ %a@ break;@]" bare_constructor_name c block b in
|
||||
(* let switch_hack ff c_b_l = (* TODO java : better thing to do ? *)
|
||||
fprintf ff "@[<2>default ://Dead code. Hack to prevent \
|
||||
\"may not be initialized\" java error.@ %a@ break;@]" block (c_b_l |> List.hd |> snd)
|
||||
in*)
|
||||
fprintf ff "@[<v4>switch (%a) {@ %a@]@\n}"
|
||||
exp e
|
||||
(print_list_r pcb """""") c_b_l
|
||||
| Aif (e,bt) ->
|
||||
fprintf ff "@[<v 4>if (%a) {@ %a }@]" exp e block bt
|
||||
| Aifelse (e,bt,bf) ->
|
||||
fprintf ff "@[<v>@[<v4>if (%a) {@ %a@]@ @[<v4>} else {@ %a@]@ }@]"
|
||||
exp e
|
||||
block bt
|
||||
block bf
|
||||
| Ablock b -> if (List.length b.b_body > 0) then fprintf ff "@[<v>@[<v4>{@ %a@]@ }@]" block b
|
||||
| Afor (x, i1, i2, b) ->
|
||||
fprintf ff "@[<hv>@[<hv 4>for (%a = %a; %a<%a; %a++) {@ %a@]@ }@]"
|
||||
(var_dec false) x
|
||||
exp i1
|
||||
var_ident x.vd_ident
|
||||
exp i2
|
||||
var_ident x.vd_ident
|
||||
block b
|
||||
| Areturn e -> fprintf ff "return %a;" exp e
|
||||
|
||||
let methode ff m =
|
||||
fprintf ff "@[<v4>%a%a%a %a @[<4>(%a)@] @[%a@]{@ %a@]@\n}"
|
||||
protection m.m_protection
|
||||
static m.m_static
|
||||
ty m.m_returns
|
||||
method_name m.m_name
|
||||
(print_list_r (var_dec false) """,""") m.m_args
|
||||
(print_list_r class_name "throws "","" ") m.m_throws
|
||||
block m.m_body
|
||||
|
||||
let constructor ff m =
|
||||
fprintf ff "@[<v4>%a%a @[<4>(%a)@] {@\n%a@]@\n}"
|
||||
protection m.m_protection
|
||||
method_name m.m_name
|
||||
(print_list_r (var_dec false) """,""") m.m_args
|
||||
block m.m_body
|
||||
|
||||
let rec class_desc ff cd =
|
||||
fprintf ff "@[<v>%a@ %a@ %a@ %a@]"
|
||||
(print_list_r field """;"";") cd.cd_fields
|
||||
(print_list_r classe """""") cd.cd_classs
|
||||
(print_list constructor """""") cd.cd_constructors
|
||||
(print_list methode """""") cd.cd_methodes
|
||||
|
||||
and classe ff c = match c.c_kind with
|
||||
| Cenum c_l ->
|
||||
fprintf ff "@\n@[<4>%a%aenum %a {@\n%a@]@\n}"
|
||||
protection c.c_protection
|
||||
static c.c_static
|
||||
bare_class_name c.c_name
|
||||
(print_list_r bare_constructor_name """,""") c_l
|
||||
| Cgeneric cd ->
|
||||
fprintf ff "@\n@[<4>%a%aclass %a @[<h>%a@]{@\n%a@]@\n}"
|
||||
protection c.c_protection
|
||||
static c.c_static
|
||||
bare_class_name c.c_name
|
||||
(print_list_r class_name "implements "",""") c.c_implements
|
||||
class_desc cd
|
||||
|
||||
let output_classe base_dir c =
|
||||
let { Names.name = file_name; Names.qual = package } = c.c_name in
|
||||
let file_name = file_name ^ ".java" in
|
||||
let package_dirs = Misc.split_string (Names.modul_to_string package) "." in
|
||||
let create_dir base_dir dir =
|
||||
let dir = Filename.concat base_dir dir in
|
||||
Compiler_utils.ensure_dir dir;
|
||||
dir
|
||||
in
|
||||
let dir = List.fold_left create_dir base_dir package_dirs in
|
||||
let oc = open_out (Filename.concat dir file_name) in
|
||||
let ff = Format.formatter_of_out_channel oc in
|
||||
pp_set_margin ff 120;
|
||||
fprintf ff "package %a;@\n@[<v>%a@]@\n%a@."
|
||||
Global_printer.print_full_modul package
|
||||
(print_list_r (fun ff n -> fprintf ff "import %a" class_name n) """;"";") c.c_imports
|
||||
classe c;
|
||||
close_out oc
|
||||
|
||||
let output_program dir (p:Java.program) =
|
||||
List.iter (output_classe dir) p
|
||||
|
@ -1,6 +0,0 @@
|
||||
|
||||
let program p =
|
||||
let filename = filename_of_module p in
|
||||
let dirname = build_path filename in
|
||||
let dir = clean_dir dirname in
|
||||
Java.print dir o
|
@ -0,0 +1,407 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Heptagon *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(** An Obc.program is a Java.package,
|
||||
Obc.type_dec, Obc.class_def are Java.classs
|
||||
Obc.const_dec is defined in the special class CONSTANTES
|
||||
Obc.Lvar are Pvar
|
||||
Obc.Lmem are this.Pvar (Pfield)
|
||||
Obc.Oobj and Oarray are simply Pvar and Parray_elem
|
||||
Obc.Types_alias are dereferenced since no simple type alias is possible in Java *)
|
||||
|
||||
(** Requires scalar Obc : [p = e] when [e] is an array is understand as a copy of the reference,
|
||||
not a copy of the array. *)
|
||||
|
||||
open Format
|
||||
open Misc
|
||||
open Names
|
||||
open Modules
|
||||
open Signature
|
||||
open Obc
|
||||
open Obc_utils
|
||||
open Java
|
||||
|
||||
|
||||
(** Additional classes created during the translation *)
|
||||
let add_classe, get_classes =
|
||||
let extra_classes = ref [] in
|
||||
(fun c -> extra_classes := c :: !extra_classes)
|
||||
,(fun () -> !extra_classes)
|
||||
|
||||
(** fresh Afor from 0 to [size] with [body] a function from [var_ident] (the iterator) to [act] list *)
|
||||
let fresh_for size body =
|
||||
let i = Idents.gen_var "obc2java" "i" in
|
||||
let id = mk_var_dec i Tint in
|
||||
Afor (id, Sint 0, size, mk_block (body i))
|
||||
|
||||
(* current module is not translated to keep track, there is no issue since printed without the qualifier *)
|
||||
let rec translate_modul m = match m with
|
||||
| Pervasives
|
||||
| LocalModule -> m
|
||||
| _ when m = g_env.current_mod -> m
|
||||
| Module n -> Module (String.lowercase n)
|
||||
| QualModule { qual = q; name = n} -> QualModule { qual = translate_modul q; name = String.lowercase n }
|
||||
|
||||
(** a [Module.const] becomes a [module.CONSTANTES.CONST] *)
|
||||
let translate_const_name { qual = m; name = n } =
|
||||
{ qual = QualModule { qual = translate_modul m; name = "CONSTANTES"}; name = String.uppercase n }
|
||||
|
||||
(** a [Module.fun] becomes a [module.FUNS.fun] *)
|
||||
let translate_fun_name { qual = m; name = n } =
|
||||
{ qual = QualModule { qual = translate_modul m; name = "FUNS"}; name = n }
|
||||
|
||||
(** a [Module.name] becomes a [module.Name]
|
||||
used for type_names, class_names, fun_names *)
|
||||
let qualname_to_class_name q =
|
||||
{ qual = translate_modul q.qual; name = String.capitalize q.name }
|
||||
|
||||
(** a [Module.name] becomes a [module.Name] even on current_mod *)
|
||||
let qualname_to_package_classe q =
|
||||
{ qual = translate_modul q.qual; name = String.capitalize q.name }
|
||||
|
||||
(** Create a fresh class qual from a name *)
|
||||
let fresh_classe n = Modules.fresh_value "obc2java" n |> qualname_to_package_classe
|
||||
|
||||
(** a [Module.Constr] of an [Module.enum] type becomes a [module.Enum.CONSTR] of the [module.Enum] class *)
|
||||
let translate_constructor_name_2 q q_ty =
|
||||
let classe = qualname_to_class_name q_ty in
|
||||
{ qual = QualModule classe; name = String.uppercase q.name }
|
||||
|
||||
let translate_constructor_name q =
|
||||
match Modules.find_constrs q with
|
||||
| Types.Tid q_ty when q_ty = Initial.pbool -> q |> shortname |> local_qn
|
||||
| Types.Tid q_ty -> translate_constructor_name_2 q q_ty
|
||||
| _ -> assert false
|
||||
|
||||
let translate_field_name f = f |> Names.shortname |> String.lowercase
|
||||
|
||||
(** a [name] becomes a [package.Name] *)
|
||||
let name_to_classe_name n = n |> Modules.current_qual |> qualname_to_package_classe
|
||||
|
||||
(** translate an ostatic_exp into an jexp *)
|
||||
let rec static_exp param_env se = match se.Types.se_desc with
|
||||
| Types.Svar c ->
|
||||
(match c.qual with
|
||||
| LocalModule ->
|
||||
let n = NamesEnv.find (shortname c) param_env in
|
||||
Svar (n |> Idents.name |> local_qn)
|
||||
| _ -> Svar (translate_const_name c))
|
||||
| Types.Sint i -> Sint i
|
||||
| Types.Sfloat f -> Sfloat f
|
||||
| Types.Sbool b -> Sbool b
|
||||
| Types.Sconstructor c -> let c = translate_constructor_name c in Sconstructor c
|
||||
| Types.Sfield f -> eprintf "ojSfield @."; assert false;
|
||||
| Types.Stuple se_l -> tuple param_env se_l
|
||||
| Types.Sarray_power (see,pow) ->
|
||||
let pow = (try Static.int_of_static_exp Names.QualEnv.empty pow
|
||||
with Errors.Error ->
|
||||
eprintf "%aStatic power of array should have integer power. \
|
||||
Please use callgraph or non-static exp in %a.@."
|
||||
Location.print_location se.Types.se_loc
|
||||
Global_printer.print_static_exp se;
|
||||
raise Errors.Error)
|
||||
in
|
||||
let se_l = Misc.repeat_list (static_exp param_env see) pow in
|
||||
Enew_array (ty param_env se.Types.se_ty, se_l)
|
||||
| Types.Sarray se_l -> Enew_array (ty param_env se.Types.se_ty, List.map (static_exp param_env) se_l)
|
||||
| Types.Srecord _ -> eprintf "ojSrecord@."; assert false; (* TODO java *)
|
||||
| Types.Sop (f, se_l) -> Efun (qualname_to_class_name f, List.map (static_exp param_env) se_l)
|
||||
|
||||
and boxed_ty param_env t = match t with
|
||||
| Types.Tprod ty_l -> tuple_ty param_env ty_l
|
||||
| Types.Tid t when t = Initial.pbool -> Tclass (Names.local_qn "Boolean")
|
||||
| Types.Tid t when t = Initial.pint -> Tclass (Names.local_qn "Integer")
|
||||
| Types.Tid t when t = Initial.pfloat -> Tclass (Names.local_qn "Float")
|
||||
| Types.Tid t -> Tclass (qualname_to_class_name t)
|
||||
| Types.Tarray (t,size) -> Tarray (boxed_ty param_env t, static_exp param_env size)
|
||||
| Types.Tmutable t -> Tref (boxed_ty param_env t)
|
||||
| Types.Tunit -> Tunit
|
||||
|
||||
and tuple_ty param_env ty_l =
|
||||
let ln = ty_l |> List.length |> Pervasives.string_of_int in
|
||||
Tclass (java_pervasive_class ("Tuple"^ln))
|
||||
|
||||
and ty param_env t :Java.ty = match t with
|
||||
| Types.Tprod ty_l -> tuple_ty param_env ty_l
|
||||
| Types.Tid t when t = Initial.pbool -> Tbool
|
||||
| Types.Tid t when t = Initial.pint -> Tint
|
||||
| Types.Tid t when t = Initial.pfloat -> Tfloat
|
||||
| Types.Tid t -> Tclass (qualname_to_class_name t)
|
||||
| Types.Tarray (t,size) -> Tarray (ty param_env t, static_exp param_env size)
|
||||
| Types.Tmutable t -> Tref (ty param_env t)
|
||||
| Types.Tunit -> Tunit
|
||||
|
||||
and var_dec param_env vd = { vd_type = ty param_env vd.v_type; vd_ident = vd.v_ident }
|
||||
|
||||
and var_dec_list param_env vd_l = List.map (var_dec param_env) vd_l
|
||||
|
||||
and exp param_env e = match e.e_desc with
|
||||
| Obc.Epattern p -> Eval (pattern param_env p)
|
||||
| Obc.Econst se -> static_exp param_env se
|
||||
| Obc.Eop (op,e_l) -> Efun (op, exp_list param_env e_l)
|
||||
| Obc.Estruct _ -> eprintf "ojEstruct@."; assert false (* TODO java *)
|
||||
| Obc.Earray e_l -> Enew_array (ty param_env e.e_ty, exp_list param_env e_l)
|
||||
|
||||
and exp_list param_env e_l = List.map (exp param_env) e_l
|
||||
|
||||
and tuple param_env se_l =
|
||||
let t = tuple_ty param_env (List.map (fun e -> e.Types.se_ty) se_l) in
|
||||
Enew (t, List.map (static_exp param_env) se_l)
|
||||
|
||||
|
||||
and pattern param_env p = match p.pat_desc with
|
||||
| Obc.Lvar v -> Pvar v
|
||||
| Obc.Lmem v -> Pthis v
|
||||
| Obc.Lfield (p,f) -> Pfield (pattern param_env p, translate_field_name f)
|
||||
| Obc.Larray (p,e) -> Parray_elem (pattern param_env p, exp param_env e)
|
||||
|
||||
let obj_ref param_env o = match o with
|
||||
| Oobj id -> Eval (Pvar id)
|
||||
| Oarray (id,p) -> Eval (Parray_elem (Pvar id, Eval (pattern param_env p)))
|
||||
|
||||
let rec act_list param_env act_l acts =
|
||||
let _act act acts = match act with
|
||||
| Obc.Aassgn (p,e) -> (Aassgn (pattern param_env p, exp param_env e))::acts
|
||||
| Obc.Acall ([], obj, Mstep, e_l) ->
|
||||
let acall = Amethod_call (obj_ref param_env obj, "step", exp_list param_env e_l) in
|
||||
acall::acts
|
||||
| Obc.Acall ([p], obj, Mstep, e_l) ->
|
||||
let ecall = Emethod_call (obj_ref param_env obj, "step", exp_list param_env e_l) in
|
||||
let assgn = Aassgn (pattern param_env p, ecall) in
|
||||
assgn::acts
|
||||
| Obc.Acall (p_l, obj, Mstep, e_l) ->
|
||||
let return_ty = p_l |> pattern_list_to_type |> (ty param_env) in
|
||||
let return_id = Idents.gen_var "obc2java" "out" in
|
||||
let return_vd = { vd_type = return_ty; vd_ident = return_id } in
|
||||
let ecall = Emethod_call (obj_ref param_env obj, "step", exp_list param_env e_l) in
|
||||
let assgn = Anewvar (return_vd, ecall) in
|
||||
let copy_return_to_var i p =
|
||||
let t = ty param_env p.pat_ty in
|
||||
let cast t e = match t with
|
||||
| Tbool -> Ecast(Tbool, Ecast(boxed_ty param_env p.pat_ty, e))
|
||||
| Tint -> Ecast(Tint, Ecast(boxed_ty param_env p.pat_ty, e))
|
||||
| Tfloat -> Ecast(Tfloat, Ecast(boxed_ty param_env p.pat_ty, e))
|
||||
| _ -> Ecast(t, e)
|
||||
in
|
||||
let p = pattern param_env p in
|
||||
Aassgn (p, cast t (Eval (Pfield (Pvar return_id, "c"^(string_of_int i)))))
|
||||
in
|
||||
let copies = Misc.mapi copy_return_to_var p_l in
|
||||
assgn::(copies@acts)
|
||||
| Obc.Acall (_, obj, Mreset, _) ->
|
||||
let acall = Amethod_call (obj_ref param_env obj, "reset", []) in
|
||||
acall::acts
|
||||
| Obc.Acase (e, c_b_l) when e.e_ty = Types.Tid Initial.pbool ->
|
||||
(match c_b_l with
|
||||
| [] -> acts
|
||||
| [(c,b)] when c = Initial.ptrue ->
|
||||
(Aif (exp param_env e, block param_env b)):: acts
|
||||
| [(c,b)] when c = Initial.pfalse ->
|
||||
(Aifelse (exp param_env e, {b_locals = []; b_body = []}, block param_env b)) :: acts
|
||||
| _ ->
|
||||
let _, _then = List.find (fun (c,_) -> c = Initial.ptrue) c_b_l in
|
||||
let _, _else = List.find (fun (c,_) -> c = Initial.pfalse) c_b_l in
|
||||
(Aifelse (exp param_env e, block param_env _then, block param_env _else)) :: acts)
|
||||
| Obc.Acase (e, c_b_l) ->
|
||||
let _c_b (c,b) = translate_constructor_name c, block param_env b in
|
||||
let acase = Aswitch (exp param_env e, List.map _c_b c_b_l) in
|
||||
acase::acts
|
||||
| Obc.Afor (v, se, se', b) ->
|
||||
let afor = Afor (var_dec param_env v, static_exp param_env se, static_exp param_env se', block param_env b) in
|
||||
afor::acts
|
||||
| Obc.Ablock b ->
|
||||
let ablock = Ablock (block param_env b) in
|
||||
ablock::acts
|
||||
in
|
||||
List.fold_right _act act_l acts
|
||||
|
||||
and block param_env ?(locals=[]) ?(end_acts=[]) ob =
|
||||
let blocals = var_dec_list param_env ob.Obc.b_locals in
|
||||
let locals = locals @ blocals in
|
||||
let acts = act_list param_env ob.Obc.b_body end_acts in
|
||||
{ b_locals = locals; b_body = acts }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(** Create the [param_env] and translate [Signature.param]s to [var_dec]s
|
||||
@return [vds, param_env] *)
|
||||
let sig_params_to_vds p_l =
|
||||
let param_to_arg param_env p =
|
||||
let p_ident = Idents.gen_var "obc2java" (String.uppercase p.Signature.p_name) in
|
||||
let p_vd = { vd_ident = p_ident; vd_type = ty param_env p.Signature.p_type } in
|
||||
let param_env = NamesEnv.add p.Signature.p_name p_ident param_env in
|
||||
p_vd, param_env
|
||||
in Misc.mapfold param_to_arg NamesEnv.empty p_l
|
||||
|
||||
(** Translate [Signature.arg]s to [var_dec]s *)
|
||||
let sig_args_to_vds param_env a_l =
|
||||
let arg_to_vd { a_name = n; a_type = t } =
|
||||
let n = match n with None -> "v" | Some s -> s in
|
||||
let id = Idents.gen_var "obc2java" n in
|
||||
mk_var_dec id (ty param_env t)
|
||||
in List.map arg_to_vd a_l
|
||||
|
||||
(** [copy_to_this vd_l] creates [this.x = x] for all [x] in [vd_l] *)
|
||||
let copy_to_this vd_l =
|
||||
let _vd vd = Aassgn (Pthis vd.vd_ident, Eval (Pvar vd.vd_ident)) in
|
||||
List.map _vd vd_l
|
||||
|
||||
|
||||
let class_def_list classes cd_l =
|
||||
let class_def classes cd =
|
||||
Idents.enter_node cd.cd_name;
|
||||
let class_name = qualname_to_package_classe cd.cd_name in
|
||||
(* [param_env] is an env mapping local param name to ident *)
|
||||
(* [params] : fields to stock the static parameters, arguments of the constructors *)
|
||||
let fields_params, vds_params, exps_params, param_env =
|
||||
let v, env = sig_params_to_vds cd.cd_params in
|
||||
let f = vds_to_fields ~protection:Pprotected v in
|
||||
let e = vds_to_exps v in
|
||||
f, v, e, env
|
||||
in
|
||||
(* [reset] is the reset method of the class,
|
||||
[reset_mems] is the block to reset the members of the class
|
||||
without call to the reset method of inner instances, it retains [this.x = 0] but not [this.I.reset()] *)
|
||||
let reset, reset_mems =
|
||||
try (* When there exist a reset method *)
|
||||
let oreset = find_reset_method cd in
|
||||
let body = block param_env oreset.Obc.m_body in
|
||||
let reset_mems = block param_env (remove_resets oreset.Obc.m_body) in
|
||||
mk_methode body "reset", reset_mems
|
||||
with Not_found -> (* stub reset method *)
|
||||
mk_methode (mk_block []) "reset", mk_block []
|
||||
in
|
||||
(* [obj_env] gives the type of an [obj_ident], needed in async because we change the classe for async obj *)
|
||||
let constructeur, obj_env =
|
||||
let obj_env = (* Mapping between Obc class and Java class, useful at least with asyncs *)
|
||||
let aux obj_env od =
|
||||
let t = Tclass (qualname_to_class_name od.o_class)
|
||||
in Idents.Env.add od.o_ident t obj_env
|
||||
in List.fold_left aux Idents.Env.empty cd.cd_objs
|
||||
in
|
||||
let body =
|
||||
(* Function to initialize the objects *)
|
||||
let obj_init_act acts od =
|
||||
let params = List.map (static_exp param_env) od.o_params in
|
||||
match od.o_size with
|
||||
| None ->
|
||||
let t = Idents.Env.find od.o_ident obj_env in
|
||||
(Aassgn (Pthis od.o_ident, Enew (t, params)))::acts
|
||||
| Some size ->
|
||||
let size = static_exp param_env size in
|
||||
let t = Idents.Env.find od.o_ident obj_env in
|
||||
let assgn_elem i = [ Aassgn (Parray_elem (Pthis od.o_ident, mk_var i), Enew (t, params)) ] in
|
||||
(Aassgn (Pthis od.o_ident, Enew_array (Tarray (t,size), [])))
|
||||
:: (fresh_for size assgn_elem)
|
||||
:: acts
|
||||
in
|
||||
(* function to allocate the arrays *)
|
||||
let allocate acts vd = match vd.v_type with
|
||||
| Types.Tarray (t, size) ->
|
||||
let t = ty param_env vd.v_type in
|
||||
( Aassgn (Pthis vd.v_ident, Enew_array (t,[])) ):: acts
|
||||
| _ -> acts
|
||||
in
|
||||
(* init actions [acts] in reverse order : *)
|
||||
(* init member variables *)
|
||||
let acts = [Ablock reset_mems] in
|
||||
(* init member objects *)
|
||||
let acts = List.fold_left obj_init_act acts cd.cd_objs in
|
||||
(* allocate member arrays *)
|
||||
let acts = List.fold_left allocate acts cd.cd_mems in
|
||||
(* init static params *)
|
||||
let acts = (copy_to_this vds_params)@acts in
|
||||
{ b_locals = []; b_body = List.rev acts }
|
||||
in mk_methode ~args:vds_params body (shortname class_name), obj_env
|
||||
in
|
||||
let fields =
|
||||
let mem_to_field fields vd = (mk_field ~protection:Pprotected (ty param_env vd.v_type) vd.v_ident) :: fields in
|
||||
let obj_to_field fields od =
|
||||
let jty = match od.o_size with
|
||||
| None -> Idents.Env.find od.o_ident obj_env
|
||||
| Some size -> Tarray (Idents.Env.find od.o_ident obj_env, static_exp param_env size)
|
||||
in
|
||||
(mk_field ~protection:Pprotected jty od.o_ident) :: fields
|
||||
in
|
||||
let fields = fields_params in
|
||||
let fields = List.fold_left mem_to_field fields cd.cd_mems in
|
||||
List.fold_left obj_to_field fields cd.cd_objs
|
||||
in
|
||||
let step =
|
||||
let ostep = find_step_method cd in
|
||||
let vd_output = var_dec_list param_env ostep.m_outputs in
|
||||
let return_ty = ostep.m_outputs |> vd_list_to_type |> (ty param_env) in
|
||||
let return_act = Areturn (match vd_output with
|
||||
| [] -> Evoid
|
||||
| [vd] -> Eval (Pvar vd.vd_ident)
|
||||
| vd_l -> Enew (return_ty, List.map (fun vd -> Eval (Pvar vd.vd_ident)) vd_l))
|
||||
in
|
||||
let body = block param_env ~locals:vd_output ~end_acts:[return_act] ostep.Obc.m_body in
|
||||
mk_methode ~args:(var_dec_list param_env ostep.Obc.m_inputs) ~returns:return_ty body "step"
|
||||
in
|
||||
let classe = mk_classe ~fields:fields
|
||||
~constrs:[constructeur] ~methodes:[step;reset] class_name in
|
||||
classe::classes
|
||||
in
|
||||
List.fold_left class_def classes cd_l
|
||||
|
||||
|
||||
let type_dec_list classes td_l =
|
||||
let param_env = NamesEnv.empty in
|
||||
let _td classes td =
|
||||
let classe_name = qualname_to_package_classe td.t_name in
|
||||
Idents.enter_node classe_name;
|
||||
match td.t_desc with
|
||||
| Type_abs -> Misc.unsupported "obc2java, abstract type." 1
|
||||
| Type_alias _ -> Misc.unsupported "obc2java, type alias." 2
|
||||
| Type_enum c_l ->
|
||||
let mk_constr_enum c = translate_constructor_name_2 c td.t_name in
|
||||
(mk_enum (List.map mk_constr_enum c_l) classe_name) :: classes
|
||||
| Type_struct f_l ->
|
||||
let mk_field_jfield { Signature.f_name = oname; Signature.f_type = oty } =
|
||||
let jty = ty param_env oty in
|
||||
let field = Idents.ident_of_name (translate_field_name oname) in
|
||||
(* [translate_field_name] will give the right result anywhere it is used,
|
||||
since the [ident_of_name] will keep it as it is unique in the class, see [Idents.enter_node classe_name] *)
|
||||
mk_field jty field
|
||||
in
|
||||
(mk_classe ~fields:(List.map mk_field_jfield f_l) classe_name) :: classes
|
||||
in
|
||||
List.fold_left _td classes td_l
|
||||
|
||||
|
||||
let const_dec_list cd_l = match cd_l with
|
||||
| [] -> []
|
||||
| _ ->
|
||||
let classe_name = "CONSTANTES" |> name_to_classe_name in
|
||||
Idents.enter_node classe_name;
|
||||
let param_env = NamesEnv.empty in
|
||||
let mk_const_field { Obc.c_name = oname ; Obc.c_value = ovalue; Obc.c_type = otype } =
|
||||
let name = oname |> translate_const_name |> shortname |> Idents.ident_of_name in
|
||||
(* name should always keep the shortname unchanged since we enter a special node free of existing variables *)
|
||||
(* thus [translate_const_name] will gives the right result anywhere it is used. *)
|
||||
let value = Some (static_exp param_env ovalue) in
|
||||
let t = ty param_env otype in
|
||||
mk_field ~static: true ~final: true ~value: value t name
|
||||
in
|
||||
let fields = List.map mk_const_field cd_l in
|
||||
[mk_classe ~fields: fields classe_name]
|
||||
|
||||
|
||||
|
||||
let program p =
|
||||
let classes = const_dec_list p.p_consts in
|
||||
let classes = type_dec_list classes p.p_types in
|
||||
let p = class_def_list classes p.p_classes in
|
||||
get_classes()@p
|
||||
|
||||
|
||||
|
@ -0,0 +1,543 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Heptagon *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
|
||||
open Signature
|
||||
open Modules
|
||||
open Format
|
||||
open Obc
|
||||
open Misc
|
||||
open Types
|
||||
open Names
|
||||
open Idents
|
||||
open Pp_tools
|
||||
|
||||
let jname_of_name name =
|
||||
let b = Buffer.create (String.length name) in
|
||||
let rec convert c =
|
||||
match c with
|
||||
| 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' ->
|
||||
Buffer.add_char b c
|
||||
| '\'' -> Buffer.add_string b "_prime"
|
||||
| _ ->
|
||||
Buffer.add_string b "lex";
|
||||
Buffer.add_string b (string_of_int (Char.code c));
|
||||
Buffer.add_string b "_" in
|
||||
|
||||
String.iter convert name;
|
||||
Buffer.contents b
|
||||
|
||||
let print_name ff name =
|
||||
fprintf ff "%s" (jname_of_name name)
|
||||
|
||||
let print_shortname ff longname =
|
||||
print_name ff (shortname longname)
|
||||
|
||||
let rec java_type_default_value = function
|
||||
| Tid id when id = Initial.pint -> "int", "0"
|
||||
| Tid id when id = Initial.pfloat -> "float", "0.0"
|
||||
| Tid id when id = Initial.pbool -> "boolean", "false"
|
||||
| Tid t ->
|
||||
(match find_type t with
|
||||
| Tabstract -> assert false
|
||||
| Talias t -> java_type_default_value t
|
||||
| Tenum _ -> "int", "0" (* TODO java *)
|
||||
| Tstruct _ -> shortname t, "null" )
|
||||
| Tarray _ -> assert false (* TODO array *)
|
||||
| Tprod _ -> assert false (* TODO java *)
|
||||
| Tunit -> "void", "null"
|
||||
|
||||
let print_type ff ty =
|
||||
let jty,_ = java_type_default_value ty in
|
||||
print_name ff jty
|
||||
|
||||
let print_field ff (name,ty) =
|
||||
fprintf ff "%a %a;"
|
||||
print_type ty
|
||||
print_name name
|
||||
|
||||
let print_const_field ff (name,ty) =
|
||||
fprintf ff "%a@ %a"
|
||||
print_type ty
|
||||
print_name name
|
||||
|
||||
let print_assgt_field ff (name,_) =
|
||||
fprintf ff "this.%a = %a;"
|
||||
print_name name
|
||||
print_name name
|
||||
|
||||
(* assumes tn is already translated with jname_of_name *)
|
||||
let print_struct_type ff tn fields =
|
||||
fprintf ff "@[<v>@[<v 2>public class %s {@ " tn;
|
||||
(* fields *)
|
||||
print_list print_field "" "" "" ff fields;
|
||||
(* constructor *)
|
||||
let sorted_fields =
|
||||
List.sort
|
||||
(fun (n1,_) (n2,_) -> String.compare n1 n2)
|
||||
fields in
|
||||
fprintf ff "@ @[<v 2>public %s(@[<hov>" tn;
|
||||
print_list print_const_field "" "," "" ff sorted_fields;
|
||||
fprintf ff "@]) {@ ";
|
||||
(* constructor assignments *)
|
||||
print_list print_assgt_field "" "" "" ff fields;
|
||||
(* constructor end *)
|
||||
fprintf ff "@]@ }";
|
||||
(* class end *)
|
||||
fprintf ff "@]@ }@]"
|
||||
|
||||
|
||||
let rec print_tags ff n = function
|
||||
| [] -> ()
|
||||
| tg :: tgs' ->
|
||||
fprintf ff "@ public static final int %a = %d;"
|
||||
print_name ( shortname tg ) (* TODO java deal with modules *)
|
||||
n;
|
||||
print_tags ff (n+1) tgs'
|
||||
|
||||
(* assumes tn is already translated with jname_of_name *)
|
||||
let print_enum_type ff tn tgs =
|
||||
fprintf ff "@[<v>@[<v 2>public class %s {" tn;
|
||||
print_tags ff 1 tgs;
|
||||
fprintf ff "@]@ }@]"
|
||||
|
||||
let rec print_type_to_file java_dir headers { t_name = tn; t_desc = td} =
|
||||
let tn = jname_of_name (shortname tn) in (* TODO java deal with modules *)
|
||||
match td with
|
||||
| Type_abs -> ()
|
||||
| Type_enum tgs ->
|
||||
let out_ch = open_out (java_dir ^ "/" ^ tn ^ ".java") in
|
||||
let ff = formatter_of_out_channel out_ch in
|
||||
(*Misc.print_header_info ff "/*" "*/"; *)
|
||||
List.iter (fprintf ff "%s") headers;
|
||||
(* fprintf ff "@[<v>package %s;@\n@\n" headers; *) (* TODO java deal with modules *)
|
||||
print_enum_type ff tn tgs;
|
||||
fprintf ff "@.";
|
||||
close_out out_ch
|
||||
| Type_struct fields ->
|
||||
let out_ch = open_out (java_dir ^ "/" ^ tn ^ ".java") in
|
||||
let ff = formatter_of_out_channel out_ch in
|
||||
(* Misc.print_header_info ff "/*" "*/"; *)(* TODO java deal with modules *)
|
||||
List.iter (fprintf ff "%s") headers;
|
||||
(* fprintf ff "@[<v>package %s;@\n@\n" headers; *)
|
||||
print_struct_type ff tn
|
||||
(List.map (fun {f_name = n;f_type = t} -> (shortname n,t)) fields); (* TODO java deal with modules *)
|
||||
fprintf ff "@.";
|
||||
close_out out_ch
|
||||
| Type_alias t -> assert false (* TODO java *)
|
||||
|
||||
let print_types java_dir headers tps =
|
||||
List.iter (print_type_to_file java_dir headers) tps
|
||||
|
||||
(******************************)
|
||||
|
||||
type answer =
|
||||
| Sing of var_ident
|
||||
| Mult of var_ident list
|
||||
|
||||
let print_const ff c ts =
|
||||
match c.se_desc with
|
||||
| Sint i -> fprintf ff "%d" i
|
||||
| Sfloat f -> fprintf ff "%f" f
|
||||
| Sbool true -> fprintf ff "true"
|
||||
| Sbool false -> fprintf ff "false"
|
||||
| Sconstructor c ->
|
||||
let tg = shortname c in (* TODO java gérer les modules *)
|
||||
let s = (fst (List.find (fun (tn, tgs) -> List.exists (fun tg' -> tg = tg') tgs) ts))
|
||||
^ "." ^ (jname_of_name tg) in
|
||||
fprintf ff "%s" s
|
||||
| _ -> assert false (* TODO java *)
|
||||
|
||||
let position a xs =
|
||||
let rec walk i = function
|
||||
| [] -> None
|
||||
| x :: xs' -> if x = a then Some i else walk (i + 1) xs'
|
||||
in walk 1 xs
|
||||
|
||||
let print_ident ff id =
|
||||
print_name ff (name id)
|
||||
|
||||
let print_var ff x avs single =
|
||||
match (position x avs) with
|
||||
| None -> print_ident ff x
|
||||
| Some n ->
|
||||
if single then print_ident ff (List.hd avs)
|
||||
else fprintf ff "step_ans.c_%d" n
|
||||
|
||||
let javaop_of_op = function
|
||||
| "=" -> "=="
|
||||
| "<>" -> "!="
|
||||
| "or" -> "||"
|
||||
| "&" -> "&&"
|
||||
| "*." -> "*"
|
||||
| "/." -> "/"
|
||||
| "+." -> "+"
|
||||
| "-." -> "-"
|
||||
| op -> op
|
||||
|
||||
let priority = function
|
||||
| "*" | "/" | "*." | "/." -> 5
|
||||
| "+" | "-" | "+." | "-." -> 4
|
||||
| "=" | "<>" | "<=" | "=>" -> 3
|
||||
| "&" -> 2
|
||||
| "|" -> 1
|
||||
| _ -> 0
|
||||
|
||||
let rec print_lhs ff e avs single =
|
||||
match e.pat_desc with
|
||||
| Lvar x ->
|
||||
print_var ff x avs single
|
||||
| Lmem x -> print_ident ff x
|
||||
| Lfield(e, field) ->
|
||||
print_lhs ff e avs single;
|
||||
fprintf ff ".%s" (jname_of_name (shortname field))
|
||||
| Larray _ -> assert false (* TODO java array *)
|
||||
|
||||
let rec print_exp ff e p avs ts single =
|
||||
match e.e_desc with
|
||||
| Epattern l -> print_lhs ff l avs single
|
||||
| Econst c -> print_const ff c ts
|
||||
| Eop (op, es) -> print_op ff op es p avs ts single
|
||||
| Estruct (type_name,fields) ->
|
||||
let fields =
|
||||
List.sort
|
||||
(fun (ln1,_) (ln2,_) ->
|
||||
String.compare (shortname ln1) (shortname ln2))
|
||||
fields in
|
||||
let exps = List.map (fun (_,e) -> e) fields in
|
||||
fprintf ff "new %a(@[<hov>"
|
||||
print_shortname type_name;
|
||||
print_exps ff exps 0 avs ts single;
|
||||
fprintf ff "@])"
|
||||
| Earray _ -> assert false (* TODO array *)
|
||||
|
||||
and print_exps ff es p avs ts single =
|
||||
match es with
|
||||
| [] -> ()
|
||||
| [e] -> print_exp ff e p avs ts single
|
||||
| e :: es' ->
|
||||
print_exp ff e p avs ts single;
|
||||
fprintf ff ",@ ";
|
||||
print_exps ff es' p avs ts single
|
||||
|
||||
and print_op ff op es p avs ts single =
|
||||
match (shortname op), es with
|
||||
| (("+" | "-" | "*" | "/"
|
||||
|"+." | "-." | "*." | "/."
|
||||
| "=" | "<>" | "<" | "<="
|
||||
| ">" | ">=" | "&" | "or") as op_name, [e1;e2]) ->
|
||||
let p' = priority op_name in
|
||||
if p' < p then fprintf ff "(" else ();
|
||||
print_exp ff e1 p' avs ts single;
|
||||
fprintf ff " %s " (javaop_of_op op_name);
|
||||
print_exp ff e2 p' avs ts single;
|
||||
if p' < p then fprintf ff ")" else ()
|
||||
| "not", [e] ->
|
||||
fprintf ff "!";
|
||||
print_exp ff e 6 avs ts single;
|
||||
| "~-", [e] ->
|
||||
fprintf ff "-";
|
||||
print_exp ff e 6 avs ts single;
|
||||
| _ ->(*
|
||||
begin
|
||||
begin
|
||||
match op with
|
||||
| Name(op_name) ->
|
||||
print_name ff op_name;
|
||||
| Modname({ qual = mod_name; id = op_name }) ->
|
||||
fprintf ff "%a.%a"
|
||||
print_name (String.uncapitalize mod_name)
|
||||
print_name op_name
|
||||
end;
|
||||
fprintf ff "@[(";
|
||||
print_exps ff es 0 avs ts single;
|
||||
fprintf ff ")@]"
|
||||
end *)
|
||||
assert false (* TODO java *)
|
||||
|
||||
let rec print_proj ff xs ao avs single =
|
||||
let rec walk ind = function
|
||||
| [] -> ()
|
||||
| x :: xs' ->
|
||||
print_lhs ff x avs single;
|
||||
fprintf ff " = %s.c_%d;@ " ao ind;
|
||||
walk (ind + 1) xs'
|
||||
in walk 1 xs
|
||||
|
||||
|
||||
let bool_case = function
|
||||
| [] -> assert false
|
||||
| ("true", _) :: _
|
||||
| ("false", _) :: _ -> true
|
||||
| _ -> false
|
||||
|
||||
let obj_ref_to_string = function
|
||||
| Oobj o -> o
|
||||
| Oarray (o,p) -> o (* TODO java array *)
|
||||
|
||||
let rec print_act ff a objs avs ts single =
|
||||
match a with
|
||||
| Aassgn (x, e) ->
|
||||
fprintf ff "@[";
|
||||
print_asgn ff x e avs ts single;
|
||||
fprintf ff ";@]"
|
||||
| Acall (xs,oref,Mstep,es) ->
|
||||
let o = obj_ref_to_string oref in
|
||||
(match xs with
|
||||
| [x] ->
|
||||
print_lhs ff x avs single;
|
||||
fprintf ff " = %s.step(" o;
|
||||
fprintf ff "@[";
|
||||
print_exps ff es 0 avs ts single;
|
||||
fprintf ff "@]";
|
||||
fprintf ff ");@ "
|
||||
| xs ->
|
||||
let cn = (List.find (fun od -> od.o_name = o) objs).o_class in
|
||||
let at = (jname_of_name (shortname cn)) ^ "Answer" in
|
||||
let ao = o ^ "_ans" in
|
||||
fprintf ff "%s %s = new %s();@ " at ao at;
|
||||
fprintf ff "%s = %s.step(" ao o;
|
||||
fprintf ff "@[";
|
||||
print_exps ff es 0 avs ts single;
|
||||
fprintf ff "@]";
|
||||
fprintf ff ");@ ";
|
||||
print_proj ff xs ao avs single)
|
||||
| Acase (e, grds) ->
|
||||
let grds =
|
||||
List.map
|
||||
(fun (ln,act) -> (shortname ln),act) grds in
|
||||
if bool_case grds
|
||||
then print_if ff e grds objs avs ts single
|
||||
else (fprintf ff "@[<v>@[<v 2>switch (%a) {@ "
|
||||
(fun ff e -> print_exp ff e 0 avs ts single) e;
|
||||
print_grds ff grds objs avs ts single;
|
||||
fprintf ff "@]@ }@]");
|
||||
| Acall (_,oref,Mreset,_) ->
|
||||
let o = obj_ref_to_string oref in
|
||||
fprintf ff "%s.reset();" o
|
||||
| Afor _ -> assert false (* TODO java array *)
|
||||
|
||||
|
||||
and print_grds ff grds objs avs ts single =
|
||||
match grds with
|
||||
| [] -> ()
|
||||
| (tg, b) :: grds' ->
|
||||
(* retrieve class name *)
|
||||
let cn = (fst
|
||||
(List.find
|
||||
(fun (tn, tgs) ->
|
||||
List.exists (fun tg' -> tg = tg') tgs)
|
||||
ts)) in
|
||||
fprintf ff "@[<v 2>case %a.%a:@ "
|
||||
print_name cn
|
||||
print_name tg;
|
||||
print_block ff b objs avs ts single;
|
||||
fprintf ff "@ break;@ @]@ ";
|
||||
print_grds ff grds' objs avs ts single
|
||||
|
||||
and print_if ff e grds objs avs ts single =
|
||||
match grds with
|
||||
| [("true", a)] ->
|
||||
fprintf ff "@[<v>@[<v 2>if (%a) {@ "
|
||||
(fun ff e -> print_exp ff e 0 avs ts single) e;
|
||||
print_block ff a objs avs ts single;
|
||||
fprintf ff "@]@ }@]"
|
||||
| [("false", a)] ->
|
||||
fprintf ff "@[<v>@[<v 2>if (!%a) {@ "
|
||||
(fun ff e -> print_exp ff e 6 avs ts single) e;
|
||||
print_block ff a objs avs ts single;
|
||||
fprintf ff "@]@ }@]"
|
||||
| [("true", a1); ("false", a2)] ->
|
||||
fprintf ff "@[<v>@[<v 2>if (%a) {@ "
|
||||
(fun ff e -> print_exp ff e 0 avs ts single) e;
|
||||
print_block ff a1 objs avs ts single;
|
||||
fprintf ff "@]@ @[<v 2>} else {@ ";
|
||||
print_block ff a2 objs avs ts single;
|
||||
fprintf ff "@]@ }@]"
|
||||
| [("false", a2); ("true", a1)] ->
|
||||
fprintf ff "@[<v>@[<v 2>if (%a) {@ "
|
||||
(fun ff e -> print_exp ff e 0 avs ts single) e;
|
||||
print_block ff a1 objs avs ts single;
|
||||
fprintf ff "@]@ @[<v 2>} else {@ ";
|
||||
print_block ff a2 objs avs ts single;
|
||||
fprintf ff "@]@ }@]"
|
||||
| _ -> assert false
|
||||
|
||||
and print_asgn ff x e avs ts single =
|
||||
fprintf ff "@[";
|
||||
print_lhs ff x avs single;
|
||||
fprintf ff " = ";
|
||||
print_exp ff e 0 avs ts single;
|
||||
fprintf ff "@]"
|
||||
|
||||
and print_block ff b objs avs ts single = () (* TODO urgent java *)
|
||||
|
||||
let print_vd ff vd =
|
||||
let jty,jdv = java_type_default_value vd.v_type in
|
||||
fprintf ff "@[<v>";
|
||||
print_name ff jty;
|
||||
fprintf ff " %s = %s;"
|
||||
(jname_of_name (name vd.v_ident))
|
||||
jdv;
|
||||
fprintf ff "@]"
|
||||
|
||||
let print_obj ff od =
|
||||
fprintf ff "@[<v>";
|
||||
fprintf ff "%a %a = new %a();"
|
||||
print_shortname od.o_class
|
||||
print_name od.o_name
|
||||
print_shortname od.o_class;
|
||||
fprintf ff "@]"
|
||||
|
||||
let rec print_objs ff ods =
|
||||
match ods with
|
||||
| [] -> ()
|
||||
| od :: ods' ->
|
||||
print_obj ff od;
|
||||
fprintf ff "@ ";
|
||||
print_objs ff ods'
|
||||
|
||||
let print_comps ff fds=
|
||||
let rec walk n = function
|
||||
| [] -> ()
|
||||
| fd :: fds' ->
|
||||
fprintf ff "@ ";
|
||||
fprintf ff "public ";
|
||||
print_type ff fd.v_type;
|
||||
fprintf ff " c_%s;" (string_of_int n);
|
||||
walk (n + 1) fds'
|
||||
in walk 1 fds
|
||||
|
||||
let print_ans_struct ff name fields =
|
||||
fprintf ff "@[<v>@[<v 2>public class %s {" name;
|
||||
print_comps ff fields;
|
||||
fprintf ff "@]@ }@]@ "
|
||||
|
||||
let print_vd' ff vd =
|
||||
fprintf ff "@[";
|
||||
print_type ff vd.v_type;
|
||||
fprintf ff "@ %s" (jname_of_name (name vd.v_ident));
|
||||
fprintf ff "@]"
|
||||
|
||||
let rec print_in ff = function
|
||||
| [] -> ()
|
||||
| [vd] -> print_vd' ff vd
|
||||
| vd :: vds' ->
|
||||
print_vd' ff vd;
|
||||
fprintf ff ",@ ";
|
||||
print_in ff vds'
|
||||
|
||||
let rec print_mem ff = function
|
||||
| [] -> ()
|
||||
| vd :: m' ->
|
||||
print_vd ff vd;
|
||||
fprintf ff "@ ";
|
||||
print_mem ff m'
|
||||
|
||||
let print_loc ff vds = print_mem ff vds
|
||||
|
||||
let print_step ff n s objs ts single =
|
||||
let n = jname_of_name n in
|
||||
fprintf ff "@[<v>@ @[<v 2>public ";
|
||||
if single then print_type ff (List.hd s.m_outputs).v_type
|
||||
else fprintf ff "%s" (n ^ "Answer");
|
||||
fprintf ff " step(@[";
|
||||
print_in ff s.m_inputs;
|
||||
fprintf ff "@]) {@ ";
|
||||
let loc = if single then (List.hd s.m_outputs) :: s.m_body.b_locals else s.m_body.b_locals in
|
||||
if loc = [] then () else (print_loc ff loc; fprintf ff "@ ");
|
||||
if single then fprintf ff "@ "
|
||||
else fprintf ff "%sAnswer step_ans = new %sAnswer();@ @ " n n;
|
||||
print_act ff s.bd objs
|
||||
(List.map (fun vd -> vd.v_ident) s.out) ts single;
|
||||
fprintf ff "@ @ return ";
|
||||
if single
|
||||
then fprintf ff "%s" (jname_of_name (Idents.name (List.hd s.out).v_ident))
|
||||
else fprintf ff "step_ans";
|
||||
fprintf ff ";@]@ }@ @]"
|
||||
|
||||
let print_reset ff r ts =
|
||||
fprintf ff "@[<v>@ @[<v 2>public void reset() {@ ";
|
||||
print_act ff r [] [] ts false;
|
||||
fprintf ff "@]@ }@ @]"
|
||||
|
||||
let print_class ff headers ts single opened_mod cl =
|
||||
let clid = jname_of_name cl.cl_id in
|
||||
List.iter (fprintf ff "%s") headers;
|
||||
(* fprintf ff "@[<v>package %s;@\n@\n" headers; *)
|
||||
(* import opened modules *)
|
||||
List.iter
|
||||
(fun m ->
|
||||
fprintf ff "import %s.*;@\n" (String.uncapitalize m))
|
||||
opened_mod;
|
||||
|
||||
fprintf ff "@\n@[<v 2>public class %s {@ " clid;
|
||||
if cl.mem = [] then ()
|
||||
else fprintf ff "@[<v>@ "; print_mem ff cl.mem; fprintf ff "@]";
|
||||
if cl.objs = [] then ()
|
||||
else fprintf ff "@[<v>@ "; print_objs ff cl.objs; fprintf ff "@]";
|
||||
print_reset ff cl.reset ts;
|
||||
print_step ff clid cl.step cl.objs ts single;
|
||||
fprintf ff "@]@ }@]"
|
||||
|
||||
let print_class_and_answer_to_file java_dir headers ts opened_mod cl =
|
||||
let clid = jname_of_name cl.cl_id in
|
||||
let print_class_to_file single =
|
||||
let out_ch = open_out (java_dir ^ "/" ^ clid ^ ".java") in
|
||||
let ff = formatter_of_out_channel out_ch in
|
||||
Misc.print_header_info ff "/*" "*/";
|
||||
print_class ff headers ts single opened_mod cl;
|
||||
fprintf ff "@.";
|
||||
close_out out_ch
|
||||
in
|
||||
match cl.step.out with
|
||||
| [_] -> print_class_to_file true
|
||||
| _ ->
|
||||
let out_ch = open_out (java_dir ^ "/" ^ clid ^ "Answer.java") in
|
||||
let ff = formatter_of_out_channel out_ch in
|
||||
Misc.print_header_info ff "/*" "*/";
|
||||
List.iter (fprintf ff "%s") headers;
|
||||
(* fprintf ff "@[<v>package %s;@\n@\n" headers; *)
|
||||
List.iter
|
||||
(fun m ->
|
||||
fprintf ff "import %s.*;@\n" (String.uncapitalize m))
|
||||
opened_mod;
|
||||
print_ans_struct ff (clid ^ "Answer") cl.step.out;
|
||||
fprintf ff "@.";
|
||||
close_out out_ch;
|
||||
print_class_to_file false
|
||||
|
||||
let print_classes java_dir headers ts opened_mod cls =
|
||||
List.iter
|
||||
(print_class_and_answer_to_file java_dir headers ts opened_mod)
|
||||
cls
|
||||
|
||||
(******************************)
|
||||
let print java_dir p =
|
||||
let headers =
|
||||
List.map snd
|
||||
(List.filter
|
||||
(fun (tag,_) -> tag = "java")
|
||||
p.o_pragmas) in
|
||||
print_types java_dir headers p.o_types;
|
||||
o_types := p.o_types;
|
||||
print_classes
|
||||
java_dir headers
|
||||
(List.flatten
|
||||
(List.map
|
||||
(function
|
||||
| { t_desc = Type_abs } -> []
|
||||
| { t_name = tn; t_desc = Type_enum tgs } -> [tn, tgs]
|
||||
| { t_name = tn; t_desc = Type_struct fields } ->
|
||||
[tn, (List.map fst fields)])
|
||||
p.o_types))
|
||||
p.o_opened
|
||||
p.o_defs
|
||||
|
||||
(******************************)
|
@ -0,0 +1,98 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Heptagon *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
|
||||
(** Sequential caml code. *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
open Idents
|
||||
open Location
|
||||
|
||||
type caml_code =
|
||||
{ c_types: (string, type_definition) Hashtbl.t;
|
||||
c_defs: (string * cexp) list;
|
||||
}
|
||||
|
||||
and immediate =
|
||||
Cbool of bool
|
||||
| Cint of int
|
||||
| Cfloat of float
|
||||
| Cchar of char
|
||||
| Cstring of string
|
||||
| Cvoid
|
||||
|
||||
and cexp =
|
||||
Cconstant of immediate
|
||||
| Cglobal of qualified_ident
|
||||
| Cvar of string
|
||||
| Cconstruct of qualified_ident * cexp list
|
||||
| Capply of cexp * cexp list
|
||||
| Cfun of pattern list * cexp
|
||||
| Cletin of is_rec * (pattern * cexp) list * cexp
|
||||
| Cifthenelse of cexp * cexp * cexp
|
||||
| Cifthen of cexp * cexp
|
||||
| Cmatch of cexp * (pattern * cexp) list
|
||||
| Ctuple of cexp list
|
||||
| Crecord of (qualified_ident * cexp) list
|
||||
| Crecord_access of cexp * qualified_ident
|
||||
| Cseq of cexp list
|
||||
| Cderef of cexp
|
||||
| Cref of cexp
|
||||
| Cset of string * cexp
|
||||
| Clabelset of string * string * cexp
|
||||
| Cmagic of cexp
|
||||
|
||||
and is_rec = bool
|
||||
|
||||
and pattern =
|
||||
Cconstantpat of immediate
|
||||
| Cvarpat of string
|
||||
| Cconstructpat of qualified_ident * pattern list
|
||||
| Ctuplepat of pattern list
|
||||
| Crecordpat of (qualified_ident * pattern) list
|
||||
| Corpat of pattern * pattern
|
||||
| Caliaspat of pattern * string
|
||||
| Cwildpat
|
||||
|
||||
let cvoidpat = Cconstantpat(Cvoid)
|
||||
let cvoid = Cconstant(Cvoid)
|
||||
let crefvoid = Cref(cvoid)
|
||||
let cfalse = Cconstant(Cbool(false))
|
||||
let ctrue = Cconstant(Cbool(true))
|
||||
let creftrue = Cref(ctrue)
|
||||
let cdummy = Cmagic (Cconstant (Cvoid))
|
||||
let cand_op = {qual = pervasives_module;id = "&&"}
|
||||
let cor_op = {qual = pervasives_module;id = "or"}
|
||||
let cnot_op = {qual = pervasives_module;id = "not"}
|
||||
let cand c1 c2 = Capply (Cglobal (cand_op), [c1;c2])
|
||||
let cor c1 c2 = Capply (Cglobal (cor_op), [c1;c2])
|
||||
let cnot c = Capply(Cglobal (cnot_op),[c])
|
||||
let cvoidfun e = Cfun([cvoidpat], e)
|
||||
let cvoidapply e = Capply(e, [cvoid])
|
||||
let cfun params e =
|
||||
match params, e with
|
||||
| params, Cfun(others, e) -> Cfun(params @ others, e)
|
||||
| [], _ -> cvoidfun e
|
||||
| _ -> Cfun(params, e)
|
||||
let capply e l = match l with [] -> cvoidapply e | _ -> Capply(e, l)
|
||||
let cifthen c e = match c with Cconstant(Cbool(true)) -> e | _ -> Cifthen(c, e)
|
||||
let cifthenelse c e1 e2 =
|
||||
match c with
|
||||
| Cconstant(Cbool(true)) -> e1
|
||||
| Cconstant(Cbool(false)) -> e2
|
||||
| _ -> Cifthenelse(c, e1, e2)
|
||||
let cseq e1 e2 =
|
||||
match e1, e2 with
|
||||
| Cconstant(Cvoid), _ -> e2
|
||||
| _, Cconstant(Cvoid) -> e1
|
||||
| e1, Cseq l2 -> Cseq(e1 :: l2)
|
||||
| Cseq(l1), e2 -> Cseq (l1 @ [e2])
|
||||
| _ -> Cseq[e1;e2]
|
||||
|
@ -0,0 +1,131 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: caml_aux.ml,v 1.1.1.1 2005-11-03 15:45:23 pouzet Exp $ *)
|
||||
|
||||
(* file caml-aux.ml *)
|
||||
(* auxiliary functions for caml expressions *)
|
||||
(* free variables *)
|
||||
|
||||
open Misc;;
|
||||
open Caml;;
|
||||
open Declarative;;
|
||||
|
||||
(* convertions from declarative structures to caml ones *)
|
||||
(* immediates *)
|
||||
let caml_of_declarative_immediate = function
|
||||
| Dbool b -> if b then Ftrue else Ffalse
|
||||
| Dint i -> Fint i
|
||||
| Dfloat f -> Ffloat f
|
||||
| Dchar c -> Fchar c
|
||||
| Dstring s -> Fstring s
|
||||
|
||||
(* globals *)
|
||||
let string_of_global g =
|
||||
let pref = g.dqualid.dqual in
|
||||
(if (pref <> "") && (pref <> "Lucy_pervasives") then
|
||||
g.dqualid.dqual^"."
|
||||
else "") ^ g.dqualid.did
|
||||
|
||||
(* pat_desc *)
|
||||
let rec caml_pattern_of_pat_desc = function
|
||||
| Dvarpat i -> Fvarpat ("x__"^(string_of_int i))
|
||||
| Dconstantpat i -> Fimpat (caml_of_declarative_immediate i)
|
||||
| Dtuplepat pl -> Ftuplepat (List.map caml_of_declarative_pattern pl)
|
||||
| Dconstruct0pat g -> Fconstruct0pat (string_of_global g)
|
||||
| Dconstruct1pat (g,p) -> Fconstruct1pat (string_of_global g,
|
||||
caml_of_declarative_pattern p)
|
||||
| Drecordpat gpl -> Frecordpat (List.map
|
||||
(fun (x,y) ->
|
||||
(string_of_global x,
|
||||
caml_of_declarative_pattern y))
|
||||
gpl)
|
||||
(* patterns *)
|
||||
and caml_of_declarative_pattern p = caml_pattern_of_pat_desc p.dp_desc
|
||||
(* ---- end of convertions *)
|
||||
|
||||
let rec flat_exp_of_pattern = function
|
||||
| Fpunit -> Fim Funit
|
||||
| Fimpat i -> Fim i
|
||||
| Fvarpat v -> Fvar { cvar_name=v; cvar_imported=false }
|
||||
| Fconstruct0pat c -> Fconstruct0 c
|
||||
| Fconstruct1pat (c,p) -> Fconstruct1 (c, flat_exp_of_pattern p)
|
||||
| Ftuplepat pl -> Ftuple (List.map flat_exp_of_pattern pl)
|
||||
| Frecordpat cpl ->
|
||||
Frecord (List.map (fun (x,y) -> (x,flat_exp_of_pattern y)) cpl)
|
||||
|
||||
(* small functions manipulating lists *)
|
||||
let union x1 x2 =
|
||||
let rec rec_union l = function
|
||||
[] -> l
|
||||
| h::t -> if List.mem h l then (rec_union l t) else (rec_union (h::l) t)
|
||||
in
|
||||
rec_union x1 x2
|
||||
|
||||
let subtract x1 x2 =
|
||||
let rec sub l = function
|
||||
[] -> l
|
||||
| h::t -> if List.mem h x2 then (sub l t) else (sub (h::l) t)
|
||||
in
|
||||
sub [] x1
|
||||
|
||||
let flat l =
|
||||
let rec f ac = function
|
||||
[] -> ac
|
||||
| t::q -> f (ac@t) q
|
||||
in
|
||||
f [] l
|
||||
|
||||
let intersect x1 x2 =
|
||||
let rec inter l = function
|
||||
[] -> l
|
||||
| h::t -> if List.mem h x1 then (inter (h::l) t) else (inter l t)
|
||||
in
|
||||
inter [] x2
|
||||
|
||||
(* make a variable *)
|
||||
let make_var n = Fvar {cvar_name = n;cvar_imported = false}
|
||||
and make_imported_var n b = Fvar {cvar_name = n;cvar_imported = b}
|
||||
|
||||
let nil_ident = "Lucy__nil"
|
||||
let state_ident = "Lucy__state"
|
||||
|
||||
(* makes a conditional *)
|
||||
let ifthenelse(c,e1,e2) =
|
||||
match c with
|
||||
Fim(Ftrue) -> e1
|
||||
| Fim(Ffalse) -> e2
|
||||
| _ -> Fifthenelse(c,e1,e2)
|
||||
|
||||
(* makes a list of conditionnals *)
|
||||
let ifseq l =
|
||||
let rec ifs l =
|
||||
let (c,e)::t = l in
|
||||
if t = [] then
|
||||
e
|
||||
else
|
||||
ifthenelse (c, e, ifs t)
|
||||
in
|
||||
ifs l
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,404 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: caml_printer.ml,v 1.20 2008-06-17 13:21:12 pouzet Exp $ *)
|
||||
|
||||
(** Printing [Caml] code *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
open Format
|
||||
open Declarative
|
||||
open Declarative_printer
|
||||
open Caml
|
||||
|
||||
(** Generic printing of a list.
|
||||
This function seems to appear in several places... *)
|
||||
let print_list print print_sep l =
|
||||
let rec printrec l =
|
||||
match l with
|
||||
[] -> ()
|
||||
| [x] ->
|
||||
print x
|
||||
| x::l ->
|
||||
open_box 0;
|
||||
print x;
|
||||
print_sep ();
|
||||
print_space ();
|
||||
printrec l;
|
||||
close_box () in
|
||||
printrec l
|
||||
|
||||
(** Prints an immediate. A patch is needed on float number for
|
||||
[ocaml] < 3.05. *)
|
||||
let print_immediate i =
|
||||
match i with
|
||||
Cbool(b) -> print_string (if b then "true" else "false")
|
||||
| Cint(i) -> print_int i
|
||||
| Cfloat(f) -> print_float f
|
||||
| Cchar(c) -> print_char '\''; print_char c; print_char '\''
|
||||
| Cstring(s) -> print_string "\"";
|
||||
print_string (String.escaped s);
|
||||
print_string "\""
|
||||
| Cvoid -> print_string "()"
|
||||
|
||||
(** Prints a name. Infix chars are surrounded by parenthesis *)
|
||||
let is_infix =
|
||||
let module StrSet = Set.Make(String) in
|
||||
let set_infix =
|
||||
List.fold_right
|
||||
StrSet.add
|
||||
["or"; "quo"; "mod"; "land"; "lor"; "lxor"; "lsl"; "lsr"; "asr"]
|
||||
StrSet.empty in
|
||||
fun s -> StrSet.mem s set_infix
|
||||
|
||||
let print_name s =
|
||||
let c = String.get s 0 in
|
||||
let s = if is_infix s then "(" ^ s ^ ")"
|
||||
else match c with
|
||||
| 'a' .. 'z' | 'A' .. 'Z' | '_' | '`' -> s
|
||||
| '*' -> "( " ^ s ^ " )"
|
||||
| _ -> if s = "()" then s else "(" ^ s ^ ")" in
|
||||
print_string s
|
||||
|
||||
(** Prints a global name *)
|
||||
let print_qualified_ident {qual=q;id=n} =
|
||||
(* special case for values imported from the standard library *)
|
||||
if (q = pervasives_module) or (q = Modules.compiled_module_name ())
|
||||
or (q = "")
|
||||
then print_name n
|
||||
else
|
||||
begin
|
||||
print_string q;
|
||||
print_string ".";
|
||||
print_name n
|
||||
end
|
||||
|
||||
let priority exp =
|
||||
match exp with
|
||||
Crecord _ | Crecord_access _ | Cvar _ | Ctuple _
|
||||
| Cglobal _ | Cconstant _ | Cconstruct(_, []) | Cderef _ -> 3
|
||||
| Clet _ | Cfun _ | Cseq _ -> 1
|
||||
| Cset _ | Clabelset _
|
||||
| Cref _ | Capply _ | Cmagic _ | Cconstruct _ -> 2
|
||||
| Cifthen _ | Cifthenelse _ | Cmatch _ -> 0
|
||||
|
||||
let priority_pattern p =
|
||||
match p with
|
||||
Cconstructpat _ | Cconstantpat _ | Cvarpat _
|
||||
| Ctuplepat _ | Crecordpat _ -> 2
|
||||
| _ -> 1
|
||||
|
||||
(** Emission of code *)
|
||||
let rec print pri e =
|
||||
open_box 2;
|
||||
(* if the priority of the context is higher than the *)
|
||||
(* priority of e, we ass a parenthesis *)
|
||||
let pri_e = priority e in
|
||||
if pri > pri_e then print_string "(";
|
||||
begin match e with
|
||||
Cconstant(e) -> print_immediate e
|
||||
| Cglobal(gl) -> print_qualified_ident gl
|
||||
| Cvar(s) -> print_name s
|
||||
| Cconstruct(gl, e_list) ->
|
||||
print_qualified_ident gl;
|
||||
if e_list <> [] then print_tuple e_list
|
||||
| Capply(f,l) ->
|
||||
print pri_e f;
|
||||
print_space ();
|
||||
print_list (print (pri_e + 1)) (fun () -> ()) l
|
||||
| Cfun(pat_list,e) ->
|
||||
print_string "fun";
|
||||
print_space ();
|
||||
print_list (print_pattern 0) (fun () -> ()) pat_list;
|
||||
print_space ();
|
||||
print_string "->";
|
||||
print_space ();
|
||||
print 0 e
|
||||
(* local definition *)
|
||||
| Clet(is_rec, l, e) -> print_let is_rec l e
|
||||
| Cifthenelse(e1,e2,e3) ->
|
||||
print_string "if";
|
||||
print_space ();
|
||||
print (pri_e - 1) e1;
|
||||
print_space ();
|
||||
print_string "then";
|
||||
print_space ();
|
||||
print 2 e2;
|
||||
print_space ();
|
||||
print_string "else";
|
||||
print_space ();
|
||||
print 2 e3
|
||||
| Cifthen(e1,e2) ->
|
||||
print_string "if";
|
||||
print_space ();
|
||||
print (pri_e - 1) e1;
|
||||
print_space ();
|
||||
print_string "then";
|
||||
print_space ();
|
||||
print 2 e2
|
||||
| Ctuple(l) -> print_tuple l
|
||||
| Crecord(l) ->
|
||||
print_string "{";
|
||||
print_list
|
||||
(fun (gl, e) -> print_qualified_ident gl;
|
||||
print_string " = ";
|
||||
print 1 e)
|
||||
(fun () -> print_string ";") l;
|
||||
print_string "}"
|
||||
| Crecord_access(e, gl) ->
|
||||
print pri_e e;
|
||||
print_string ".";
|
||||
print_qualified_ident gl
|
||||
| Cmatch(e,l) ->
|
||||
print_string "match ";
|
||||
print 0 e;
|
||||
print_string " with";
|
||||
print_space ();
|
||||
List.iter
|
||||
(fun pat_expr ->
|
||||
print_string "| ";
|
||||
print_match_pat_expr 2 pat_expr) l
|
||||
| Cseq l -> print_list (print 2) (fun () -> print_string ";") l
|
||||
| Cderef(e) ->
|
||||
print_string "!";
|
||||
print pri_e e
|
||||
| Cref(e) ->
|
||||
print_string "ref";
|
||||
print_space ();
|
||||
print (pri_e + 1) e
|
||||
| Cset(s, e) ->
|
||||
print_string s;
|
||||
print_string " :=";
|
||||
print_space ();
|
||||
print pri_e e
|
||||
| Clabelset(s, l, e) ->
|
||||
print_string s;
|
||||
print_string ".";
|
||||
print_string l;
|
||||
print_space ();
|
||||
print_string "<-";
|
||||
print_space ();
|
||||
print pri_e e
|
||||
| Cmagic(e) ->
|
||||
print_string "Obj.magic";
|
||||
print_space ();
|
||||
print (pri_e+1) e
|
||||
end;
|
||||
if pri > pri_e then print_string ")";
|
||||
close_box()
|
||||
|
||||
and print_tuple e_list =
|
||||
print_string "(";
|
||||
print_list (print 2) (fun () -> print_string ",") e_list;
|
||||
print_string ")"
|
||||
|
||||
and print_let_pat_expr (pat, expr) =
|
||||
match pat, expr with
|
||||
pat, Cfun(pat_list, expr) ->
|
||||
open_box 2;
|
||||
print_list (print_pattern 0) (fun () -> ()) (pat :: pat_list);
|
||||
print_string " =";
|
||||
print_space ();
|
||||
print 0 expr;
|
||||
close_box ()
|
||||
| _ ->
|
||||
print_pattern 0 pat;
|
||||
print_string " = ";
|
||||
print 0 expr
|
||||
|
||||
and print_let is_rec l e =
|
||||
open_box 0;
|
||||
if is_rec then print_string "let rec " else print_string "let ";
|
||||
print_list print_let_pat_expr
|
||||
(fun () -> print_string "\n"; print_string "and ") l;
|
||||
print_string " in";
|
||||
print_break 1 0;
|
||||
print 0 e;
|
||||
close_box ()
|
||||
|
||||
and print_pattern pri pat =
|
||||
open_box 2;
|
||||
let pri_e = priority_pattern pat in
|
||||
if pri > pri_e then print_string "(";
|
||||
begin match pat with
|
||||
Cconstantpat(i) -> print_immediate i
|
||||
| Cvarpat(v) -> print_string v
|
||||
| Cconstructpat(gl, pat_list) ->
|
||||
print_qualified_ident gl;
|
||||
if pat_list <> [] then print_tuple_pat pat_list
|
||||
| Ctuplepat(pat_list) ->
|
||||
print_tuple_pat pat_list
|
||||
| Crecordpat(l) ->
|
||||
print_string "{";
|
||||
print_list (fun (gl, pat) -> print_qualified_ident gl;
|
||||
print_string "=";
|
||||
print_pattern (pri_e - 1) pat)
|
||||
(fun () -> print_string ";") l;
|
||||
print_string "}"
|
||||
| Corpat(pat1, pat2) ->
|
||||
print_pattern pri_e pat1;
|
||||
print_string "|";
|
||||
print_pattern pri_e pat2
|
||||
| Caliaspat(pat, s) ->
|
||||
print_pattern pri_e pat;
|
||||
print_space ();
|
||||
print_string "as";
|
||||
print_space ();
|
||||
print_string s
|
||||
| Cwildpat -> print_string "_"
|
||||
end;
|
||||
if pri > pri_e then print_string ")";
|
||||
close_box ()
|
||||
|
||||
and print_tuple_pat pat_list =
|
||||
print_string "(";
|
||||
print_list (print_pattern 0) (fun () -> print_string ",") pat_list;
|
||||
print_string ")"
|
||||
|
||||
and print_match_pat_expr prio (pat, expr) =
|
||||
open_box 2;
|
||||
print_pattern 0 pat;
|
||||
print_space (); print_string "->"; print_space ();
|
||||
print prio expr;
|
||||
close_box ();
|
||||
print_space ();;
|
||||
|
||||
(* print a definition *)
|
||||
let print_definition (name, e) =
|
||||
print_string "let ";
|
||||
print_let_pat_expr (Cvarpat(name), e)
|
||||
|
||||
(* print code *)
|
||||
let print_code e = print 0 e
|
||||
|
||||
(* print types *)
|
||||
let rec print_type typ =
|
||||
open_box 1;
|
||||
begin match typ with
|
||||
Darrow(is_node, typ1, typ2) ->
|
||||
print_type typ1;
|
||||
if is_node then print_string " => " else print_string " -> ";
|
||||
print_type typ2
|
||||
| Dproduct(ty_list) ->
|
||||
print_list print_type (fun _ -> print_string " *") ty_list
|
||||
| Dconstr(qual_ident, ty_list) ->
|
||||
if ty_list <> [] then
|
||||
begin
|
||||
print_string "(";
|
||||
print_list print_type (fun _ -> print_string ",") ty_list;
|
||||
print_string ")";
|
||||
print_space ()
|
||||
end;
|
||||
print_qualified_ident qual_ident
|
||||
| Dtypvar(i) -> print_type_name i
|
||||
| Dbase(b) -> print_base_type b
|
||||
| Dsignal(ty) -> print_type ty; print_space (); print_string "sig"
|
||||
end;
|
||||
close_box ()
|
||||
|
||||
and print_type_name n =
|
||||
print_string "'a";
|
||||
print_int n
|
||||
|
||||
and print_base_type b =
|
||||
match b with
|
||||
Dtyp_bool -> print_string "bool"
|
||||
| Dtyp_int -> print_string "int"
|
||||
| Dtyp_float -> print_string "float"
|
||||
| Dtyp_unit -> print_string "unit"
|
||||
| Dtyp_string -> print_string "string"
|
||||
| Dtyp_char -> print_string "char"
|
||||
|
||||
(* print variant *)
|
||||
let print_variant (qualid, { arg = typ_list; res = typ }) =
|
||||
print_string " | ";
|
||||
print_qualified_ident qualid;
|
||||
match typ_list with
|
||||
[] -> (* arity = 0 *)
|
||||
()
|
||||
| _ -> print_string " of ";
|
||||
print_list print_type (fun () -> print_string "*") typ_list
|
||||
|
||||
let print_record (qualid, is_mutable, { res = typ1 }) =
|
||||
if is_mutable then print_string "mutable ";
|
||||
print_qualified_ident qualid;
|
||||
print_string ":";
|
||||
print_type typ1;
|
||||
print_string ";"
|
||||
|
||||
let print_type_declaration s { d_type_desc = td; d_type_arity = l } =
|
||||
open_box 2;
|
||||
if l <> [] then
|
||||
begin
|
||||
print_string "(";
|
||||
print_list print_type_name (fun _ -> print_string ",") l;
|
||||
print_string ")";
|
||||
print_space ()
|
||||
end;
|
||||
print_string s;
|
||||
print_string " = ";
|
||||
begin match td with
|
||||
Dabstract_type -> ()
|
||||
| Dabbrev(ty) ->
|
||||
print_type ty
|
||||
| Dvariant_type variant_list ->
|
||||
List.iter print_variant variant_list
|
||||
| Drecord_type record_list ->
|
||||
print_string "{";
|
||||
print_list print_record (fun _ -> ()) record_list;
|
||||
print_string "}"
|
||||
end;
|
||||
print_newline ();
|
||||
close_box ()
|
||||
|
||||
let print_type_declarations l =
|
||||
let rec printrec l =
|
||||
match l with
|
||||
[] -> ()
|
||||
| [s, d] -> print_type_declaration s d
|
||||
| (s, d) :: l ->
|
||||
print_type_declaration s d;
|
||||
print_string "and ";
|
||||
printrec l in
|
||||
open_box 0;
|
||||
print_string "type ";
|
||||
printrec l;
|
||||
print_newline ();
|
||||
close_box ();;
|
||||
|
||||
(* the main function *)
|
||||
set_max_boxes max_int ;;
|
||||
|
||||
let output_expr oc e =
|
||||
(* emit on channel oc *)
|
||||
set_formatter_out_channel oc;
|
||||
print 0 e;
|
||||
print_flush ()
|
||||
|
||||
let output_code oc c =
|
||||
(* emit on channel oc *)
|
||||
set_formatter_out_channel oc;
|
||||
print_code c
|
||||
|
||||
let output_definitions oc d_list =
|
||||
(* emit on channel oc *)
|
||||
set_formatter_out_channel oc;
|
||||
print_list print_definition print_newline d_list;
|
||||
print_flush ()
|
||||
|
||||
let output oc caml_code =
|
||||
set_formatter_out_channel oc;
|
||||
(* print type declarations *)
|
||||
let l = Misc.listoftable caml_code.c_types in
|
||||
if l <> [] then print_type_declarations l;
|
||||
(* print value definitions *)
|
||||
print_list print_definition print_newline caml_code.c_code;
|
||||
print_flush ()
|
||||
|
@ -0,0 +1,46 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: cenvironment.ml,v 1.1 2006-03-18 08:04:25 pouzet Exp $ *)
|
||||
|
||||
open Misc
|
||||
open Declarative
|
||||
|
||||
(** Environment with static link **)
|
||||
type cblock =
|
||||
{ c_block: block; (* table of free names *)
|
||||
c_state: name; (* the name of the internal state *)
|
||||
c_write: name; (* temporary values *)
|
||||
}
|
||||
type env = cblock list
|
||||
let empty_env = []
|
||||
let current env = List.hd env
|
||||
let cblock env = (current env).c_block
|
||||
let statename env = (current env).c_state
|
||||
|
||||
let push_block block env =
|
||||
{ c_block = block;
|
||||
c_state = symbol#name;
|
||||
c_write = symbol#name } :: env
|
||||
let push block env =
|
||||
if env = empty_env
|
||||
then push_block block env
|
||||
else let cblock = current env in
|
||||
{ cblock with c_block = block } :: env
|
||||
let rec findall env i =
|
||||
match env with
|
||||
[] -> raise Not_found
|
||||
| { c_block = b; c_state = st; c_write = wt } :: env ->
|
||||
try
|
||||
Hashtbl.find b.b_env i, st, wt
|
||||
with
|
||||
Not_found -> findall env i
|
||||
let find env i =
|
||||
let id, _, _ = findall env i in
|
||||
id
|
@ -0,0 +1,848 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: coiteration.ml,v 1.27 2008-06-10 06:54:36 delaval Exp $ *)
|
||||
|
||||
|
||||
(** Translating [declarative] code into sequential [caml] code. *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
open Declarative
|
||||
open Rw
|
||||
open Dmisc
|
||||
open Caml
|
||||
open Cenvironment
|
||||
|
||||
let prefix_for_names = "_"
|
||||
let prefix_for_inits = "_init"
|
||||
let prefix_for_memos = "_pre"
|
||||
let prefix_for_statics = "_static"
|
||||
let prefix_for_clocks = "_cl"
|
||||
let prefix_for_lasts = "__last"
|
||||
|
||||
let prefix_state_type = "_state_"
|
||||
let prefix_state_constr = "`St_"
|
||||
let prefix_state_label = "_mem_"
|
||||
let prefix_state_constr_nil = "`Snil_"
|
||||
let prefix_for_self_state = "_self_"
|
||||
let prefix_for_temp = "_temp_"
|
||||
|
||||
(** the type of unknown states *)
|
||||
(* type 'a state = Snil | St of 'a *)
|
||||
let state_nil = Cconstruct(qualid prefix_state_constr_nil, [])
|
||||
let state_nil_pat = Cconstructpat(qualid prefix_state_constr_nil, [])
|
||||
let state_pat pat_list = Cconstructpat(qualid prefix_state_constr, pat_list)
|
||||
let state e_list = Cconstruct(qualid prefix_state_constr, e_list)
|
||||
let state_record name_e_list =
|
||||
Crecord(List.map (fun (name, e) -> (qualid name), e) name_e_list)
|
||||
|
||||
let intro_state_type () =
|
||||
let tname = prefix_state_type in
|
||||
let result_type =
|
||||
Dconstr(qualid prefix_state_type, [Dtypvar(0)]) in
|
||||
let variants =
|
||||
[(qualid prefix_state_constr_nil, { arg = []; res = result_type });
|
||||
(qualid prefix_state_constr, {arg = [Dtypvar(0)]; res = result_type})]
|
||||
in
|
||||
let type_def =
|
||||
{ d_type_desc = Dvariant_type(variants);
|
||||
d_type_arity = [0] } in
|
||||
add_type (tname, type_def)
|
||||
|
||||
(** introduce a new type for enumerated states *)
|
||||
(* type ('a1,...,'an) state_k = St1 of 'a1 | ... Stm of 'an *)
|
||||
let intro_enum_type n =
|
||||
let l = Misc.from n in
|
||||
(* name of the result type *)
|
||||
let tname = prefix_state_type ^ (string_of_int(symbol#name)) in
|
||||
let result_type =
|
||||
Dconstr(qualid tname, List.map (fun name -> Dtypvar(name)) l) in
|
||||
let variants =
|
||||
List.map
|
||||
(fun name ->
|
||||
(qualid (tname ^ prefix_state_constr ^ (string_of_int name)),
|
||||
{ arg = [Dtypvar(name)]; res = result_type })) l in
|
||||
let type_def =
|
||||
{ d_type_desc = Dvariant_type(variants);
|
||||
d_type_arity = l } in
|
||||
add_type (tname, type_def);
|
||||
tname ^ prefix_state_constr
|
||||
|
||||
(** introduce a new type for record states *)
|
||||
(* type ('a1,...,'an) state_k = {mutable name1:a1;...;mutable namen:an} *)
|
||||
let intro_record_type name_value_list =
|
||||
let l = Misc.from (List.length name_value_list) in
|
||||
let tname = prefix_state_type ^ (string_of_int(symbol#name)) in
|
||||
let result_type =
|
||||
Dconstr(qualid tname, List.map (fun name -> Dtypvar(name)) l) in
|
||||
let labels =
|
||||
List.map2
|
||||
(fun (name,_) ai ->
|
||||
(qualid name,
|
||||
true,
|
||||
{ res = Dtypvar(ai); arg = result_type })) name_value_list l in
|
||||
let type_def =
|
||||
{ d_type_desc = Drecord_type(labels);
|
||||
d_type_arity = l } in
|
||||
add_type (tname, type_def)
|
||||
|
||||
(** the intermediate code generated during the compilation process *)
|
||||
type tcode =
|
||||
Tlet of pattern * cexp
|
||||
| Tset of string * cexp
|
||||
| Tlabelset of string * string * cexp
|
||||
| Tletrec of (pattern * cexp) list
|
||||
| Texp of cexp
|
||||
|
||||
(* and its translation into caml code *)
|
||||
let rec clet tcode ce =
|
||||
let code2c tcode ce =
|
||||
match tcode with
|
||||
Tlet(p, c) -> Clet(false, [p,c], ce)
|
||||
| Tset(s, e) -> cseq (Cset(s,e)) ce
|
||||
| Tlabelset(s, n, e) -> cseq (Clabelset(s, n, e)) ce
|
||||
| Tletrec(l) -> Clet(true, l, ce)
|
||||
| Texp(c) when ce = cvoid -> c
|
||||
| Texp(c) -> cseq c ce in
|
||||
match tcode with
|
||||
[] -> ce
|
||||
| tc :: tcode -> code2c tc (clet tcode ce)
|
||||
|
||||
let cseq tcode = clet tcode cvoid
|
||||
let ifthen c ce =
|
||||
match c with
|
||||
Cconstant(Cbool(true)) -> ce
|
||||
| _ -> Cifthen(c, ce)
|
||||
|
||||
let merge code ce l =
|
||||
(* we make special treatments for conditionals *)
|
||||
match l with
|
||||
[] -> code
|
||||
| [Cconstantpat(Cbool(b1)), c1;
|
||||
Cconstantpat(Cbool(b2)), c2] ->
|
||||
if b1 then
|
||||
Texp(Cifthenelse(ce, c1, c2)) :: code
|
||||
else
|
||||
Texp(Cifthenelse(ce, c2, c1)) :: code
|
||||
(* general case *)
|
||||
| _ -> Texp(Cmatch(ce, l)) :: code
|
||||
|
||||
|
||||
(** extract the set of static computations from an expression *)
|
||||
let rec static acc e =
|
||||
let acc, desc = match e.d_desc with
|
||||
| Dconstant _ | Dvar _ | Dfun _ -> acc, e.d_desc
|
||||
| Dtuple l ->
|
||||
let acc, l = static_list acc l in
|
||||
acc, Dtuple(l)
|
||||
| Dprim(g, e_list) ->
|
||||
(* pointwise application *)
|
||||
let acc, e_list = static_list acc e_list in
|
||||
acc, Dprim(g, e_list)
|
||||
| Dconstruct(g, e_list) ->
|
||||
let acc, e_list = static_list acc e_list in
|
||||
acc, Dconstruct(g, e_list)
|
||||
| Drecord(gl_expr_list) ->
|
||||
let static_record (gl, expr) (acc, gl_expr_list) =
|
||||
let acc, e = static acc expr in
|
||||
acc, (gl, e) :: gl_expr_list in
|
||||
let acc, l =
|
||||
List.fold_right static_record gl_expr_list (acc, []) in
|
||||
acc, Drecord(l)
|
||||
| Drecord_access(expr, gl) ->
|
||||
let acc, e = static acc expr in
|
||||
acc, Drecord_access(e, gl)
|
||||
| Difthenelse(e0, e1, e2) ->
|
||||
let acc, e0 = static acc e0 in
|
||||
let acc, e1 = static acc e1 in
|
||||
let acc, e2 = static acc e2 in
|
||||
acc, Difthenelse(e0, e1, e2)
|
||||
| Dlet(block, e_let) ->
|
||||
let acc, block = static_block acc block in
|
||||
let acc, e = static acc e_let in
|
||||
acc, Dlet(block, e_let)
|
||||
| Dapply(is_state, f, l) ->
|
||||
let acc, f = static acc f in
|
||||
let acc, l = static_list acc l in
|
||||
acc, Dapply(is_state, f, l)
|
||||
| Deseq(e1, e2) ->
|
||||
let acc, e1 = static acc e1 in
|
||||
let acc, e2 = static acc e2 in
|
||||
acc, Deseq(e1, e2)
|
||||
| Dwhen(e1) ->
|
||||
let acc, e1 = static acc e1 in
|
||||
acc, Dwhen(e1)
|
||||
| Dclock(ck) ->
|
||||
acc, Dclock(ck)
|
||||
| Dlast _ | Dinit _ | Dpre _ | Dtest _ ->
|
||||
(* this case should not arrive *)
|
||||
fatal_error "static" in
|
||||
acc, { e with d_desc = desc }
|
||||
|
||||
and static_list acc l =
|
||||
match l with
|
||||
[] -> acc, []
|
||||
| e :: l ->
|
||||
let acc, e = static acc e in
|
||||
let acc, l = static_list acc l in
|
||||
acc, e :: l
|
||||
|
||||
and static_block acc b =
|
||||
let acc, eq = static_eq acc b.b_equations in
|
||||
acc, { b with b_equations = eq }
|
||||
|
||||
(* extract the set of static computations from an equation *)
|
||||
and static_eqs acc eq_list =
|
||||
match eq_list with
|
||||
[] -> acc, []
|
||||
| eq :: eq_list ->
|
||||
let acc, eq = static_eq acc eq in
|
||||
let acc, eq_list = static_eqs acc eq_list in
|
||||
acc, dcons eq eq_list
|
||||
|
||||
and static_eq acc eq =
|
||||
match eq with
|
||||
Dget _ -> acc, eq
|
||||
| Dequation(pat, e) ->
|
||||
let acc, e = static acc e in
|
||||
acc, Dequation(pat, e)
|
||||
| Dwheneq(eq, ck) ->
|
||||
let acc, eq = static_eq acc eq in
|
||||
acc, Dwheneq(eq, ck)
|
||||
| Dmerge(is_static, e, p_block_list) ->
|
||||
let acc, e = static acc e in
|
||||
let acc, p_block_list = static_pat_block_list acc p_block_list in
|
||||
acc, Dmerge(is_static, e, p_block_list)
|
||||
| Dnext(n, e) ->
|
||||
let acc, e = static acc e in
|
||||
acc, Dnext(n, e)
|
||||
| Dseq(eq_list) ->
|
||||
let acc, eq_list = static_eqs acc eq_list in
|
||||
acc, Dseq(eq_list)
|
||||
| Dpar(eq_list) ->
|
||||
let acc, eq_list = static_eqs acc eq_list in
|
||||
acc, Dpar(eq_list)
|
||||
| Dblock(block) ->
|
||||
let acc, block = static_block acc block in
|
||||
acc, Dblock(block)
|
||||
| Dstatic(pat, e) ->
|
||||
(pat, e) :: acc, no_equation
|
||||
| Demit _ | Dlasteq _ | Dautomaton _ | Dreset _ | Dpresent _ ->
|
||||
(* these cases should not arrive since control structures have *)
|
||||
(* been translated into the basic kernel *)
|
||||
fatal_error "static_eq"
|
||||
|
||||
and static_pat_block_list acc p_block_list =
|
||||
(* treat one handler *)
|
||||
let static_pat_block acc (pat, block) =
|
||||
let acc, block = static_block acc block in
|
||||
acc, (pat, block) in
|
||||
match p_block_list with
|
||||
[] -> acc, []
|
||||
| pat_block :: pat_block_list ->
|
||||
let acc, pat_block = static_pat_block acc pat_block in
|
||||
let acc, pat_block_list = static_pat_block_list acc pat_block_list in
|
||||
acc, pat_block :: pat_block_list
|
||||
|
||||
(** Auxiliary definitions **)
|
||||
let string_of_ident ident =
|
||||
let prefix =
|
||||
match ident.id_kind with
|
||||
Kinit -> prefix_for_inits
|
||||
| Kstatic -> prefix_for_statics
|
||||
| Kmemo -> prefix_for_memos
|
||||
| Kclock -> prefix_for_clocks
|
||||
| Klast -> prefix_for_lasts
|
||||
| _ -> prefix_for_names in
|
||||
let suffix =
|
||||
match ident.id_original with
|
||||
None -> ""
|
||||
| Some(n) when (is_an_infix_or_prefix_operator n) -> "__infix"
|
||||
| Some(n) -> "__" ^ n in
|
||||
prefix ^ (string_of_int ident.id_name) ^ suffix
|
||||
|
||||
let string_of_name env i =
|
||||
(* find the original name when it exists *)
|
||||
let ident = find env i in
|
||||
string_of_ident ident
|
||||
|
||||
let name i = prefix_for_names ^ (string_of_int i)
|
||||
let memo i = prefix_for_memos ^ (string_of_int i)
|
||||
let initial i = prefix_for_inits ^ (string_of_int i)
|
||||
let clock i = prefix_for_clocks ^ (string_of_int i)
|
||||
let stat i = prefix_for_statics ^ (string_of_int i)
|
||||
|
||||
(* the name of the current state *)
|
||||
let selfstate env = prefix_for_self_state ^ (string_of_int (statename env))
|
||||
|
||||
(* access to a write variable *)
|
||||
let access_write wt s = Cderef (Cvar s)
|
||||
|
||||
(* makes an access to a name *)
|
||||
let access env i =
|
||||
let ident, st, wt = findall env i in
|
||||
let s = string_of_ident ident in
|
||||
match ident.id_kind with
|
||||
Kinit | Kmemo | Kstatic ->
|
||||
Crecord_access(Cvar(prefix_for_self_state ^ (string_of_int st)),
|
||||
qualid s)
|
||||
| _ ->
|
||||
if is_a_write ident
|
||||
then access_write wt s
|
||||
else Cvar(s)
|
||||
|
||||
let set name c = Tset(name, c)
|
||||
let next self name c = Tlabelset(self, name, c)
|
||||
|
||||
(** Compilation of functions *)
|
||||
(* x1...xn.<init, code, res> is translated into
|
||||
|
||||
(1) combinatorial function
|
||||
|
||||
\x1...xn.code;res
|
||||
|
||||
(2) \x1...xn.self.
|
||||
let self = match !self with
|
||||
Nil -> let v = { ... init ... } in
|
||||
self := St(v);v
|
||||
| St(self) -> self in
|
||||
code;
|
||||
res
|
||||
|
||||
r = f [...] x1...xn is translated into:
|
||||
|
||||
(1) combinatorial function
|
||||
|
||||
f = f [...] x1...xn
|
||||
|
||||
(2) state function
|
||||
|
||||
st = ref Nil initialisation part
|
||||
|
||||
r = f x1...xn st step part
|
||||
|
||||
Rmk: we can also write: "if reset then self := { ... }"
|
||||
*)
|
||||
|
||||
let co_apply env is_state (init_write, init_mem) f subst e_list =
|
||||
if is_state then
|
||||
(* state function *)
|
||||
let st = prefix_for_names ^ (string_of_int symbol#name) in
|
||||
let prefix = selfstate env in
|
||||
(init_write, (st, Cref(state_nil)) :: init_mem),
|
||||
Capply(f,
|
||||
(subst @ e_list @ [Crecord_access(Cvar(prefix), qualid st)]))
|
||||
else
|
||||
(init_write, init_mem), Capply(f, subst @ e_list)
|
||||
|
||||
(* prepare the initialization of memory variables *)
|
||||
let cmatchstate self states =
|
||||
let v = prefix_for_names ^ (string_of_int (symbol#name)) in
|
||||
let st = prefix_state_constr ^ (string_of_int (symbol#name)) in
|
||||
Cmatch(Cderef(Cvar(self)),
|
||||
[Cconstructpat(qualid st,[Cvarpat(self)]), Cvar(self);
|
||||
Cwildpat, Clet(false, [Cvarpat(v), states],
|
||||
Cseq[Cset(self,
|
||||
Cconstruct(qualid st, [Cvar(v)]));
|
||||
Cvar(v)])])
|
||||
|
||||
(* prepare the initialization of write variables *)
|
||||
let define_init_writes env init_write code =
|
||||
List.fold_right
|
||||
(fun (name, e) code -> Clet(false, [Cvarpat(name), Cref e], code))
|
||||
init_write code
|
||||
|
||||
let co_fun env
|
||||
is_state params p_list static (init_write, init_mem) code result =
|
||||
if init_mem <> [] then intro_record_type init_mem;
|
||||
|
||||
let code = clet code result in
|
||||
let code =
|
||||
if init_write <> []
|
||||
then define_init_writes env init_write code
|
||||
else code in
|
||||
let self = selfstate env in
|
||||
if is_state
|
||||
then
|
||||
if init_mem = [] then Cfun(params @ p_list @ [Cvarpat(self)], code)
|
||||
else Cfun(params @ p_list @ [Cvarpat(self)],
|
||||
Clet(false, [Cvarpat(self),
|
||||
cmatchstate self
|
||||
(clet static (state_record init_mem))],
|
||||
code))
|
||||
else Cfun(params @ p_list, code)
|
||||
|
||||
(** Compilation of pattern matching *)
|
||||
(*
|
||||
match e with
|
||||
P1 -> e1
|
||||
| ...
|
||||
| Pn -> en
|
||||
|
||||
(1) e is a static computation
|
||||
|
||||
- initialisation code
|
||||
let memory = match e with
|
||||
P1 -> St1 { ... }
|
||||
| ...
|
||||
| Pn -> Stn { ... }
|
||||
|
||||
- step code
|
||||
match memory with
|
||||
St1{...} -> step1
|
||||
| ...
|
||||
| Stn{...} -> stepn
|
||||
|
||||
(2) e may evolve at every instant
|
||||
|
||||
- init code
|
||||
...i1...
|
||||
...in...
|
||||
|
||||
- match e with
|
||||
P1 -> step1
|
||||
| ...
|
||||
| Pn -> stepn
|
||||
|
||||
for the moment, we treat case (1) as case (2) *)
|
||||
|
||||
(*
|
||||
let co_static_merge e (pat, init_code_fvars_list) =
|
||||
(* introduces the type definitions for the representation of states *)
|
||||
let n = List.length init_code_fvars_list in
|
||||
let prefix_constructor = intro_enum_type n in
|
||||
|
||||
(* builds a constructor value *)
|
||||
let constructor prefix number f_vars =
|
||||
Cconstruct(qualid (prefix ^ (string_of_int number)),
|
||||
List.map (fun name -> Cvar(name)) fvars) in
|
||||
let constructor_pat prefix number f_vars =
|
||||
Cconstructpat(qualid (prefix ^ (string_of_int number)),
|
||||
List.map (fun name -> Cvarpat(name)) fvars) in
|
||||
|
||||
(* computes the initialisation part *)
|
||||
let rec states number init_code_fvars_list =
|
||||
match init_code_fvars_list with
|
||||
[] -> []
|
||||
| (pat, init, _, fvars) :: init_code_fvars_list ->
|
||||
let pat_code = (pat, clet init (constructor prefix number fvars)) in
|
||||
let pat_code_list = states (number + 1) init_code_fvars_list in
|
||||
pat_code :: code_list in
|
||||
|
||||
(* computes the transition part *)
|
||||
let rec steps number init_code_fvars_list =
|
||||
match init_code_fvars_list with
|
||||
[] -> []
|
||||
| (_, _, code, fvars) :: init_code_fvars_list ->
|
||||
let pat_code = (constructor_pat prefix number fvars, code) in
|
||||
let pat_code_list = steps (number + 1) init_code_fvars_list in
|
||||
pat_code :: pat_code_list in
|
||||
|
||||
(* make the final code *)
|
||||
let memory = symbol#name in
|
||||
let init_code = Cmatch(e, states 0 init_code_fvars_list) in
|
||||
let step_code = Cmatch(Cvar memory, steps 0 init_code_fvars_list) in
|
||||
Tlet(memory, init_code), step_code
|
||||
|
||||
*)
|
||||
|
||||
(** Compilation of clocks *)
|
||||
let rec translate_clock env init ck =
|
||||
match ck with
|
||||
Dfalse -> init, cfalse
|
||||
| Dtrue -> init, ctrue
|
||||
| Dclockvar(n) -> init, access env n
|
||||
| Don(is_on, ck, car) ->
|
||||
let init, ck = translate_clock env init ck in
|
||||
let init, car = translate_carrier env init car in
|
||||
init, if is_on then cand car ck
|
||||
else cand (cnot car) ck
|
||||
|
||||
and translate_carrier env init car =
|
||||
match car with
|
||||
Dcfalse -> init, cfalse
|
||||
| Dctrue -> init, ctrue
|
||||
| Dcvar(n) -> init, access env n
|
||||
| Dcglobal(g, res, ck) ->
|
||||
(* a global clock allocates memory *)
|
||||
(* and is compiled as a function call *)
|
||||
let res = match res with None -> cfalse | Some(n) -> access env n in
|
||||
let init, c = translate_clock env init ck in
|
||||
let init, new_ce =
|
||||
co_apply env true init (Cglobal g) [c] [res] in
|
||||
init, new_ce
|
||||
|
||||
(** Compiling immediate. *)
|
||||
let translate_immediate i =
|
||||
match i with
|
||||
| Dbool(b) -> Cbool(b)
|
||||
| Dint(i) -> Cint(i)
|
||||
| Dfloat(f) -> Cfloat(f)
|
||||
| Dchar(c) -> Cchar(c)
|
||||
| Dstring(s) -> Cstring(s)
|
||||
| Dvoid -> Cvoid
|
||||
|
||||
(** Compiling variables. *)
|
||||
let translate_var env v =
|
||||
match v with
|
||||
Dglobal(g) -> Cglobal(g)
|
||||
| Dlocal(n) -> access env n
|
||||
|
||||
(** Compiling a pattern. *)
|
||||
let rec translate_pat env pat =
|
||||
match pat with
|
||||
| Dconstantpat(i) -> Cconstantpat(translate_immediate(i))
|
||||
| Dvarpat(s) -> Cvarpat(string_of_name env s)
|
||||
| Dtuplepat(l) -> Ctuplepat(List.map (translate_pat env) l)
|
||||
| Dconstructpat(gl, pat_list) ->
|
||||
Cconstructpat(gl, List.map (translate_pat env) pat_list)
|
||||
| Dorpat(pat1, pat2) -> Corpat(translate_pat env pat1,
|
||||
translate_pat env pat2)
|
||||
| Drecordpat(gl_pat_list) ->
|
||||
Crecordpat
|
||||
(List.map (fun (gl, pat) -> (gl, translate_pat env pat))
|
||||
gl_pat_list)
|
||||
| Daliaspat(pat, i) -> Caliaspat(translate_pat env pat,
|
||||
string_of_name env i)
|
||||
| Dwildpat -> Cwildpat
|
||||
|
||||
(*
|
||||
(* add accesses to write variables defined in patterns *)
|
||||
let rec add_write_access env code pat =
|
||||
match pat with
|
||||
Dconstantpat(i) -> code
|
||||
| Dvarpat(s) when is_a_write (find env s) ->
|
||||
Tset(string_of_name env s, access env s) :: code
|
||||
| Dvarpat _ -> code
|
||||
| Dtuplepat(l) | Dconstructpat(_, l) ->
|
||||
List.fold_left (add_write_access env) code l
|
||||
| Dorpat(pat1, pat2) ->
|
||||
add_write_access env (add_write_access env code pat1) pat2
|
||||
| Drecordpat(gl_pat_list) ->
|
||||
List.fold_left (fun code (_, pat) -> add_write_access env code pat)
|
||||
code gl_pat_list
|
||||
| Daliaspat(pat, i) ->
|
||||
add_write_access env (add_write_access env code pat) (Dvarpat(i))
|
||||
| Dwildpat -> code
|
||||
*)
|
||||
|
||||
(** Compiling an expression *)
|
||||
(* takes an environment giving information about variables *)
|
||||
(* and an expression and returns the new code *)
|
||||
let rec translate env init e =
|
||||
match e.d_desc with
|
||||
| Dconstant(i) ->
|
||||
let i = translate_immediate i in
|
||||
init, Cconstant(i)
|
||||
| Dvar(v, subst) ->
|
||||
let v = translate_var env v in
|
||||
let init, s = translate_subst env init subst in
|
||||
let v = match s with [] -> v | l -> Capply(v, l) in
|
||||
init, v
|
||||
| Dtuple l ->
|
||||
let init, lc = translate_list env init l in
|
||||
init, Ctuple(lc)
|
||||
| Dfun(is_state, params, p_list, body, result) ->
|
||||
(* state function *)
|
||||
let env = push_block body env in
|
||||
(* compiles types and clock abstractions *)
|
||||
let params = translate_forall env params in
|
||||
(* compiles parameters *)
|
||||
let p_list = List.map (translate_pat env) p_list in
|
||||
(* remove static computation from the body *)
|
||||
(* and put it in the allocation place for stateful functions *)
|
||||
let (static_code, init_code, body, result) =
|
||||
if is_state
|
||||
then
|
||||
let static_code, body = static_block [] body in
|
||||
let static_code, result = static static_code result in
|
||||
let static_code = List.rev static_code in
|
||||
(* translate the static code *)
|
||||
let static_code, init_code =
|
||||
translate_static_code env static_code in
|
||||
(static_code, init_code, body, result)
|
||||
else
|
||||
([], ([], []), body, result) in
|
||||
(* then translate the body *)
|
||||
let init_code, body = translate_block env init_code body in
|
||||
let init_code, result = translate env init_code result in
|
||||
init,
|
||||
co_fun env is_state params p_list static_code init_code body result
|
||||
| Dprim(g, e_list) ->
|
||||
(* pointwise application *)
|
||||
let init, ce_list = translate_list env init e_list in
|
||||
init, Capply(Cglobal(g), ce_list)
|
||||
| Dconstruct(g, e_list) ->
|
||||
let init, ce_list = translate_list env init e_list in
|
||||
init, Cconstruct(g, ce_list)
|
||||
| Drecord(gl_expr_list) ->
|
||||
let translate_record (gl, expr) (init, gl_expr_list) =
|
||||
let init, ce = translate env init expr in
|
||||
init, (gl, ce) :: gl_expr_list in
|
||||
let init, l =
|
||||
List.fold_right translate_record gl_expr_list (init, []) in
|
||||
init, Crecord(l)
|
||||
| Drecord_access(expr, gl) ->
|
||||
let init, ce = translate env init expr in
|
||||
init, Crecord_access(ce, gl)
|
||||
| Difthenelse(e0, e1, e2) ->
|
||||
let init, c0 = translate env init e0 in
|
||||
let init, c1 = translate env init e1 in
|
||||
let init, c2 = translate env init e2 in
|
||||
init, Cifthenelse(c0, c1, c2)
|
||||
| Dlet(block, e_let) ->
|
||||
let env = push block env in
|
||||
let init, code = translate_block env init block in
|
||||
let init, ce = translate env init e_let in
|
||||
init, clet code ce
|
||||
| Dapply(is_state, { d_desc = Dvar(f, subst) }, l) ->
|
||||
let f = translate_var env f in
|
||||
let init, l = translate_list env init l in
|
||||
let init, subst = translate_subst env init subst in
|
||||
co_apply env is_state init f subst l
|
||||
| Dapply(is_state, f, l) ->
|
||||
let init, f = translate env init f in
|
||||
let init, l = translate_list env init l in
|
||||
co_apply env is_state init f [] l
|
||||
| Deseq(e1, e2) ->
|
||||
let init, e1 = translate env init e1 in
|
||||
let init, e2 = translate env init e2 in
|
||||
init, Cseq [e1; e2]
|
||||
| Dwhen(e1) ->
|
||||
translate env init e1
|
||||
| Dclock(ck) ->
|
||||
translate_clock env init ck
|
||||
| Dlast _ | Dinit _ | Dpre _ | Dtest _ ->
|
||||
(* this case should not arrive *)
|
||||
fatal_error "translate"
|
||||
|
||||
and translate_list env init l =
|
||||
match l with
|
||||
[] -> init, []
|
||||
| ce :: l ->
|
||||
let init, ce = translate env init ce in
|
||||
let init, l = translate_list env init l in
|
||||
init, ce :: l
|
||||
|
||||
and translate_block env init b =
|
||||
(* allocate the memory in the initialisation part *)
|
||||
let init = allocate_memory env init in
|
||||
(* compiles the body *)
|
||||
let init, code = translate_equation env init [] b.b_equations in
|
||||
(* sets code in the correct order *)
|
||||
let code = List.rev code in
|
||||
(* returns the components of the block *)
|
||||
init, code
|
||||
|
||||
(* the input equations must be already scheduled *)
|
||||
and translate_equations env init code eq_list =
|
||||
match eq_list with
|
||||
[] -> init, code
|
||||
| eq :: eq_list ->
|
||||
let init, code = translate_equation env init code eq in
|
||||
translate_equations env init code eq_list
|
||||
|
||||
and translate_equation_into_exp env init eq =
|
||||
let init, code = translate_equation env init [] eq in
|
||||
(* sets code in the correct order *)
|
||||
let code = List.rev code in
|
||||
init, cseq code
|
||||
|
||||
and translate_block_into_exp env init block =
|
||||
let init, code = translate_block env init block in
|
||||
init, cseq code
|
||||
|
||||
and translate_equation env init code eq =
|
||||
match eq with
|
||||
Dget(pat, v) ->
|
||||
let cpat = translate_pat env pat in
|
||||
let n = translate_var env v in
|
||||
init, Tlet(cpat, n) :: code
|
||||
| Dequation(Dvarpat(n), e) when is_a_write (find env n) ->
|
||||
let name = string_of_name env n in
|
||||
let init, ce = translate env init e in
|
||||
init, (set name ce) :: code
|
||||
| Dequation(pat, e) | Dstatic(pat, e) ->
|
||||
let is_rec = is_recursive pat e in
|
||||
let pat = translate_pat env pat in
|
||||
let init, ce = translate env init e in
|
||||
init, if is_rec then Tletrec([pat, ce]) :: code
|
||||
else Tlet(pat, ce) :: code
|
||||
| Dwheneq(eq, ck) ->
|
||||
let init, ce = translate_equation_into_exp env init eq in
|
||||
let init, ck_ce = translate_clock env init ck in
|
||||
init, Texp(ifthen ck_ce ce) :: code
|
||||
| Dmerge(is_static, e, p_block_list) ->
|
||||
let init, ce = translate env init e in
|
||||
let init, l = translate_pat_block_list env init p_block_list in
|
||||
init, merge code ce l
|
||||
| Dnext(n, e) ->
|
||||
(* n is either a memo or an initialisation variable *)
|
||||
let init, ce = translate env init e in
|
||||
init, (next (selfstate env) (string_of_name env n) ce) :: code
|
||||
| Dseq(eq_list) | Dpar(eq_list) ->
|
||||
translate_equations env init code eq_list
|
||||
| Dblock(block) ->
|
||||
translate_block env init block
|
||||
| Demit _ | Dlasteq _ | Dautomaton _ | Dreset _ | Dpresent _ ->
|
||||
(* these cases should not arrive since control structures have *)
|
||||
(* been translated into the basic kernel *)
|
||||
fatal_error "translate_equation"
|
||||
|
||||
(* compilation of pattern matching *)
|
||||
and translate_pat_block_list env init p_block_list =
|
||||
(* compile one handler *)
|
||||
let translate_pat_block init (pat, block) =
|
||||
let env = push block env in
|
||||
let cpat = translate_pat env pat in
|
||||
let init, ce = translate_block_into_exp env init block in
|
||||
init, (cpat, ce) in
|
||||
match p_block_list with
|
||||
[] -> init, []
|
||||
| pat_block :: pat_block_list ->
|
||||
let init, pat_ce = translate_pat_block init pat_block in
|
||||
let init, pat_ce_list =
|
||||
translate_pat_block_list env init pat_block_list in
|
||||
init, pat_ce :: pat_ce_list
|
||||
|
||||
(* translate a pure (stateless) expression *)
|
||||
and translate_pure env e =
|
||||
let init, ce = translate env ([], []) e in
|
||||
assert (init = ([], []));
|
||||
ce
|
||||
|
||||
(* computes extra parameters for clock abstraction *)
|
||||
and translate_forall env params =
|
||||
let p_clocks =
|
||||
List.map (fun n -> Cvarpat(string_of_name env n)) params.s_clock in
|
||||
let p_carriers =
|
||||
List.map (fun n -> Cvarpat(string_of_name env n)) params.s_carrier in
|
||||
p_clocks @ p_carriers
|
||||
|
||||
(* generates an application for clock instanciation *)
|
||||
and translate_subst env init subst =
|
||||
let rec translate_clock_list init cl_list =
|
||||
match cl_list with
|
||||
[] -> init, []
|
||||
| cl :: cl_list ->
|
||||
let init, cl = translate_clock env init cl in
|
||||
let init, cl_list = translate_clock_list init cl_list in
|
||||
init, cl :: cl_list in
|
||||
let rec translate_carrier_list init car_list =
|
||||
match car_list with
|
||||
[] -> init, []
|
||||
| car :: car_list ->
|
||||
let init, car = translate_carrier env init car in
|
||||
let init, car_list = translate_carrier_list init car_list in
|
||||
init, car :: car_list in
|
||||
let init, cl_list = translate_clock_list init subst.s_clock in
|
||||
let init, car_list = translate_carrier_list init subst.s_carrier in
|
||||
init, cl_list @ car_list
|
||||
|
||||
(* Initialisation code *)
|
||||
and allocate_memory env init =
|
||||
let allocate _ ident (acc_write, acc_mem) =
|
||||
match ident.id_kind with
|
||||
Kmemo ->
|
||||
(* we allocate only one cell *)
|
||||
let default = default_value env ident in
|
||||
acc_write, (memo ident.id_name, default) :: acc_mem
|
||||
| Kinit ->
|
||||
(* init variables are considered to be state variables *)
|
||||
acc_write, (initial ident.id_name, Cconstant(Cbool(true))) :: acc_mem
|
||||
| _ when is_a_write ident ->
|
||||
(* local write variables are allocated too *)
|
||||
(* but they will be stored in a stack allocated structure *)
|
||||
let name = string_of_name env ident.id_name in
|
||||
let default = default_value env ident in
|
||||
(name, default) :: acc_write, acc_mem
|
||||
| _ -> acc_write, acc_mem in
|
||||
Hashtbl.fold allocate (cblock env).b_env init
|
||||
|
||||
(* add static code into the initialisation part *)
|
||||
and translate_static_code env static_code =
|
||||
(* add one equation *)
|
||||
(* we compute the list of introduced names and compile the equation *)
|
||||
let translate_eq acc (pat, e) =
|
||||
let acc = fv_pat acc pat in
|
||||
let pat = translate_pat env pat in
|
||||
let ce = translate_pure env e in
|
||||
acc, Tlet(pat, ce) in
|
||||
let rec translate_static_code acc static_code =
|
||||
match static_code with
|
||||
[] -> acc, []
|
||||
| pat_e :: static_code ->
|
||||
let acc, cpat_ce = translate_eq acc pat_e in
|
||||
let acc, static_code = translate_static_code acc static_code in
|
||||
acc, cpat_ce :: static_code in
|
||||
(* introduced names must be added to the memory *)
|
||||
let intro acc_mem n =
|
||||
let v = string_of_name env n in
|
||||
(* modify the kind of [n] *)
|
||||
set_static (find env n);
|
||||
(string_of_name env n, Cvar(v)) :: acc_mem in
|
||||
|
||||
(* first compile the static code *)
|
||||
let acc, static_code = translate_static_code [] static_code in
|
||||
(* introduced names must be added to the memory initialisation *)
|
||||
let acc_mem = List.fold_left intro [] acc in
|
||||
static_code, ([], acc_mem)
|
||||
|
||||
(* default value *)
|
||||
and default_value env ident =
|
||||
(* find a value from a type *)
|
||||
let rec value ty =
|
||||
match ty with
|
||||
Dproduct(ty_l) -> Ctuple(List.map value ty_l)
|
||||
| Dbase(b) ->
|
||||
let v = match b with
|
||||
Dtyp_bool -> Cbool(false)
|
||||
| Dtyp_int -> Cint(0)
|
||||
| Dtyp_float -> Cfloat(0.0)
|
||||
| Dtyp_unit -> Cvoid
|
||||
| Dtyp_char -> Cchar(' ')
|
||||
| Dtyp_string -> Cstring("") in
|
||||
Cconstant(v)
|
||||
| Dsignal(ty) -> Ctuple[value ty; cfalse]
|
||||
| Dtypvar _ | Darrow _ -> cdummy
|
||||
| Dconstr(qualid, _) ->
|
||||
try
|
||||
let desc = find_type qualid in
|
||||
match desc.d_type_desc with
|
||||
Dabstract_type -> cdummy
|
||||
| Dabbrev(ty) ->
|
||||
value ty
|
||||
| Dvariant_type l ->
|
||||
let case = List.hd l in
|
||||
begin match case with
|
||||
(qual, { arg = ty_l }) ->
|
||||
Cconstruct(qual, List.map value ty_l)
|
||||
end
|
||||
| Drecord_type l ->
|
||||
let field_of_type (qual, _, ty_ty) = (qual, value ty_ty.res) in
|
||||
Crecord (List.map field_of_type l)
|
||||
with
|
||||
Not_found -> cdummy in
|
||||
let value (Dtypforall(_, ty)) = value ty in
|
||||
match ident.id_value with
|
||||
None -> value ident.id_typ
|
||||
| Some(e) -> translate_pure env e
|
||||
|
||||
(** Compilation of a table of declarative code *)
|
||||
let translate table =
|
||||
let translate (s, e) = (s, translate_pure empty_env e) in
|
||||
(* introduce the type of states *)
|
||||
(* intro_state_type (); *)
|
||||
(* then translate *)
|
||||
(* translate the code *)
|
||||
{ c_types = table.d_types;
|
||||
c_code = List.map translate table.d_code;
|
||||
c_vars = table.d_vars;
|
||||
}
|
@ -0,0 +1,295 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: declarative.ml,v 1.18 2007-01-11 07:35:53 pouzet Exp $ *)
|
||||
(* the intermediate format *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
|
||||
(* one set of (unique) names *)
|
||||
type name = int
|
||||
|
||||
type global =
|
||||
Gname of string * name
|
||||
| Gmodname of qualified_ident
|
||||
|
||||
(* type definitions *)
|
||||
type type_definition =
|
||||
{ d_type_desc: type_components;
|
||||
d_type_arity: int list
|
||||
}
|
||||
|
||||
and ('a, 'b) ptyp = { arg: 'a; res: 'b }
|
||||
|
||||
and type_components =
|
||||
Dabstract_type
|
||||
| Dabbrev of typ
|
||||
| Dvariant_type of (qualified_ident * (typ list, typ) ptyp) list
|
||||
| Drecord_type of (qualified_ident * is_mutable * (typ, typ) ptyp) list
|
||||
|
||||
and is_mutable = bool
|
||||
|
||||
(* types *)
|
||||
and typs = Dtypforall of name list * typ
|
||||
and typ =
|
||||
| Darrow of is_node * typ * typ
|
||||
| Dproduct of typ list
|
||||
| Dconstr of qualified_ident * typ list
|
||||
| Dtypvar of name
|
||||
| Dbase of base_typ
|
||||
| Dsignal of typ
|
||||
|
||||
and is_node = bool
|
||||
|
||||
and base_typ =
|
||||
Dtyp_bool | Dtyp_int | Dtyp_float | Dtyp_unit |
|
||||
Dtyp_char | Dtyp_string
|
||||
|
||||
type guard = clock
|
||||
|
||||
and clock =
|
||||
| Dfalse (* the false clock *)
|
||||
| Dtrue (* the base clock *)
|
||||
| Don of bool * clock * carrier (* "cl on c" or "cl on not c" *)
|
||||
| Dclockvar of name (* 'a *)
|
||||
|
||||
and carrier =
|
||||
Dcfalse
|
||||
| Dctrue
|
||||
| Dcvar of name
|
||||
| Dcglobal of qualified_ident * name option * clock
|
||||
(* identifier, reset name and clock *)
|
||||
|
||||
(* immediate values *)
|
||||
type immediate =
|
||||
| Dbool of bool
|
||||
| Dint of int
|
||||
| Dfloat of float
|
||||
| Dchar of char
|
||||
| Dstring of string
|
||||
| Dvoid
|
||||
|
||||
type 'a desc =
|
||||
{ d_desc: 'a;
|
||||
d_ty: typ;
|
||||
d_guard: guard
|
||||
}
|
||||
|
||||
(* patterns *)
|
||||
type pattern =
|
||||
| Dwildpat
|
||||
| Dvarpat of name
|
||||
| Dconstantpat of immediate
|
||||
| Dtuplepat of pattern list
|
||||
| Dconstructpat of qualified_ident * pattern list
|
||||
| Drecordpat of (qualified_ident * pattern) list
|
||||
| Daliaspat of pattern * name
|
||||
| Dorpat of pattern * pattern
|
||||
|
||||
(* signal expressions *)
|
||||
type spattern =
|
||||
| Dandpat of spattern * spattern
|
||||
| Dexppat of expr
|
||||
| Dcondpat of expr * pattern
|
||||
|
||||
(* expressions *)
|
||||
and expr = expr_desc desc
|
||||
|
||||
and expr_desc =
|
||||
| Dconstant of immediate
|
||||
| Dvar of var * subst
|
||||
| Dlast of name
|
||||
| Dpre of expr option * expr
|
||||
| Difthenelse of expr * expr * expr
|
||||
| Dinit of clock * name option
|
||||
| Dtuple of expr list
|
||||
| Dconstruct of qualified_ident * expr list
|
||||
| Drecord of (qualified_ident * expr) list
|
||||
| Drecord_access of expr * qualified_ident
|
||||
| Dprim of qualified_ident * expr list
|
||||
| Dfun of is_state * params * pattern list * block * expr
|
||||
| Dapply of is_state * expr * expr list
|
||||
| Dlet of block * expr
|
||||
| Deseq of expr * expr
|
||||
| Dtest of expr (* testing the presence "?" *)
|
||||
| Dwhen of expr (* instruction "when" *)
|
||||
| Dclock of clock
|
||||
|
||||
and is_state = bool
|
||||
|
||||
and var =
|
||||
| Dlocal of name
|
||||
| Dglobal of qualified_ident
|
||||
|
||||
and is_external = bool (* true for imported ML values *)
|
||||
|
||||
(* type and clock instance *)
|
||||
and ('a, 'b, 'c) substitution =
|
||||
{ s_typ: 'a list;
|
||||
s_clock: 'b list;
|
||||
s_carrier: 'c list }
|
||||
|
||||
and subst = (typ, clock, carrier) substitution
|
||||
and params = (name, name, name) substitution
|
||||
|
||||
(* block *)
|
||||
and block =
|
||||
{ b_env: (name, ident) Hashtbl.t; (* environment *)
|
||||
mutable b_write: name list; (* write variables *)
|
||||
b_equations: equation; (* equations *)
|
||||
}
|
||||
|
||||
(* equation *)
|
||||
and equation =
|
||||
Dequation of pattern * expr (* equation p = e *)
|
||||
| Dnext of name * expr (* next x = e *)
|
||||
| Dlasteq of name * expr (* last x = e *)
|
||||
| Demit of pattern * expr (* emit pat = e *)
|
||||
| Dstatic of pattern * expr (* static pat = e *)
|
||||
| Dget of pattern * var (* pat = x *)
|
||||
| Dwheneq of equation * guard (* eq when clk *)
|
||||
| Dmerge of is_static * expr (* control structure *)
|
||||
* (pattern * block) list
|
||||
| Dreset of equation * expr (* reset *)
|
||||
| Dautomaton of clock * (state_pat * block * block * escape * escape) list
|
||||
(* automaton weak and strong *)
|
||||
| Dpar of equation list (* parallel equations *)
|
||||
| Dseq of equation list (* sequential equations *)
|
||||
| Dblock of block (* block structure *)
|
||||
| Dpresent of clock * (spattern * block) list * block
|
||||
(* presence testing *)
|
||||
|
||||
and escape = (spattern * block * is_continue * state) list
|
||||
|
||||
and is_static = bool
|
||||
and is_strong = bool
|
||||
and is_continue = bool
|
||||
|
||||
and state_pat = string * pattern list
|
||||
and state = string * expr list
|
||||
|
||||
(* ident definition *)
|
||||
and ident =
|
||||
{ id_name: name; (* its name (unique identifier) *)
|
||||
id_original: string option; (* its original name when possible *)
|
||||
id_typ: typs; (* its type *)
|
||||
id_value: expr option; (* its initial value when possible *)
|
||||
mutable id_kind: id_kind; (* kind of identifier *)
|
||||
mutable id_write: bool; (* physically assigned or not *)
|
||||
mutable id_last: bool; (* do we need its last value also? *)
|
||||
mutable id_signal: bool; (* is-it a signal? *)
|
||||
}
|
||||
|
||||
(* a local variable in a block may be of four different kinds *)
|
||||
and id_kind =
|
||||
Kinit (* initialisation state variable *)
|
||||
| Kclock (* clock variable *)
|
||||
| Kreset (* reset variable *)
|
||||
| Kmemo (* state variable *)
|
||||
| Kstatic (* static variable *)
|
||||
| Klast (* last variable *)
|
||||
| Kvalue (* defined variable *)
|
||||
| Kshared (* shared variable with several definitions *)
|
||||
| Kinput (* input variable, i.e, argument *)
|
||||
|
||||
(* global definition *)
|
||||
(* Invariant: expr must be bounded and static *)
|
||||
|
||||
(* the declarative code associated to a file *)
|
||||
type declarative_code =
|
||||
{ mutable d_modname: string; (* module name *)
|
||||
mutable d_types: (string, type_definition) Hashtbl.t;
|
||||
(* type definitions *)
|
||||
mutable d_code: (string * expr) list; (* value definitions *)
|
||||
mutable d_vars: string list; (* defined names *)
|
||||
}
|
||||
|
||||
|
||||
(* the generated code of a module *)
|
||||
let dc = { d_modname = "";
|
||||
d_types = Hashtbl.create 7;
|
||||
d_code = [];
|
||||
d_vars = []
|
||||
}
|
||||
|
||||
let code () = dc
|
||||
|
||||
(* thing to do when starting the production of declarative code *)
|
||||
(* for a file *)
|
||||
let start modname =
|
||||
dc.d_modname <- modname;
|
||||
dc.d_types <- Hashtbl.create 7;
|
||||
dc.d_code <- [];
|
||||
dc.d_vars <- []
|
||||
|
||||
(* things to do at the end of the front-end*)
|
||||
let finish () =
|
||||
dc.d_code <- List.rev dc.d_code
|
||||
|
||||
(* apply a function to every value *)
|
||||
let replace translate =
|
||||
let rec replace (s, e) =
|
||||
let e = translate e in
|
||||
dc.d_code <- (s, e) :: dc.d_code in
|
||||
let code = dc.d_code in
|
||||
dc.d_code <- [];
|
||||
List.iter replace code;
|
||||
dc.d_code <- List.rev dc.d_code
|
||||
|
||||
|
||||
(* add an input to the declarative code *)
|
||||
let add_dec (name, code) =
|
||||
dc.d_code <- (name, code) :: dc.d_code;
|
||||
dc.d_vars <- name :: dc.d_vars
|
||||
|
||||
(* add a type definition to the declarative code *)
|
||||
let add_type (name, type_def) =
|
||||
Hashtbl.add dc.d_types name type_def
|
||||
|
||||
(* read code from and write code into a file *)
|
||||
let read_declarative_code ic = input_value ic
|
||||
|
||||
let write_declarative_code oc =
|
||||
output_value oc (code ())
|
||||
|
||||
(* the list of opened modules *)
|
||||
let dc_modules = (Hashtbl.create 7 : (string, declarative_code) Hashtbl.t)
|
||||
|
||||
(* add a module to the list of opened modules *)
|
||||
let add_module m =
|
||||
let name = String.uncapitalize m in
|
||||
try
|
||||
let fullname = find_in_path (name ^ ".dcc") in
|
||||
let ic = open_in fullname in
|
||||
let dc = input_value ic in
|
||||
Hashtbl.add dc_modules m dc;
|
||||
close_in ic;
|
||||
dc
|
||||
with
|
||||
Cannot_find_file _ ->
|
||||
Printf.eprintf
|
||||
"Cannot find the compiled declarative file %s.dcc.\n"
|
||||
name;
|
||||
raise Error
|
||||
|
||||
let find_value qualid =
|
||||
let dc =
|
||||
if qualid.qual = dc.d_modname then dc
|
||||
else raise Not_found
|
||||
(*
|
||||
try
|
||||
Hashtbl.find dc_modules qualid.qual
|
||||
with
|
||||
Not_found -> add_module qualid.qual *) in
|
||||
List.assoc qualid.id dc.d_code
|
||||
|
||||
let find_type qualid =
|
||||
if qualid.qual = dc.d_modname then Hashtbl.find dc.d_types qualid.qual
|
||||
else raise Not_found
|
@ -0,0 +1,699 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: declarative_printer.ml,v 1.13 2007-01-11 07:35:53 pouzet Exp $ *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
open Declarative
|
||||
open Modules
|
||||
open Format
|
||||
|
||||
(* generic printing of a list *)
|
||||
let print_list print l =
|
||||
let rec printrec l =
|
||||
match l with
|
||||
[] -> ()
|
||||
| [x] ->
|
||||
print x
|
||||
| x::l ->
|
||||
print x;
|
||||
print_space ();
|
||||
printrec l in
|
||||
printrec l
|
||||
|
||||
(* local name *)
|
||||
let print_name i =
|
||||
print_string "/";print_int i
|
||||
|
||||
(* global names *)
|
||||
let print_qualified_ident { qual = q; id = id } =
|
||||
if (q = pervasives_module) or (q = compiled_module_name ())
|
||||
or (q = "")
|
||||
then print_string id
|
||||
else
|
||||
begin
|
||||
print_string q;
|
||||
print_string ".";
|
||||
print_string id
|
||||
end
|
||||
|
||||
(* print types *)
|
||||
let rec print_type typ =
|
||||
open_box 1;
|
||||
begin match typ with
|
||||
Darrow(is_node, typ1, typ2) ->
|
||||
print_string "(";
|
||||
if is_node then print_string "=>" else print_string "->";
|
||||
print_space ();
|
||||
print_list print_type [typ1;typ2];
|
||||
print_string ")"
|
||||
| Dproduct(ty_list) ->
|
||||
print_string "(";
|
||||
print_string "*";
|
||||
print_space ();
|
||||
print_list print_type ty_list;
|
||||
print_string ")"
|
||||
| Dconstr(qual_ident, ty_list) ->
|
||||
if ty_list <> [] then print_string "(";
|
||||
print_qualified_ident qual_ident;
|
||||
if ty_list <> [] then
|
||||
begin print_space ();
|
||||
print_list print_type ty_list;
|
||||
print_string ")"
|
||||
end
|
||||
| Dsignal(ty) -> print_type ty; print_space (); print_string "sig"
|
||||
| Dtypvar(i) -> print_int i
|
||||
| Dbase(b) -> print_base_type b
|
||||
end;
|
||||
close_box ()
|
||||
|
||||
and print_base_type b =
|
||||
match b with
|
||||
Dtyp_bool -> print_string "bool"
|
||||
| Dtyp_int -> print_string "int"
|
||||
| Dtyp_float -> print_string "float"
|
||||
| Dtyp_unit -> print_string "unit"
|
||||
| Dtyp_string -> print_string "string"
|
||||
| Dtyp_char -> print_string "char"
|
||||
|
||||
let print_typs (Dtypforall(l, typ)) =
|
||||
match l with
|
||||
[] -> (* we do not print the quantifier when there is no type variable *)
|
||||
print_type typ
|
||||
| l ->
|
||||
open_box 1;
|
||||
print_string "(forall";
|
||||
print_space ();
|
||||
print_list print_name l;
|
||||
print_space ();
|
||||
print_type typ;
|
||||
print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* print clocks *)
|
||||
let rec print_clock clk =
|
||||
match clk with
|
||||
| Dfalse -> print_string "false"
|
||||
| Dtrue -> print_string "true"
|
||||
| Dclockvar(i) -> print_name i
|
||||
| Don(b, clk, c) ->
|
||||
print_string "(";
|
||||
if b then print_string "on" else print_string "onot";
|
||||
print_space ();
|
||||
print_clock clk;
|
||||
print_space ();
|
||||
print_carrier c;
|
||||
print_string ")"
|
||||
and print_carrier c =
|
||||
match c with
|
||||
Dcfalse -> print_string "false"
|
||||
| Dctrue -> print_string "true"
|
||||
| Dcvar(i) -> print_name i
|
||||
| Dcglobal(qual_ident, res, clk) ->
|
||||
print_qualified_ident qual_ident;
|
||||
print_string "(";
|
||||
(match res with
|
||||
None -> ()
|
||||
| Some(n) -> print_space ();print_name n;print_space ());
|
||||
print_clock clk;
|
||||
print_string ")"
|
||||
|
||||
(* immediate values *)
|
||||
let print_immediate i =
|
||||
match i with
|
||||
Dbool(b) -> print_string (if b then "true" else "false")
|
||||
| Dint(i) -> print_int i
|
||||
| Dfloat(f) -> print_float f
|
||||
| Dchar(c) -> print_char c
|
||||
| Dstring(s) -> print_string s
|
||||
| Dvoid -> print_string "()"
|
||||
|
||||
(* print patterns *)
|
||||
let atom_pat pat =
|
||||
match pat with
|
||||
Dconstantpat _ | Dvarpat _ | Dwildpat -> true
|
||||
| _ -> false
|
||||
|
||||
let rec print_pat pat =
|
||||
open_box 1;
|
||||
if not (atom_pat pat) then print_string "(";
|
||||
begin match pat with
|
||||
Dwildpat -> print_string "_"
|
||||
| Dconstantpat(i) -> print_immediate i
|
||||
| Dvarpat(i) -> print_name i
|
||||
| Dconstructpat(qual_ident, pat_list) ->
|
||||
print_string "constr";
|
||||
print_space ();
|
||||
print_qualified_ident qual_ident;
|
||||
if pat_list <> [] then print_space ();
|
||||
print_list print_pat pat_list
|
||||
| Dtuplepat(pat_list) ->
|
||||
print_string ",";
|
||||
print_space ();
|
||||
print_list print_pat pat_list
|
||||
| Drecordpat(l) ->
|
||||
print_string "record";
|
||||
print_list
|
||||
(fun (qual_ident, pat) ->
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
print_qualified_ident qual_ident;
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_string ")";
|
||||
close_box ()) l
|
||||
| Dorpat(pat1, pat2) ->
|
||||
print_string "orpat";
|
||||
print_space ();
|
||||
print_list print_pat [pat1;pat2]
|
||||
| Daliaspat(pat, i) ->
|
||||
print_string "as";
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print_int i
|
||||
end;
|
||||
if not (atom_pat pat) then print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* print statepat *)
|
||||
let print_statepat (s, l) =
|
||||
match l with
|
||||
[] -> print_string s
|
||||
| l -> print_string "(";
|
||||
print_string s;
|
||||
print_space ();
|
||||
print_list print_pat l;
|
||||
print_string ")"
|
||||
|
||||
(* print expressions *)
|
||||
let atom e =
|
||||
match e.d_desc with
|
||||
Dconstant _ -> true
|
||||
| _ -> false
|
||||
|
||||
(* print variables *)
|
||||
let print_var v =
|
||||
match v with
|
||||
Dlocal(n) ->
|
||||
print_string "local";
|
||||
print_space ();
|
||||
print_name n
|
||||
| Dglobal(qual_ident) ->
|
||||
print_string "global";
|
||||
print_space ();
|
||||
print_qualified_ident qual_ident
|
||||
|
||||
let rec print e =
|
||||
open_box 1;
|
||||
if not (atom e) then print_string "(";
|
||||
begin match e.d_desc with
|
||||
Dconstant(i) -> print_immediate i
|
||||
| Dvar(v, subst) ->
|
||||
print_var v;
|
||||
print_subst subst
|
||||
| Dlast(i) ->
|
||||
print_string "last";
|
||||
print_space ();
|
||||
print_name i
|
||||
| Dpre(opt_default, e) ->
|
||||
print_string "pre";
|
||||
print_space ();
|
||||
begin match opt_default with
|
||||
None -> print e
|
||||
| Some(default) ->
|
||||
print default; print_space (); print e
|
||||
end
|
||||
| Dinit(ck, None) ->
|
||||
print_string "init";
|
||||
print_space ();
|
||||
print_clock ck
|
||||
| Dinit(ck, Some(n)) ->
|
||||
print_string "init";
|
||||
print_space ();
|
||||
print_clock ck;
|
||||
print_space ();
|
||||
print_name n
|
||||
| Difthenelse(e0,e1,e2) ->
|
||||
print_string "if";
|
||||
print_space ();
|
||||
print e0;
|
||||
print_space ();
|
||||
print e1;
|
||||
print_space ();
|
||||
print e2
|
||||
| Dtuple(l) ->
|
||||
print_string ",";
|
||||
print_space ();
|
||||
print_list print l
|
||||
| Dconstruct(qual_ident,l) ->
|
||||
print_string "constr";
|
||||
print_space ();
|
||||
print_qualified_ident qual_ident;
|
||||
if l <> [] then print_space ();
|
||||
print_list print l
|
||||
| Dprim(qual_ident, l) ->
|
||||
print_string "(";
|
||||
print_qualified_ident qual_ident;
|
||||
print_space ();
|
||||
print_list print l;
|
||||
print_string ")"
|
||||
| Drecord(l) ->
|
||||
print_string "record";
|
||||
print_space ();
|
||||
print_list (fun (qual_ident, e) ->
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
print_qualified_ident qual_ident;
|
||||
print_space ();
|
||||
print e;
|
||||
print_string ")";
|
||||
close_box ()) l
|
||||
| Drecord_access(e,qual_ident) ->
|
||||
print_string "access";
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_qualified_ident qual_ident
|
||||
| Dfun(is_state, params, args, block, e) ->
|
||||
print_string ("fun" ^ (if is_state then "(s)" else "(c)"));
|
||||
print_space ();
|
||||
print_params params;
|
||||
print_space ();
|
||||
print_list print_pat args;
|
||||
print_space ();
|
||||
print_block block;
|
||||
print_space ();
|
||||
print_string "return ";
|
||||
print e
|
||||
| Dapply(is_state, f, e_list) ->
|
||||
print_string ("apply" ^ (if is_state then "(s)" else "(c)"));
|
||||
print_space ();
|
||||
print f;
|
||||
print_space ();
|
||||
print_list print e_list
|
||||
| Dlet(block, e) ->
|
||||
print_string "let";
|
||||
print_space ();
|
||||
print_block block;
|
||||
print_space ();
|
||||
print e
|
||||
| Deseq(e1, e2) ->
|
||||
print_string "seq";
|
||||
print_space ();
|
||||
print e1;
|
||||
print_space ();
|
||||
print e2
|
||||
| Dtest(e1) ->
|
||||
print_string "test";
|
||||
print_space ();
|
||||
print e1
|
||||
| Dwhen(e1) ->
|
||||
print_string "when";
|
||||
print_space ();
|
||||
print e1
|
||||
| Dclock(ck) ->
|
||||
print_string "clock";
|
||||
print_space ();
|
||||
print_clock ck
|
||||
end;
|
||||
if not (atom e) then print_string ")";
|
||||
close_box()
|
||||
|
||||
and print_block b =
|
||||
(* print variable definitions *)
|
||||
let print_env env =
|
||||
open_box 1;
|
||||
print_string "(env";
|
||||
print_space ();
|
||||
Hashtbl.iter (fun i ident -> print_ident ident;print_space ()) env;
|
||||
print_string ")";
|
||||
close_box () in
|
||||
(* main function *)
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
(* environment *)
|
||||
print_env b.b_env;
|
||||
print_space ();
|
||||
(* equations *)
|
||||
print_equation b.b_equations;
|
||||
print_space ();
|
||||
(* write variables *)
|
||||
print_string "(write";
|
||||
print_space ();
|
||||
print_list print_name b.b_write;
|
||||
print_string ")";
|
||||
print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* print ident declarations *)
|
||||
(* e.g, "(kind x/412 (int) (cl) (write) (last) (signal) (= 412))" *)
|
||||
and print_ident id =
|
||||
let print_kind () =
|
||||
match id.id_kind with
|
||||
Kinit -> print_string "init"
|
||||
| Kclock -> print_string "clock"
|
||||
| Kmemo -> print_string "memo"
|
||||
| Kstatic -> print_string "static"
|
||||
| Klast -> print_string "last"
|
||||
| Kreset -> print_string "reset"
|
||||
| Kvalue -> print_string "value"
|
||||
| Kinput -> print_string "input"
|
||||
| Kshared -> print_string "shared" in
|
||||
let print_name () =
|
||||
begin match id.id_original with
|
||||
None -> ()
|
||||
| Some(s) -> print_string s
|
||||
end;
|
||||
print_name id.id_name in
|
||||
let print_typs () =
|
||||
print_string "(";
|
||||
print_typs id.id_typ;
|
||||
print_string ")" in
|
||||
let print_write () =
|
||||
if id.id_write then
|
||||
begin print_space (); print_string "(write)" end in
|
||||
let print_last () =
|
||||
if id.id_last then
|
||||
begin print_space (); print_string "(last)" end in
|
||||
let print_signal () =
|
||||
if id.id_signal then
|
||||
begin print_space (); print_string "(signal)" end in
|
||||
let print_expr () =
|
||||
match id.id_value with
|
||||
None -> ()
|
||||
| Some(e) ->
|
||||
print_space ();print_string "(= "; print e; print_string ")" in
|
||||
(* main function *)
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
print_kind ();
|
||||
print_space ();
|
||||
print_name ();
|
||||
print_space ();
|
||||
print_typs ();
|
||||
print_space ();
|
||||
print_write ();
|
||||
print_last ();
|
||||
print_signal ();
|
||||
print_expr ();
|
||||
print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* prints a sequence of sets of parallel equations *)
|
||||
and print_equation eq =
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
begin match eq with
|
||||
Dequation(pat, e) ->
|
||||
print_string "let";
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_clock e.d_guard
|
||||
| Dlasteq(n, e) ->
|
||||
print_string "last";
|
||||
print_space ();
|
||||
print_name n;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_clock e.d_guard
|
||||
| Demit(pat, e) ->
|
||||
print_string "emit";
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_clock e.d_guard
|
||||
| Dstatic(pat, e) ->
|
||||
print_string "static";
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_clock e.d_guard
|
||||
| Dnext(n, e) ->
|
||||
print_string "next";
|
||||
print_space ();
|
||||
print_name n;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_clock e.d_guard
|
||||
| Dget(pat, v) ->
|
||||
print_string "get";
|
||||
print_space ();
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print_var v
|
||||
| Dwheneq(eq, clk) ->
|
||||
print_string "when";
|
||||
print_space ();
|
||||
print_clock clk;
|
||||
print_space ();
|
||||
print_equation eq
|
||||
| Dmerge(is_static, e, pat_block_list) ->
|
||||
print_string "merge";
|
||||
print_space ();
|
||||
if is_static then print_string "static"
|
||||
else print_clock e.d_guard;
|
||||
print_space ();
|
||||
print e;
|
||||
print_space ();
|
||||
print_list (fun (pat, block) ->
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
print_pat pat;
|
||||
print_space ();
|
||||
print_block block;
|
||||
print_string ")";
|
||||
close_box ()) pat_block_list
|
||||
| Dpresent(ck, scondpat_block_list, block) ->
|
||||
print_string "present";
|
||||
print_space ();
|
||||
print_clock ck;
|
||||
print_space ();
|
||||
print_list (fun (scondpat, block) ->
|
||||
open_box 1;
|
||||
print_string "(";
|
||||
print_spat scondpat;
|
||||
print_space ();
|
||||
print_block block;
|
||||
print_string ")";
|
||||
close_box ()) scondpat_block_list;
|
||||
print_space ();
|
||||
print_block block
|
||||
| Dreset(eq, e) ->
|
||||
print_string "reset";
|
||||
print_space ();
|
||||
print_equation eq;
|
||||
print_space ();
|
||||
print e
|
||||
| Dautomaton(ck, handlers) ->
|
||||
print_string "automaton";
|
||||
print_space ();
|
||||
print_clock ck;
|
||||
print_space ();
|
||||
print_list print_handler handlers
|
||||
| Dpar(eq_list) ->
|
||||
print_string "par";
|
||||
print_space ();
|
||||
print_list print_equation eq_list
|
||||
| Dseq(eq_list) ->
|
||||
print_string "seq";
|
||||
print_space ();
|
||||
print_list print_equation eq_list
|
||||
| Dblock(b) ->
|
||||
print_string "block";
|
||||
print_space ();
|
||||
print_block b
|
||||
end;
|
||||
print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* print the handlers of an automaton *)
|
||||
and print_handler (statepat, b_weak, b_strong, weak_escape, strong_escape) =
|
||||
open_box 1;
|
||||
print_string "(state";
|
||||
print_space ();
|
||||
print_statepat statepat;
|
||||
print_space ();
|
||||
print_block b_weak;
|
||||
print_space ();
|
||||
print_block b_strong;
|
||||
print_space ();
|
||||
print_string "(weak ";
|
||||
print_escape weak_escape;
|
||||
print_string ")";
|
||||
print_space ();
|
||||
print_string "(strong ";
|
||||
print_escape weak_escape;
|
||||
print_string ")";
|
||||
print_string ")";
|
||||
close_box ()
|
||||
|
||||
and print_escape escape_list =
|
||||
print_list
|
||||
(fun (spat, b, is_continue, state) ->
|
||||
print_string "(";
|
||||
if is_continue then print_string "continue " else print_string "then ";
|
||||
print_spat spat;
|
||||
print_space ();
|
||||
print_block b;
|
||||
print_space ();
|
||||
print_state state;
|
||||
print_string ")")
|
||||
escape_list;
|
||||
close_box ()
|
||||
|
||||
|
||||
(* print type and clock instance *)
|
||||
and print_subst { s_typ = st; s_clock = scl; s_carrier = sc } =
|
||||
match st, scl, sc with
|
||||
[],[],[] -> ()
|
||||
| l1,l2,l3 ->
|
||||
print_string "[";
|
||||
print_list print_type l1;
|
||||
print_string "]";
|
||||
print_space ();
|
||||
print_string "[";
|
||||
print_list print_clock l2;
|
||||
print_string "]";
|
||||
print_space ();
|
||||
print_string "[";
|
||||
print_list print_carrier l3;
|
||||
print_string "]";
|
||||
|
||||
and print_params { s_typ = pt; s_clock = pcl; s_carrier = pc } =
|
||||
match pt, pcl, pc with
|
||||
[],[],[] -> ()
|
||||
| l1,l2,l3 ->
|
||||
print_string "[";
|
||||
print_list print_name l1;
|
||||
print_string "]";
|
||||
print_space ();
|
||||
print_string "[";
|
||||
print_list print_name l2;
|
||||
print_string "]";
|
||||
print_space ();
|
||||
print_string "[";
|
||||
print_list print_name l3;
|
||||
print_string "]"
|
||||
|
||||
and print_state (s, l) =
|
||||
match l with
|
||||
[] -> print_string s
|
||||
| l -> print_string "(";
|
||||
print_string s;
|
||||
print_space ();
|
||||
print_list print l;
|
||||
print_string ")"
|
||||
|
||||
and atom_spat spat =
|
||||
match spat with
|
||||
Dexppat _ | Dcondpat _ -> true
|
||||
| _ -> false
|
||||
|
||||
and print_spat spat =
|
||||
open_box 1;
|
||||
if not (atom_spat spat) then print_string "(";
|
||||
begin match spat with
|
||||
Dandpat(spat1, spat2) ->
|
||||
print_string "& ";
|
||||
print_spat spat1;
|
||||
print_space ();
|
||||
print_spat spat2
|
||||
| Dexppat(e) ->
|
||||
print e
|
||||
| Dcondpat(e, pat) ->
|
||||
print_string "is ";
|
||||
print e;
|
||||
print_space ();
|
||||
print_pat pat
|
||||
end;
|
||||
if not (atom_spat spat) then print_string ")";
|
||||
close_box ()
|
||||
|
||||
(* the main entry for printing definitions *)
|
||||
let print_definition (name, e) =
|
||||
open_box 2;
|
||||
print_string "(def ";
|
||||
if is_an_infix_or_prefix_operator name
|
||||
then begin print_string "( "; print_string name; print_string " )" end
|
||||
else print_string name;
|
||||
print_space ();
|
||||
print e;
|
||||
print_string ")";
|
||||
print_newline ();
|
||||
close_box ()
|
||||
|
||||
(* print types *)
|
||||
let print_variant (qualid, { arg = typ_list; res = typ }) =
|
||||
print_string "(";
|
||||
print_qualified_ident qualid;
|
||||
print_string "(";
|
||||
print_list print_type typ_list;
|
||||
print_string ")";
|
||||
print_space ();
|
||||
print_type typ;
|
||||
print_string ")"
|
||||
|
||||
let print_record (qualid, is_mutable, { arg = typ1; res = typ2 }) =
|
||||
print_string "(";
|
||||
if is_mutable then print_string "true" else print_string "false";
|
||||
print_space ();
|
||||
print_qualified_ident qualid;
|
||||
print_space ();
|
||||
print_type typ1;
|
||||
print_space ();
|
||||
print_type typ2;
|
||||
print_string ")"
|
||||
|
||||
let print_type_declaration s { d_type_desc = td; d_type_arity = arity } =
|
||||
open_box 2;
|
||||
print_string "(type[";
|
||||
print_list print_name arity;
|
||||
print_string "]";
|
||||
print_space ();
|
||||
print_string s;
|
||||
print_space ();
|
||||
begin match td with
|
||||
Dabstract_type -> ()
|
||||
| Dabbrev(ty) ->
|
||||
print_type ty
|
||||
| Dvariant_type variant_list ->
|
||||
List.iter print_variant variant_list
|
||||
| Drecord_type record_list ->
|
||||
List.iter print_record record_list
|
||||
end;
|
||||
print_string ")";
|
||||
print_newline ();
|
||||
close_box ();;
|
||||
|
||||
(* the main functions *)
|
||||
set_max_boxes max_int ;;
|
||||
|
||||
let output_equations oc eqs =
|
||||
set_formatter_out_channel oc;
|
||||
List.iter print_equation eqs
|
||||
|
||||
let output oc declarative_code =
|
||||
set_formatter_out_channel oc;
|
||||
(* print type declarations *)
|
||||
Hashtbl.iter print_type_declaration declarative_code.d_types;
|
||||
(* print value definitions *)
|
||||
List.iter print_definition declarative_code.d_code;
|
||||
print_flush ()
|
||||
|
@ -0,0 +1,63 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Gregoire Hamon, Marc Pouzet *)
|
||||
(* Organization : SPI team, LIP6 laboratory, University Paris 6 *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: default_value.ml,v 1.1.1.1 2005-11-03 15:45:23 pouzet Exp $ *)
|
||||
|
||||
(** Computes a default value from a type *)
|
||||
|
||||
open Misc
|
||||
open Names
|
||||
open Def_types
|
||||
open Types
|
||||
open Initialization
|
||||
open Caml
|
||||
|
||||
let default x ty =
|
||||
let rec def ty =
|
||||
match ty with
|
||||
TypeVar{contents = Typindex _} -> Cdummy ""
|
||||
| TypeVar{contents = Typlink ty} -> def ty
|
||||
| Tarrow _ -> x
|
||||
| Tproduct(t_list) ->
|
||||
if t_list = []
|
||||
then Cdummy ""
|
||||
else Ctuple (List.map def t_list)
|
||||
| Tconstr (info, tlist) ->
|
||||
if info.qualid.qual = pervasives_module then
|
||||
match info.qualid.id with
|
||||
| "int" -> Cim (Cint 0)
|
||||
| "bool" | "clock" -> Cim (Cbool false)
|
||||
| "float" -> Cim (Cfloat 0.0)
|
||||
| "char" -> Cim (Cchar 'a')
|
||||
| "string" -> Cim (Cstring "")
|
||||
| "unit" -> Cim (Cvoid)
|
||||
| _ -> Cdummy ""
|
||||
else
|
||||
match info.info_in_table.type_desc with
|
||||
Abstract_type -> Cdummy ""
|
||||
| Variant_type l ->
|
||||
begin
|
||||
let case = List.hd l in
|
||||
match case.info_in_table.typ_desc with
|
||||
Tarrow (ty1, ty2) ->
|
||||
Cconstruct1 ({ cqual = case.qualid.qual;
|
||||
cid = case.qualid.id }, def ty1)
|
||||
| _ ->
|
||||
Cconstruct0 { cqual = case.qualid.qual;
|
||||
cid = case.qualid.id }
|
||||
end
|
||||
| Record_type l ->
|
||||
let field_of_type x =
|
||||
let ty1,_ = filter_arrow x.info_in_table.typ_desc in
|
||||
({ cqual = x.qualid.qual; cid = x.qualid.id }, def ty1) in
|
||||
Crecord (List.map field_of_type l)
|
||||
in
|
||||
def ty
|
||||
|
||||
|
@ -0,0 +1,295 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Lucid Synchrone *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(* $Id: misc.ml,v 1.11 2006-09-30 12:27:27 pouzet Exp $ *)
|
||||
|
||||
(* version of the compiler *)
|
||||
let version = "3.0b"
|
||||
|
||||
let date = DATE
|
||||
|
||||
(* standard module *)
|
||||
let pervasives_module = Pervasives
|
||||
let standard_lib = STDLIB
|
||||
|
||||
(* variable creation *)
|
||||
(* generating names *)
|
||||
class name_generator =
|
||||
object
|
||||
val mutable counter = 0
|
||||
method name =
|
||||
counter <- counter + 1;
|
||||
counter
|
||||
method reset =
|
||||
counter <- 0
|
||||
method init i =
|
||||
counter <- i
|
||||
end
|
||||
|
||||
(* association table with memoization *)
|
||||
class name_assoc_table f =
|
||||
object
|
||||
val mutable counter = 0
|
||||
val mutable assoc_table: (int * string) list = []
|
||||
method name var =
|
||||
try
|
||||
List.assq var assoc_table
|
||||
with
|
||||
not_found ->
|
||||
let n = f counter in
|
||||
counter <- counter + 1;
|
||||
assoc_table <- (var,n) :: assoc_table;
|
||||
n
|
||||
method reset =
|
||||
counter <- 0;
|
||||
assoc_table <- []
|
||||
end
|
||||
|
||||
(* error during the whole process *)
|
||||
exception Error
|
||||
|
||||
(* internal error : for example, an abnormal pattern matching failure *)
|
||||
(* gives the name of the function *)
|
||||
exception Internal_error of string
|
||||
|
||||
let fatal_error s = raise (Internal_error s)
|
||||
|
||||
let not_yet_implemented s =
|
||||
Printf.eprintf "The construction %s is not implemented yet.\n" s;
|
||||
raise Error
|
||||
|
||||
(* creating a name generator for type and clock calculus *)
|
||||
(* ensure unicity for the whole process *)
|
||||
let symbol = new name_generator
|
||||
|
||||
(* generic and non generic variables in the various type systems *)
|
||||
let generic = -1
|
||||
let notgeneric = 0
|
||||
let maxlevel = max_int
|
||||
|
||||
let binding_level = ref 0
|
||||
let top_binding_level () = !binding_level = 0
|
||||
|
||||
let push_binding_level () = binding_level := !binding_level + 1
|
||||
let pop_binding_level () =
|
||||
binding_level := !binding_level - 1;
|
||||
assert (!binding_level > generic)
|
||||
let reset_binding_level () = binding_level := 0
|
||||
|
||||
(* realtime mode *)
|
||||
let realtime = ref false
|
||||
|
||||
(* assertions *)
|
||||
let no_assert = ref false
|
||||
|
||||
(* converting integers into variable names *)
|
||||
(* variables are printed 'a, 'b *)
|
||||
let int_to_letter bound i =
|
||||
if i < 26
|
||||
then String.make 1 (Char.chr (i+bound))
|
||||
else String.make 1 (Char.chr ((i mod 26) + bound)) ^ string_of_int (i/26)
|
||||
|
||||
let int_to_alpha i = int_to_letter 97 i
|
||||
|
||||
(* printing information *)
|
||||
class on_off =
|
||||
object
|
||||
val mutable status = false
|
||||
method set = status <- true
|
||||
method get = status
|
||||
end
|
||||
|
||||
let print_type = new on_off
|
||||
let print_clock = new on_off
|
||||
let print_init = new on_off
|
||||
let print_causality = new on_off
|
||||
let no_causality = ref false
|
||||
let no_initialisation = ref false
|
||||
|
||||
let no_deadcode = ref false
|
||||
|
||||
(* control what is done in the compiler *)
|
||||
exception Stop
|
||||
|
||||
let only = ref ""
|
||||
let set_only_info o = only := o
|
||||
let parse_only () =
|
||||
if !only = "parse" then raise Stop
|
||||
let type_only () =
|
||||
if !only = "type" then raise Stop
|
||||
let clock_only () =
|
||||
if !only = "clock" then raise Stop
|
||||
let caus_only () =
|
||||
if !only = "caus" then raise Stop
|
||||
let init_only () =
|
||||
if !only = "init" then raise Stop
|
||||
let dec_only () =
|
||||
if !only = "parse" or !only = "type"
|
||||
or !only = "clock" or !only = "init"
|
||||
or !only = "dec" then raise Stop
|
||||
|
||||
(* load paths *)
|
||||
let load_path = ref ([] : string list)
|
||||
|
||||
(* no link *)
|
||||
let no_link = ref false
|
||||
|
||||
(* simulation node *)
|
||||
let simulation_node = ref ""
|
||||
|
||||
(* sampling rate *)
|
||||
let sampling_rate : int option ref = ref None
|
||||
|
||||
(* level of inlining *)
|
||||
let inlining_level = ref 10
|
||||
|
||||
(* emiting declarative code *)
|
||||
let print_declarative_code = ref false
|
||||
let print_auto_declarative_code = ref false
|
||||
let print_total_declarative_code = ref false
|
||||
let print_last_declarative_code = ref false
|
||||
let print_signals_declarative_code = ref false
|
||||
let print_reset_declarative_code = ref false
|
||||
let print_linearise_declarative_code = ref false
|
||||
let print_initialize_declarative_code = ref false
|
||||
let print_split_declarative_code = ref false
|
||||
let print_inline_declarative_code = ref false
|
||||
let print_constant_declarative_code = ref false
|
||||
let print_deadcode_declarative_code = ref false
|
||||
let print_copt_declarative_code = ref false
|
||||
|
||||
(* total emission of signals *)
|
||||
let set_total_emit = ref false
|
||||
|
||||
(* generating C *)
|
||||
let make_c_code = ref false
|
||||
|
||||
(* profiling information about the compilation *)
|
||||
let print_exec_time = ref false
|
||||
|
||||
exception Cannot_find_file of string
|
||||
|
||||
let find_in_path filename =
|
||||
if Sys.file_exists filename then
|
||||
filename
|
||||
else if not(Filename.is_implicit filename) then
|
||||
raise(Cannot_find_file filename)
|
||||
else
|
||||
let rec find = function
|
||||
[] ->
|
||||
raise(Cannot_find_file filename)
|
||||
| a::rest ->
|
||||
let b = Filename.concat a filename in
|
||||
if Sys.file_exists b then b else find rest
|
||||
in find !load_path
|
||||
|
||||
|
||||
(* Prompts: [error_prompt] is printed before compiler error *)
|
||||
(* and warning messages *)
|
||||
let error_prompt = ">"
|
||||
|
||||
(* list intersection *)
|
||||
let intersect l1 l2 =
|
||||
List.exists (fun el -> List.mem el l1) l2
|
||||
|
||||
(* remove an entry from an association list *)
|
||||
let rec remove n l =
|
||||
match l with
|
||||
[] -> raise Not_found
|
||||
| (m, v) :: l ->
|
||||
if n = m then l else (m, v) :: remove n l
|
||||
|
||||
(* list substraction. l1 - l2 *)
|
||||
let sub_list l1 l2 =
|
||||
let rec sl l l1 =
|
||||
match l1 with
|
||||
[] -> l
|
||||
| h :: t -> sl (if List.mem h l2 then l else (h :: l)) t in
|
||||
sl [] l1
|
||||
|
||||
(* union *)
|
||||
let rec union l1 l2 =
|
||||
match l1, l2 with
|
||||
[], l2 -> l2
|
||||
| l1, [] -> l1
|
||||
| x :: l1, l2 ->
|
||||
if List.mem x l2 then union l1 l2 else x :: union l1 l2
|
||||
|
||||
let addq x l = if List.memq x l then l else x :: l
|
||||
|
||||
let rec unionq l1 l2 =
|
||||
match l1, l2 with
|
||||
[], l2 -> l2
|
||||
| l1, [] -> l1
|
||||
| x :: l1, l2 ->
|
||||
if List.memq x l2 then unionq l1 l2 else x :: unionq l1 l2
|
||||
|
||||
(* intersection *)
|
||||
let rec intersection l1 l2 =
|
||||
match l1, l2 with
|
||||
([], _) | (_, []) -> []
|
||||
| x :: l1, l2 -> if List.mem x l2 then x :: intersection l1 l2
|
||||
else intersection l1 l2
|
||||
|
||||
(* the last element of a list *)
|
||||
let rec last l =
|
||||
match l with
|
||||
[] -> raise (Failure "last")
|
||||
| [x] -> x
|
||||
| _ :: l -> last l
|
||||
|
||||
(* iterator *)
|
||||
let rec map_fold f acc l =
|
||||
match l with
|
||||
[] -> acc, []
|
||||
| x :: l ->
|
||||
let acc, v = f acc x in
|
||||
let acc, l = map_fold f acc l in
|
||||
acc, v :: l
|
||||
|
||||
(* flat *)
|
||||
let rec flat l =
|
||||
match l with
|
||||
[] -> []
|
||||
| x :: l -> x @ flat l
|
||||
|
||||
(* reverse *)
|
||||
let reverse l =
|
||||
let rec reverse acc l =
|
||||
match l with
|
||||
[] -> acc
|
||||
| x :: l -> reverse (x :: acc) l in
|
||||
reverse [] l
|
||||
|
||||
(* generic printing of a list *)
|
||||
let print_list print print_sep l =
|
||||
let rec printrec l =
|
||||
match l with
|
||||
[] -> ()
|
||||
| [x] ->
|
||||
print x
|
||||
| x::l ->
|
||||
print x;
|
||||
print_sep ();
|
||||
printrec l in
|
||||
printrec l
|
||||
|
||||
(* generates the sequence of integers *)
|
||||
let rec from n = if n = 0 then [] else n :: from (n-1)
|
||||
|
||||
(* for infix operators, print parenthesis around *)
|
||||
let is_an_infix_or_prefix_operator op =
|
||||
if op = "" then false
|
||||
else
|
||||
let c = String.get op 0 in
|
||||
not (((c >= 'a') & (c <= 'z')) or ((c >= 'A') & (c <= 'Z')))
|
||||
|
||||
(* making a list from a hash-table *)
|
||||
let listoftable t =
|
||||
Hashtbl.fold (fun key value l -> (key, value) :: l) t []
|
@ -0,0 +1,2 @@
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Heptagon *)
|
||||
(* *)
|
||||
(* Author : Marc Pouzet *)
|
||||
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
(** Remove implicit array's deep copy. If ever some p = e with p of type array still exist,
|
||||
they are only used as reference to the array, no copy is implied :
|
||||
array assignation after [scalarize] is pointer wise assignation *)
|
||||
|
||||
|
||||
open Misc
|
||||
open Obc
|
||||
open Obc_utils
|
||||
open Obc_mapfold
|
||||
|
||||
|
||||
(** fresh Afor from 0 to [size] with [body] a function from [var_ident] (the iterator) to [act] list *)
|
||||
let fresh_for size body =
|
||||
let i = Idents.gen_var "scalarize" "i" in
|
||||
let id = mk_var_dec i Initial.tint in
|
||||
let ei = mk_evar_int i in
|
||||
Afor (id, Initial.mk_static_int 0, size, mk_block (body ei))
|
||||
|
||||
|
||||
let act funs () a = match a with
|
||||
| Aassgn (p,e) ->
|
||||
(match e.e_ty with
|
||||
| Types.Tarray (t, size) ->
|
||||
(* a reference (alias) to the array, since we could have a full expression *)
|
||||
let array_ref = Idents.gen_var "scalarize" "a_ref" in
|
||||
let vd_array_ref = mk_var_dec array_ref (Types.Tmutable p.pat_ty) in
|
||||
(* reference initialization *)
|
||||
let pat_array_ref = mk_pattern ~loc:e.e_loc p.pat_ty (Lvar array_ref) in
|
||||
let init_array_ref = Aassgn (pat_array_ref, e) in
|
||||
(* the copy loop *)
|
||||
let array_ref_i i = mk_pattern_exp t (Larray (pat_array_ref, i)) in
|
||||
let p_i i = mk_pattern t (Larray (p, i)) in
|
||||
let copy_i i =
|
||||
(* recursive call to deal with multidimensional arrays (go deeper) *)
|
||||
let a = Aassgn (p_i i, array_ref_i i) in
|
||||
let a, _ = act_it funs () a in
|
||||
[a]
|
||||
in
|
||||
let copy_array = fresh_for size copy_i in
|
||||
(* resulting block *)
|
||||
let block = mk_block ~locals:[vd_array_ref] [init_array_ref; copy_array] in
|
||||
Ablock block, ()
|
||||
| _ -> raise Errors.Fallback
|
||||
)
|
||||
| _ -> raise Errors.Fallback
|
||||
|
||||
|
||||
let program p =
|
||||
let p, _ = program_it { defaults with act = act } () p in
|
||||
p
|
||||
|
||||
|
@ -0,0 +1,128 @@
|
||||
package jeptagon;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Pervasives {
|
||||
|
||||
public static final ExecutorService executor_cached = Executors.newCachedThreadPool();
|
||||
|
||||
public static class StaticFuture<V> implements Future<V> {
|
||||
V v;
|
||||
|
||||
public StaticFuture(V v) { this.v = v; }
|
||||
|
||||
public boolean cancel(boolean mayInterruptIfRunning) { return false; }
|
||||
|
||||
public boolean isCancelled() { return false; }
|
||||
|
||||
public boolean isDone() { return true; }
|
||||
|
||||
public V get() { return v; }
|
||||
|
||||
public V get(long timeout, TimeUnit unit) { return v; }
|
||||
}
|
||||
|
||||
public static class Tuple1 {
|
||||
public final Object c0;
|
||||
public Tuple1(Object v) {
|
||||
c0 = v;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple2 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public Tuple2(Object v0, Object v1) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple3 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public final Object c2;
|
||||
public Tuple3(Object v0, Object v1, Object v2) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
c2 = v2;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple4 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public final Object c2;
|
||||
public final Object c3;
|
||||
public Tuple4(Object v0, Object v1, Object v2, Object v3) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
c2 = v2;
|
||||
c3 = v3;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple5 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public final Object c2;
|
||||
public final Object c3;
|
||||
public final Object c4;
|
||||
public Tuple5(Object v0, Object v1, Object v2, Object v3, Object v4) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
c2 = v2;
|
||||
c3 = v3;
|
||||
c4 = v4;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple6 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public final Object c2;
|
||||
public final Object c3;
|
||||
public final Object c4;
|
||||
public final Object c5;
|
||||
public Tuple6(Object v0, Object v1, Object v2, Object v3, Object v4, Object v5) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
c2 = v2;
|
||||
c3 = v3;
|
||||
c4 = v4;
|
||||
c5 = v5;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tuple7 {
|
||||
public final Object c0;
|
||||
public final Object c1;
|
||||
public final Object c2;
|
||||
public final Object c3;
|
||||
public final Object c4;
|
||||
public final Object c5;
|
||||
public final Object c6;
|
||||
public Tuple7(Object v0, Object v1, Object v2, Object v3, Object v4, Object v5, Object v6) {
|
||||
c0 = v0;
|
||||
c1 = v1;
|
||||
c2 = v2;
|
||||
c3 = v3;
|
||||
c4 = v4;
|
||||
c5 = v5;
|
||||
c6 = v6;
|
||||
}
|
||||
}
|
||||
|
||||
public static int do_stuff(int coeff) {
|
||||
int x = 13;
|
||||
for (int i = 0; i < coeff; i++) {
|
||||
for (int j = 0; j < 1000000; j++) {
|
||||
x = (x + j) % (x + j/x) + 13;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
node updown(b : bool) returns (o : bool)
|
||||
var o',on_off:bool;
|
||||
var o2,on_off:bool;
|
||||
let
|
||||
on_off = true;
|
||||
automaton
|
||||
state Down
|
||||
do o' = false until on_off then Up
|
||||
do o2 = false until on_off then Up
|
||||
state Up
|
||||
do o' = true until on_off then Down
|
||||
do o2 = true until on_off then Down
|
||||
end;
|
||||
o = merge b (true-> o') (false -> false)
|
||||
o = merge b (true-> o2) (false -> false)
|
||||
tel
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue