## module-dependencies-summary-io.pkg
## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
# Compiled by:
#
src/app/makelib/makelib.sublib# Reading and writing module_dependencies_summarys to module_dependencies_summary files.
# Module_Dependencies_Summarys provide a quick summary of a file,
# often saving us from generating a full parsetree.
# Or that's the idea, anyhow.
#
# Our runtime calls are from (only)
#
#
src/app/makelib/compilable/thawedlib-tome.pkgstipulate
package mds = module_dependencies_summary; # module_dependencies_summary is from
src/app/makelib/compilable/module-dependencies-summary.pkg package ts = timestamp; # timestamp is from
src/app/makelib/paths/timestamp.pkgherein
api Module_Dependencies_Summary_Io {
#
read: (/*filename:*/String, ts::Timestamp) -> Null_Or( mds::Declaration );
write: (/*filename:*/String, mds::Declaration, ts::Timestamp) -> Void;
};
end;
stipulate
package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package mds = module_dependencies_summary; # module_dependencies_summary is from
src/app/makelib/compilable/module-dependencies-summary.pkg package pkr = pickler; # pickler is from
src/lib/compiler/src/library/pickler.pkg package spp = symbol_and_picklehash_pickling; # symbol_and_picklehash_pickling is from
src/lib/compiler/front/semantic/pickle/symbol-and-picklehash-pickling.pkg package syp = symbol_path; # symbol_path is from
src/lib/compiler/front/typer-stuff/basics/symbol-path.pkg package sys = symbol_set; # symbol_set is from
src/app/makelib/stuff/symbol-set.pkg package tag = pickler_sumtype_tags; # pickler_sumtype_tags is from
src/lib/compiler/src/library/pickler-sumtype-tags.pkg package upr = unpickler; # unpickler is from
src/lib/compiler/src/library/unpickler.pkgherein
package module_dependencies_summary_io
: Module_Dependencies_Summary_Io # Module_Dependencies_Summary_Io is from
src/app/makelib/compilable/module-dependencies-summary-io.pkg {
exception FORMAT = upr::FORMAT;
#
s2b = byte::string_to_bytes; # byte is from
src/lib/std/src/byte.pkg b2s = byte::bytes_to_string;
b2c = byte::byte_to_char;
version = "Module_Dependencies_Summary 5\n";
fun makeset l
=
sys::add_list (sys::empty, l);
fun read_line stream
=
loop []
where
fun finish resultlist
=
string::implode (reverse resultlist);
fun loop resultlist
=
case (null_or::map b2c (data_file__premicrothread::read_one stream))
#
NULL => finish ('\n' ! resultlist);
THE '\n' => finish ('\n' ! resultlist);
THE c => loop (c ! resultlist);
esac;
end;
fun write_decl (s, d)
=
{
wrap_symbol = spp::wrap_symbol;
wrap_list = pkr::wrap_list;
mknod = pkr::make_funtree_node tag::symbol_path;
fun wrap_symbol_path (syp::SYMBOL_PATH p)
=
mknod "p" [wrap_list wrap_symbol p];
fun wrap_declaration arg
=
d arg
where
mknod = pkr::make_funtree_node tag::mds_declaration;
#
fun d (mds::BIND (name, def)) => mknod "a" [wrap_symbol name, wrap_module_expression def];
d (mds::LOCAL (x, y)) => mknod "b" [wrap_declaration x, wrap_declaration y];
d (mds::PAR l) => mknod "c" [wrap_list wrap_declaration l];
d (mds::SEQ l) => mknod "d" [wrap_list wrap_declaration l];
d (mds::OPEN d) => mknod "e" [wrap_module_expression d];
d (mds::REF s) => mknod "f" [wrap_list wrap_symbol (sys::vals_list s)];
end;
end
also
fun wrap_module_expression arg
=
m arg
where
mknod = pkr::make_funtree_node tag::mds_module_expression;
#
fun m (mds::VARIABLE p) => mknod "g" [wrap_symbol_path p];
m (mds::DECL d) => mknod "h" [wrap_list wrap_declaration d];
m (mds::LET (d, e)) => mknod "i" [wrap_list wrap_declaration d, wrap_module_expression e];
m (mds::IGN1 (e1, e2)) => mknod "j" [wrap_module_expression e1, wrap_module_expression e2];
end;
end;
pickle = s2b (pkr::funtree_to_pickle () (wrap_declaration d));
data_file__premicrothread::write (s, byte::string_to_bytes version);
data_file__premicrothread::write (s, pickle);
};
# data_file__premicrothread is from
src/lib/std/src/posix/data-file--premicrothread.pkg fun read_decl s
=
{ first_line = read_line s;
unpickler = upr::make_unpickler (upr::make_charstream_for_string (b2s (data_file__premicrothread::read_all s)));
string = upr::read_string unpickler;
symbol = symbol_and_picklehash_unpickling::read_symbol (unpickler, string);
fun list sharemap read_element
=
upr::read_list unpickler sharemap read_element;
fun read_sharable_value sharemap read_value
=
upr::read_sharable_value unpickler sharemap read_value;
symbol_path_sharemap = upr::make_sharemap ();
symbol_list_m = upr::make_sharemap ();
declaration_sharemap = upr::make_sharemap ();
decl_list_m = upr::make_sharemap ();
module_expression_sharemap = upr::make_sharemap ();
symbollist
=
list symbol_list_m symbol;
fun path ()
=
read_sharable_value symbol_path_sharemap p
where
fun p 'p' => syp::SYMBOL_PATH (symbollist ());
p _ => raise exception FORMAT;
end;
end;
fun decl ()
=
read_sharable_value declaration_sharemap d
where
fun d 'a' => mds::BIND (symbol (), module_expression ());
d 'b' => mds::LOCAL (decl (), decl ());
d 'c' => mds::PAR (decllist ());
d 'd' => mds::SEQ (decllist ());
d 'e' => mds::OPEN (module_expression ());
d 'f' => mds::REF (makeset (symbollist ()));
d _ => raise exception FORMAT;
end;
end
also
fun decllist ()
=
list decl_list_m decl ()
also
fun module_expression ()
=
read_sharable_value module_expression_sharemap m
where
fun m 'g' => mds::VARIABLE (path ());
m 'h' => mds::DECL (decllist ());
m 'i' => mds::LET (decllist (), module_expression ());
m 'j' => mds::IGN1 (module_expression (), module_expression ());
m _ => raise exception FORMAT;
end;
end;
if (first_line != version) raise exception FORMAT; fi;
decl ();
};
fun read (s, timestamp)
=
if (timestamp::needs_update
{
target => timestamp::last_file_modification_time s,
source => timestamp
}
)
NULL;
else
THE (
safely::do {
open_it => {. data_file__premicrothread::open_for_read s; },
close_it => data_file__premicrothread::close_input,
cleanup => \\ _ = ()
}
read_decl
)
except
_ = NULL;
fi;
# XXX BUGGO DELETEME
fun abbreviate (full_pathname: String)
=
{ root = "/pub/home/cynbe/src/mythryl/mythryl7/mythryl7.110.58/mythryl7.110.58";
if (string::is_prefix root full_pathname)
"$ROOT"
+
string::extract (full_pathname, string::length_in_bytes root, NULL);
else
full_pathname;
fi;
};
# timestamp is from
src/app/makelib/paths/timestamp.pkg # safely is from
src/lib/std/safely.pkg # data_file__premicrothread is from
src/lib/std/src/posix/data-file--premicrothread.pkg # winix__premicrothread is from
src/lib/std/winix--premicrothread.pkg # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg # autodir is from
src/app/makelib/stuff/autodir.pkg fun make_temporary_filename filename
=
{ # Voice of Experience: During a parallel compile,
# multiple versions of the compiler may be writing
# the same module_dependencies_summary file at the same time, which
# can result in a crash trying to set the timestamp
# (below).
#
# To avoid that, we create the module_dependencies_summary file under
# a private temporary name, then set its timestamp,
# and only then rename it to its final name -- that
# being an atomic operation not subject to race
# conditions:
#
pid = winix__premicrothread::process::get_process_id ();
include package sfprintf;
pid = sprintf' "%d" [ INT pid ];
temporary_filename = filename + "." + pid + ".tmp";
temporary_filename;
};
fun write (filename, sk, timestamp)
=
{ temporary_filename
=
make_temporary_filename filename;
fun cleanup _
=
{ winix__premicrothread::file::remove_file temporary_filename
except
_ = ();
fil::say {. cat ["[writing ", temporary_filename, " failed]\n"]; };
};
safely::do
{
open_it => {. autodir::open_binary_output temporary_filename; },
close_it => data_file__premicrothread::close_output,
cleanup
}
{. write_decl (#stream, sk); };
timestamp::set_last_file_modification_time (temporary_filename, timestamp);
winix__premicrothread::file::rename_file
{
from => temporary_filename,
to => filename
};
};
};
end;