aboutsummaryrefslogtreecommitdiff
path: root/src/boot/fe/cexp.ml
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-06-23 21:03:09 -0700
committerGraydon Hoare <[email protected]>2010-06-23 21:03:09 -0700
commitd6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch)
treeb425187e232966063ffc2f0d14c04a55d8f004ef /src/boot/fe/cexp.ml
parentInitial git commit. (diff)
downloadrust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.xz
rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip
Populate tree.
Diffstat (limited to 'src/boot/fe/cexp.ml')
-rw-r--r--src/boot/fe/cexp.ml762
1 files changed, 762 insertions, 0 deletions
diff --git a/src/boot/fe/cexp.ml b/src/boot/fe/cexp.ml
new file mode 100644
index 00000000..6dffdb96
--- /dev/null
+++ b/src/boot/fe/cexp.ml
@@ -0,0 +1,762 @@
+
+open Common;;
+open Token;;
+open Parser;;
+
+(* NB: cexps (crate-expressions / constant-expressions) are only used
+ * transiently during compilation: they are the outermost expression-language
+ * describing crate configuration and constants. They are completely evaluated
+ * at compile-time, in a little micro-interpreter defined here, with the
+ * results of evaluation being the sequence of directives controlling the rest
+ * of the compiler.
+ *
+ * Cexps, like pexps, do not escape the language front-end.
+ *
+ * You can think of the AST as a statement-language called "item" sandwiched
+ * between two expression-languages, "cexp" on the outside and "pexp" on the
+ * inside. The front-end evaluates cexp on the outside in order to get one big
+ * directive-list, evaluating those parts of pexp that are directly used by
+ * cexp in passing, and desugaring those remaining parts of pexp that are
+ * embedded within the items of the directives.
+ *
+ * The rest of the compiler only deals with the directives, which are mostly
+ * just a set of containers for items. Items are what most of AST describes
+ * ("most" because the type-grammar spans both items and pexps).
+ *
+ *)
+
+type meta = (Ast.ident * Pexp.pexp) array;;
+
+type meta_pat = (Ast.ident * (Pexp.pexp option)) array;;
+
+type auth = (Ast.name * Ast.effect);;
+
+type cexp =
+ CEXP_alt of cexp_alt identified
+ | CEXP_let of cexp_let identified
+ | CEXP_src_mod of cexp_src identified
+ | CEXP_dir_mod of cexp_dir identified
+ | CEXP_use_mod of cexp_use identified
+ | CEXP_nat_mod of cexp_nat identified
+ | CEXP_meta of meta identified
+ | CEXP_auth of auth identified
+
+and cexp_alt =
+ { alt_val: Pexp.pexp;
+ alt_arms: (Pexp.pexp * cexp array) array;
+ alt_else: cexp array }
+
+and cexp_let =
+ { let_ident: Ast.ident;
+ let_value: Pexp.pexp;
+ let_body: cexp array; }
+
+and cexp_src =
+ { src_ident: Ast.ident;
+ src_path: Pexp.pexp option }
+
+and cexp_dir =
+ { dir_ident: Ast.ident;
+ dir_path: Pexp.pexp option;
+ dir_body: cexp array }
+
+and cexp_use =
+ { use_ident: Ast.ident;
+ use_meta: meta_pat; }
+
+and cexp_nat =
+ { nat_abi: string;
+ nat_ident: Ast.ident;
+ nat_path: Pexp.pexp option;
+ (*
+ * FIXME: possibly support embedding optional strings as
+ * symbol-names, to handle mangling schemes that aren't
+ * Token.IDENT values
+ *)
+ nat_items: Ast.mod_items;
+ }
+;;
+
+
+(* Cexp grammar. *)
+
+let parse_meta_input (ps:pstate) : (Ast.ident * Pexp.pexp option) =
+ let lab = (ctxt "meta input: label" Pexp.parse_ident ps) in
+ match peek ps with
+ EQ ->
+ bump ps;
+ let v =
+ match peek ps with
+ UNDERSCORE -> bump ps; None
+ | _ -> Some (Pexp.parse_pexp ps)
+ in
+ (lab, v)
+ | _ -> raise (unexpected ps)
+;;
+
+let parse_meta_pat (ps:pstate) : meta_pat =
+ bracketed_zero_or_more LPAREN RPAREN
+ (Some COMMA) parse_meta_input ps
+;;
+
+let parse_meta (ps:pstate) : meta =
+ Array.map
+ begin
+ fun (id,v) ->
+ match v with
+ None ->
+ raise (err ("wildcard found in meta pattern "
+ ^ "where value expected") ps)
+ | Some v -> (id,v)
+ end
+ (parse_meta_pat ps)
+;;
+
+let parse_optional_meta_pat
+ (ps:pstate)
+ (ident:Ast.ident)
+ : meta_pat =
+ match peek ps with
+ LPAREN -> parse_meta_pat ps
+ | _ ->
+ let apos = lexpos ps in
+ [| ("name", Some (span ps apos apos (Pexp.PEXP_str ident))) |]
+;;
+
+let rec parse_cexps (ps:pstate) (term:Token.token) : cexp array =
+ let cexps = Queue.create () in
+ while ((peek ps) <> term)
+ do
+ Queue.push (parse_cexp ps) cexps
+ done;
+ expect ps term;
+ queue_to_arr cexps
+
+and parse_cexp (ps:pstate) : cexp =
+
+ let apos = lexpos ps in
+ match peek ps with
+ MOD ->
+ begin
+ bump ps;
+ let name = ctxt "mod: name" Pexp.parse_ident ps in
+ let path = ctxt "mod: path" parse_eq_pexp_opt ps
+ in
+ match peek ps with
+ SEMI ->
+ bump ps;
+ let bpos = lexpos ps in
+ CEXP_src_mod
+ (span ps apos bpos { src_ident = name;
+ src_path = path })
+ | LBRACE ->
+ let body =
+ bracketed_zero_or_more LBRACE RBRACE
+ None parse_cexp ps
+ in
+ let bpos = lexpos ps in
+ CEXP_dir_mod
+ (span ps apos bpos { dir_ident = name;
+ dir_path = path;
+ dir_body = body })
+ | _ -> raise (unexpected ps)
+ end
+
+ | NATIVE ->
+ begin
+ bump ps;
+ let abi =
+ match peek ps with
+ MOD -> "cdecl"
+ | LIT_STR s -> bump ps; s
+ | _ -> raise (unexpected ps)
+ in
+ let _ = expect ps MOD in
+ let name = ctxt "native mod: name" Pexp.parse_ident ps in
+ let path = ctxt "native mod: path" parse_eq_pexp_opt ps in
+ let items = Hashtbl.create 0 in
+ let get_item ps =
+ let (ident, item) = Item.parse_mod_item_from_signature ps in
+ htab_put items ident item;
+ in
+ ignore (bracketed_zero_or_more
+ LBRACE RBRACE None get_item ps);
+ let bpos = lexpos ps in
+ CEXP_nat_mod
+ (span ps apos bpos { nat_abi = abi;
+ nat_ident = name;
+ nat_path = path;
+ nat_items = items })
+ end
+
+ | USE ->
+ begin
+ bump ps;
+ let ident = ctxt "use mod: name" Pexp.parse_ident ps in
+ let meta =
+ ctxt "use mod: meta" parse_optional_meta_pat ps ident
+ in
+ let bpos = lexpos ps in
+ expect ps SEMI;
+ CEXP_use_mod
+ (span ps apos bpos { use_ident = ident;
+ use_meta = meta })
+ end
+
+ | LET ->
+ begin
+ bump ps;
+ expect ps LPAREN;
+ let id = Pexp.parse_ident ps in
+ expect ps EQ;
+ let v = Pexp.parse_pexp ps in
+ expect ps RPAREN;
+ expect ps LBRACE;
+ let body = parse_cexps ps RBRACE in
+ let bpos = lexpos ps in
+ CEXP_let
+ (span ps apos bpos
+ { let_ident = id;
+ let_value = v;
+ let_body = body })
+ end
+
+ | ALT ->
+ begin
+ bump ps;
+ expect ps LPAREN;
+ let v = Pexp.parse_pexp ps in
+ expect ps RPAREN;
+ expect ps LBRACE;
+ let rec consume_arms arms =
+ match peek ps with
+ CASE ->
+ begin
+ bump ps;
+ expect ps LPAREN;
+ let cond = Pexp.parse_pexp ps in
+ expect ps RPAREN;
+ expect ps LBRACE;
+ let consequent = parse_cexps ps RBRACE in
+ let arm = (cond, consequent) in
+ consume_arms (arm::arms)
+ end
+ | ELSE ->
+ begin
+ bump ps;
+ expect ps LBRACE;
+ let consequent = parse_cexps ps RBRACE in
+ expect ps RBRACE;
+ let bpos = lexpos ps in
+ span ps apos bpos
+ { alt_val = v;
+ alt_arms = Array.of_list (List.rev arms);
+ alt_else = consequent }
+ end
+
+ | _ -> raise (unexpected ps)
+ in
+ CEXP_alt (consume_arms [])
+ end
+
+ | META ->
+ bump ps;
+ let meta = parse_meta ps in
+ expect ps SEMI;
+ let bpos = lexpos ps in
+ CEXP_meta (span ps apos bpos meta)
+
+ | AUTH ->
+ bump ps;
+ let name = Pexp.parse_name ps in
+ expect ps EQ;
+ let effect = Pexp.parse_effect ps in
+ expect ps SEMI;
+ let bpos = lexpos ps in
+ CEXP_auth (span ps apos bpos (name, effect))
+
+ | _ -> raise (unexpected ps)
+
+
+and parse_eq_pexp_opt (ps:pstate) : Pexp.pexp option =
+ match peek ps with
+ EQ ->
+ begin
+ bump ps;
+ Some (Pexp.parse_pexp ps)
+ end
+ | _ -> None
+;;
+
+
+(*
+ * Dynamic-typed micro-interpreter for the cexp language.
+ *
+ * The product of evaluating a pexp is a pval.
+ *
+ * The product of evlauating a cexp is a cdir array.
+ *)
+
+type pval =
+ PVAL_str of string
+ | PVAL_num of int64
+ | PVAL_bool of bool
+;;
+
+type cdir =
+ CDIR_meta of ((Ast.ident * string) array)
+ | CDIR_syntax of Ast.name
+ | CDIR_check of (Ast.name * pval array)
+ | CDIR_mod of (Ast.ident * Ast.mod_item)
+ | CDIR_auth of auth
+
+type env = { env_bindings: (Ast.ident * pval) list;
+ env_prefix: filename list;
+ env_items: (filename, Ast.mod_items) Hashtbl.t;
+ env_files: (node_id,filename) Hashtbl.t;
+ env_required: (node_id, (required_lib * nabi_conv)) Hashtbl.t;
+ env_required_syms: (node_id, string) Hashtbl.t;
+ env_ps: pstate; }
+
+let unexpected_val (expected:string) (v:pval) =
+ let got =
+ match v with
+ PVAL_str s -> "str \"" ^ (String.escaped s) ^ "\""
+ | PVAL_num i -> "num " ^ (Int64.to_string i)
+ | PVAL_bool b -> if b then "bool true" else "bool false"
+ in
+ (* FIXME: proper error reporting, please. *)
+ bug () "expected %s, got %s" expected got
+;;
+
+let rewrap_items id items =
+ let item = decl [||] (Ast.MOD_ITEM_mod items) in
+ { id = id; node = item }
+;;
+
+
+let rec eval_cexps (env:env) (exps:cexp array) : cdir array =
+ Parser.arj (Array.map (eval_cexp env) exps)
+
+and eval_cexp (env:env) (exp:cexp) : cdir array =
+ match exp with
+ CEXP_alt {node=ca} ->
+ let v = eval_pexp env ca.alt_val in
+ let rec try_arm i =
+ if i >= Array.length ca.alt_arms
+ then ca.alt_else
+ else
+ let (arm_head, arm_body) = ca.alt_arms.(i) in
+ let v' = eval_pexp env arm_head in
+ if v' = v
+ then arm_body
+ else try_arm (i+1)
+ in
+ eval_cexps env (try_arm 0)
+
+ | CEXP_let {node=cl} ->
+ let ident = cl.let_ident in
+ let v = eval_pexp env cl.let_value in
+ let env = { env with
+ env_bindings = ((ident,v)::env.env_bindings ) }
+ in
+ eval_cexps env cl.let_body
+
+ | CEXP_src_mod {node=s; id=id} ->
+ let name = s.src_ident in
+ let path =
+ match s.src_path with
+ None -> name ^ ".rs"
+ | Some p -> eval_pexp_to_str env p
+ in
+ let full_path =
+ List.fold_left Filename.concat ""
+ (List.rev (path :: env.env_prefix))
+ in
+ let ps = env.env_ps in
+ let p =
+ make_parser
+ ps.pstate_temp_id
+ ps.pstate_node_id
+ ps.pstate_opaque_id
+ ps.pstate_sess
+ ps.pstate_get_mod
+ ps.pstate_infer_lib_name
+ env.env_required
+ env.env_required_syms
+ full_path
+ in
+ let items = Item.parse_mod_items p EOF in
+ htab_put env.env_files id full_path;
+ [| CDIR_mod (name, rewrap_items id items) |]
+
+ | CEXP_dir_mod {node=d; id=id} ->
+ let items = Hashtbl.create 0 in
+ let name = d.dir_ident in
+ let path =
+ match d.dir_path with
+ None -> name
+ | Some p -> eval_pexp_to_str env p
+ in
+ let env = { env with
+ env_prefix = path :: env.env_prefix } in
+ let sub_directives = eval_cexps env d.dir_body in
+ let add d =
+ match d with
+ CDIR_mod (name, item) ->
+ htab_put items name item
+ | _ -> raise (err "non-'mod' directive found in 'dir' directive"
+ env.env_ps)
+ in
+ Array.iter add sub_directives;
+ [| CDIR_mod (name, rewrap_items id (Item.empty_view, items)) |]
+
+ | CEXP_use_mod {node=u; id=id} ->
+ let ps = env.env_ps in
+ let name = u.use_ident in
+ let (path, items) =
+ let meta_pat =
+ Array.map
+ begin
+ fun (k,vo) ->
+ match vo with
+ None -> (k, None)
+ | Some p -> (k, Some (eval_pexp_to_str env p))
+ end
+ u.use_meta
+ in
+ ps.pstate_get_mod meta_pat id ps.pstate_node_id ps.pstate_opaque_id
+ in
+ iflog ps
+ begin
+ fun _ ->
+ log ps "extracted mod signature from %s (binding to %s)"
+ path name;
+ log ps "%a" Ast.sprintf_mod_items items;
+ end;
+ let rlib = REQUIRED_LIB_rust { required_libname = path;
+ required_prefix = 1 }
+ in
+ let item = decl [||] (Ast.MOD_ITEM_mod (Item.empty_view, items)) in
+ let item = { id = id; node = item } in
+ let span = Hashtbl.find ps.pstate_sess.Session.sess_spans id in
+ Item.note_required_mod env.env_ps span CONV_rust rlib item;
+ [| CDIR_mod (name, item) |]
+
+ | CEXP_nat_mod {node=cn;id=id} ->
+ let conv =
+ let v = cn.nat_abi in
+ match string_to_conv v with
+ None -> unexpected_val "calling convention" (PVAL_str v)
+ | Some c -> c
+ in
+ let name = cn.nat_ident in
+ let filename =
+ match cn.nat_path with
+ None -> env.env_ps.pstate_infer_lib_name name
+ | Some p -> eval_pexp_to_str env p
+ in
+ let item =
+ decl [||] (Ast.MOD_ITEM_mod (Item.empty_view, cn.nat_items))
+ in
+ let item = { id = id; node = item } in
+ let rlib = REQUIRED_LIB_c { required_libname = filename;
+ required_prefix = 1 }
+ in
+ let ps = env.env_ps in
+ let span = Hashtbl.find ps.pstate_sess.Session.sess_spans id in
+ Item.note_required_mod env.env_ps span conv rlib item;
+ [| CDIR_mod (name, item) |]
+
+ | CEXP_meta m ->
+ [| CDIR_meta
+ begin
+ Array.map
+ begin
+ fun (id, p) -> (id, eval_pexp_to_str env p)
+ end
+ m.node
+ end |]
+
+ | CEXP_auth a -> [| CDIR_auth a.node |]
+
+
+and eval_pexp (env:env) (exp:Pexp.pexp) : pval =
+ match exp.node with
+ | Pexp.PEXP_binop (bop, a, b) ->
+ begin
+ let av = eval_pexp env a in
+ let bv = eval_pexp env b in
+ match (bop, av, bv) with
+ (Ast.BINOP_add, PVAL_str az, PVAL_str bz) ->
+ PVAL_str (az ^ bz)
+ | _ ->
+ let av = (need_num av) in
+ let bv = (need_num bv) in
+ PVAL_num
+ begin
+ match bop with
+ Ast.BINOP_add -> Int64.add av bv
+ | Ast.BINOP_sub -> Int64.sub av bv
+ | Ast.BINOP_mul -> Int64.mul av bv
+ | Ast.BINOP_div -> Int64.div av bv
+ | _ ->
+ bug ()
+ "unhandled arithmetic op in Cexp.eval_pexp"
+ end
+ end
+
+ | Pexp.PEXP_unop (uop, a) ->
+ begin
+ match uop with
+ Ast.UNOP_not ->
+ PVAL_bool (not (eval_pexp_to_bool env a))
+ | Ast.UNOP_neg ->
+ PVAL_num (Int64.neg (eval_pexp_to_num env a))
+ | _ -> bug () "Unexpected unop in Cexp.eval_pexp"
+ end
+
+ | Pexp.PEXP_lval (Pexp.PLVAL_ident ident) ->
+ begin
+ match ltab_search env.env_bindings ident with
+ None -> raise (err (Printf.sprintf "no binding for '%s' found"
+ ident) env.env_ps)
+ | Some v -> v
+ end
+
+ | Pexp.PEXP_lit (Ast.LIT_bool b) ->
+ PVAL_bool b
+
+ | Pexp.PEXP_lit (Ast.LIT_int (i, _)) ->
+ PVAL_num i
+
+ | Pexp.PEXP_str s ->
+ PVAL_str s
+
+ | _ -> bug () "unexpected Pexp in Cexp.eval_pexp"
+
+
+and eval_pexp_to_str (env:env) (exp:Pexp.pexp) : string =
+ match eval_pexp env exp with
+ PVAL_str s -> s
+ | v -> unexpected_val "str" v
+
+and need_num (cv:pval) : int64 =
+ match cv with
+ PVAL_num n -> n
+ | v -> unexpected_val "num" v
+
+and eval_pexp_to_num (env:env) (exp:Pexp.pexp) : int64 =
+ need_num (eval_pexp env exp)
+
+and eval_pexp_to_bool (env:env) (exp:Pexp.pexp) : bool =
+ match eval_pexp env exp with
+ PVAL_bool b -> b
+ | v -> unexpected_val "bool" v
+
+;;
+
+
+let find_main_fn
+ (ps:pstate)
+ (crate_items:Ast.mod_items)
+ : Ast.name =
+ let fns = ref [] in
+ let extend prefix_name ident =
+ match prefix_name with
+ None -> Ast.NAME_base (Ast.BASE_ident ident)
+ | Some n -> Ast.NAME_ext (n, Ast.COMP_ident ident)
+ in
+ let rec dig prefix_name items =
+ Hashtbl.iter (extract_fn prefix_name) items
+ and extract_fn prefix_name ident item =
+ if not (Array.length item.node.Ast.decl_params = 0) ||
+ Hashtbl.mem ps.pstate_required item.id
+ then ()
+ else
+ match item.node.Ast.decl_item with
+ Ast.MOD_ITEM_mod (_, items) ->
+ dig (Some (extend prefix_name ident)) items
+
+ | Ast.MOD_ITEM_fn _ ->
+ if ident = "main"
+ then fns := (extend prefix_name ident) :: (!fns)
+ else ()
+
+ | _ -> ()
+ in
+ dig None crate_items;
+ match !fns with
+ [] -> raise (err "no 'main' function found" ps)
+ | [x] -> x
+ | _ -> raise (err "multiple 'main' functions found" ps)
+;;
+
+
+let with_err_handling sess thunk =
+ try
+ thunk ()
+ with
+ Parse_err (ps, str) ->
+ Session.fail sess "Parse error: %s\n%!" str;
+ List.iter
+ (fun (cx,pos) ->
+ Session.fail sess "%s:E (parse context): %s\n%!"
+ (Session.string_of_pos pos) cx)
+ ps.pstate_ctxt;
+ let apos = lexpos ps in
+ span ps apos apos
+ { Ast.crate_items = (Item.empty_view, Hashtbl.create 0);
+ Ast.crate_meta = [||];
+ Ast.crate_auth = Hashtbl.create 0;
+ Ast.crate_required = Hashtbl.create 0;
+ Ast.crate_required_syms = Hashtbl.create 0;
+ Ast.crate_main = None;
+ Ast.crate_files = Hashtbl.create 0 }
+;;
+
+
+let parse_crate_file
+ (sess:Session.sess)
+ (get_mod:get_mod_fn)
+ (infer_lib_name:(Ast.ident -> filename))
+ : Ast.crate =
+ let fname = Session.filename_of sess.Session.sess_in in
+ let tref = ref (Temp 0) in
+ let nref = ref (Node 0) in
+ let oref = ref (Opaque 0) in
+ let required = Hashtbl.create 4 in
+ let required_syms = Hashtbl.create 4 in
+ let ps =
+ make_parser tref nref oref sess get_mod
+ infer_lib_name required required_syms fname
+ in
+
+ let files = Hashtbl.create 0 in
+ let items = Hashtbl.create 4 in
+ let target_bindings =
+ let (os, arch, libc) =
+ match sess.Session.sess_targ with
+ Linux_x86_elf -> ("linux", "x86", "libc.so.6")
+ | Win32_x86_pe -> ("win32", "x86", "msvcrt.dll")
+ | MacOS_x86_macho -> ("macos", "x86", "libc.dylib")
+ in
+ [
+ ("target_os", PVAL_str os);
+ ("target_arch", PVAL_str arch);
+ ("target_libc", PVAL_str libc)
+ ]
+ in
+ let build_bindings =
+ [
+ ("build_compiler", PVAL_str Sys.executable_name);
+ ("build_input", PVAL_str fname);
+ ]
+ in
+ let initial_bindings =
+ target_bindings
+ @ build_bindings
+ in
+ let env = { env_bindings = initial_bindings;
+ env_prefix = [Filename.dirname fname];
+ env_items = Hashtbl.create 0;
+ env_files = files;
+ env_required = required;
+ env_required_syms = required_syms;
+ env_ps = ps; }
+ in
+ let auth = Hashtbl.create 0 in
+ with_err_handling sess
+ begin
+ fun _ ->
+ let apos = lexpos ps in
+ let cexps = parse_cexps ps EOF in
+ let cdirs = eval_cexps env cexps in
+ let meta = Queue.create () in
+ let _ =
+ Array.iter
+ begin
+ fun d ->
+ match d with
+ CDIR_mod (name, item) -> htab_put items name item
+ | CDIR_meta metas ->
+ Array.iter (fun m -> Queue.add m meta) metas
+ | CDIR_auth (n,e) ->
+ if Hashtbl.mem auth n
+ then raise (err "duplicate 'auth' clause" ps)
+ else Hashtbl.add auth n e
+ | _ ->
+ raise
+ (err "unhandled directive at top level" ps)
+ end
+ cdirs
+ in
+ let bpos = lexpos ps in
+ let main =
+ if ps.pstate_sess.Session.sess_library_mode
+ then None
+ else Some (find_main_fn ps items) in
+ let crate = { Ast.crate_items = (Item.empty_view, items);
+ Ast.crate_meta = queue_to_arr meta;
+ Ast.crate_auth = auth;
+ Ast.crate_required = required;
+ Ast.crate_required_syms = required_syms;
+ Ast.crate_main = main;
+ Ast.crate_files = files }
+ in
+ let cratei = span ps apos bpos crate in
+ htab_put files cratei.id fname;
+ cratei
+ end
+;;
+
+let parse_src_file
+ (sess:Session.sess)
+ (get_mod:get_mod_fn)
+ (infer_lib_name:(Ast.ident -> filename))
+ : Ast.crate =
+ let fname = Session.filename_of sess.Session.sess_in in
+ let tref = ref (Temp 0) in
+ let nref = ref (Node 0) in
+ let oref = ref (Opaque 0) in
+ let required = Hashtbl.create 0 in
+ let required_syms = Hashtbl.create 0 in
+ let ps =
+ make_parser tref nref oref sess get_mod
+ infer_lib_name required required_syms fname
+ in
+ with_err_handling sess
+ begin
+ fun _ ->
+ let apos = lexpos ps in
+ let items = Item.parse_mod_items ps EOF in
+ let bpos = lexpos ps in
+ let files = Hashtbl.create 0 in
+ let main =
+ if ps.pstate_sess.Session.sess_library_mode
+ then None
+ else Some (find_main_fn ps (snd items))
+ in
+ let crate = { Ast.crate_items = items;
+ Ast.crate_required = required;
+ Ast.crate_required_syms = required_syms;
+ Ast.crate_auth = Hashtbl.create 0;
+ Ast.crate_meta = [||];
+ Ast.crate_main = main;
+ Ast.crate_files = files }
+ in
+ let cratei = span ps apos bpos crate in
+ htab_put files cratei.id fname;
+ cratei
+ end
+;;
+
+
+(*
+ * 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:
+ *)