1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-26 04:00:43 +03:00

Improved project dependency graph

This commit is contained in:
Graham Nelson 2020-03-09 12:44:59 +00:00
parent de0965a93e
commit 5a16b16e12
16 changed files with 204 additions and 144 deletions

View file

@ -20,7 +20,7 @@ pathname *path_to_inbuild = NULL;
pathname *path_to_tools = NULL;
int inbuild_task = INSPECT_TTASK;
int dry_run_mode = FALSE;
int dry_run_mode = FALSE, build_trace_mode = FALSE;
linked_list *targets = NULL; /* of |inbuild_copy| */
inbuild_nest *destination_nest = NULL;
text_stream *filter_text = NULL;
@ -43,6 +43,7 @@ int main(int argc, char **argv) {
build_methodology *BM;
if (path_to_tools) BM = BuildMethodology::new(path_to_tools, FALSE, use);
else BM = BuildMethodology::new(Pathnames::up(path_to_inbuild), TRUE, use);
if (build_trace_mode) trace_ibg = TRUE;
if (Str::len(unit_test) > 0) {
if (Str::eq(unit_test, I"compatibility")) Compatibility::test(STDOUT);
else if (Str::eq(unit_test, I"semver")) VersionNumbers::test(STDOUT);
@ -93,6 +94,7 @@ int main(int argc, char **argv) {
@e NEEDS_CLSW
@e INSPECT_CLSW
@e DRY_CLSW
@e BUILD_TRACE_CLSW
@e TOOLS_CLSW
@e CONTENTS_OF_CLSW
@e MATCHING_CLSW
@ -122,6 +124,8 @@ int main(int argc, char **argv) {
L"make X the directory of intools executables, and exit developer mode");
CommandLine::declare_boolean_switch(DRY_CLSW, L"dry", 1,
L"make this a dry run (print but do not execute shell commands)", FALSE);
CommandLine::declare_boolean_switch(BUILD_TRACE_CLSW, L"build-trace", 1,
L"show verbose reasoning during -build", FALSE);
CommandLine::declare_switch(MATCHING_CLSW, L"matching", 2,
L"apply to all works in nest(s) matching requirement X");
CommandLine::declare_switch(CONTENTS_OF_CLSW, L"contents-of", 2,
@ -175,6 +179,7 @@ void Main::option(int id, int val, text_stream *arg, void *state) {
case MATCHING_CLSW: filter_text = Str::duplicate(arg); break;
case CONTENTS_OF_CLSW: Main::load_many(Pathnames::from_text(arg)); break;
case DRY_CLSW: dry_run_mode = val; break;
case BUILD_TRACE_CLSW: build_trace_mode = val; break;
case COPY_TO_CLSW: inbuild_task = COPY_TO_TTASK;
destination_nest = Nests::new(Pathnames::from_text(arg));
break;

View file

@ -542,7 +542,7 @@ void Inbuild::pass_kit_requests(void) {
if ((shared_project) && (kits_requested_at_command_line)) {
text_stream *kit_name;
LOOP_OVER_LINKED_LIST(kit_name, text_stream, kits_requested_at_command_line) {
Projects::add_kit_dependency(shared_project, kit_name);
Projects::add_kit_dependency(shared_project, kit_name, NULL, NULL);
Projects::not_necessarily_parser_IF(shared_project);
}
}

View file

@ -36,6 +36,7 @@ Setting up the use of this module.
@e known_extension_clash_MT
@e build_skill_MT
@e control_structure_phrase_MT
@e kit_dependency_MT
=
ALLOCATE_INDIVIDUALLY(heading)
@ -65,6 +66,7 @@ ALLOCATE_INDIVIDUALLY(extension_dictionary_entry)
ALLOCATE_INDIVIDUALLY(known_extension_clash)
ALLOCATE_INDIVIDUALLY(build_skill)
ALLOCATE_INDIVIDUALLY(control_structure_phrase)
ALLOCATE_INDIVIDUALLY(kit_dependency)
ALLOCATE_IN_ARRAYS(inbuild_work_database_entry, 100)
@ -122,6 +124,8 @@ void InbuildModule::end(void) {
@ =
DECLARE_ANNOTATION_FUNCTIONS(embodying_heading, heading)
MAKE_ANNOTATION_FUNCTIONS(embodying_heading, heading)
DECLARE_ANNOTATION_FUNCTIONS(inclusion_of_extension, inform_extension)
MAKE_ANNOTATION_FUNCTIONS(inclusion_of_extension, inform_extension)
heading *InbuildModule::heading(parse_node *PN) {
return ParseTree::get_embodying_heading(PN);

View file

@ -9,7 +9,6 @@ with a given title, and/or version number.
typedef struct inbuild_requirement {
struct inbuild_work *work;
struct semver_range *version_range;
int allow_malformed;
MEMORY_MANAGEMENT
} inbuild_requirement;
@ -17,7 +16,6 @@ inbuild_requirement *Requirements::new(inbuild_work *work, semver_range *R) {
inbuild_requirement *req = CREATE(inbuild_requirement);
req->work = work;
req->version_range = R;
req->allow_malformed = FALSE;
return req;
}
@ -57,11 +55,6 @@ inbuild_requirement *Requirements::from_text(text_stream *T, text_stream *errors
void Requirements::impose_clause(inbuild_requirement *req, text_stream *T, text_stream *errors) {
Str::trim_white_space(T);
if (Str::get_last_char(T) == '*') {
req->allow_malformed = TRUE;
Str::delete_last_character(T);
Str::trim_white_space(T);
}
if (Str::eq(T, I"all")) return;
TEMPORARY_TEXT(clause);
@ -145,7 +138,6 @@ void Requirements::write(OUTPUT_STREAM, inbuild_requirement *req) {
WRITE("range="); VersionNumbers::write_range(OUT, req->version_range);
}
if (claused == FALSE) WRITE("all");
if (req->allow_malformed) WRITE("*");
}
int Requirements::meets(inbuild_edition *edition, inbuild_requirement *req) {
@ -155,7 +147,6 @@ int Requirements::meets(inbuild_edition *edition, inbuild_requirement *req) {
if (req->work->genre != edition->work->genre)
return FALSE;
}
if ((req->allow_malformed) && (Str::len(edition->work->title) == 0)) return TRUE;
if (Str::len(req->work->title) > 0) {
if (Str::ne_insensitive(req->work->title, edition->work->title))
return FALSE;

View file

@ -153,12 +153,21 @@ void Graphs::show_needs(OUTPUT_STREAM, build_vertex *V) {
void Graphs::show_needs_r(OUTPUT_STREAM, build_vertex *V, int depth, int true_depth) {
if (V->type == COPY_VERTEX) {
for (int i=0; i<depth; i++) WRITE(" ");
Copies::write_copy(OUT, V->buildable_if_copy); WRITE("\n");
inbuild_copy *C = V->buildable_if_copy;
WRITE("%S: ", C->edition->work->genre->genre_name);
Copies::write_copy(OUT, C); WRITE("\n");
depth++;
}
if (V->type == REQUIREMENT_VERTEX) {
for (int i=0; i<depth; i++) WRITE(" ");
Requirements::write(OUT, V->findable); WRITE("\n");
WRITE("missing %S: ", V->findable->work->genre->genre_name);
Works::write(OUT, V->findable->work);
if (VersionNumbers::is_any_range(V->findable->version_range) == FALSE) {
WRITE(", need version in range "); VersionNumbers::write_range(OUT, V->findable->version_range);
} else {
WRITE(", any version will do");
}
WRITE("\n");
depth++;
}
build_vertex *W;
@ -223,36 +232,43 @@ time_t Graphs::time_of_most_recent_used_resource(build_vertex *V) {
=
int Graphs::build(OUTPUT_STREAM, build_vertex *V, build_methodology *meth) {
return Graphs::build_r(OUT, BUILD_GB, V, meth);
int changes = 0;
return Graphs::build_r(OUT, BUILD_GB, V, meth, &changes);
}
int Graphs::rebuild(OUTPUT_STREAM, build_vertex *V, build_methodology *meth) {
return Graphs::build_r(OUT, BUILD_GB + FORCE_GB, V, meth);
int changes = 0;
return Graphs::build_r(OUT, BUILD_GB + FORCE_GB, V, meth, &changes);
}
int trace_ibg = FALSE;
int Graphs::build_r(OUTPUT_STREAM, int gb, build_vertex *V, build_methodology *meth) {
if (trace_ibg) { WRITE_TO(STDOUT, "Build: "); Graphs::describe(STDOUT, V, FALSE); }
int Graphs::build_r(OUTPUT_STREAM, int gb, build_vertex *V, build_methodology *meth, int *changes) {
if (trace_ibg) { WRITE_TO(STDOUT, "Visit: "); Graphs::describe(STDOUT, V, FALSE); }
if (V->built) return TRUE;
int changes_so_far = *changes;
STREAM_INDENT(STDOUT);
int rv = TRUE;
build_vertex *W;
LOOP_OVER_LINKED_LIST(W, build_vertex, V->build_edges)
if (rv)
rv = Graphs::build_r(OUT, gb | USE_GB, W, meth);
rv = Graphs::build_r(OUT, gb | USE_GB, W, meth, changes);
if (gb & USE_GB)
LOOP_OVER_LINKED_LIST(W, build_vertex, V->use_edges)
if (rv)
rv = Graphs::build_r(OUT, gb & (BUILD_GB + FORCE_GB), W, meth);
rv = Graphs::build_r(OUT, gb & (BUILD_GB + FORCE_GB), W, meth, changes);
STREAM_OUTDENT(STDOUT);
if (rv) {
int needs_building = FALSE;
if ((gb & FORCE_GB) || (V->force_this)) needs_building = TRUE;
else if ((V->type == GHOST_VERTEX) && (*changes > changes_so_far)) needs_building = TRUE;
else @<Decide based on timestamps@>;
if (needs_building) {
if (trace_ibg) { WRITE_TO(STDOUT, "Exec\n"); }
if (trace_ibg) { WRITE_TO(STDOUT, "Build: "); Graphs::describe(STDOUT, V, FALSE); }
(*changes)++;
rv = BuildScripts::execute(V, V->script, meth);
} else {
if (trace_ibg) { WRITE_TO(STDOUT, "No Build\n"); }
}
}
V->built = rv;

View file

@ -18,10 +18,10 @@ int Inform7Skill::inform7_via_shell(build_skill *skill, build_step *S, text_stre
Shell::quote_file(command, meth->to_inform7);
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include) {
WRITE_TO(command, "-kit %S ", K->as_copy->edition->work->title);
}
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
WRITE_TO(command, "-kit %S ", kd->kit->as_copy->edition->work->title);
WRITE_TO(command, "-format=%S ", TargetVMs::get_unblorbed_extension(S->for_vm));
inbuild_nest *N;

View file

@ -61,12 +61,11 @@ void PipelineManager::claim_as_copy(inbuild_genre *gen, inbuild_copy **C,
if (directory_status == TRUE) return;
if (Str::eq_insensitive(ext, I"interpipeline")) {
filename *F = Filenames::from_text(arg);
*C = PipelineManager::claim_file_as_copy(F, NULL, FALSE);
*C = PipelineManager::claim_file_as_copy(F, NULL);
}
}
inbuild_copy *PipelineManager::claim_file_as_copy(filename *F, text_stream *error_text,
int allow_malformed) {
inbuild_copy *PipelineManager::claim_file_as_copy(filename *F, text_stream *error_text) {
if (TextFiles::exists(F) == FALSE) return NULL;
semantic_version_number V = VersionNumbers::null();
TEMPORARY_TEXT(unext);
@ -94,8 +93,7 @@ void PipelineManager::search_nest_for(inbuild_genre *gen, inbuild_nest *N,
while (Directories::next(D, LEAFNAME)) {
if (Str::get_last_char(LEAFNAME) != FOLDER_SEPARATOR) {
filename *F = Filenames::in_folder(P, LEAFNAME);
inbuild_copy *C = PipelineManager::claim_file_as_copy(F, NULL,
req->allow_malformed);
inbuild_copy *C = PipelineManager::claim_file_as_copy(F, NULL);
if ((C) && (Requirements::meets(C->edition, req))) {
Nests::add_search_result(search_results, N, C, req);
}

View file

@ -248,7 +248,6 @@ easily be scrolled down off screen when the user first visits the page.
=
inform_extension *Extensions::Documentation::load(inbuild_work *work) {
inbuild_requirement *req = Requirements::any_version_of(work);
req->allow_malformed = TRUE;
inform_extension *E;
LOOP_OVER(E, inform_extension)

View file

@ -296,10 +296,8 @@ void Extensions::read_source_text_for(inform_extension *E) {
E->read_into_file->your_ref = STORE_POINTER_inbuild_copy(E->as_copy);
wording EXW = E->read_into_file->text_read;
if (Wordings::nonempty(EXW)) @<Break the extension's text into body and documentation@>;
#ifdef CORE_MODULE
inform_project *project = Inbuild::project();
if (project) E->syntax_tree = project->syntax_tree;
#endif
Sentences::break(E->syntax_tree, E->body_text, TRUE, E->as_copy, -1);
E->body_text_unbroken = FALSE;
}

View file

@ -153,7 +153,7 @@ int Kits::perform_ittt(inform_kit *K, inform_project *project, int parity) {
if ((ITTT->if_included == parity) &&
(Projects::uses_kit(project, ITTT->then_name) == FALSE) &&
(Projects::uses_kit(project, ITTT->if_name) == ITTT->if_included)) {
Projects::add_kit_dependency(project, ITTT->then_name);
Projects::add_kit_dependency(project, ITTT->then_name, NULL, K);
changes_made = TRUE;
}
return changes_made;
@ -248,7 +248,17 @@ void Kits::construct_graph(inform_kit *K) {
inbuild_requirement *req;
LOOP_OVER_LINKED_LIST(req, inbuild_requirement, K->extensions) {
build_vertex *EV = Graphs::req_vertex(req);
Graphs::need_this_to_use(KV, EV);
int found = FALSE;
inform_extension *E;
LOOP_OVER(E, inform_extension)
if (Requirements::meets(E->as_copy->edition, req)) {
Graphs::need_this_to_use(KV, E->as_copy->vertex);
found = TRUE;
break;
}
if (found == FALSE) {
build_vertex *RV = Graphs::req_vertex(req);
Graphs::need_this_to_use(KV, RV);
}
}
}

View file

@ -3,12 +3,19 @@
An Inform 7 project.
@ =
typedef struct kit_dependency {
struct inform_kit *kit;
struct inform_language *because_of_language;
struct inform_kit *because_of_kit;
MEMORY_MANAGEMENT
} kit_dependency;
typedef struct inform_project {
struct inbuild_copy *as_copy;
struct semantic_version_number version;
struct linked_list *source_vertices; /* of |build_vertex| */
int assumed_to_be_parser_IF;
struct linked_list *kits_to_include; /* of |inform_kit| */
struct linked_list *kits_to_include; /* of |kit_dependency| */
struct inform_language *language_of_play;
struct inform_language *language_of_syntax;
struct inform_language *language_of_index;
@ -25,7 +32,7 @@ inform_project *Projects::new_ip(text_stream *name, filename *F, pathname *P) {
project->as_copy = NULL;
project->version = VersionNumbers::null();
project->source_vertices = NEW_LINKED_LIST(build_vertex);
project->kits_to_include = NEW_LINKED_LIST(inform_kit);
project->kits_to_include = NEW_LINKED_LIST(kit_dependency);
project->assumed_to_be_parser_IF = TRUE;
project->language_of_play = NULL;
project->language_of_syntax = NULL;
@ -129,67 +136,70 @@ linked_list *Projects::source(inform_project *project) {
return project->source_vertices;
}
void Projects::add_kit_dependency(inform_project *project, text_stream *kit_name) {
void Projects::add_kit_dependency(inform_project *project, text_stream *kit_name,
inform_language *because_of_language, inform_kit *because_of_kit) {
RUN_ONLY_BEFORE_PHASE(OPERATIONAL_INBUILD_PHASE)
if (Projects::uses_kit(project, kit_name)) return;
linked_list *nest_list = Inbuild::nest_list();
inform_kit *kit = Kits::load(kit_name, nest_list);
ADD_TO_LINKED_LIST(kit, inform_kit, project->kits_to_include);
kit_dependency *kd = CREATE(kit_dependency);
kd->kit = Kits::load(kit_name, Inbuild::nest_list());
kd->because_of_language = because_of_language;
kd->because_of_kit = because_of_kit;
ADD_TO_LINKED_LIST(kd, kit_dependency, project->kits_to_include);
}
int Projects::uses_kit(inform_project *project, text_stream *name) {
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
if (Str::eq(K->as_copy->edition->work->title, name))
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if (Str::eq(kd->kit->as_copy->edition->work->title, name))
return TRUE;
return FALSE;
}
void Projects::finalise_kit_dependencies(inform_project *project) {
Projects::add_kit_dependency(project, I"BasicInformKit");
Projects::add_kit_dependency(project, I"BasicInformKit", NULL, NULL);
inform_language *L = project->language_of_play;
if (L) {
text_stream *kit_name = Languages::kit_name(L);
Projects::add_kit_dependency(project, kit_name);
Projects::add_kit_dependency(project, kit_name, L, NULL);
}
if (project->assumed_to_be_parser_IF)
Projects::add_kit_dependency(project, I"CommandParserKit");
Projects::add_kit_dependency(project, I"CommandParserKit", NULL, NULL);
int parity = TRUE;
@<Perform if-this-then-that@>;
parity = FALSE;
@<Perform if-this-then-that@>;
linked_list *sorted = NEW_LINKED_LIST(inform_kit);
linked_list *sorted = NEW_LINKED_LIST(kit_dependency);
for (int p=0; p<100; p++) {
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
if (K->priority == p)
ADD_TO_LINKED_LIST(K, inform_kit, sorted);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if (kd->kit->priority == p)
ADD_TO_LINKED_LIST(kd, kit_dependency, sorted);
}
project->kits_to_include = sorted;
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
LOG("Using Inform kit '%S' (priority %d).\n", K->as_copy->edition->work->title, K->priority);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
LOG("Using Inform kit '%S' (priority %d).\n", kd->kit->as_copy->edition->work->title, kd->kit->priority);
}
@<Perform if-this-then-that@> =
int changes_made = TRUE;
while (changes_made) {
changes_made = FALSE;
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
if (Kits::perform_ittt(K, project, parity))
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if (Kits::perform_ittt(kd->kit, project, parity))
changes_made = TRUE;
}
@ =
#ifdef CORE_MODULE
void Projects::load_types(inform_project *project) {
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
Kits::load_types(K);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
Kits::load_types(kd->kit);
}
#endif
@ -197,28 +207,28 @@ void Projects::load_types(inform_project *project) {
void Projects::activate_plugins(inform_project *project) {
LOG("Activate plugins...\n");
Plugins::Manage::activate(CORE_PLUGIN_NAME);
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
Kits::activate_plugins(K);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
Kits::activate_plugins(kd->kit);
Plugins::Manage::show(DL, "Included", TRUE);
Plugins::Manage::show(DL, "Excluded", FALSE);
}
#endif
int Projects::Main_defined(inform_project *project) {
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
if (K->defines_Main)
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if (kd->kit->defines_Main)
return TRUE;
return FALSE;
}
text_stream *Projects::index_template(inform_project *project) {
text_stream *I = NULL;
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
if (K->index_template)
I = K->index_template;
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if (kd->kit->index_template)
I = kd->kit->index_template;
return I;
}
@ -230,17 +240,17 @@ may be multiple sentences, which we need to count up.
=
void Projects::early_source_text(OUTPUT_STREAM, inform_project *project) {
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include)
Kits::early_source_text(OUT, K);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
Kits::early_source_text(OUT, kd->kit);
}
#ifdef CODEGEN_MODULE
linked_list *Projects::list_of_inter_libraries(inform_project *project) {
linked_list *requirements_list = NEW_LINKED_LIST(link_instruction);
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include) {
LOG("Okay so K is %S\n", K->as_copy->edition->work->title);
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include) {
inform_kit *K = kd->kit;
link_instruction *link = CodeGen::LinkInstructions::new(
K->as_copy->location_if_path, K->attachment_point);
ADD_TO_LINKED_LIST(link, link_instruction, requirements_list);
@ -289,41 +299,53 @@ void Projects::construct_build_target(inform_project *project, target_vm *VM,
BuildSteps::attach(project->blorbed_vertex, package_using_inblorb_skill,
Inbuild::nest_list(), releasing, VM, NULL, project->as_copy);
// inter_V->force_this = TRUE;
if (compile_only) {
project->chosen_build_target = inf_V;
inf_V->force_this = TRUE;
inter_V->force_this = TRUE;
} else if (releasing) project->chosen_build_target = project->blorbed_vertex;
else project->chosen_build_target = project->unblorbed_vertex;
}
void Projects::graph_dependent_kit(inform_project *project, build_vertex *V, kit_dependency *kd, int use) {
build_vertex *KV = kd->kit->as_copy->vertex;
if (use) Graphs::need_this_to_use(V, KV);
else Graphs::need_this_to_build(V, KV);
kit_dependency *kd2;
LOOP_OVER_LINKED_LIST(kd2, kit_dependency, project->kits_to_include)
if ((kd2->because_of_kit == kd->kit) && (kd2->because_of_language == NULL))
Projects::graph_dependent_kit(project, KV, kd2, TRUE);
}
void Projects::graph_dependent_language(inform_project *project, build_vertex *V, inform_language *L, int use) {
build_vertex *LV = L->as_copy->vertex;
if (use) Graphs::need_this_to_use(V, LV);
else Graphs::need_this_to_build(V, LV);
kit_dependency *kd2;
LOOP_OVER_LINKED_LIST(kd2, kit_dependency, project->kits_to_include)
if ((kd2->because_of_kit == NULL) && (kd2->because_of_language == L))
Projects::graph_dependent_kit(project, LV, kd2, TRUE);
}
void Projects::construct_graph(inform_project *project) {
RUN_ONLY_IN_PHASE(GOING_OPERATIONAL_INBUILD_PHASE)
if (project == NULL) return;
build_vertex *V = project->as_copy->vertex;
inform_kit *K;
LOOP_OVER_LINKED_LIST(K, inform_kit, project->kits_to_include) {
Graphs::need_this_to_build(V, K->as_copy->vertex);
}
build_vertex *S;
LOOP_OVER_LINKED_LIST(S, build_vertex, project->source_vertices) {
Graphs::need_this_to_build(V, S);
}
kit_dependency *kd;
LOOP_OVER_LINKED_LIST(kd, kit_dependency, project->kits_to_include)
if ((kd->because_of_kit == NULL) && (kd->because_of_language == NULL))
Projects::graph_dependent_kit(project, V, kd, FALSE);
inform_language *L = project->language_of_play;
if (L) {
build_vertex *LV = L->as_copy->vertex;
Graphs::need_this_to_build(V, LV);
}
if (L) Projects::graph_dependent_language(project, V, L, FALSE);
L = project->language_of_syntax;
if (L) {
build_vertex *LV = L->as_copy->vertex;
Graphs::need_this_to_build(V, LV);
}
if (L) Projects::graph_dependent_language(project, V, L, FALSE);
L = project->language_of_index;
if (L) {
build_vertex *LV = L->as_copy->vertex;
Graphs::need_this_to_build(V, LV);
}
if (L) Projects::graph_dependent_language(project, V, L, FALSE);
}
@
@ -335,13 +357,13 @@ void Projects::read_source_text_for(inform_project *project) {
Projects::finalise_kit_dependencies(project);
parse_node *inclusions_heading = ParseTree::new(HEADING_NT);
ParseTree::set_text(inclusions_heading, Feeds::feed_text_expanding_strings(L"Implied inclusions"));
ParseTree::set_text(inclusions_heading,
Feeds::feed_text_expanding_strings(L"Implied inclusions"));
ParseTree::insert_sentence(project->syntax_tree, inclusions_heading);
#ifdef CORE_MODULE
ParseTree::annotate_int(inclusions_heading, sentence_unparsed_ANNOT, FALSE);
ParseTree::annotate_int(inclusions_heading, heading_level_ANNOT, 0);
ParseTree::annotate_int(inclusions_heading, implied_heading_ANNOT, TRUE);
Headings::declare(project->syntax_tree, inclusions_heading);
#endif
int wc = lexer_wordcount, bwc = -1;
TEMPORARY_TEXT(early);
@ -376,11 +398,9 @@ void Projects::read_source_text_for(inform_project *project) {
parse_node *implicit_heading = ParseTree::new(HEADING_NT);
ParseTree::set_text(implicit_heading, Feeds::feed_text_expanding_strings(L"Invented sentences"));
ParseTree::insert_sentence(project->syntax_tree, implicit_heading);
#ifdef CORE_MODULE
ParseTree::annotate_int(implicit_heading, sentence_unparsed_ANNOT, FALSE);
ParseTree::annotate_int(implicit_heading, heading_level_ANNOT, 0);
Headings::declare(project->syntax_tree, implicit_heading);
#endif
ParseTree::pop_attachment_point(project->syntax_tree, l);
ParseTree::push_attachment_point(project->syntax_tree, implicit_heading);
@ -390,6 +410,10 @@ void Projects::read_source_text_for(inform_project *project) {
#endif
Inclusions::traverse(project->as_copy, project->syntax_tree);
Headings::satisfy_dependencies(project->syntax_tree, project->as_copy);
#ifndef CORE_MODULE
Copies::list_problems_arising(STDERR, project->as_copy);
#endif
}
@ It might seem sensible to parse the opening sentence of the source text,

View file

@ -29,18 +29,24 @@ void Inclusions::traverse(inbuild_copy *C, parse_node_tree *T) {
do {
includes_cleared = TRUE;
if (problem_count > 0) break;
parse_node *elder = NULL;
ParseTree::traverse_ppni(T, Inclusions::visit, &elder, &includes_cleared);
ParseTree::traverse_ppni(T, Inclusions::visit, &includes_cleared);
} while (includes_cleared == FALSE);
inclusions_errors_to = NULL;
}
void Inclusions::visit(parse_node_tree *T, parse_node *pn, parse_node **elder, int *includes_cleared) {
build_vertex *Inclusions::spawned_from_vertex(parse_node *H0) {
if (H0) {
inform_extension *ext = ParseTree::get_inclusion_of_extension(H0);
if (ext) return ext->as_copy->vertex;
}
if (inclusions_errors_to == NULL) internal_error("no H0 ext or inclusion");
return inclusions_errors_to->vertex;
}
void Inclusions::visit(parse_node_tree *T, parse_node *pn, parse_node *last_H0, int *includes_cleared) {
if (ParseTree::get_type(pn) == INCLUDE_NT) {
@<Replace INCLUDE node with sentence nodes for any extensions required@>;
*includes_cleared = FALSE;
} else if (ParseTree::get_type(pn) != ROOT_NT) {
*elder = pn;
}
}
@ -51,13 +57,19 @@ void Inclusions::visit(parse_node_tree *T, parse_node *pn, parse_node **elder, i
internal_error("malformed INCLUDE");
wording title = GET_RW(<structural-sentence>, 1);
wording author = GET_RW(<structural-sentence>, 2);
int l = ParseTree::begin_inclusion(T, pn);
inform_extension *E = Inclusions::fulfill_request_to_include_extension(title, author);
ParseTree::end_inclusion(T, l);
ParseTree::set_type(pn, INCLUSION_NT); pn->down = NULL;
int l = ParseTree::push_attachment_point(T, pn);
inform_extension *E = Inclusions::fulfill_request_to_include_extension(last_H0, title, author);
ParseTree::pop_attachment_point(T, l);
if (E) {
build_vertex *V = inclusions_errors_to->vertex;
build_vertex *EV = E->as_copy->vertex;
Graphs::need_this_to_build(V, EV);
for (parse_node *c = pn->down; c; c = c->next)
if (ParseTree::get_type(c) == HEADING_NT)
ParseTree::set_inclusion_of_extension(c, E);
if ((last_H0) && (ParseTree::int_annotation(last_H0, implied_heading_ANNOT) != TRUE)) {
build_vertex *V = Inclusions::spawned_from_vertex(last_H0);
build_vertex *EV = E->as_copy->vertex;
Graphs::need_this_to_build(V, EV);
}
}
@
@ -94,7 +106,6 @@ void Inclusions::visit(parse_node_tree *T, parse_node *pn, parse_node **elder, i
CE->error_subcategory = IncludeExtQuoted_SYNERROR;
CE->details_node = current_sentence;
Copies::attach(inclusions_errors_to, CE);
WRITE_TO(STDERR, "Listen %X!\n", inclusions_errors_to->edition->work);
@ This internal parses version text such as "12/110410".
@ -105,7 +116,7 @@ void Inclusions::visit(parse_node_tree *T, parse_node *pn, parse_node **elder, i
}
@ =
inform_extension *Inclusions::fulfill_request_to_include_extension(wording TW, wording AW) {
inform_extension *Inclusions::fulfill_request_to_include_extension(parse_node *last_H0, wording TW, wording AW) {
inform_extension *E = NULL;
<<t1>> = -1; <<t2>> = -1;
<extension-title-and-version>(TW);
@ -143,13 +154,13 @@ parse tree.
DISCARD_TEXT(exft);
DISCARD_TEXT(exfa);
E = Inclusions::load(current_sentence, req);
E = Inclusions::load(last_H0, current_sentence, req);
@h Extension loading.
Extensions are loaded here.
=
inform_extension *Inclusions::load(parse_node *at, inbuild_requirement *req) {
inform_extension *Inclusions::load(parse_node *last_H0, parse_node *at, inbuild_requirement *req) {
@<Do not load the same extension work twice@>;
inform_extension *E = NULL;
@ -178,7 +189,6 @@ can't know at load time what we will ultimately require.)
}
@<Read the extension file into the lexer, and break it into body and documentation@> =
req->allow_malformed = TRUE;
inbuild_search_result *search_result = Nests::first_found(req, Inbuild::nest_list());
if (search_result) {
E = ExtensionManager::from_copy(search_result->copy);
@ -194,13 +204,17 @@ can't know at load time what we will ultimately require.)
} else {
Copies::read_source_text_for(search_result->copy);
}
#ifdef CORE_MODULE
SourceProblems::issue_problems_arising(search_result->copy);
#endif
#ifndef CORE_MODULE
Copies::list_problems_arising(STDERR, search_result->copy);
#endif
} else @<Issue a cannot-find problem@>;
} else {
#ifdef CORE_MODULE
@<Issue a cannot-find problem@>;
#endif
build_vertex *RV = Graphs::req_vertex(req);
build_vertex *V = Inclusions::spawned_from_vertex(last_H0);
Graphs::need_this_to_build(V, RV);
}
@ Here the problem is not that the extension is broken in some way: it's
just not what we can currently use. Therefore the correction should be a

View file

@ -1,10 +1,10 @@
Inform 7.10.1 build 6Q21 has started.
I've now read your source text, which is 40 words long.
I've also read Basic Inform by Graham Nelson, which is 7645 words long.
I've also read Standard Rules by Graham Nelson, which is 32123 words long.
I've also read English Language by Graham Nelson, which is 2328 words long.
I've also read Standard Rules by Graham Nelson, which is 32123 words long.
Problem__ PM_HeadingInPlaceOfSubordinate
In Part 1 - The Discussing Action:
In Part Six - Grammar in the extension Standard Rules by Graham Nelson:
>--> In the sentence 'Section 1 - Greeting definitions (in place of Part Six
- Grammar in Standard Rules by Graham Nelson)' (source text, line 5), it
looks as if you intend to replace a section of source text from the
@ -13,4 +13,4 @@ In Part 1 - The Discussing Action:
(''Part 1 - The Discussing Action (in place of Part Six - Grammar in
Standard Rules by Graham Nelson)' (source text, line 3)') which is already
being replaced spliced into 'Standard Rules by Graham Nelson'.
Inform 7 has finished: 10 centiseconds used.
Inform 7 has finished.

View file

@ -48,6 +48,10 @@ int Task::carry_out(build_step *S) {
latest_syntax_tree = project->syntax_tree;
SourceProblems::issue_problems_arising(project->as_copy);
inform_extension *E;
LOOP_OVER(E, inform_extension)
SourceProblems::issue_problems_arising(E->as_copy);
if (problem_count > 0) return FALSE;
if (inform7_task) internal_error("cannot re-enter with new task");
@ -62,10 +66,10 @@ int Task::carry_out(build_step *S) {
inform7_task->stage_of_compilation = -1;
inform7_task->next_resource_number = 3;
inform_language *E = NaturalLanguages::English();
Projects::set_language_of_syntax(project, E);
Projects::set_language_of_index(project, E);
Projects::set_language_of_play(project, E);
inform_language *En = NaturalLanguages::English();
Projects::set_language_of_syntax(project, En);
Projects::set_language_of_index(project, En);
Projects::set_language_of_play(project, En);
int rv = Sequence::carry_out(TargetVMs::debug_enabled(inform7_task->task->for_vm));
inform7_task = NULL;

View file

@ -405,8 +405,10 @@ void ParseTreeUsage::write_permissions(void) {
ParseTree::allow_annotation_to_category(L1_NCAT, clears_pronouns_ANNOT);
ParseTree::allow_annotation(HEADING_NT, embodying_heading_ANNOT);
ParseTree::allow_annotation(HEADING_NT, inclusion_of_extension_ANNOT);
ParseTree::allow_annotation(HEADING_NT, interpretation_of_subject_ANNOT);
ParseTree::allow_annotation(HEADING_NT, suppress_heading_dependencies_ANNOT);
ParseTree::allow_annotation(HEADING_NT, implied_heading_ANNOT);
ParseTree::allow_annotation_to_category(L1_NCAT, module_ANNOT);
ParseTree::allow_annotation_to_category(L2_NCAT, clears_pronouns_ANNOT);

View file

@ -185,6 +185,8 @@ typedef struct parse_node_annotation {
@e sentence_unparsed_ANNOT /* int: set if verbs haven't been sought yet here */
@e suppress_heading_dependencies_ANNOT /* int: ignore extension dependencies on this heading node */
@e embodying_heading_ANNOT /* |heading|: for parse nodes of headings */
@e inclusion_of_extension_ANNOT /* |inform_extension|: for parse nodes of headings */
@e implied_heading_ANNOT /* int: set only for the heading of implied inclusions */
@d MAX_ANNOT_NUMBER (NO_DEFINED_ANNOT_VALUES+1)
@ -995,16 +997,21 @@ void ParseTree::traverse_from_ppn(parse_node *pn, void (*visitor)(parse_node *,
}
current_sentence = SCS;
}
void ParseTree::traverse_ppni(parse_node_tree *T, void (*visitor)(parse_node_tree *, parse_node *, parse_node **, int *), parse_node **X, int *N) {
ParseTree::traverse_from_ppni(T, T->root_node, visitor, X, N);
void ParseTree::traverse_ppni(parse_node_tree *T, void (*visitor)(parse_node_tree *, parse_node *, parse_node *, int *), int *N) {
ParseTree::traverse_from_ppni(T, T->root_node, visitor, NULL, N);
}
void ParseTree::traverse_from_ppni(parse_node_tree *T, parse_node *pn, void (*visitor)(parse_node_tree *, parse_node *, parse_node **, int *), parse_node **X, int *N) {
void ParseTree::traverse_from_ppni(parse_node_tree *T, parse_node *pn, void (*visitor)(parse_node_tree *, parse_node *, parse_node *, int *), parse_node *last_h0, int *N) {
parse_node *SCS = current_sentence;
for (; pn; pn = pn->next) {
if (ParseTree::top_level(pn->node_type)) ParseTree::traverse_from_ppni(T, pn->down, visitor, X, N);
if (ParseTree::top_level(pn->node_type)) {
parse_node *H0 = last_h0;
if ((ParseTree::is(pn, HEADING_NT)) && (ParseTree::int_annotation(pn, heading_level_ANNOT) == 0))
H0 = pn;
ParseTree::traverse_from_ppni(T, pn->down, visitor, H0, N);
}
if (ParseTree::visitable(pn->node_type)) {
if (SENTENCE_NODE(pn->node_type)) current_sentence = pn;
(*visitor)(T, pn, X, N);
(*visitor)(T, pn, last_h0, N);
}
}
current_sentence = SCS;
@ -1364,15 +1371,3 @@ void ParseTree::add_single_pr_inv(parse_node *E, parse_node *N) {
E->next_alternative = N; N->next_alternative = NULL;
}
#endif
@h Handling an inclusion.
=
int ParseTree::begin_inclusion(parse_node_tree *T, parse_node *pn) {
ParseTree::set_type(pn, INCLUSION_NT); pn->down = NULL;
return ParseTree::push_attachment_point(T, pn);
}
void ParseTree::end_inclusion(parse_node_tree *T, int l) {
ParseTree::pop_attachment_point(T, l);
}