flan/lib/front.ml

41 lines
1.8 KiB
OCaml

(** The front half of a compile: read a file, load it with its imports, check
it, and decide the link. What [flan build], [flan run], [flan emit] and
[flan check] do before a backend is reached, and what the test binaries do
before theirs, so that the two cannot drift apart.
[all] chooses how a refusal is reported. With it, the parser and the
checker keep going and raise [Loc.Errors] with every declaration they
refused, which is what the command-line drivers want: write everything,
compile at the end, work through the list. Without it they stop at the
first and raise [Loc.Error], which is what a test asserting on one message
wants. For a program with no errors the two are the same. *)
let load ?(all = false) path : Load.t =
Load.program ~file:path
~parse:(if all then Parse.program_all else Parse.program)
(Source.read_file path)
let check ?(all = false) (l : Load.t) : Tast.program =
(if all then Check.program_all else Check.program) l.Load.decls
let checked ?all path =
let l = load ?all path in
(l, check ?all l)
type linked = {
load : Load.t; (* the declarations, as loaded *)
program : Tast.program; (* checked, and pruned to what is reached *)
csrcs : string list; (* the packages' C that the link needs *)
lflags : string list; (* ...and their linker arguments *)
}
(* [before_link] sees the checked program before [Reach.link] prunes it. The
questions asked there — [Check.no_gc], the memory warnings — are about what
was written, and a function nothing calls is still something somebody
wrote. *)
let linked ?(dev = false) ?all ?(before_link = fun _ -> ()) path =
let l, p = checked ?all path in
before_link p;
let program, csrcs, lflags = Reach.link ~dev l p in
{ load = l; program; csrcs; lflags }