123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153(** High-level compilation functions. *)open!LplibopenTimedopenCommonopenErroropenParsingopenCoreopenSignopenLibrary(** [gen_obj] indicates whether we should generate object files when compiling
source files. The default behaviour is not te generate them. *)letgen_obj=Stdlib.reffalse(** [parse_file fname] selects and runs the correct parser on file [fname], by
looking at its extension. *)letparse_file:string->Syntax.ast=funfname->matchFilename.check_suffixfnamesrc_extensionwith|true->Parser.Lp.parse_filefname|false->Parser.Dk.parse_filefname(** [compile_with ~handle ~force mp] compiles the file corresponding to module
path [mp] using function [~handle] to process commands. Module [mp] is
processed when it is necessary, i.e. the corresponding object file does not
exist, or it must be updated, or [~force] is [true]. In that case, the
produced signature is stored in the corresponding object file if the option
[--gen_obj] or [-c] is set. *)letreccompile_with:handle:(Command.compiler->Sig_state.t->Syntax.p_command->Sig_state.t)->force:bool->Command.compiler=fun~handle~forcemp->letbase=file_of_pathmpinletsrc()=(* Searching for source is delayed because we may not need it
in case of "ghost" signatures (such as for unification rules). *)letsrc=base^src_extensioninletlegacy=base^legacy_src_extensioninmatch(Sys.file_existssrc,Sys.file_existslegacy)with|(false,false)->fatal_no_pos"File \"%s.lp\" (or .dk) not found."base|(true,true)->wrnNone"Both \"%s\" and \"%s\" exist. We take \"%s\"."srclegacysrc;src|(true,false)->src|(false,true)->legacyinletobj=base^obj_extensioninifList.memmp!loadingthenbeginfatal_msg"Circular dependencies detected in \"%s\".@."(src());fatal_msg"Dependency stack for module %a:@."Print.pp_pathmp;List.iter(fatal_msg"- %a@."Print.pp_path)!loading;fatal_no_pos"Build aborted."end;matchPath.Map.find_optmp!loadedwith|Somesign->sign|None->ifforce||Extra.more_recent(src())objthenbeginletforced=ifforcethen" (forced)"else""inletsrc=src()inConsole.out1"Loading \"%s\"%s ..."srcforced;loading:=mp::!loading;letsign=Sig_state.create_signmpinletsig_st=Stdlib.ref(Sig_state.of_signsign)in(* [sign] is added to [loaded] before processing the commands so that it
is possible to qualify the symbols of the current modules. *)loaded:=Path.Map.addmpsign!loaded;Stdlib.(Tactic.admitted:=-1);letconsumecmd=Stdlib.(sig_st:=handle(compile_with~handle~force:false)!sig_stcmd)inDebug.stream_iterconsume(parse_filesrc);Sign.strip_privatesign;ifStdlib.(!gen_obj)thenSign.writesignobj;loading:=List.tl!loading;signendelsebeginConsole.out1"Loading \"%s\" ..."(src());letsign=Sign.readobjinletcompilemp_=ignore(compile_with~handle~force:falsemp)inPath.Map.itercompile!(sign.sign_deps);loaded:=Path.Map.addmpsign!loaded;Sign.linksign;(* Since Unif_rule.sign is always assumed to be already loaded, we need
to explicitly update the decision tree of Unif_rule.equiv since it is
not done in linking which normally follows loading. *)letsm=Path.Map.findUnif_rule.path!(sign.sign_deps)inifExtra.StrMap.memUnif_rule.equiv.sym_namesmthenTree.update_dtreeUnif_rule.equiv;signend(** [compile force mp] compiles module path [mp] using [compile_with], forcing
compilation of up-to-date files if [force] is true. *)letcompileforce=compile_with~handle:Command.handle~force(** [recompile] indicates whether we should recompile files who have an object
file that is already up to date. Note that this flag only applies to files
that are given on the command line explicitly, not their dependencies. *)letrecompile=Stdlib.reffalse(** [compile_file fname] is the main compiling function. It is called from the
main program exclusively. *)letcompile_file:string->Sign.t=funfname->Package.apply_configfname;(* Compute the module path (checking the extension). *)letmp=path_of_fileLpLexer.escapefnamein(* Run compilation. *)compileStdlib.(!recompile)mpopenConsole(** Pure wrappers around compilation functions. Functions provided perform the
same computations as the ones defined earlier, but restores the state when
they have finished. An optional library mapping or state can be passed as
argument to change the settings. *)modulePure:sigvalcompile:?lm:Path.t*string->?st:State.t->bool->Path.t->Sign.tvalcompile_file:?lm:Path.t*string->?st:State.t->string->Sign.tend=struct(* [pure_apply_cfg ?lm ?st f] is function [f] but pure (without side
effects). The side effects taken into account occur in {!val:State.t} and
{!val:Library.lib_mappings}. Arguments [?lm] allows to set the library
mappings and [?st] sets the state. *)letpure_apply_cfg:?lm:Path.t*string->?st:State.t->('a->'b)->'a->'b=fun?lm?stfx->letlibmap=!lib_mappingsinState.push();Option.iterLibrary.add_mappinglm;Option.iterState.applyst;letrestore()=State.pop();lib_mappings:=libmapintryletres=fxinrestore();reswithe->restore();raiseeletcompile?lm?stforcemp=letf(force,mp)=compileforcempinpure_apply_cfg?lm?stf(force,mp)letcompile_file?lm?st=pure_apply_cfg?lm?stcompile_fileend