## thawedlib-tome.pkg
#
# This is where we track information about a sourcecode file
# which we have compiled, are compiling, or might compile.
#
# We track in particular the name of the file and the name
# of the foo.lib library claiming that file.
#
# We track in addition basically all relevant information
# about that file which doesn't require compiling it.
#
# Compiler-produced info about the file is stored separately in
#
#
src/app/makelib/compile/thawedlib-tome--to--compiledfile-contents--map-g.pkg#
# using our Thawedlib_Tome record as the lookup key.
# Compiled by:
#
src/app/makelib/makelib.sublib# See overview comments in
#
src/app/makelib/compilable/thawedlib-tome.apistipulate
package ad = anchor_dictionary; # anchor_dictionary is from
src/app/makelib/paths/anchor-dictionary.pkg package bio = data_file__premicrothread; # data_file__premicrothread is from
src/lib/std/src/posix/data-file--premicrothread.pkg package cf = compiledfile; # compiledfile is from
src/lib/compiler/execution/compiledfile/compiledfile.pkg package ctl = global_controls; # global_controls is from
src/lib/compiler/toplevel/main/global-controls.pkg package err = error_message; # error_message is from
src/lib/compiler/front/basics/errormsg/error-message.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package fp = filename_policy; # filename_policy is from
src/app/makelib/main/filename-policy.pkg package iox = io_exceptions; # io_exceptions is from
src/lib/std/src/io/io-exceptions.pkg package lsi = library_source_index; # library_source_index is from
src/app/makelib/stuff/library-source-index.pkg package mds = module_dependencies_summary; # module_dependencies_summary is from
src/app/makelib/compilable/module-dependencies-summary.pkg package mld = makelib_defaults; # makelib_defaults is from
src/app/makelib/stuff/makelib-defaults.pkg package mls = makelib_state; # makelib_state is from
src/app/makelib/main/makelib-state.pkg package mp = mythryl_parser; # mythryl_parser is from
src/lib/compiler/front/parser/main/mythryl-parser.pkg package pm = parse_mythryl; # parse_mythryl is from
src/lib/compiler/front/parser/main/parse-mythryl.pkg package pn = parse_nada; # parse_nada is from
src/lib/compiler/front/parser/main/parse-nada.pkg package pp = standard_prettyprinter; # standard_prettyprinter is from
src/lib/prettyprint/big/src/standard-prettyprinter.pkg package raw = raw_syntax; # raw_syntax is from
src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg package sci = sourcecode_info; # sourcecode_info is from
src/lib/compiler/front/basics/source/sourcecode-info.pkg package shm = sharing_mode; # sharing_mode is from
src/app/makelib/stuff/sharing-mode.pkg package spm = source_path_map; # source_path_map is from
src/app/makelib/paths/source-path-map.pkg package sm = line_number_db; # line_number_db is from
src/lib/compiler/front/basics/source/line-number-db.pkg package syx = symbolmapstack; # symbolmapstack is from
src/lib/compiler/front/typer-stuff/symbolmapstack/symbolmapstack.pkg package sy = symbol; # symbol is from
src/lib/compiler/front/basics/map/symbol.pkg package ts = timestamp; # timestamp is from
src/app/makelib/paths/timestamp.pkg package wnx = winix__premicrothread; # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkgherein
package thawedlib_tome
: Thawedlib_Tome # Thawedlib_Tome is from
src/app/makelib/compilable/thawedlib-tome.api {
Source_Code_Region = sm::Source_Code_Region;
Inlining_Request = ctl::inline::Localsetting;
Plaint_Sink = err::Plaint_Sink;
Attributes
=
{ crossmodule_inlining_aggressiveness: Inlining_Request, # This gets used in
src/lib/compiler/back/top/improve/do-crossmodule-anormcode-inlining.pkg #
is_runtime_package: Bool, # Special bootstrap kludge supporting access C-code level -- see
src/lib/core/init/runtime.pkg noguid: Bool,
#
explicit_core_symbol: Null_Or( sy::Symbol ), # Deep bootstrap magic for special "_Core"/"Core" package.
extra_static_compile_dictionary: Null_Or( syx::Symbolmapstack ) # See bottom-of-file comments in
src/app/makelib/compilable/thawedlib-tome.api };
Controller
=
{ save_controller_state: Void -> Void -> Void, # Generate a thunk containing the current controller state, which when run will restore the controller to that state.
set: Void -> Void
};
Info_Args # Argument to the make_thawedlib_tome and make_thawedlib_tome' calls which create Thawedlib_Tome instances.
=
{ sourcepath: ad::File, # File containing source code which compiles to produce .compiled file in question.
library: (ad::File, Source_Code_Region),
sharing_request: shm::Request,
pre_compile_code: Null_Or(String),
postcompile_code: Null_Or(String),
is_local: Bool,
controllers: List( Controller )
};
Sourcefile_Syntax
=
MYTHRYL
| NADA;
Generation
=
Ref( Void );
# 2007-08-20 CrT:
# You'd think from the name that we must
# store Persistent_Tome_Info records on disk
# somewhere, but I find no evidence of this.
# I think its name comes from the fact that
# it is what our 'known_info' in-memory index
# stores on a per-file basis.
#
Persistent_Tome_Info
=
PERSISTENT_TOME_INFO
{
library: (ad::File, Source_Code_Region),
generation: Ref( Generation ),
#
sourcefile_timestamp
:
Ref( ts::Timestamp ),
raw_declaration_and_sourcecode_info: Ref( Null_Or( (raw::Declaration, sci::Sourcecode_Info)) ),
module_dependencies_summary: Ref( Null_Or( mds::Declaration ) ),
# The sharing_mode is an elaboration of sharing_request.
# It must be persistent and gets properly recomputed
# when there is a new sharing_request:
sharing_mode: Ref( shm::Mode ),
get_compiledfile_version: Void -> String, # Something like: "version-$ROOT/src/app/makelib/(makelib-lib.lib):compilable/thawedlib-tome.pkg-1187780741.285"
set_compiledfile_version: String -> Void, # Reverse of previous.
sourcefile_syntax: Sourcefile_Syntax # XXX BUGGO FIXME Do we need to be saving and restoring this in some pickling code somewhere?
};
Thawedlib_Tome # Named is for symmetry with Frozenlib_Tome from
src/app/makelib/freezefile/frozenlib-tome.pkg =
#
# This is our central record describing one .api or .pkg sourcefile.
# This is also the main sumtype entrypoint into this file,
# referenced in particular by THAWEDLIB_TOME in
#
#
src/app/makelib/depend/intra-library-dependency-graph.pkg #
THAWEDLIB_TOME {
#
sourcepath: ad::File, # File containing source code which compiles to produce us.
make_module_dependencies_summaryfile_name: Void -> String, # File in which we cache a brief summary of the source code.
make_compiledfile_name: Void -> String, # File to which we should write the generated .compiled binary -- normally "foo.pkg.compiled" if input is "foo.pkg".
#
persistent_tome_info: Persistent_Tome_Info,
sharing_request: shm::Request,
attributes: Attributes,
#
pre_compile_code: Null_Or(String), # 'tool' support: Mythryl source code to execute before compile.
postcompile_code: Null_Or(String), # 'tool' support: Mythryl source code to execute after compile.
# See compile_and_run_mythryl_codestring() in
src/app/makelib/compile/compile-in-dependency-order-g.pkg is_local: Bool,
controllers: List( Controller )
};
Key = Thawedlib_Tome;
stipulate
generation = REF (REF ()); # XXX BUGGO FIXME More icky buried global state preventing multithreading :(
herein
fun now ()
=
*generation;
#
fun new_generation ()
=
generation := REF ();
end;
fun make_compiledfile_name (THAWEDLIB_TOME t) = t.make_compiledfile_name ();
fun sourcepath_of (THAWEDLIB_TOME t) = t.sourcepath;
fun sharing_request_of (THAWEDLIB_TOME t) = t.sharing_request;
fun attributes_of (THAWEDLIB_TOME t) = t.attributes;
fun pre_compile_code_of (THAWEDLIB_TOME t) = t.pre_compile_code;
fun postcompile_code_of (THAWEDLIB_TOME t) = t.postcompile_code;
fun controllers_of (THAWEDLIB_TOME t) = t.controllers;
fun is_local (THAWEDLIB_TOME t) = t.is_local;
fun module_dependencies_summaryfile_name_of (THAWEDLIB_TOME t) = t.make_module_dependencies_summaryfile_name ();
#
fun get_sharing_mode (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { sharing_mode => REF m, ... }, ... } )
=
m;
#
fun set_sharing_mode (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { sharing_mode, ... }, ... }, m)
=
sharing_mode := m;
#
fun sourcefile_syntax_of (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { sourcefile_syntax, ... }, ... } )
=
sourcefile_syntax;
#
fun gerror (makelib_state: mls::Makelib_State)
=
lsi::error makelib_state.library_source_index;
#
fun error makelib_state (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { library, ... }, ... } )
=
gerror makelib_state library;
#
fun group_of (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { library => (g, _), ... }, ... } )
=
g;
#
fun compare (THAWEDLIB_TOME { sourcepath => p, ... }, THAWEDLIB_TOME { sourcepath => p', ... } )
=
ad::compare (p, p');
#
fun same_thawedlib_tome (i, i')
=
compare (i, i') == EQUAL;
#
fun sourcefile_timestamp_of (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { sourcefile_timestamp, ... }, ... } )
=
*sourcefile_timestamp;
# XXX BUGGO FIXME more thread-unsafe mutable global state:
known_info # XXX BUGGO FIXME There's got to be a more perspicuous name for than this. :(
=
REF (spm::empty: spm::Map( Persistent_Tome_Info ));
#
fun is_known (THAWEDLIB_TOME { sourcepath, ... } )
=
not_null (spm::get (*known_info, sourcepath));
#
fun count_parse_trees ()
=
spm::fold_forward
count_one
0
*known_info
where
fun count_one (PERSISTENT_TOME_INFO { raw_declaration_and_sourcecode_info => REF (THE _), ... }, count)
=>
count + 1;
count_one (_, count) => count;
end;
end;
#
# Counting the trees explicitly may be a bit slow,
# but maintaining an accurate count is difficult,
# and this method is at least robust. I don't think
# that the overhead of counting will make a noticeable
# difference. -- Matthias Blume
#
fun forget_raw_declaration_and_sourcecode_info (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { raw_declaration_and_sourcecode_info, ... }, ... } )
=
raw_declaration_and_sourcecode_info
:=
NULL;
#
fun clean_library now_built g
=
{ n = now ();
#
fun is_current (PERSISTENT_TOME_INFO { generation => REF gen, library => (g', _), ... } )
=
((not now_built) and gen == n)
or
ad::compare (g, g') != EQUAL;
known_info := spm::filter is_current *known_info;
};
#
fun clear_state ()
=
known_info := spm::empty;
# Check timestamp and throw away any invalid cache:
#
fun validate (sourcepath, PERSISTENT_TOME_INFO persistent_tome_info)
=
{ # We avoid using the "..." pattern here
# so as to have the compiler flag additions
# to the type via a compile error message:
#
persistent_tome_info
->
{ library,
sourcefile_timestamp,
raw_declaration_and_sourcecode_info,
module_dependencies_summary,
sharing_mode,
generation,
get_compiledfile_version,
set_compiledfile_version,
sourcefile_syntax
};
timestamp = *sourcefile_timestamp;
new_timestamp = ad::timestamp sourcepath;
if (ts::needs_update {
source => new_timestamp,
target => timestamp
}
)
sourcefile_timestamp
:=
new_timestamp;
generation := now ();
raw_declaration_and_sourcecode_info
:=
NULL;
module_dependencies_summary := NULL;
fi;
};
# timestamp is from
src/app/makelib/paths/timestamp.pkg # Construct and return a THAWEDLIB_TOME record
# for a given .api or .pkg file. (This record
# is our primary internal representative for
# a file which is being -- or has been -- compiled.)
#
# This function is called directly from "fun sml" in
#
src/app/makelib/mythryl-compiler-compiler/process-mythryl-primordial-library.pkg # We also get called via our below "fun make_thawedlib_tome" wrapper from
# fun smlfile_collections in
#
src/app/makelib/stuff/raw-libfile.pkg #
fun make_thawedlib_tome'
attributes
(makelib_state: mls::Makelib_State)
arg
=
THAWEDLIB_TOME
{
sourcepath, # File containing source code which compiles to produce .compiled in question.
make_module_dependencies_summaryfile_name,
make_compiledfile_name,
#
persistent_tome_info => get_or_make_persistent_tome_info (),
sharing_request,
#
attributes,
pre_compile_code, # Arbitrary code to execute before compiling this file.
postcompile_code, # Arbitrary code to execute after compiling this file.
is_local,
#
controllers
}
where
arg ->
{ library => gr as (library, source_code_region),
sourcepath, # File containing source code which compiles to produce .compiled in question.
sharing_request,
pre_compile_code, # Random code to execute before compiling this file.
postcompile_code, # Random code to execute after compiling this file.
is_local,
controllers
};
policy = makelib_state.makelib_session.filename_policy;
#
fun make_module_dependencies_summaryfile_name () = fp::make_module_dependencies_summaryfile_name policy sourcepath;
fun make_compiledfile_name () = fp::make_compiledfile_name policy sourcepath;
fun make_versionfile_name () = fp::make_versionfile_name policy sourcepath;
library_source_index
=
makelib_state.library_source_index;
# NB: The 'noguid' attribute appears to default to FALSE
# and to be set to TRUE by c-glue-maker, and to be
# almost entirely undocumented. The below 'if' appears
# to be the only place it is tested and used:
#
my (get_compiledfile_version, set_compiledfile_version)
=
if attributes.noguid # So apparently 'noguid' means "Don't use compiledfile versions", implying "guid" == "globally unique identifier"(presumably) == compiledfile version.
#
( \\ () = "",
\\ _ = ()
);
else
(get_compiledfile_version, set_compiledfile_version)
where
compiledfile_version_cache = REF NULL; # Or (say) (THE "version-$ROOT/src/app/makelib/(makelib-lib.lib):compilable/thawedlib-tome.pkg-1187780741.285")
#
fun version_string_from_compiled_file ()
=
# Return NULL immediately if file is unreadable.
# This isn't strictly necessary, but avoids
# generating background failed-to-open-file
# errors that can be distracting when debugging:
#
{ filename = make_compiledfile_name ();
if (not (wnx::file::access (filename, [wnx::file::MAY_READ])))
#
NULL;
else
safely::do
{
open_it => {. bio::open_for_read filename; },
close_it => bio::close_input,
cleanup => \\ _ = ()
}
(THE o cf::read_version)
except
iox::IO _ = NULL;
fi;
};
# compiledfile is from
src/lib/compiler/execution/compiledfile/compiledfile.pkg #
fun version_string_from_version_file ()
=
{ filename = make_versionfile_name ();
# Return NULL immediately if file is unreadable.
# This isn't strictly necessary, but avoids
# generating background failed-to-open-file
# errors that can be distracting when debugging:
#
if (not (wnx::file::access (filename, [wnx::file::MAY_READ])))
#
NULL;
else
safely::do
{
open_it => {. fil::open_for_read filename; },
close_it => fil::close_input,
cleanup => \\ _ = ()
}
(THE o fil::read_all)
except # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg iox::IO _ = NULL;
fi;
};
#
fun set_compiledfile_version compiledfile_version_string
=
{ compiledfile_version_cache := THE compiledfile_version_string;
#
write_to_versionfile compiledfile_version_string
where
fun write_to_versionfile compiledfile_version_string # Say, "version-$ROOT/src/app/makelib/(makelib-lib.lib):compilable/thawedlib-tome.pkg-1187780741.285"
=
{ version_filename # For
src/app/makelib/compilable/thawedlib-tome.pkg = # this will be src/app/makelib/compilable/thawedlib-tome.pkg.version
make_versionfile_name ();
safely::do
{
open_it => {. autodir::open_text_output version_filename; },
close_it => fil::close_output,
cleanup => \\ _ = wnx::file::remove_file version_filename
}
{. fil::write (#s, compiledfile_version_string); };
};
end;
};
#
fun save_compiledfile_version compiledfile_version_string
=
{ set_compiledfile_version compiledfile_version_string;
#
compiledfile_version_string;
};
# Try successively up to four ways of obtaining
# the version string for our .compiled file:
# o Cached in our version_cache variable;
# o Stored in the .compiled file itself;
# o Stored in the .version file;
# o Create a new one from scratch.
#
# XXX BUGGO DELETEME This 'version' game is not worth the code complexity candle -- it should all be ripped out. 2007-11-03 CrT
fun get_compiledfile_version ()
=
{ # Create a version string. This will look like
# "version-$ROOT/src/app/makelib/(makelib-lib.lib):compilable/thawedlib-tome.pkg-1187780741.285"
# XXX BUGGO FIXME This should probably be in a separate version-string.pkg or such.
# XXX BUGGO FIXME We apparently just assume no two compiles of the same source
# can complete at the same millisecond. With parallel compiles
# in different processes on on multicore machines and such, this
# may not be true -- some sort of explicit file locking or such is probably needed.
#
fun make_compiledfile_version_string () # XXX BUGGO DELETEME This 'version' game is not worth the code complexity candle -- it should all be ripped out. 2007-11-03 CrT
=
cat [ "version-",
# ad::describe sourcepath, # sourcepath was in "fun make_thawedlib_tome'"'s 'arg' argument, above.
# "-",
# ts::to_string( ad::timestamp sourcepath ),
# time::to_string (time::now ()), # Matthias had this, which screws up 'make fixpoint', so I substituted the above. I don't understand what the point of all this is, however, so that might be bad. XXX BUGGO FIXME
"\n"
];
# time is from
src/lib/std/time.pkg case *compiledfile_version_cache
#
THE compiledfile_version_string => compiledfile_version_string;
#
NULL =>
case (version_string_from_compiled_file ())
#
THE compiledfile_version_string
=>
save_compiledfile_version compiledfile_version_string;
#
NULL =>
case (version_string_from_version_file ())
#
THE compiledfile_version_string => compiledfile_version_string;
NULL => save_compiledfile_version (make_compiledfile_version_string ());
esac;
esac;
esac;
};
end;
fi;
# Our syntactic scope at this point is within the fun make_thawedlib_tome' definition code block.
#
fun make_persistent_tome_info ()
=
persistent_tome_info
where
timestamp = ad::timestamp sourcepath; # sourcepath was in "fun make'"'s 'arg' argument, above.
filename = ad::os_string' sourcepath;
sourcefile_syntax
=
if (string::is_suffix ".pkg7" filename) NADA;
elif (string::is_suffix ".api7" filename) NADA;
else MYTHRYL;
fi;
# string is from
src/lib/std/string.pkg persistent_tome_info
=
PERSISTENT_TOME_INFO
{
sourcefile_timestamp => REF timestamp,
library => gr,
#
raw_declaration_and_sourcecode_info => REF NULL,
module_dependencies_summary => REF NULL,
sharing_mode => REF (shm::SHARE FALSE),
generation => REF (now ()),
set_compiledfile_version,
get_compiledfile_version,
sourcefile_syntax
};
known_info
:=
spm::set
(*known_info, sourcepath, persistent_tome_info);
end;
#
fun get_or_make_persistent_tome_info ()
=
case (spm::get (*known_info, sourcepath))
#
NULL => make_persistent_tome_info ();
#
THE (persistent_tome_info as PERSISTENT_TOME_INFO { library => gr' as (g, r), generation, ... } )
=>
if (ad::compare (library, g) == EQUAL)
#
validate (sourcepath, persistent_tome_info);
persistent_tome_info;
else
n = ad::describe sourcepath;
if (*generation == now ())
#
gerror makelib_state gr err::ERROR
(cat ["Source file ", n,
" appears in more than one library"])
err::null_error_body;
#
gerror makelib_state gr' err::ERROR
(cat ["(previous occurence of ", n, ")"])
err::null_error_body;
else
gerror makelib_state gr err::WARNING
(cat ["Source file ", n,
" has switched libraries"])
err::null_error_body;
fi;
make_persistent_tome_info ();
fi;
esac;
end; # fun make_thawedlib_tome'
# This function seems to mainly be called from
# fun smlfile_collections in
#
src/app/makelib/stuff/raw-libfile.pkg #
fun make_thawedlib_tome (crossmodule_inlining_aggressiveness, noguid)
=
make_thawedlib_tome'
{
extra_static_compile_dictionary => NULL,
is_runtime_package => FALSE,
explicit_core_symbol => NULL,
crossmodule_inlining_aggressiveness,
noguid
};
# The following functions are only
# concerned with getting the data,
# not with checking time stamps:
#
fun get_parsetree
#
makelib_state
#
{ thawedlib_tome as THAWEDLIB_TOME tome_record, # XXX BUGGO FIXME this should be a record not a tuple, for readability
quiet,
unparse_info
}
=
{ tome_record
->
{ persistent_tome_info => PERSISTENT_TOME_INFO { raw_declaration_and_sourcecode_info, sourcefile_syntax, ... },
sourcepath,
controllers,
...
};
#
fun err m
=
error makelib_state thawedlib_tome err::ERROR m err::null_error_body;
#
case *raw_declaration_and_sourcecode_info
#
THE raw_declaration_and_sourcecode_info =>
THE raw_declaration_and_sourcecode_info;
#
NULL =>
{ previous_controller_settings # Save states of our controllers as a list of thunks; evaluating those thunks will restore the original controller states.
=
map (\\ controller = controller.save_controller_state ())
controllers;
#
fun parse_sourcefile source_stream
=
{
if (mld::debug.get ()) printf "thawedlib-tome: parse_sourcefile(%s)/TOP [makelib::debug]\n" (ad::os_string' sourcepath); fi;
if (not quiet)
#
fil::say {.
cat [
" thawedlib-tome.pkg: Parsing source file ",
ad::os_string' sourcepath
];
};
fi;
# XXX BUGGO DELETEME this is temporary codebase conversion infrastructure
#
if *mp::log_edit_requests
#
filename = cat [ ad::os_string' sourcepath,
".EDIT_REQUESTS"
];
stream = fil::open_for_write filename;
mp::edit_request_stream
:=
THE stream;
fi;
sourcecode_info
=
sci::make_sourcecode_info
{
file_name => ad::os_string' sourcepath,
line_num => 1,
source_stream,
is_interactive => FALSE,
error_consumer => makelib_state.plaint_sink
};
apply
(\\ c = c.set ())
controllers;
# If unparse_info is not NULL, we also
# prettyprint the parsetree to a diskfile:
#
case unparse_info
#
NULL =>
(
case sourcefile_syntax
#
MYTHRYL => pm::parse_complete_mythryl_file sourcecode_info;
NADA => pn::parse_complete_nada_file sourcecode_info;
esac,
sourcecode_info
)
then
apply
(\\ r = r ())
previous_controller_settings;
(THE (symbolmapstack, unparse_generic))
=>
result
where
result
=
( case sourcefile_syntax
#
MYTHRYL => pm::parse_complete_mythryl_file sourcecode_info;
NADA => pn::parse_complete_nada_file sourcecode_info;
esac,
sourcecode_info
)
then
apply
(\\ r = r ())
previous_controller_settings;
raw_syntax_tree = #1 result;
unparse_filename = cat [ ad::os_string' sourcepath, ".PRETTY_PRINT" ];
unparse_textstream = fil::open_for_write unparse_filename;
output_stream
=
{ consumer => (\\ string = fil::write (unparse_textstream, string)),
flush => {. fil::flush unparse_textstream; },
close => {. fil::close_output unparse_textstream; }
};
prettyprinter = pp::make_prettyprinter output_stream [];
unparse_generic
(symbolmapstack, NULL)
prettyprinter
( raw_syntax_tree,
1000 # Arbitrary large output device width
);
pp::flush_prettyprinter prettyprinter;
fil::flush unparse_textstream;
fil::close_output unparse_textstream;
end;
esac
# XXX BUGGO DELETEME this is temporary codebase conversion infrastructure
then
case *mp::edit_request_stream
#
NULL => ();
#
THE stream
=>
{ fil::flush stream;
fil::close_output stream;
mp::edit_request_stream
:=
NULL;
};
esac;
}; # fun parse_sourcefile
#
fun open_it ()
=
fil::open_for_read (ad::os_string sourcepath);
#
fun cleanup _
=
apply (\\ r = r ()) previous_controller_settings;
optional_parsetree
=
THE (
safely::do {
open_it,
cleanup,
close_it => fil::close_input
}
parse_sourcefile
);
ntrees = count_parse_trees ();
treelimit = mld::parse_caching.get ();
if (ntrees < treelimit)
#
raw_declaration_and_sourcecode_info
:=
optional_parsetree;
fi;
optional_parsetree;
}
except
exn as iox::IO _
=>
{ err (exceptions::exception_message exn);
NULL;
};
compilation_exception::COMPILE msg
=>
{ err msg;
NULL;
};
end;
esac;
}; # fun get_parsetree
#
fun module_dependencies_summary makelib_state (i as THAWEDLIB_TOME tome_record)
=
{ tome_record
->
{ sourcepath,
make_module_dependencies_summaryfile_name,
persistent_tome_info => PERSISTENT_TOME_INFO persistent_tome_info_record,
...
};
persistent_tome_info_record
->
{ module_dependencies_summary,
sourcefile_timestamp,
...
};
#
case *module_dependencies_summary
#
THE module_dependencies_summary =>
THE module_dependencies_summary;
#
NULL =>
{ module_dependencies_summaryfile_name
=
make_module_dependencies_summaryfile_name ();
# module_dependencies_summary_io is from
src/app/makelib/compilable/module-dependencies-summary-io.pkg #
case (module_dependencies_summary_io::read (module_dependencies_summaryfile_name, *sourcefile_timestamp))
#
THE module_dependencies_summary'
=>
{ module_dependencies_summary := THE module_dependencies_summary';
THE module_dependencies_summary';
};
#
NULL =>
case (get_parsetree
#
makelib_state
#
{ thawedlib_tome => i,
quiet => FALSE,
unparse_info => NULL
}
)
#
NULL => NULL;
#
THE (tree, source)
=>
{ fun err sv source_code_region s
=
err::error source source_code_region sv s err::null_error_body;
# raw_syntax_to_module_dependencies_summary is from
src/app/makelib/compilable/raw-syntax-to-module-dependencies-summary.pkg # module_dependencies_summary_io is from
src/app/makelib/compilable/module-dependencies-summary-io.pkg my { module_dependencies_summary => module_dependencies_summary',
complain
}
=
raw_syntax_to_module_dependencies_summary::convert
{
tree,
err
};
complain ();
if (err::saw_errors (err::errors source))
#
error makelib_state i err::ERROR
"error (s) in source file"
err::null_error_body;
else
module_dependencies_summary_io::write
(module_dependencies_summaryfile_name, module_dependencies_summary', *sourcefile_timestamp);
module_dependencies_summary
:=
THE module_dependencies_summary' ;
fi;
THE module_dependencies_summary' ;
};
esac;
esac;
};
esac;
};
# We only complain at the time of getting the exports:
#
fun exports makelib_state i
=
null_or::map
get_toplevel_module_dependencies_summary_exports::get_toplevel_module_dependencies_summary_exports
(module_dependencies_summary makelib_state i);
# null_or is from
src/lib/std/src/null-or.pkg # get_toplevel_module_dependencies_summary_exports is from
src/app/makelib/compilable/get-toplevel-module-dependencies-summary-exports.pkg # Return the raw parsetree for this file.
# We get it from in-memory cache if possible,
# otherwise we read and parse the source file.
#
fun find_raw_declaration_and_sourcecode_info # Called (only) from
src/app/makelib/compile/compile-in-dependency-order-g.pkg #
makelib_state
unparse_info # NULL or top-level compiler symbol table plus prettyprint fn.
thawedlib_tome # Has all info on the file, including sourcefile name.
#
: Null_Or( (raw::Declaration, sci::Sourcecode_Info) )
=
get_parsetree
#
makelib_state
#
{ thawedlib_tome,
quiet => TRUE,
unparse_info
};
#
fun describe_thawedlib_tome (THAWEDLIB_TOME { sourcepath, ... } ) # Something like "src/lib/reactive/(reactive.lib):reactive.pkg" or "src/lib/x-kit/(xkit.lib):xclient/(xclient.sublib):(xclient-internals.sublib):src/color/rgb.pkg"
=
ad::describe sourcepath;
#
fun error_location (makelib_state: mls::Makelib_State) (THAWEDLIB_TOME info)
=
{ info
->
{ persistent_tome_info => PERSISTENT_TOME_INFO { library => (library, reg), ... }, ... };
err::match_error_string
(lsi::look_up makelib_state.library_source_index library)
reg;
};
#
fun get_compiledfile_version (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { get_compiledfile_version, ... }, ... } )
=
get_compiledfile_version ();
#
fun set_compiledfile_version (THAWEDLIB_TOME { persistent_tome_info => PERSISTENT_TOME_INFO { set_compiledfile_version, ... }, ... }, compiledfile_version)
=
set_compiledfile_version compiledfile_version;
};
end;
## Copyright (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.