(* * There are two kinds of rust files: * * .rc files, containing crates. * .rs files, containing source. * *) open Common;; open Fmt;; type ident = string ;; type slot_key = KEY_ident of ident | KEY_temp of temp_id ;; (* "names" are statically computable references to particular items; they never involve dynamic indexing (nor even static tuple-indexing; you could add it but there are few contexts that need names that would benefit from it). Each component of a name may also be type-parametric; you must supply type parameters to reference through a type-parametric name component. So for example if foo is parametric in 2 types, you can write foo[int,int].bar but not foo.bar. *) type effect = PURE | IO | STATE | UNSAFE ;; type name_base = BASE_ident of ident | BASE_temp of temp_id | BASE_app of (ident * (ty array)) and name_component = COMP_ident of ident | COMP_app of (ident * (ty array)) | COMP_idx of int and name = NAME_base of name_base | NAME_ext of (name * name_component) (* * Type expressions are transparent to type names, their equality is * structural. (after normalization) *) and ty = TY_any | TY_nil | TY_bool | TY_mach of ty_mach | TY_int | TY_uint | TY_char | TY_str | TY_tup of ty_tup | TY_vec of ty | TY_rec of ty_rec (* * Note that ty_idx is only valid inside a ty of a ty_iso group, not * in a general type term. *) | TY_tag of ty_tag | TY_iso of ty_iso | TY_idx of int | TY_fn of ty_fn | TY_chan of ty | TY_port of ty | TY_obj of ty_obj | TY_task | TY_native of opaque_id | TY_param of (ty_param_idx * effect) | TY_named of name | TY_type | TY_exterior of ty | TY_mutable of ty | TY_constrained of (ty * constrs) (* * FIXME: this should be cleaned up to be a different * type definition. Only args can be by-ref, only locals * can be auto. The structure here is historical. *) and mode = | MODE_interior | MODE_alias and slot = { slot_mode: mode; slot_ty: ty option; } and ty_tup = ty array (* In closed type terms a constraint may refer to components of the term by * anchoring off the "formal symbol" '*', which represents "the term this * constraint is attached to". * * * For example, if I have a tuple type tup(int,int), I may wish to enforce the * lt predicate on it; I can write this as a constrained type term like: * * tup(int,int) : lt( *._0, *._1 ) * * In fact all tuple types are converted to this form for purpose of * type-compatibility testing; the argument tuple in a function * * fn (int x, int y) : lt(x, y) -> int * * desugars to * * fn (tup(int, int) : lt( *._1, *._2 )) -> int * *) and carg_base = BASE_formal | BASE_named of name_base and carg_path = CARG_base of carg_base | CARG_ext of (carg_path * name_component) and carg = CARG_path of carg_path | CARG_lit of lit and constr = { constr_name: name; constr_args: carg array; } and constrs = constr array and ty_rec = (ident * ty) array (* ty_tag is a sum type. * * a tag type expression either normalizes to a TY_tag or a TY_iso, * which (like in ocaml) is an indexed projection from an iso-recursive * group of TY_tags. *) and ty_tag = (name, ty_tup) Hashtbl.t and ty_iso = { iso_index: int; iso_group: ty_tag array } and ty_sig = { sig_input_slots: slot array; sig_input_constrs: constrs; sig_output_slot: slot; } and ty_fn_aux = { fn_is_iter: bool; fn_effect: effect; } and ty_fn = (ty_sig * ty_fn_aux) and ty_obj_header = (slot array * constrs) and ty_obj = (effect * ((ident,ty_fn) Hashtbl.t)) and check_calls = (lval * (atom array)) array and rec_input = (ident * atom) and tup_input = atom and stmt' = (* lval-assigning stmts. *) STMT_spawn of (lval * domain * lval * (atom array)) | STMT_init_rec of (lval * (rec_input array) * lval option) | STMT_init_tup of (lval * (tup_input array)) | STMT_init_vec of (lval * atom array) | STMT_init_str of (lval * string) | STMT_init_port of lval | STMT_init_chan of (lval * (lval option)) | STMT_init_exterior of (lval * atom) | STMT_copy of (lval * expr) | STMT_copy_binop of (lval * binop * atom) | STMT_call of (lval * lval * (atom array)) | STMT_bind of (lval * lval * ((atom option) array)) | STMT_recv of (lval * lval) | STMT_slice of (lval * lval * slice) (* control-flow stmts. *) | STMT_while of stmt_while | STMT_do_while of stmt_while | STMT_for of stmt_for | STMT_for_each of stmt_for_each | STMT_if of stmt_if | STMT_put of (atom option) | STMT_put_each of (lval * (atom array)) | STMT_ret of (atom option) | STMT_be of (lval * (atom array)) | STMT_alt_tag of stmt_alt_tag | STMT_alt_type of stmt_alt_type | STMT_alt_port of stmt_alt_port (* structural and misc stmts. *) | STMT_fail | STMT_yield | STMT_join of lval | STMT_send of (lval * lval) | STMT_log of atom | STMT_note of atom | STMT_prove of (constrs) | STMT_check of (constrs * check_calls) | STMT_check_expr of expr | STMT_check_if of (constrs * check_calls * block) | STMT_block of block | STMT_decl of stmt_decl and stmt = stmt' identified and stmt_alt_tag = { alt_tag_lval: lval; alt_tag_arms: arm array; } and stmt_alt_type = { alt_type_lval: lval; alt_type_arms: (ident * slot * stmt) array; alt_type_else: stmt option; } and block' = stmt array and block = block' identified and stmt_decl = DECL_mod_item of (ident * mod_item) | DECL_slot of (slot_key * (slot identified)) and stmt_alt_port = { (* else lval is a timeout value. *) alt_port_arms: (lval * lval) array; alt_port_else: (lval * stmt) option; } and stmt_while = { while_lval: ((stmt array) * expr); while_body: block; } and stmt_for_each = { for_each_slot: (slot identified * ident); for_each_call: (lval * atom array); for_each_head: block; for_each_body: block; } and stmt_for = { for_slot: (slot identified * ident); for_seq: ((stmt array) * lval); for_body: block; } and stmt_if = { if_test: expr; if_then: block; if_else: block option; } and slice = { slice_start: atom option; slice_len: atom option; } and domain = DOMAIN_local | DOMAIN_thread (* * PAT_tag uses lval for the tag constructor so that we can reuse our lval * resolving machinery. The lval is restricted during parsing to have only * named components. *) and pat = PAT_lit of lit | PAT_tag of (lval * (pat array)) | PAT_slot of ((slot identified) * ident) | PAT_wild and arm' = pat * block and arm = arm' identified and atom = ATOM_literal of (lit identified) | ATOM_lval of lval and expr = EXPR_binary of (binop * atom * atom) | EXPR_unary of (unop * atom) | EXPR_atom of atom and lit = | LIT_nil | LIT_bool of bool | LIT_mach of (ty_mach * int64 * string) | LIT_int of (int64 * string) | LIT_uint of (int64 * string) | LIT_char of int and lval_component = COMP_named of name_component | COMP_atom of atom (* identifying the name_base here is sufficient to identify the full lval *) and lval = LVAL_base of name_base identified | LVAL_ext of (lval * lval_component) and binop = BINOP_or | BINOP_and | BINOP_xor | BINOP_eq | BINOP_ne | BINOP_lt | BINOP_le | BINOP_ge | BINOP_gt | BINOP_lsl | BINOP_lsr | BINOP_asr | BINOP_add | BINOP_sub | BINOP_mul | BINOP_div | BINOP_mod | BINOP_send and unop = UNOP_not | UNOP_bitnot | UNOP_neg | UNOP_cast of ty identified and header_slots = ((slot identified) * ident) array and header_tup = (slot identified) array and fn = { fn_input_slots: header_slots; fn_input_constrs: constrs; fn_output_slot: slot identified; fn_aux: ty_fn_aux; fn_body: block; } and obj = { obj_state: header_slots; obj_effect: effect; obj_constrs: constrs; obj_fns: (ident,fn identified) Hashtbl.t; obj_drop: block option; } (* * An 'a decl is a sort-of-thing that represents a parametric (generative) * declaration. Every reference to one of these involves applying 0 or more * type arguments, as part of *name resolution*. * * Slots are *not* parametric declarations. A slot has a specific type * even if it's a type that's bound by a quantifier in its environment. *) and ty_param = ident * (ty_param_idx * effect) and mod_item' = MOD_ITEM_type of ty | MOD_ITEM_tag of (header_tup * ty_tag * node_id) | MOD_ITEM_mod of (mod_view * mod_items) | MOD_ITEM_fn of fn | MOD_ITEM_obj of obj and mod_item_decl = { decl_params: (ty_param identified) array; decl_item: mod_item'; } and mod_item = mod_item_decl identified and mod_items = (ident, mod_item) Hashtbl.t and export = EXPORT_all_decls | EXPORT_ident of ident and mod_view = { view_imports: (ident, name) Hashtbl.t; view_exports: (export, unit) Hashtbl.t; } and meta = (ident * string) array and meta_pat = (ident * string option) array and crate' = { crate_items: (mod_view * mod_items); crate_meta: meta; crate_auth: (name, effect) Hashtbl.t; crate_required: (node_id, (required_lib * nabi_conv)) Hashtbl.t; crate_required_syms: (node_id, string) Hashtbl.t; crate_files: (node_id,filename) Hashtbl.t; crate_main: name option; } and crate = crate' identified ;; (* * NB: names can only be type-parametric in their *last* path-entry. * All path-entries before that must be ident or idx (non-parametric). *) let sane_name (n:name) : bool = let rec sane_prefix (n:name) : bool = match n with NAME_base (BASE_ident _) | NAME_base (BASE_temp _) -> true | NAME_ext (prefix, COMP_ident _) | NAME_ext (prefix, COMP_idx _) -> sane_prefix prefix | _ -> false in match n with NAME_base _ -> true | NAME_ext (prefix, _) -> sane_prefix prefix ;; (***********************************************************************) (* FIXME (issue #19): finish all parts with ?foo? as their output. *) let fmt_ident (ff:Format.formatter) (i:ident) : unit = fmt ff "%s" i let fmt_temp (ff:Format.formatter) (t:temp_id) : unit = fmt ff ".t%d" (int_of_temp t) let fmt_slot_key ff (s:slot_key) : unit = match s with KEY_ident i -> fmt_ident ff i | KEY_temp t -> fmt_temp ff t let rec fmt_app (ff:Format.formatter) (i:ident) (tys:ty array) : unit = fmt ff "%s" i; fmt_app_args ff tys and fmt_app_args (ff:Format.formatter) (tys:ty array) : unit = fmt ff "[@["; for i = 0 to (Array.length tys) - 1; do if i != 0 then fmt ff ",@ "; fmt_ty ff tys.(i); done; fmt ff "@]]" and fmt_name_base (ff:Format.formatter) (nb:name_base) : unit = match nb with BASE_ident i -> fmt_ident ff i | BASE_temp t -> fmt_temp ff t | BASE_app (id, tys) -> fmt_app ff id tys and fmt_name_component (ff:Format.formatter) (nc:name_component) : unit = match nc with COMP_ident i -> fmt_ident ff i | COMP_app (id, tys) -> fmt_app ff id tys | COMP_idx i -> fmt ff "_%d" i and fmt_name (ff:Format.formatter) (n:name) : unit = match n with NAME_base nb -> fmt_name_base ff nb | NAME_ext (n, nc) -> fmt_name ff n; fmt ff "."; fmt_name_component ff nc and fmt_mode (ff:Format.formatter) (m:mode) : unit = match m with | MODE_alias -> fmt ff "&" | MODE_interior -> () and fmt_slot (ff:Format.formatter) (s:slot) : unit = match s.slot_ty with None -> fmt ff "auto" | Some t -> fmt_mode ff s.slot_mode; fmt_ty ff t and fmt_tys (ff:Format.formatter) (tys:ty array) : unit = fmt_bracketed_arr_sep "(" ")" "," fmt_ty ff tys and fmt_ident_tys (ff:Format.formatter) (entries:(ident * ty) array) : unit = fmt_bracketed_arr_sep "(" ")" "," (fun ff (ident, ty) -> fmt_ty ff ty; fmt ff " "; fmt_ident ff ident) ff entries and fmt_slots (ff:Format.formatter) (slots:slot array) (idents:(ident array) option) : unit = fmt ff "(@["; for i = 0 to (Array.length slots) - 1 do if i != 0 then fmt ff ",@ "; fmt_slot ff slots.(i); begin match idents with None -> () | Some ids -> (fmt ff " "; fmt_ident ff ids.(i)) end; done; fmt ff "@])" and fmt_effect (ff:Format.formatter) (effect:effect) : unit = match effect with PURE -> () | IO -> fmt ff "io" | STATE -> fmt ff "state" | UNSAFE -> fmt ff "unsafe" and fmt_ty_fn (ff:Format.formatter) (ident_and_params:(ident * ty_param array) option) (tf:ty_fn) : unit = let (tsig, ta) = tf in fmt_effect ff ta.fn_effect; if ta.fn_effect <> PURE then fmt ff " "; fmt ff "%s" (if ta.fn_is_iter then "iter" else "fn"); begin match ident_and_params with Some (id, params) -> fmt ff " "; fmt_ident_and_params ff id params | None -> () end; fmt_slots ff tsig.sig_input_slots None; fmt_decl_constrs ff tsig.sig_input_constrs; fmt ff " -> "; fmt_slot ff tsig.sig_output_slot; and fmt_tag (ff:Format.formatter) (ttag:ty_tag) : unit = fmt ff "@[tag(@["; let first = ref true in Hashtbl.iter begin fun name ttup -> (if !first then first := false else fmt ff ",@ "); fmt_name ff name; fmt_tys ff ttup end ttag; fmt ff "@])@]" and fmt_iso (ff:Format.formatter) (tiso:ty_iso) : unit = fmt ff "@[iso [@["; for i = 0 to (Array.length tiso.iso_group) - 1 do if i != 0 then fmt ff ",@ "; if i == tiso.iso_index then fmt ff "<%d>: " i else fmt ff "%d: " i; fmt_tag ff tiso.iso_group.(i); done; fmt ff "@]]@]" and fmt_ty (ff:Format.formatter) (t:ty) : unit = match t with TY_any -> fmt ff "any" | TY_nil -> fmt ff "()" | TY_bool -> fmt ff "bool" | TY_mach m -> fmt_mach ff m | TY_int -> fmt ff "int" | TY_uint -> fmt ff "uint" | TY_char -> fmt ff "char" | TY_str -> fmt ff "str" | TY_tup tys -> (fmt ff "tup"; fmt_tys ff tys) | TY_vec t -> (fmt ff "vec["; fmt_ty ff t; fmt ff "]") | TY_chan t -> (fmt ff "chan["; fmt_ty ff t; fmt ff "]") | TY_port t -> (fmt ff "port["; fmt_ty ff t; fmt ff "]") | TY_rec entries -> fmt ff "@[rec"; fmt_ident_tys ff entries; fmt ff "@]" | TY_param (i, e) -> (fmt_effect ff e; if e <> PURE then fmt ff " "; fmt ff "
" i)
| TY_native oid -> fmt ff " " i
done;
fmt ff "]"
end;
and fmt_header_slots (ff:Format.formatter) (hslots:header_slots) : unit =
fmt_slots ff
(Array.map (fun (s,_) -> s.node) hslots)
(Some (Array.map (fun (_, i) -> i) hslots))
and fmt_ident_and_params
(ff:Format.formatter)
(id:ident)
(params:ty_param array)
: unit =
fmt_ident ff id;
fmt_decl_params ff params
and fmt_fn
(ff:Format.formatter)
(id:ident)
(params:ty_param array)
(f:fn)
: unit =
fmt_obox ff;
fmt_effect ff f.fn_aux.fn_effect;
if f.fn_aux.fn_effect <> PURE then fmt ff " ";
fmt ff "%s "(if f.fn_aux.fn_is_iter then "iter" else "fn");
fmt_ident_and_params ff id params;
fmt_header_slots ff f.fn_input_slots;
fmt_decl_constrs ff f.fn_input_constrs;
fmt ff " -> ";
fmt_slot ff f.fn_output_slot.node;
fmt ff " ";
fmt_obr ff;
fmt_stmts ff f.fn_body.node;
fmt_cbb ff
and fmt_obj
(ff:Format.formatter)
(id:ident)
(params:ty_param array)
(obj:obj)
: unit =
fmt_obox ff;
fmt_effect ff obj.obj_effect;
if obj.obj_effect <> PURE then fmt ff " ";
fmt ff "obj ";
fmt_ident_and_params ff id params;
fmt_header_slots ff obj.obj_state;
fmt_decl_constrs ff obj.obj_constrs;
fmt ff " ";
fmt_obr ff;
Hashtbl.iter
begin
fun id fn ->
fmt ff "@\n";
fmt_fn ff id [||] fn.node
end
obj.obj_fns;
begin
match obj.obj_drop with
None -> ()
| Some d ->
begin
fmt ff "@\n";
fmt_obox ff;
fmt ff "drop ";
fmt_obr ff;
fmt_stmts ff d.node;
fmt_cbb ff;
end
end;
fmt_cbb ff
and fmt_mod_item (ff:Format.formatter) (id:ident) (item:mod_item) : unit =
fmt ff "@\n";
let params = item.node.decl_params in
let params = Array.map (fun i -> i.node) params in
begin
match item.node.decl_item with
MOD_ITEM_type ty ->
fmt ff "type ";
fmt_ident_and_params ff id params;
fmt ff " = ";
fmt_ty ff ty;
fmt ff ";";
| MOD_ITEM_tag (hdr, ttag, _) ->
fmt ff "fn ";
fmt_ident_and_params ff id params;
fmt_header_slots ff
(Array.mapi (fun i s -> (s,(Printf.sprintf "_%d" i))) hdr);
fmt ff " -> ";
fmt_ty ff (TY_tag ttag);
fmt ff ";";
| MOD_ITEM_mod (view,items) ->
fmt_obox ff;
fmt ff "mod ";
fmt_ident_and_params ff id params;
fmt ff " ";
fmt_obr ff;
fmt_mod_view ff view;
fmt_mod_items ff items;
fmt_cbb ff
| MOD_ITEM_fn f ->
fmt_fn ff id params f
| MOD_ITEM_obj obj ->
fmt_obj ff id params obj
end
and fmt_import (ff:Format.formatter) (ident:ident) (name:name) : unit =
fmt ff "@\n";
fmt ff "import ";
fmt ff "%s = " ident;
fmt_name ff name;
and fmt_export (ff:Format.formatter) (export:export) _ : unit =
fmt ff "@\n";
match export with
EXPORT_all_decls -> fmt ff "export *;"
| EXPORT_ident i -> fmt ff "export %s;" i
and fmt_mod_view (ff:Format.formatter) (mv:mod_view) : unit =
Hashtbl.iter (fmt_import ff) mv.view_imports;
Hashtbl.iter (fmt_export ff) mv.view_exports
and fmt_mod_items (ff:Format.formatter) (mi:mod_items) : unit =
Hashtbl.iter (fmt_mod_item ff) mi
and fmt_crate (ff:Format.formatter) (c:crate) : unit =
let (view,items) = c.node.crate_items in
fmt_mod_view ff view;
fmt_mod_items ff items
let sprintf_expr = sprintf_fmt fmt_expr;;
let sprintf_name = sprintf_fmt fmt_name;;
let sprintf_lval = sprintf_fmt fmt_lval;;
let sprintf_lval_component = sprintf_fmt fmt_lval_component;;
let sprintf_atom = sprintf_fmt fmt_atom;;
let sprintf_slot = sprintf_fmt fmt_slot;;
let sprintf_slot_key = sprintf_fmt fmt_slot_key;;
let sprintf_ty = sprintf_fmt fmt_ty;;
let sprintf_effect = sprintf_fmt fmt_effect;;
let sprintf_tag = sprintf_fmt fmt_tag;;
let sprintf_carg = sprintf_fmt fmt_carg;;
let sprintf_constr = sprintf_fmt fmt_constr;;
let sprintf_stmt = sprintf_fmt fmt_stmt;;
let sprintf_mod_items = sprintf_fmt fmt_mod_items;;
let sprintf_decl_params = sprintf_fmt fmt_decl_params;;
let sprintf_app_args = sprintf_fmt fmt_app_args;;
(*
* Local Variables:
* fill-column: 78;
* indent-tabs-mode: nil
* buffer-file-coding-system: utf-8-unix
* compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
* End:
*)