heptagon/compiler/obc/ml/declarative_printer.ml
2011-01-24 16:09:27 +01:00

700 lines
17 KiB
OCaml

(**************************************************************************)
(* *)
(* 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 ()