From 0c0c148830c121488e1b5d45783733ca35f564ba Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Sat, 20 Jul 2019 12:40:27 +0100 Subject: [PATCH] Added interpipeline files --- docs/codegen-module/1-ppl.html | 120 ++++-- docs/codegen-module/1-stg.html | 12 + docs/codegen-module/2-alm.html | 3 - docs/codegen-module/4-cg.html | 1 + docs/core-module/1-mr.html | 56 ++- docs/core-module/1-wel.html | 8 + docs/core-module/26-uo.html | 10 +- docs/inter/1-bsc.html | 2 +- docs/inter/1-mn.html | 78 ++-- docs/inter/P-cas.html | 281 ------------ docs/inter/P-io.html | 2 +- docs/inter/P-pas.html | 400 ++++++++++++++++++ docs/inter/P-ui.html | 77 ++-- docs/inter/index.html | 4 +- inform7/Internal/Inter/default.interpipeline | 8 + inform7/Tests/Test Inter/Luna.txt | 42 -- inform7/Tests/inform7.intest | 70 +-- inform7/Tests/test-pl.interpipeline | 8 + inform7/core-module/Chapter 1/Main Routine.w | 54 ++- .../Chapter 1/Where Everything Lives.w | 8 + inform7/core-module/Chapter 26/Use Options.w | 10 +- inter/.gitignore | 14 +- inter/Chapter 1/Main.w | 78 ++-- inter/Contents.w | 2 +- inter/Preliminaries/Chains and Stages.w | 182 -------- inter/Preliminaries/Pipelines and Stages.w | 238 +++++++++++ inter/Preliminaries/Using Inter.w | 49 ++- .../{Assimilate => General}/Assim.intert | 0 .../{Generations => General}/Cons.intert | 0 inter/Tests/{RCC => General}/EasyRCC.intert | 0 inter/Tests/{RCC => General}/IftrueRCC.intert | 0 .../{Generations => General}/ObjKind.intert | 0 inter/Tests/{PLM => General}/PLM.intert | 0 .../Predeclared.intert | 0 .../Primitives.intert | 0 .../{ERL => General}/Redundancies.intert | 0 .../SimpleKind.intert | 0 .../SimpleRoutines.intert | 0 .../General/_Pipelines/Assim.interpipeline | 5 + .../General/_Pipelines/Cons.interpipeline | 5 + .../General/_Pipelines/EasyRCC.interpipeline | 4 + .../_Pipelines/IftrueRCC.interpipeline | 4 + .../General/_Pipelines/ObjKind.interpipeline | 5 + .../General/_Pipelines/PLM.interpipeline | 3 + .../_Pipelines/Predeclared.interpipeline | 5 + .../_Pipelines/Primitives.interpipeline | 5 + .../_Pipelines/Redundancies.interpipeline | 3 + .../_Pipelines/SimpleKind.interpipeline | 5 + .../_Pipelines/SimpleRoutines.interpipeline | 5 + .../_Results_Ideal/Assim.txt | 0 .../_Results_Ideal/Cons.txt | 0 .../_Results_Ideal/EasyRCC.txt | 0 .../_Results_Ideal/IftrueRCC.txt | 0 .../_Results_Ideal/ObjKind.txt | 0 .../{PLM => General}/_Results_Ideal/PLM.txt | 0 .../_Results_Ideal/Predeclared.txt | 0 .../_Results_Ideal/Primitives.txt | 0 .../_Results_Ideal/Redundancies.txt | 0 .../_Results_Ideal/SimpleKind.txt | 0 .../_Results_Ideal/SimpleRoutines.txt | 0 inter/Tests/inter.intest | 95 +---- inter/codegen-module/Chapter 1/Pipelines.w | 108 +++-- inter/codegen-module/Chapter 1/Stages.w | 10 + inter/codegen-module/Chapter 2/Assimilate.w | 3 - .../Chapter 4/Code Generation.w | 1 + inter/gitignorescript.txt | 14 +- scripts/makescript.txt | 30 +- 67 files changed, 1205 insertions(+), 922 deletions(-) delete mode 100644 docs/inter/P-cas.html create mode 100644 docs/inter/P-pas.html create mode 100644 inform7/Internal/Inter/default.interpipeline delete mode 100644 inform7/Tests/Test Inter/Luna.txt create mode 100644 inform7/Tests/test-pl.interpipeline delete mode 100644 inter/Preliminaries/Chains and Stages.w create mode 100644 inter/Preliminaries/Pipelines and Stages.w rename inter/Tests/{Assimilate => General}/Assim.intert (100%) rename inter/Tests/{Generations => General}/Cons.intert (100%) rename inter/Tests/{RCC => General}/EasyRCC.intert (100%) rename inter/Tests/{RCC => General}/IftrueRCC.intert (100%) rename inter/Tests/{Generations => General}/ObjKind.intert (100%) rename inter/Tests/{PLM => General}/PLM.intert (100%) rename inter/Tests/{Generations => General}/Predeclared.intert (100%) rename inter/Tests/{Generations => General}/Primitives.intert (100%) rename inter/Tests/{ERL => General}/Redundancies.intert (100%) rename inter/Tests/{Generations => General}/SimpleKind.intert (100%) rename inter/Tests/{Generations => General}/SimpleRoutines.intert (100%) create mode 100644 inter/Tests/General/_Pipelines/Assim.interpipeline create mode 100644 inter/Tests/General/_Pipelines/Cons.interpipeline create mode 100644 inter/Tests/General/_Pipelines/EasyRCC.interpipeline create mode 100644 inter/Tests/General/_Pipelines/IftrueRCC.interpipeline create mode 100644 inter/Tests/General/_Pipelines/ObjKind.interpipeline create mode 100644 inter/Tests/General/_Pipelines/PLM.interpipeline create mode 100644 inter/Tests/General/_Pipelines/Predeclared.interpipeline create mode 100644 inter/Tests/General/_Pipelines/Primitives.interpipeline create mode 100644 inter/Tests/General/_Pipelines/Redundancies.interpipeline create mode 100644 inter/Tests/General/_Pipelines/SimpleKind.interpipeline create mode 100644 inter/Tests/General/_Pipelines/SimpleRoutines.interpipeline rename inter/Tests/{Assimilate => General}/_Results_Ideal/Assim.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/Cons.txt (100%) rename inter/Tests/{RCC => General}/_Results_Ideal/EasyRCC.txt (100%) rename inter/Tests/{RCC => General}/_Results_Ideal/IftrueRCC.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/ObjKind.txt (100%) rename inter/Tests/{PLM => General}/_Results_Ideal/PLM.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/Predeclared.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/Primitives.txt (100%) rename inter/Tests/{ERL => General}/_Results_Ideal/Redundancies.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/SimpleKind.txt (100%) rename inter/Tests/{Generations => General}/_Results_Ideal/SimpleRoutines.txt (100%) diff --git a/docs/codegen-module/1-ppl.html b/docs/codegen-module/1-ppl.html index eb100be51..9a925241a 100644 --- a/docs/codegen-module/1-ppl.html +++ b/docs/codegen-module/1-ppl.html @@ -30,6 +30,7 @@ have no meaningful contents when the step is not running. struct pathname **the_PP; int the_N; int to_debugging_log; + int repository_argument; struct text_stream *text_out_file; struct inter_repository *repository; MEMORY_MANAGEMENT @@ -40,6 +41,7 @@ have no meaningful contents when the step is not running. step->step_stage = NULL; step->step_argument = NULL; step->package_argument = NULL; + step->repository_argument = -1; CodeGen::Pipeline::clean_step(step); return step; } @@ -49,7 +51,7 @@ have no meaningful contents when the step is not running.

The function CodeGen::Pipeline::new_step is used in §3.

-

The structure pipeline_step is accessed in 2/lnk, 2/plm, 2/rcc, 2/alm, 2/res, 2/unq, 2/rv, 2/erm, 2/erl, 4/cg, 5/fti, 5/fbi, 5/fi and here.

+

The structure pipeline_step is accessed in 1/stg, 2/lnk, 2/plm, 2/rcc, 2/alm, 2/res, 2/unq, 2/rv, 2/erm, 2/erl, 4/cg, 5/fti, 5/fbi, 5/fi and here.

§2. This wipes clean the temporary storage for a step.

@@ -81,18 +83,22 @@ logging: if (step->step_stage->stage_arg != NO_STAGE_ARG) { if (step->package_argument) WRITE(" %S", step->package_argument); WRITE(":"); + if (step->repository_argument >= 0) WRITE(" %d <-", step->repository_argument); if (step->target_argument) WRITE(" %S ->", step->target_argument->target_name); WRITE(" %S", step->step_argument); } } - pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, text_stream *leafname) { + pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, dictionary *D) { CodeGen::Stage::make_stages(); CodeGen::Targets::make_targets(); pipeline_step *ST = CodeGen::Pipeline::new_step(); match_results mr = Regexp::create_mr(); - if (Regexp::match(&mr, step, L"(%c+?) *: *(%C*) *-> *(%c*)")) { - ST->step_argument = Str::new(); + if (Regexp::match(&mr, step, L"(%c+?) *: *(%d) *<- *(%c*)")) { + ST->repository_argument = Str::atoi(mr.exp[1], 0); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[2], D); + Str::copy(step, mr.exp[0]); + } else if (Regexp::match(&mr, step, L"(%c+?) *: *(%C*) *-> *(%c*)")) { code_generation_target *cgt; LOOP_OVER(cgt, code_generation_target) if (Str::eq(mr.exp[1], cgt->target_name)) @@ -101,18 +107,14 @@ logging: WRITE_TO(STDERR, "No such code generation target as '%S'\n", mr.exp[1]); internal_error("no such target"); } - Str::copy(ST->step_argument, mr.exp[2]); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[2], D); Str::copy(step, mr.exp[0]); - if (Str::eq(ST->step_argument, I"*")) Str::copy(ST->step_argument, leafname); } else if (Regexp::match(&mr, step, L"(%c+?) *: *(%c*)")) { - ST->step_argument = Str::new(); - Str::copy(ST->step_argument, mr.exp[1]); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[1], D); Str::copy(step, mr.exp[0]); - if (Str::eq(ST->step_argument, I"*")) Str::copy(ST->step_argument, leafname); } if (Regexp::match(&mr, step, L"(%C+?) (%c+)")) { - ST->package_argument = Str::new(); - Str::copy(ST->package_argument, mr.exp[1]); + ST->package_argument = CodeGen::Pipeline::read_parameter(mr.exp[1], D); Str::copy(step, mr.exp[0]); } @@ -127,6 +129,16 @@ logging: Regexp::dispose_of(&mr); return ST; } + + text_stream *CodeGen::Pipeline::read_parameter(text_stream *from, dictionary *D) { + if (Str::get_first_char(from) == '*') { + text_stream *find = Dictionaries::get_text(D, from); + if (find) return Str::duplicate(find); + WRITE_TO(STDERR, "No such pipeline variable as '%S'\n", from); + internal_error("no such pipeline variable"); + } + return Str::duplicate(from); + }

@@ -135,31 +147,58 @@ logging:

The function CodeGen::Pipeline::read_step is used in §4.

+

The function CodeGen::Pipeline::read_parameter appears nowhere else.

+

§4. Pipelines. And then a pipeline is just a linked list of steps.

     typedef struct codegen_pipeline {
+        struct dictionary *variables;
+        struct inter_repository *repositories[10];
         struct linked_list *steps;     of pipeline_step
         MEMORY_MANAGEMENT
     } codegen_pipeline;
 
-    codegen_pipeline *CodeGen::Pipeline::new(void) {
+    dictionary *CodeGen::Pipeline::basic_dictionary(text_stream *leafname) {
+        dictionary *D = Dictionaries::new(16, TRUE);
+        if (Str::len(leafname) > 0) Str::copy(Dictionaries::create_text(D, I"*out"), leafname);
+        Str::copy(Dictionaries::create_text(D, I"*log"), I"*log");
+        return D;
+    }
+
+    codegen_pipeline *CodeGen::Pipeline::new(dictionary *D) {
         codegen_pipeline *S = CREATE(codegen_pipeline);
+        S->variables = D;
         S->steps = NEW_LINKED_LIST(pipeline_step);
+        for (int i=0; i<10; i++) S->repositories[i] = NULL;
         return S;
     }
 
-    codegen_pipeline *CodeGen::Pipeline::parse(text_stream *instructions, text_stream *leafname) {
-        codegen_pipeline *S = CodeGen::Pipeline::new();
-        CodeGen::Pipeline::parse_into(S, instructions, leafname);
+    codegen_pipeline *CodeGen::Pipeline::parse_from_file(filename *F, dictionary *D) {
+        TEMPORARY_TEXT(A);
+        TextFiles::read(F, FALSE, "can't open inter pipeline file",
+            TRUE, CodeGen::Pipeline::scan_line, NULL, (void *) A);
+        codegen_pipeline *S = CodeGen::Pipeline::new(D);
+        CodeGen::Pipeline::parse_into(S, A);
+        DISCARD_TEXT(A);
         return S;
     }
 
-    void CodeGen::Pipeline::parse_into(codegen_pipeline *S, text_stream *instructions, text_stream *leafname) {
-        if (instructions == NULL)
-            instructions = I"link:Output.i6t, parse-linked-matter, resolve-conditional-compilation, assimilate, reconcile-verbs, generate: inform6 -> *";
+    void CodeGen::Pipeline::scan_line(text_stream *line, text_file_position *tfp, void *X) {
+        text_stream *A = (text_stream *) X;
+        if (Str::len(A) > 0) WRITE_TO(A, ", ");
+        WRITE_TO(A, "%S", line);
+    }
+
+    codegen_pipeline *CodeGen::Pipeline::parse(text_stream *instructions, dictionary *D) {
+        codegen_pipeline *S = CodeGen::Pipeline::new(D);
+        CodeGen::Pipeline::parse_into(S, instructions);
+        return S;
+    }
+
+    void CodeGen::Pipeline::parse_into(codegen_pipeline *S, text_stream *instructions) {
         TEMPORARY_TEXT(T);
         LOOP_THROUGH_TEXT(P, instructions)
             if (Characters::is_babel_whitespace(Str::get(P)))
@@ -167,30 +206,35 @@ logging:
             else
                 PUT_TO(T, Str::get(P));
         match_results mr = Regexp::create_mr();
-        while (Regexp::match(&mr, T, L" *(%c+?) *, *(%c*?) *")) {
-            pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], leafname);
-            ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps);
+        while (Regexp::match(&mr, T, L" *(%c+?) *,+ *(%c*?) *")) {
+            pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], S->variables);
+            if (ST) ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps);
             Str::copy(T, mr.exp[1]);
         }
         if (Regexp::match(&mr, T, L" *(%c+?) *")) {
-            pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], leafname);
-            ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps);
+            pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], S->variables);
+            if (ST) ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps);
         }
     }
 
-    void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, inter_repository *I, int N, pathname **PP, pathname *PM, pathname *FM) {
-        if (S == NULL) return;
-        clock_t start = clock();
+    void CodeGen::Pipeline::set_repository(codegen_pipeline *S, inter_repository *I) {
+        S->repositories[0] = I;
+    }
 
-        CodeGen::Pipeline::prepare_to_run(I);
+    void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, int N, pathname **PP) {
+        if (S == NULL) return;
+        if (S->repositories[0] == NULL) S->repositories[0] = Inter::create(1, 32);
+        clock_t start = clock();
 
         int step_count = 0, step_total = 0;
         pipeline_step *step;
         LOOP_OVER_LINKED_LIST(step, pipeline_step, S->steps) step_total++;
 
-        int active = TRUE;
+        int active = TRUE, current_repo = 0;
+        CodeGen::Pipeline::prepare_to_run(S->repositories[current_repo]);
         LOOP_OVER_LINKED_LIST(step, pipeline_step, S->steps)
             if (active) {
+                inter_repository *I = S->repositories[current_repo];
                 CodeGen::Pipeline::lint(I);
 
                 CodeGen::Pipeline::clean_step(step);
@@ -209,18 +253,17 @@ logging:
                     (step->step_stage->stage_arg == TEXT_OUT_STAGE_ARG) ||
                     (step->step_stage->stage_arg == EXT_FILE_STAGE_ARG) ||
                     (step->step_stage->stage_arg == EXT_TEXT_OUT_STAGE_ARG)) {
-                    if (Str::eq(step->step_argument, I"log")) {
+                    if (Str::eq(step->step_argument, I"*log")) {
                         step->to_debugging_log = TRUE;
                     } else {
+                        step->parsed_filename = Filenames::from_text(step->step_argument);
                         int slashes = FALSE;
                         LOOP_THROUGH_TEXT(pos, step->step_argument)
                             if (Str::get(pos) == '/')
                                 slashes = TRUE;
                         if (slashes) step->parsed_filename = Filenames::from_text(step->step_argument);
-                        else if ((step->step_stage->stage_arg == EXT_FILE_STAGE_ARG) ||
-                                (step->step_stage->stage_arg == EXT_TEXT_OUT_STAGE_ARG))
-                            step->parsed_filename = Filenames::in_folder(FM, step->step_argument);
                         else step->parsed_filename = Filenames::in_folder(P, step->step_argument);
+                        LOG("Parsed %S == %f\n", step->step_argument, step->parsed_filename);
                     }
                 }
 
@@ -249,18 +292,31 @@ logging:
                     (step->to_debugging_log == FALSE)) {
                     STREAM_CLOSE(T);
                 }
+
+                if (step->repository_argument >= 0) {
+                    current_repo = step->repository_argument;
+                    CodeGen::Pipeline::prepare_to_run(S->repositories[current_repo]);
+                }
             }
     }
 

+

The function CodeGen::Pipeline::basic_dictionary appears nowhere else.

+

The function CodeGen::Pipeline::new appears nowhere else.

+

The function CodeGen::Pipeline::parse_from_file appears nowhere else.

+ +

The function CodeGen::Pipeline::scan_line appears nowhere else.

+

The function CodeGen::Pipeline::parse appears nowhere else.

The function CodeGen::Pipeline::parse_into appears nowhere else.

+

The function CodeGen::Pipeline::set_repository appears nowhere else.

+

The function CodeGen::Pipeline::run appears nowhere else.

The structure codegen_pipeline is private to this section.

diff --git a/docs/codegen-module/1-stg.html b/docs/codegen-module/1-stg.html index 59f49e6a5..ac100b8a6 100644 --- a/docs/codegen-module/1-stg.html +++ b/docs/codegen-module/1-stg.html @@ -63,6 +63,7 @@ to the routine below. if (stages_made == FALSE) { stages_made = TRUE; CodeGen::Stage::new(I"stop", CodeGen::Stage::run_stop_stage, NO_STAGE_ARG); + CodeGen::Stage::new(I"read", CodeGen::Stage::run_read_stage, FILE_STAGE_ARG); CodeGen::create_pipeline_stage(); CodeGen::Assimilate::create_pipeline_stage(); @@ -91,12 +92,23 @@ the pipeline: int CodeGen::Stage::run_stop_stage(pipeline_step *step) { return FALSE; } + + int CodeGen::Stage::run_read_stage(pipeline_step *step) { + filename *F = Filenames::from_text(step->step_argument); + if (Inter::Binary::test_file(F)) + Inter::Binary::read(step->repository, F); + else + Inter::Textual::read(step->repository, F); + return TRUE; + }

The function CodeGen::Stage::run_stop_stage is used in §2.

+

The function CodeGen::Stage::run_read_stage is used in §2.

+

diff --git a/docs/codegen-module/2-alm.html b/docs/codegen-module/2-alm.html index 8e6a1266b..2fc6668f7 100644 --- a/docs/codegen-module/2-alm.html +++ b/docs/codegen-module/2-alm.html @@ -201,9 +201,6 @@ text_stream *suffix = NULL; inter_symbol *subpackage_type = plain_packagetype; - if (plm == ATTRIBUTE_PLM) trace_AME = TRUE; - else trace_AME = FALSE; - switch (plm) { case VERB_PLM: if (command_ptype_symbol) subpackage_type = command_ptype_symbol; diff --git a/docs/codegen-module/4-cg.html b/docs/codegen-module/4-cg.html index 927d0d542..b22b14c44 100644 --- a/docs/codegen-module/4-cg.html +++ b/docs/codegen-module/4-cg.html @@ -37,6 +37,7 @@ internal_error("that's not a package name"); } } + code_generation *gen = CodeGen::new_generation(step, step->repository, which, step->target_argument); if (CodeGen::Targets::begin_generation(gen) == FALSE) { diff --git a/docs/core-module/1-mr.html b/docs/core-module/1-mr.html index 9870928c4..8ba1fc202 100644 --- a/docs/core-module/1-mr.html +++ b/docs/core-module/1-mr.html @@ -87,7 +87,8 @@ Inform 6 code is complete.
     int report_clock_time = FALSE;
     time_t right_now;
-    text_stream *inter_processing_chain = NULL;
+    text_stream *inter_processing_file = NULL;
+    text_stream *inter_processing_pipeline = NULL;
     pathname *path_to_inform7 = NULL;
 
     int CoreMain::main(int argc, char *argv[]) {
@@ -138,7 +139,7 @@ Inform 6 code is complete.
 
         Errors::set_internal_handler(&Problems::Issue::internal_error_fn);
         story_filename_extension = I"ulx";
-        inter_processing_chain = I"link: Output.i6t, parse-linked-matter, resolve-conditional-compilation, assimilate, make-identifiers-unique, resolve-external-symbols, reconcile-verbs, generate: inform6 -> *";
+        inter_processing_pipeline = Str::new();
 
         PRINT("%B build %B has started.\n", FALSE, TRUE);
         STREAM_FLUSH(STDOUT);
@@ -171,7 +172,8 @@ list is not exhaustive.
     enum RNG_CLSW
     enum SIGILS_CLSW
     enum TRANSIENT_CLSW
-    enum INTER_CLSW
+    enum PIPELINE_CLSW
+    enum PIPELINE_FILE_CLSW
 

§4.3. <Register command-line arguments 4.3> = @@ -207,8 +209,10 @@ list is not exhaustive. L"make any source links refer to the source in extension example X"); CommandLine::declare_switch(REQUIRE_PROBLEM_CLSW, L"require-problem", 2, L"return 0 unless exactly this Problem message is generated (for testing)"); - CommandLine::declare_switch(INTER_CLSW, L"inter", 2, - L"specify code-generation chain for inter code"); + CommandLine::declare_switch(PIPELINE_CLSW, L"pipeline", 2, + L"specify code-generation pipeline"); + CommandLine::declare_switch(PIPELINE_FILE_CLSW, L"pipeline-file", 2, + L"specify code-generation pipeline from file X"); CommandLine::declare_switch(PROJECT_CLSW, L"project", 2, L"work within the Inform project X"); @@ -568,13 +572,28 @@ list is not exhaustive. LOG("Front end elapsed time: %dcs\n", ((int) (front_end - start)) / (CLOCKS_PER_SEC/100)); CoreMain::go_to_log_phase(I"Converting inter to Inform 6"); if (existing_story_file == FALSE) { - codegen_pipeline *SS = CodeGen::Pipeline::new(); - CodeGen::Pipeline::parse_into(SS, inter_processing_chain, + dictionary *D = CodeGen::Pipeline::basic_dictionary( Filenames::get_leafname(filename_of_compiled_i6_code)); + codegen_pipeline *SS = NULL; + if (inter_processing_file) + SS = CodeGen::Pipeline::parse_from_file(Filenames::from_text(inter_processing_file), D); + else if (Str::len(inter_processing_pipeline) > 0) + SS = CodeGen::Pipeline::parse(inter_processing_pipeline, D); + else { + for (int area=0; area<NO_FS_AREAS; area++) { + pathname *P = pathname_of_inter_resources[area]; + filename *F = Filenames::in_folder(P, I"default.interpipeline"); + LOG("Trying %f\n", F); + if (TextFiles::exists(F)) { + SS = CodeGen::Pipeline::parse_from_file(F, D); + break; + } + } + } + if (SS == NULL) internal_error("no inter pipeline could be found"); + CodeGen::Pipeline::set_repository(SS, Emit::repository()); CodeGen::Pipeline::run(Filenames::get_path_to(filename_of_compiled_i6_code), - SS, Emit::repository(), NO_FS_AREAS, pathname_of_i6t_files, - pathname_of_i6t_files[INTERNAL_FS_AREA], - pathname_of_i6t_files[INTERNAL_FS_AREA]); + SS, NO_FS_AREAS, pathname_of_i6t_files); } LOG("Back end elapsed time: %dcs\n", ((int) (clock() - front_end)) / (CLOCKS_PER_SEC/100)); } @@ -693,7 +712,8 @@ list is not exhaustive. case FORMAT_CLSW: story_filename_extension = Str::duplicate(arg); break; case CASE_CLSW: HTMLFiles::set_source_link_case(arg); break; case REQUIRE_PROBLEM_CLSW: Problems::Fatal::require(arg); break; - case INTER_CLSW: inter_processing_chain = Str::duplicate(arg); break; + case PIPELINE_CLSW: inter_processing_pipeline = Str::duplicate(arg); break; + case PIPELINE_FILE_CLSW: inter_processing_file = Str::duplicate(arg); break; Useful pathnames case PROJECT_CLSW: Locations::set_project(arg); break; @@ -714,12 +734,12 @@ list is not exhaustive. disable_import = TRUE; } - void CoreMain::set_inter_chain(wording W) { - inter_processing_chain = Str::new(); - WRITE_TO(inter_processing_chain, "%W", W); - Str::delete_first_character(inter_processing_chain); - Str::delete_last_character(inter_processing_chain); - LOG("Setting chain %S\n", inter_processing_chain); + void CoreMain::set_inter_pipeline(wording W) { + inter_processing_pipeline = Str::new(); + WRITE_TO(inter_processing_pipeline, "%W", W); + Str::delete_first_character(inter_processing_pipeline); + Str::delete_last_character(inter_processing_pipeline); + LOG("Setting pipeline %S\n", inter_processing_pipeline); }

@@ -731,7 +751,7 @@ list is not exhaustive.

The function CoreMain::disable_importation is used in 7/hdn (§10.2).

-

The function CoreMain::set_inter_chain is used in 26/uo (§11.2).

+

The function CoreMain::set_inter_pipeline is used in 26/uo (§11.2).



diff --git a/docs/core-module/1-wel.html b/docs/core-module/1-wel.html index 1a8421dbd..bb41719a1 100644 --- a/docs/core-module/1-wel.html +++ b/docs/core-module/1-wel.html @@ -44,6 +44,7 @@ not here. First, some "areas": pathname *pathname_of_area[NO_FS_AREAS] = { NULL, NULL, NULL }; pathname *pathname_of_extensions[NO_FS_AREAS] = { NULL, NULL, NULL }; pathname *pathname_of_i6t_files[NO_FS_AREAS] = { NULL, NULL, NULL }; + pathname *pathname_of_inter_resources[NO_FS_AREAS] = { NULL, NULL, NULL }; pathname *pathname_of_languages[NO_FS_AREAS] = { NULL, NULL, NULL }; pathname *pathname_of_website_templates[NO_FS_AREAS] = { NULL, NULL, NULL }; @@ -75,6 +76,7 @@ not here. First, some "areas": filename *filename_of_cblorb_report_model = NULL; filename *filename_of_compiled_i6_code = NULL; filename *filename_of_debugging_log = NULL; + filename *filename_of_default_inter_pipeline = NULL; filename *filename_of_documentation_snippets = NULL; filename *filename_of_epsfile = NULL; filename *filename_of_existing_story_file = NULL; @@ -219,6 +221,11 @@ example, live inside the Extensions part of this. Locations::EILT_at(INTERNAL_FS_AREA, pathname_of_area[INTERNAL_FS_AREA]); + pathname *inter_resources = + Pathnames::subfolder(pathname_of_area[INTERNAL_FS_AREA], I"Inter"); + filename_of_default_inter_pipeline = + Filenames::in_folder(inter_resources, I"default.interpipeline"); + <Miscellaneous other stuff 6.1.1>; @@ -710,6 +717,7 @@ template files, language definitions and website templates. pathname_of_i6t_files[area] = Pathnames::subfolder(P, I"I6T"); pathname_of_languages[area] = Pathnames::subfolder(P, I"Languages"); pathname_of_website_templates[area] = Pathnames::subfolder(P, I"Templates"); + pathname_of_inter_resources[area] = Pathnames::subfolder(P, I"Inter"); } diff --git a/docs/core-module/26-uo.html b/docs/core-module/26-uo.html index 61bc096e4..4a67b9f9c 100644 --- a/docs/core-module/26-uo.html +++ b/docs/core-module/26-uo.html @@ -214,8 +214,8 @@ option name is taken from the ...<definite-article> ... | ==> 0 ... ==> 0 - <use-inter-chain> ::= - inter chain {<quoted-text>} ==> TRUE + <use-inter-pipeline> ::= + inter pipeline {<quoted-text>} ==> TRUE

@@ -292,7 +292,7 @@ there is no need to translate this to other languages.) UseOptions::set_use_options(p->down->next); return; } - if (<use-inter-chain>(ParseTree::get_text(p))) <Set the chain given in this word range 11.2> + if (<use-inter-pipeline>(ParseTree::get_text(p))) <Set the chain given in this word range 11.2> else if (<use-sentence-object>(ParseTree::get_text(p))) <Set the option given in this word range 11.1>; if (traverse == 1) return; LOG("Used: %W\n", ParseTree::get_text(p)); @@ -349,8 +349,8 @@ there is no need to translate this to other languages.)
-        wording CW = GET_RW(<use-inter-chain>, 1);
-        if (traverse == 1) CoreMain::set_inter_chain(CW);
+        wording CW = GET_RW(<use-inter-pipeline>, 1);
+        if (traverse == 1) CoreMain::set_inter_pipeline(CW);
         return;
 
diff --git a/docs/inter/1-bsc.html b/docs/inter/1-bsc.html index 1bd0a8118..a7ae84195 100644 --- a/docs/inter/1-bsc.html +++ b/docs/inter/1-bsc.html @@ -1,7 +1,7 @@ - P/cas + P/pas diff --git a/docs/inter/1-mn.html b/docs/inter/1-mn.html index 284109fb4..472689bb3 100644 --- a/docs/inter/1-mn.html +++ b/docs/inter/1-mn.html @@ -19,13 +19,24 @@
     enum TEXTUAL_CLSW
     enum BINARY_CLSW
-    enum INTER_CLSW
+    enum PIPELINE_CLSW
+    enum PIPELINE_FILE_CLSW
+    enum PIPELINE_VARIABLE_CLSW
     enum DOMAIN_CLSW
     enum TEMPLATE_CLSW
     enum TEST_CLSW
 
+    pathname *template_path = NULL;
+    pathname *domain_path = NULL;
+    filename *output_textually = NULL;
+    filename *output_binarily = NULL;
+    filename *unit_test_file = NULL;
+    dictionary *pipeline_vars = NULL;
+    filename *pipeline_as_file = NULL;
+    text_stream *pipeline_as_text = NULL;
+
     int main(int argc, char **argv) {
         Foundation::start();
         InterModule::start();
@@ -39,8 +50,12 @@
             L"write to file X in textual format");
         CommandLine::declare_switch(BINARY_CLSW, L"binary", 2,
             L"write to file X in binary format");
-        CommandLine::declare_switch(INTER_CLSW, L"inter", 2,
-            L"specify code-generation chain for inter code");
+        CommandLine::declare_switch(PIPELINE_CLSW, L"pipeline", 2,
+            L"specify pipeline textually");
+        CommandLine::declare_switch(PIPELINE_FILE_CLSW, L"pipeline-file", 2,
+            L"specify pipeline from file X");
+        CommandLine::declare_switch(PIPELINE_VARIABLE_CLSW, L"variable", 2,
+            L"set pipeline variable X (in form name=value)");
         CommandLine::declare_switch(TEMPLATE_CLSW, L"template", 2,
             L"specify folder holding i6t template files");
         CommandLine::declare_switch(TEST_CLSW, L"test", 2,
@@ -48,6 +63,8 @@
         CommandLine::declare_switch(DOMAIN_CLSW, L"domain", 2,
             L"specify folder to read/write inter files from/to");
 
+        pipeline_vars = CodeGen::Pipeline::basic_dictionary(I"output.i6");
+
         CommandLine::read(argc, argv, NULL, &Main::respond, &Main::add_file);
 
         Main::act();
@@ -69,20 +86,28 @@
 
 
 
-    pathname *template_path = NULL;
-    pathname *domain_path = NULL;
-    filename *output_textually = NULL;
-    filename *output_binarily = NULL;
-    filename *unit_test_file = NULL;
-    text_stream *inter_processing_chain = NULL;
-
     void Main::respond(int id, int val, text_stream *arg, void *state) {
         switch (id) {
             case TEXTUAL_CLSW: output_textually = Filenames::from_text(arg); break;
-            case BINARY_CLSW: output_binarily = Filenames::from_text(arg); inter_processing_chain = NULL; break;
-            case INTER_CLSW: inter_processing_chain = Str::duplicate(arg); break;
-            case DOMAIN_CLSW: domain_path = Pathnames::from_text(arg); inter_processing_chain = NULL; break;
-            case TEMPLATE_CLSW: template_path = Pathnames::from_text(arg); inter_processing_chain = NULL; break;
+            case BINARY_CLSW: output_binarily = Filenames::from_text(arg); pipeline_as_text = NULL; break;
+            case PIPELINE_CLSW: pipeline_as_text = Str::duplicate(arg); break;
+            case PIPELINE_FILE_CLSW: pipeline_as_file = Filenames::from_text(arg); break;
+            case PIPELINE_VARIABLE_CLSW: {
+                match_results mr = Regexp::create_mr();
+                if (Regexp::match(&mr, arg, L"(%c+)=(%c+)")) {
+                    if (Str::get_first_char(arg) != '*') {
+                        Errors::fatal("-variable names must begin with '*'");
+                    } else {
+                        Str::copy(Dictionaries::create_text(pipeline_vars, mr.exp[0]), mr.exp[1]);
+                    }
+                } else {
+                    Errors::fatal("-variable should take the form 'name=value'");
+                }
+                Regexp::dispose_of(&mr);
+                break;
+            }
+            case DOMAIN_CLSW: domain_path = Pathnames::from_text(arg); pipeline_as_text = NULL; break;
+            case TEMPLATE_CLSW: template_path = Pathnames::from_text(arg); pipeline_as_text = NULL; break;
             case TEST_CLSW: unit_test_file = Filenames::from_text(arg); break;
         }
     }
@@ -118,22 +143,27 @@
 
 
     void Main::act(void) {
-        inter_repository *I = Inter::create(1, 32);
-        inter_file *IF;
-        LOOP_OVER(IF, inter_file)
-            if (Inter::Binary::test_file(IF->inter_filename))
-                Inter::Binary::read(I, IF->inter_filename);
-            else
-                Inter::Textual::read(I, IF->inter_filename);
-        if (inter_processing_chain) {
+        if ((pipeline_as_file) || (pipeline_as_text)) {
+            if (NUMBER_CREATED(inter_file) > 0)
+                Errors::fatal("-pipeline and -pipeline-file cannot be combined with inter file parameters");
             int NO_FS_AREAS = 0;
             pathname *pathname_of_i6t_files[1];
             if (template_path) { NO_FS_AREAS = 1; pathname_of_i6t_files[0] = template_path; }
-            codegen_pipeline *SS = CodeGen::Pipeline::parse(inter_processing_chain, I"output.i6");
-            CodeGen::Pipeline::run(domain_path, SS, I, NO_FS_AREAS, pathname_of_i6t_files, template_path, NULL);
+            codegen_pipeline *SS;
+            if (pipeline_as_file) SS = CodeGen::Pipeline::parse_from_file(pipeline_as_file, pipeline_vars);
+            else SS = CodeGen::Pipeline::parse(pipeline_as_text, pipeline_vars);
+            CodeGen::Pipeline::run(domain_path, SS, NO_FS_AREAS, pathname_of_i6t_files);
         } else if (unit_test_file) {
             UnitTests::run(unit_test_file);
         } else {
+            inter_repository *I = Inter::create(1, 32);
+            inter_file *IF;
+            LOOP_OVER(IF, inter_file) {
+                if (Inter::Binary::test_file(IF->inter_filename))
+                    Inter::Binary::read(I, IF->inter_filename);
+                else
+                    Inter::Textual::read(I, IF->inter_filename);
+            }
             if (output_textually) {
                 text_stream C_struct; text_stream *OUT = &C_struct;
                 if (STREAM_OPEN_TO_FILE(OUT, output_textually, UTF8_ENC) == FALSE)
diff --git a/docs/inter/P-cas.html b/docs/inter/P-cas.html
deleted file mode 100644
index ae5a8f3ed..000000000
--- a/docs/inter/P-cas.html
+++ /dev/null
@@ -1,281 +0,0 @@
-
-
-	
-		P/io
-		
-		
-		
-	
-	
-
-
-

Sequences of named code-generation stages are called chains.

- -
- -

§1. Stages and descriptions. A processing stage is a step in code generation which acts on a repository -of inter in memory. Some stages change, add to or edit down that code, while -others leave it untouched but output a file based on it. -

- -

Each stage can see an entire repository of inter code at a time, and is -not restricted to working through it in sequence. Those which read in or write -out a file also have a filename supplied to them as a parameter, but there -are otherwise no configuration options. It's not possible to tell a stage -to work on one specific function alone, for example. -

- -

Stages are named, which are written without spaces, and conventionally use -hyphens: for example, resolve-conditional-compilation. Where a filename has -to be supplied, it appears after a colon. Thus generate-inter:my.intert -is a valid stage description. -

- -

A "chain" is a comma-separated list of stage descriptions, and represents a -sort of program to follow: memory inter is passed through each stage in turn. -The special stage stop halts processing of the chain midway. At present -this is only useful for making experimental edits to chain descriptions -to see what just the first half does, without deleting the second half of -the description. -

- -

§2. There are three ways to use chains. One is from the command line of Inter: -

- -

- - -
-        $ inter/Tangled/inter FILE -inter 'CHAIN'
-
- -

The other is to use two experimental features of Inform. This sentence: -

- -
-

Use inter chain "STAGES".

- -
- -

replaces the chain normally used for code generation with the one supplied. -(This may very well cause the compiler not to produce viable code, of course.) -Equivalently, a replacement chain can be specified at the Inform 7 command line: -

- -

- - -
-        $ inform7/Tangled/inform7 ... -inter 'CHAIN'
-
- -

When using a chain within Inform, one further description syntax is allowed: -the filename * means "the filename Inform wants to use for the final -Inform 6 file". -

- -

§3. The code-generation stages. The following are all experimental, and have probably not yet reached their -final form or names. But this briefly describes the stages which currently -exist in the code generator. In the description below, the "repository" is -the reservoir of memory inter code being worked on. -

- -

Although one thinks of code generation as a process of turning inter into -Inform 6, in fact it goes both ways, because we also have to read in -the "template" of standing Inform 6 code. The early code generation stages -convert the template from Inform 6 into inter, merging it with the inter -already produced by the front end of the compiler. The later stages then -turn this merged repository into Inform 6 code. (Routines in the template, -therefore, are converted out of Inform 6 and then back into it again. This -sounds inefficient but is surprisingly fast, and enables many optimisations.) -

- -

§4. link:T reads in the I6T template file T, converts it to inter in a very -basic way (creating many splats), and merges it with the repository. Splats -are the unhappiest of inter statements, simply including verbatim snippets -of Inform 6 code. -

- -

§5. parse-linked-matter examines the splats produced by linking and annotates -them by what they seem to want to do. For example, -

- -

- - -
-        splat &"Global nitwit = 2;\n"
-
- -

is recognised as an Inform 6 variable declaration, and annotated thus: -

- -

- - -
-        splat GLOBAL &"Global nitwit = 2;\n"
-
- -

- -

§6. resolve-conditional-compilation looks for splats arising from Inform 6 -conditional compilation directives such as #ifdef, #ifndef, #endif; -it then detects whether the relevant symbols are defined, or looks at their -values, and deletes sections of code not to be compiled. At the end of this -stage, there are no conditional compilation splats left in the repository. -For example: -

- -

- - -
-        constant MAGIC K_number = 16339
-        splat IFTRUE &"#iftrue MAGIC == 16339;\n"
-        constant WIZARD K_number = 5
-        splat IFNOT &"#ifnot;\n"
-        constant MUGGLE K_number = 0
-        splat ENDIF &"#endif;\n"
-
- -

is resolved to: -

- -

- - -
-        constant MAGIC K_number = 16339
-        constant WIZARD K_number = 5
-
- -

- -

§7. assimilate aims to convert all remaining splats in the repository into -higher-level inter statements. For example, -

- -

- - -
-        splat STUB &"#Stub Peach 0;\n"
-        splat ATTRIBUTE &"Attribute marmorial;\n"
-
- -

becomes: -

- -

- - -
-        constant Peach K_unchecked_function = Peach_B __assimilated=1
-        property marmorial K_truth_state __assimilated=1 __attribute=1 __either_or=1
-
- -

At the end of this stage, there should be no splats left in the repository, -and the linking process is complete. -

- -

§8. make-identifiers-unique looks for symbols marked with the MAKE_NAME_UNIQUE -flag (represented in textual form by an asterisk after its name), This flag -means that Inform wants the symbol name to be globally unique in the repository. -For example, if Inform generates the symbol name fruit*, it's really telling -the code generator that it eventually wants this to have a name which won't -collide with anything else. -

- -

What make-identifiers-unique does is to append _U1, _U2, ... to such -names across the repository. Thus fruit* might become fruit_U176, and it -is guaranteed that no other symbol has the same name. -

- -

This stage is needed because whereas the inter language has namespces, so -that the same name can mean different things in different parts of the -program, Inform 6 (mostly) does not. There cannot be two functions with the -same name in any I6 program, for example. -

- -

At the end of this stage, no symbol still has the MAKE_NAME_UNIQUE flag. -

- -

§9. reconcile-verbs is a short stage looking for clashes between any verbs (in -the parser interactive fiction sense) which have been assimilated from the -template, and verbs which have been defined in the main source text. For -example, suppose the source creates the command verb "abstract": this would -collide with the command meta-verb "abstract", intended for debugging, which -appears in the template. What this stage does is to detect such problems, -and if it finds one, to prefix the template verb with !. Thus we would end -up with two command verbs: abstract, with its source text meaning, and -!abstract, with its template meaning. -

- -

At the end of this stage, all parser verbs have distinct textual forms. -

- -

§10. eliminate-redundant-labels performs peephole optimisation on all of -the functions in the repository to remove all labels which are declared -but can never be jumped to. -

- -

At the end of this stage, all labels inside functions are targets of some -branch, either by inv !jump or in assembly language. -

- -

§11. generate-inter:F writes out the repository as a textual inter file F. -(By default, Inform doesn't do this: the inter ordinarily stays in memory -throughout.) -

- -

This stage leaves the repository unchanged. -

- -

§12. generate-inter-binary:F writes out the repository as a binary inter -file F. (By default, Inform doesn't do this: the inter ordinarily stays in -memory throughout.) -

- -

This stage leaves the repository unchanged. -

- -

§13. generate-i6:F translates the repository to an Inform 6 program. This is -normally the final stage in the Inform code generation chain. -

- -

This stage leaves the repository unchanged. -

- -

§14. Diagnostic or non-working stages.

- -

§15. show-dependencies:F and log-dependencies output a dependency graph of -the symbols in the current repository, one to a file, the other to the -debugging log. A dependency means that one can't be compiled without the -other: for example, if a function has a local variable of a given kind, then -the function depends on that kind. -

- -

eliminate-redundant-code is a stage which removes all material from -the repository which the main routine is not dependent on. This can result -in many template routines being kicked out, and substantially reduces -story file sizes. The stage mostly works, but needs more refinement before -we could safely enable it by default with Inform. -

- -

§16. summarise:F is a very slow diagnostic stage showing the breakdown of the -current repository into packages, writing the output to file F. (Slow in -this sense means that it roughly triples compilation time.) -

- -

§17. export:F and import:F were part of an experiment to do with caching the -inter generated by the Standard Rules. This eventually worked, but was put on -ice while a better and more systematic solution was found. -

- -
-
- - - - diff --git a/docs/inter/P-io.html b/docs/inter/P-io.html index 02e7f42d9..73be3cc11 100644 --- a/docs/inter/P-io.html +++ b/docs/inter/P-io.html @@ -204,7 +204,7 @@ possible, function packages are self-contained.


-
+
diff --git a/docs/inter/P-pas.html b/docs/inter/P-pas.html new file mode 100644 index 000000000..23ba0b58f --- /dev/null +++ b/docs/inter/P-pas.html @@ -0,0 +1,400 @@ + + + + P/io + + + + + + + +

Sequences of named code-generation stages are called pipelines.

+ +
+ +

§1. Stages and descriptions. A processing stage is a step in code generation which acts on a repository +of inter in memory. Some stages change, add to or edit down that code, while +others leave it untouched but output a file based on it. +

+ +

Each stage can see an entire repository of inter code at a time, and is +not restricted to working through it in sequence. +

+ +

Stages are named, which are written without spaces, and conventionally use +hyphens: for example, resolve-conditional-compilation. Where a filename has +to be supplied, it appears after a colon. Thus generate-inter:my.intert +is a valid stage description. +

+ +

A "pipeline" is a list of stage descriptions. If the pipeline is spelled +out textually on the command line, then commas are used to divide the stages: +

+ +

+ + +
+        $ inter/Tangled/inter -pipeline 'plugh, xyzzy, plover'
+
+ +

If the pipeline is in an external file, then one stage should appear on +each line, and the comma is not needed: +

+ +

+ + +
+        plugh
+        xyzzy
+        plover
+
+ +

+ +

§2. A pipeline can work on up to 10 different repositories, called 0 to 9, +which are initially empty (but see below). +

+ +

A pipeline description can make use of "variables". These hold only text, +and generally represent filenames. Variable names begin with a star *. +The pipeline cannot create variables: instead, the user of the pipeline has +to make them before use. For example, +

+ +

+ + +
+        $ inter/Tangled/inter -variable '*X=ex/why' -pipeline-file mypl.interpipeline
+
+ +

creates the variable *X with the textual contents ex/why before running +the given pipeline. Inside the pipeline, a line such as: +

+ +

+ + +
+        generate: inform6 -> *X
+
+ +

would then be read as: +

+ +

+ + +
+        generate: inform6 -> ex/why
+
+ +

After variable substitution like this, filenames inside the pipeline +description are interpreted as follows: +

+ +

+ +
  • (a) If a filename contains a slash character, it is considered a literal +filename. +
  • (b) If not, it is considered to be a leafname inside the "domain" directory. +By default this is the current working directory, but using -domain at +the Inter command line changes that. +
+

The special variable *log, which always exists, means the debugging log. +A command to write a text file to *log is interpreted instead to mean +"spool the output you would otherwise write to the debugging log instead". +For example, +

+ +

+ + +
+        generate: inventory -> *log
+
+ +

Template filenames are a little different: those are searched for inside +a path of possible directories. By default there's no such path, but using +-template T at the Inter command line gives a path of just one directory. +

+ +

§3. Pipelines run by Inform. As the above implies, Inter pipelines normally begin with a clean slate: +no repositories, no variables. +

+ +

When a pipeline is being run by the main Inform 7 compiler, however, +repository 0 will be preloaded with the inter code Inform has generated +in memory. The variable *out is set to the filename to which final I6 code +needs to be written, and the "domain" is the directory containing that. +The template search path is set to the one used in Inform, that is, the +template file Whatever.i6t would be looked for first in the project's +X.materials/I6T directory, then in the user's I6T directory, and failing +that in Inform's built-in one. +

+ +

The pipeline is itself looked for in the same way. If you have a project +called Strange.inform, then Inform first looks for +

+ +

+ + +
+        Strange.materials/Inter/default.interpipeline
+
+ +

If it can't find this file, it next looks for default.interpipeline in +the user's folder, and then in Inform's built-in one. If you're curious to +read the pipeline normally used by a shipping version of Inform, the file +can be found here in the Github repository for Inform: +

+ +

+ + +
+        inform7/Internal/Inter/default.interpipeline
+
+ +

The best way to change the pipeline, then, is to put a new file in the +project's Materials folder. But there are also two other ways. +

+ +

1. This sentence: +

+ +
+

Use inter pipeline "PIPELINE".

+ +
+ +

replaces the pipeline normally used for code generation with the one supplied. +(That may very well cause the compiler not to produce viable code, of course.) +

+ +

2. A replacement pipeline can be specified at the Inform 7 command line: +

+ +

+ + +
+        $ inform7/Tangled/inform7 ... -pipeline 'PIPELINE'
+
+ +

Exactly as with Inter, Inform 7 also responds to -pipeline-file: +

+ +

+ + +
+        $ inform7/Tangled/inform7 ... -pipeline-file FILE
+
+ +

+ +

§4. Reading and generating. The read stage reads Inter from a file into a repository in memory. +(Its previous contents, if any, are discarded.) This then becomes the +repository to which subsequent stages apply. The format is: +

+ +

+ + +
+        read REPOSITORY <- FILE
+
+ +

where REPOSITORY is 0 to 9. Conventionally, we use 0 most of the time. +The FILE can contain either binary or textual Inter, and this is +automatically detected. +

+ +

+ + +
+        generate: FORMAT -> FILE
+
+ +

writes the contents of the current repository out into the given FILE. +There are several possible formats: binary and text mean a binary or +textual Inter file, inventory means a textual summary of the contents, +and inform6 means an Inform 6 program. +

+ +

The generate stage leaves the repository unchanged, so it's possible +to generate multiple representations of the same repository into different +files. +

+ +

§5. The code-generation stages. The following are all experimental, and have probably not yet reached their +final form or names. +

+ +

Although one thinks of code generation as a process of turning inter into +Inform 6, in fact it goes both ways, because we also have to read in +the "template" of standing Inform 6 code. The early code generation stages +convert the template from Inform 6 into inter, merging it with the inter +already produced by the front end of the compiler. The later stages then +turn this merged repository into Inform 6 code. (Routines in the template, +therefore, are converted out of Inform 6 and then back into it again. This +sounds inefficient but is surprisingly fast, and enables many optimisations.) +

+ +

§6. link:T reads in the I6T template file T, converts it to inter in a very +basic way (creating many splats), and merges it with the repository. Splats +are the unhappiest of inter statements, simply including verbatim snippets +of Inform 6 code. +

+ +

§7. parse-linked-matter examines the splats produced by linking and annotates +them by what they seem to want to do. For example, +

+ +

+ + +
+        splat &"Global nitwit = 2;\n"
+
+ +

is recognised as an Inform 6 variable declaration, and annotated thus: +

+ +

+ + +
+        splat GLOBAL &"Global nitwit = 2;\n"
+
+ +

+ +

§8. resolve-conditional-compilation looks for splats arising from Inform 6 +conditional compilation directives such as #ifdef, #ifndef, #endif; +it then detects whether the relevant symbols are defined, or looks at their +values, and deletes sections of code not to be compiled. At the end of this +stage, there are no conditional compilation splats left in the repository. +For example: +

+ +

+ + +
+        constant MAGIC K_number = 16339
+        splat IFTRUE &"#iftrue MAGIC == 16339;\n"
+        constant WIZARD K_number = 5
+        splat IFNOT &"#ifnot;\n"
+        constant MUGGLE K_number = 0
+        splat ENDIF &"#endif;\n"
+
+ +

is resolved to: +

+ +

+ + +
+        constant MAGIC K_number = 16339
+        constant WIZARD K_number = 5
+
+ +

+ +

§9. assimilate aims to convert all remaining splats in the repository into +higher-level inter statements. For example, +

+ +

+ + +
+        splat STUB &"#Stub Peach 0;\n"
+        splat ATTRIBUTE &"Attribute marmorial;\n"
+
+ +

becomes: +

+ +

+ + +
+        constant Peach K_unchecked_function = Peach_B __assimilated=1
+        property marmorial K_truth_state __assimilated=1 __attribute=1 __either_or=1
+
+ +

At the end of this stage, there should be no splats left in the repository, +and the linking process is complete. +

+ +

§10. make-identifiers-unique looks for symbols marked with the MAKE_NAME_UNIQUE +flag (represented in textual form by an asterisk after its name), This flag +means that Inform wants the symbol name to be globally unique in the repository. +For example, if Inform generates the symbol name fruit*, it's really telling +the code generator that it eventually wants this to have a name which won't +collide with anything else. +

+ +

What make-identifiers-unique does is to append _U1, _U2, ... to such +names across the repository. Thus fruit* might become fruit_U176, and it +is guaranteed that no other symbol has the same name. +

+ +

This stage is needed because whereas the inter language has namespces, so +that the same name can mean different things in different parts of the +program, Inform 6 (mostly) does not. There cannot be two functions with the +same name in any I6 program, for example. +

+ +

At the end of this stage, no symbol still has the MAKE_NAME_UNIQUE flag. +

+ +

§11. reconcile-verbs is a short stage looking for clashes between any verbs (in +the parser interactive fiction sense) which have been assimilated from the +template, and verbs which have been defined in the main source text. For +example, suppose the source creates the command verb "abstract": this would +collide with the command meta-verb "abstract", intended for debugging, which +appears in the template. What this stage does is to detect such problems, +and if it finds one, to prefix the template verb with !. Thus we would end +up with two command verbs: abstract, with its source text meaning, and +!abstract, with its template meaning. +

+ +

At the end of this stage, all parser verbs have distinct textual forms. +

+ +

§12. eliminate-redundant-code deletes all packages which Inter can prove +will not be used in the final code generated from the repository. For +example, functions never called, or arrays never referred to, are deleted. +

+ +

§13. eliminate-redundant-labels performs peephole optimisation on all of +the functions in the repository to remove all labels which are declared +but can never be jumped to. +

+ +

At the end of this stage, all labels inside functions are targets of some +branch, either by inv !jump or in assembly language. +

+ +

§14. The special stage stop halts processing of the pipeline midway. At present +this is only useful for making experimental edits to pipeline descriptions +to see what just the first half does, without deleting the second half of +the description. +

+ +
+
+ + + + diff --git a/docs/inter/P-ui.html b/docs/inter/P-ui.html index a06430a96..da7e506e3 100644 --- a/docs/inter/P-ui.html +++ b/docs/inter/P-ui.html @@ -30,17 +30,22 @@ or for future applications of inter code.

§2. Command-line usage. If you have compiled the standard distribution of the command-line tools for Inform then the Inter executable will be at inter/Tangled/inter. -The usage is: +

+ +

Inter has three basic modes. In the first, the command line specifies only +a single file:

-        $ inter/Tangled/inter FILE1 FILE2 ... [OPTIONS]
+        $ inter/Tangled/inter INTERFILE
 
-

Though multiple files can be supplied, it's usual to supply just one. +

Inter simply verifies this file for correctness: that is, to see if the inter +code supplied conforms to the inter specification. It returns the exit code 0 +if all is well, and issues error messages and returns 1 if not.

Such files can be in either textual or binary form, and Inter automatically @@ -49,13 +54,7 @@ have the filename extension .intert< not how Inter decides.)

-

§3. Inter has three basic modes. In the first, when no options are supplied, -Inter simply verifies its input for correctness: that is, to see if the inter -code supplied conforms to the inter specification. It returns the exit code 0 -if all is well, and issues error messages and returns 1 if not. -

- -

§4. In the second mode, Inter converts from textual to binary form or vice +

§3. In the second mode, Inter converts from textual to binary form or vice versa. The option -binary X writes a binary form of the inter to file X, and -textual X writes a text form. So, for example,

@@ -80,49 +79,73 @@ and -textual X writes

-

§5. In the third and most flexible mode, Inter runs the supplied code through -a "chain" of processing stages. The chain, which must contain at least -one stage, is a textual list of comma-separated stage names. For example, +

§4. In the third and most flexible mode, Inter runs the supplied code through +a pipeline of processing stages. The pipeline, which must contain at least +one stage, can be quite elaborate (see later), but for example:

-        resolve-conditional-compilation,assimilate,make-identifiers-unique
+        read: 0 <- myfile.inter, resolve-conditional-compilation, generate: inform6 -> myfile.i6
 
-

is a valid three-stage chain. The command to do this is then: +

is a valid three-stage pipeline. The command to do this is then:

-        $ inter/Tangled/inter my.intert -inter 'CHAIN'
+        $ inter/Tangled/inter -pipeline 'PIPELINE'
 
-

where CHAIN is the chain description. -

- -

In practice, this will only be useful if you can access the result, so it's -normal for the final stage to output something: perhaps Inform 6 code, perhaps -textual inter. For example: +

where PIPELINE is a textual description like the one above. In practice, +it may not be convenient to spell the pipeline out on the command line, so +one can also put it into a text file:

-        $ inter/Tangled/inter in.intert -inter 'parse-linked-matter, generate-inter:out.intert'
+        $ inter/Tangled/inter -pipeline-file mypl.interpipeline
 
-

Two more options may be helpful to supplement this: -domain D sets the -directory D to be the default location for reading and writing inter files; -and -template T tells Inter that it can find the I6T template files at -the file system location T. (Some code-generation stages import these.) +

Pipelines can contain variables, and their values can be set at the command +line with e.g.:

+

+ + +
+        -variable '*out=myfile.i6'
+
+ +

It is also possible to set the default directory for reading and writing files: +

+ +

+ + +
+        -domain D
+
+ +

Finally, we can tell Inter where to find I6T template files: +

+ +

+ + +
+        -template T
+
+ +

+

diff --git a/docs/inter/index.html b/docs/inter/index.html index 0a398c20c..00c72294c 100644 --- a/docs/inter/index.html +++ b/docs/inter/index.html @@ -44,8 +44,8 @@ The standard hierarchy of inter code generated by Inform.

  • -

    Chains and Stages - - Sequences of named code-generation stages are called chains.

    +

    Pipelines and Stages - + Sequences of named code-generation stages are called pipelines.

  • diff --git a/inform7/Internal/Inter/default.interpipeline b/inform7/Internal/Inter/default.interpipeline new file mode 100644 index 000000000..c9f04d1d8 --- /dev/null +++ b/inform7/Internal/Inter/default.interpipeline @@ -0,0 +1,8 @@ +link: Output.i6t +parse-linked-matter +resolve-conditional-compilation +assimilate +make-identifiers-unique +resolve-external-symbols +reconcile-verbs +generate: inform6 -> *out diff --git a/inform7/Tests/Test Inter/Luna.txt b/inform7/Tests/Test Inter/Luna.txt deleted file mode 100644 index a4bc1e36b..000000000 --- a/inform7/Tests/Test Inter/Luna.txt +++ /dev/null @@ -1,42 +0,0 @@ -Moon is a room. A rock is a thing. - -To present (decider - a phrase nothing -> truth state): - showme the decider. - -An astronaut is a kind of person. - -Jet is an astronaut in the Moon. -Doc is an astronaut in the Moon. - -Doc can be calm, agitated or solemn. - -The Decontamination Station is a room. A control panel is here. "Three -buttons -- red, blue, and green -- adorn the control panel in front of you. -A sign above the buttons reads: CAUTION: RADIATION PURGE." - -A red button is part of the control panel. A green button is part of the -control panel. A blue button is part of the control panel. - -The lower levels is a region. The access tunnels is a region. The -residential bays is a region. -  -Purging something is an activity. -  -Before purging a region (called the purged area), say "Initiating purge -protocols in [the purged area]..." -  -Rule for purging the lower levels: say "The lower levels have been purged." -Rule for purging the access tunnels: say "The access tunnels have been purged." -Rule for purging the residential bays: say "The residential bays have been purged." -  -After purging a region: say "Purge complete." -  -Instead of pushing the red button, carry out the purging activity with the lower levels. -Instead of pushing the green button, carry out the purging activity with the access tunnels. -Instead of pushing the blue button, carry out the purging activity with the residential bays.  -  -Test me with "push red / push blue / push green". - -Eightball is a scene. - -Eightball has a number called countervalue. diff --git a/inform7/Tests/inform7.intest b/inform7/Tests/inform7.intest index d93c214c0..798a618a1 100644 --- a/inform7/Tests/inform7.intest +++ b/inform7/Tests/inform7.intest @@ -5,7 +5,6 @@ -set hash_cache 'inform7/Tests/hashes.intest' -cases [Main] 'inform7/Tests/Test Cases' -! -cases [Inter] 'inform7/Tests/Test Inter' -if osx -cases [Index] 'inform7/Tests/Test Index' -if osx -cases [Map] 'inform7/Tests/Test Maps' -if osx -cases [Release] 'inform7/Tests/Test Releases' @@ -80,7 +79,7 @@ set: $SRINTERB = inform7/Internal/I6T/sr-Z.interb endif - set: $INTERCHAIN = link:Output.i6t,parse-linked-matter,resolve-conditional-compilation,assimilate,make-identifiers-unique,resolve-external-symbols,reconcile-verbs,generate:inform6->* + set: $PIPELINE = inform7/Tests/test-pl.interpipeline ! First, problem message cases, where we require ni to fail and with the ! correct output. @@ -88,7 +87,7 @@ if: $TYPE problem set: $A = $PATH/_Results_Actual/$CASE.txt set: $I = $PATH/_Results_Ideal/$CASE.txt - fail step: $I7 `$I7OPTIONS -require-problem $CASE -project $WORK/Example.inform -inter $INTERCHAIN >$A 2>&1 + fail step: $I7 `$I7OPTIONS -require-problem $CASE -project $WORK/Example.inform -pipeline-file $PIPELINE >$A 2>&1 or: 'failed to produce its namesake Problem message' $A show: $A exists: $I @@ -101,7 +100,7 @@ ! And then the general case. set: $I7CONSOLE = $WORK/Example.inform/Build/i7_output.txt - step: $I7 `$I7OPTIONS -format=$FORMAT -project $WORK/Example.inform -inter $INTERCHAIN >$I7CONSOLE 2>&1 + step: $I7 `$I7OPTIONS -format=$FORMAT -project $WORK/Example.inform -pipeline-file $PIPELINE >$I7CONSOLE 2>&1 or: 'failed with Problem message(s)' $I7CONSOLE show: $I7CONSOLE @@ -266,69 +265,6 @@ -end --recipe [Inter] - - set: $I7 = inform7/Tangled/inform7 - set: $INTER = inter/Tangled/inter - set: $INTERNAL = inform7/Internal - set: $WORKSPACE = intest/Workspace - - ! First we decide whether to compile it for the Z-machine or Glulx. - - set: $VM = Z - if: $CASE %c*-G - set: $VM = G - endif - if: $CASE %c*Metric%c*Units%c* - set: $VM = G - endif - - ! On the basis of which: - - if: $VM G - set: $FORMAT = ulx - else - set: $FORMAT = z8 - endif - - mkdir: $PATH/_Inter_Binary - mkdir: $PATH/_Inter_Textual - mkdir: $PATH/_Inter_Actual - mkdir: $PATH/_Inter_Ideal - - ! Now we extract the source text from whatever file originated the test - ! case: this is a non-trivial operation when the file is an Extension or - ! an example, but is a simple copy operation otherwise. - - extract: $WORK/Example.inform/Source/story.ni $VM - - set: $I7OPTIONS = -format=$FORMAT -noprogress -fixtime -rng -sigils -clock -log nothing -external inform7/Tests -transient $WORK/Transient -noindex -internal $INTERNAL - - set: $INTERB = $PATH/_Inter_Binary/$CASE.interb - set: $INTERT = $PATH/_Inter_Textual/$CASE.intert - set: $INTERCHAIN = generate-inter:$INTERT,generate-inter-binary:$INTERB - - set: $I7CONSOLE = $WORK/Example.inform/Build/i7_output.txt - step: $I7 `$I7OPTIONS -format=$FORMAT -project $WORK/Example.inform -inter $INTERCHAIN >$I7CONSOLE 2>&1 - or: 'failed with Problem message(s)' $I7CONSOLE - - set: $INTERA = $PATH/_Inter_Actual/$CASE.intert - set: $INTERI = $PATH/_Inter_Ideal/$CASE.intert - - set: $INTERCONSOLE = $WORK/Example.inform/Build/inter_output.txt - step: $INTER $INTERB -textual $INTERA >$INTERCONSOLE 2>&1 - or: 'failed to read inter' $INTERCONSOLE - - show: $INTERCONSOLE - - match text: $INTERA $INTERI - or: 'produced the wrong inter code' - show: $INTERA - - pass: 'passed' - --end - -recipe [Release] set: $I7 = inform7/Tangled/inform7 diff --git a/inform7/Tests/test-pl.interpipeline b/inform7/Tests/test-pl.interpipeline new file mode 100644 index 000000000..c9f04d1d8 --- /dev/null +++ b/inform7/Tests/test-pl.interpipeline @@ -0,0 +1,8 @@ +link: Output.i6t +parse-linked-matter +resolve-conditional-compilation +assimilate +make-identifiers-unique +resolve-external-symbols +reconcile-verbs +generate: inform6 -> *out diff --git a/inform7/core-module/Chapter 1/Main Routine.w b/inform7/core-module/Chapter 1/Main Routine.w index 3f9a86fb7..a44671894 100644 --- a/inform7/core-module/Chapter 1/Main Routine.w +++ b/inform7/core-module/Chapter 1/Main Routine.w @@ -58,7 +58,8 @@ int indexing_stage = FALSE; /* Everything is done except indexing */ @ = int report_clock_time = FALSE; time_t right_now; -text_stream *inter_processing_chain = NULL; +text_stream *inter_processing_file = NULL; +text_stream *inter_processing_pipeline = NULL; pathname *path_to_inform7 = NULL; int CoreMain::main(int argc, char *argv[]) { @@ -97,7 +98,7 @@ int CoreMain::main(int argc, char *argv[]) { @ = Errors::set_internal_handler(&Problems::Issue::internal_error_fn); story_filename_extension = I"ulx"; - inter_processing_chain = I"link: Output.i6t, parse-linked-matter, resolve-conditional-compilation, assimilate, make-identifiers-unique, resolve-external-symbols, reconcile-verbs, generate: inform6 -> *"; + inter_processing_pipeline = Str::new(); PRINT("%B build %B has started.\n", FALSE, TRUE); STREAM_FLUSH(STDOUT); @@ -122,7 +123,8 @@ list is not exhaustive. @e RNG_CLSW @e SIGILS_CLSW @e TRANSIENT_CLSW -@e INTER_CLSW +@e PIPELINE_CLSW +@e PIPELINE_FILE_CLSW @ = CommandLine::declare_heading( @@ -153,8 +155,10 @@ list is not exhaustive. L"make any source links refer to the source in extension example X"); CommandLine::declare_switch(REQUIRE_PROBLEM_CLSW, L"require-problem", 2, L"return 0 unless exactly this Problem message is generated (for testing)"); - CommandLine::declare_switch(INTER_CLSW, L"inter", 2, - L"specify code-generation chain for inter code"); + CommandLine::declare_switch(PIPELINE_CLSW, L"pipeline", 2, + L"specify code-generation pipeline"); + CommandLine::declare_switch(PIPELINE_FILE_CLSW, L"pipeline-file", 2, + L"specify code-generation pipeline from file X"); CommandLine::declare_switch(PROJECT_CLSW, L"project", 2, L"work within the Inform project X"); @@ -390,13 +394,28 @@ with "Output.i6t". LOG("Front end elapsed time: %dcs\n", ((int) (front_end - start)) / (CLOCKS_PER_SEC/100)); CoreMain::go_to_log_phase(I"Converting inter to Inform 6"); if (existing_story_file == FALSE) { - codegen_pipeline *SS = CodeGen::Pipeline::new(); - CodeGen::Pipeline::parse_into(SS, inter_processing_chain, + dictionary *D = CodeGen::Pipeline::basic_dictionary( Filenames::get_leafname(filename_of_compiled_i6_code)); + codegen_pipeline *SS = NULL; + if (inter_processing_file) + SS = CodeGen::Pipeline::parse_from_file(Filenames::from_text(inter_processing_file), D); + else if (Str::len(inter_processing_pipeline) > 0) + SS = CodeGen::Pipeline::parse(inter_processing_pipeline, D); + else { + for (int area=0; area; @ Most of these files are to help Inblorb to perform a release. The @@ -463,6 +470,7 @@ void Locations::EILT_at(int area, pathname *P) { pathname_of_i6t_files[area] = Pathnames::subfolder(P, I"I6T"); pathname_of_languages[area] = Pathnames::subfolder(P, I"Languages"); pathname_of_website_templates[area] = Pathnames::subfolder(P, I"Templates"); + pathname_of_inter_resources[area] = Pathnames::subfolder(P, I"Inter"); } @h Location of extensions. diff --git a/inform7/core-module/Chapter 26/Use Options.w b/inform7/core-module/Chapter 26/Use Options.w index c61c4f3ca..e35bce7fd 100644 --- a/inform7/core-module/Chapter 26/Use Options.w +++ b/inform7/core-module/Chapter 26/Use Options.w @@ -142,8 +142,8 @@ option name is taken from the |...| or |###| as appropriate: ... | ==> 0 ... ==> 0 - ::= - inter chain {} ==> TRUE + ::= + inter pipeline {} ==> TRUE @ These are use option names which Inform provides special support for; it recognises the English names when they are defined by the Standard Rules. (So @@ -206,7 +206,7 @@ void UseOptions::set_use_options(parse_node *p) { UseOptions::set_use_options(p->down->next); return; } - if ((ParseTree::get_text(p))) @ + if ((ParseTree::get_text(p))) @ else if ((ParseTree::get_text(p))) @; if (traverse == 1) return; LOG("Used: %W\n", ParseTree::get_text(p)); @@ -239,8 +239,8 @@ void UseOptions::set_use_options(parse_node *p) { } @ = - wording CW = GET_RW(, 1); - if (traverse == 1) CoreMain::set_inter_chain(CW); + wording CW = GET_RW(, 1); + if (traverse == 1) CoreMain::set_inter_pipeline(CW); return; @ = diff --git a/inter/.gitignore b/inter/.gitignore index 782c7849f..c3e156fed 100644 --- a/inter/.gitignore +++ b/inter/.gitignore @@ -15,19 +15,9 @@ inter-module/Woven/ inter.mk -Tests/Assimilate/_Results_Actual/ -Tests/Assimilate/_Console/ -Tests/Generations/_Results_Actual/ -Tests/Generations/_Console/ -Tests/Graph/_Results_Actual/ -Tests/Graph/_Console/ Tests/Invalid/_Results_Actual/ -Tests/PLM/_Results_Actual/ -Tests/PLM/_Console/ -Tests/RCC/_Results_Actual/ -Tests/RCC/_Console/ -Tests/ERL/_Results_Actual/ -Tests/ERL/_Console/ +Tests/General/_Results_Actual/ +Tests/General/_Console/ Tests/Valid/_Binary/ Tests/Valid/_Console/ Tests/Valid/_Textual/ diff --git a/inter/Chapter 1/Main.w b/inter/Chapter 1/Main.w index 26032c4a9..26de045e3 100644 --- a/inter/Chapter 1/Main.w +++ b/inter/Chapter 1/Main.w @@ -7,12 +7,23 @@ this plan out. @e TEXTUAL_CLSW @e BINARY_CLSW -@e INTER_CLSW +@e PIPELINE_CLSW +@e PIPELINE_FILE_CLSW +@e PIPELINE_VARIABLE_CLSW @e DOMAIN_CLSW @e TEMPLATE_CLSW @e TEST_CLSW = +pathname *template_path = NULL; +pathname *domain_path = NULL; +filename *output_textually = NULL; +filename *output_binarily = NULL; +filename *unit_test_file = NULL; +dictionary *pipeline_vars = NULL; +filename *pipeline_as_file = NULL; +text_stream *pipeline_as_text = NULL; + int main(int argc, char **argv) { Foundation::start(); InterModule::start(); @@ -26,8 +37,12 @@ int main(int argc, char **argv) { L"write to file X in textual format"); CommandLine::declare_switch(BINARY_CLSW, L"binary", 2, L"write to file X in binary format"); - CommandLine::declare_switch(INTER_CLSW, L"inter", 2, - L"specify code-generation chain for inter code"); + CommandLine::declare_switch(PIPELINE_CLSW, L"pipeline", 2, + L"specify pipeline textually"); + CommandLine::declare_switch(PIPELINE_FILE_CLSW, L"pipeline-file", 2, + L"specify pipeline from file X"); + CommandLine::declare_switch(PIPELINE_VARIABLE_CLSW, L"variable", 2, + L"set pipeline variable X (in form name=value)"); CommandLine::declare_switch(TEMPLATE_CLSW, L"template", 2, L"specify folder holding i6t template files"); CommandLine::declare_switch(TEST_CLSW, L"test", 2, @@ -35,6 +50,8 @@ int main(int argc, char **argv) { CommandLine::declare_switch(DOMAIN_CLSW, L"domain", 2, L"specify folder to read/write inter files from/to"); + pipeline_vars = CodeGen::Pipeline::basic_dictionary(I"output.i6"); + CommandLine::read(argc, argv, NULL, &Main::respond, &Main::add_file); Main::act(); @@ -48,20 +65,28 @@ int main(int argc, char **argv) { } @ = -pathname *template_path = NULL; -pathname *domain_path = NULL; -filename *output_textually = NULL; -filename *output_binarily = NULL; -filename *unit_test_file = NULL; -text_stream *inter_processing_chain = NULL; - void Main::respond(int id, int val, text_stream *arg, void *state) { switch (id) { case TEXTUAL_CLSW: output_textually = Filenames::from_text(arg); break; - case BINARY_CLSW: output_binarily = Filenames::from_text(arg); inter_processing_chain = NULL; break; - case INTER_CLSW: inter_processing_chain = Str::duplicate(arg); break; - case DOMAIN_CLSW: domain_path = Pathnames::from_text(arg); inter_processing_chain = NULL; break; - case TEMPLATE_CLSW: template_path = Pathnames::from_text(arg); inter_processing_chain = NULL; break; + case BINARY_CLSW: output_binarily = Filenames::from_text(arg); pipeline_as_text = NULL; break; + case PIPELINE_CLSW: pipeline_as_text = Str::duplicate(arg); break; + case PIPELINE_FILE_CLSW: pipeline_as_file = Filenames::from_text(arg); break; + case PIPELINE_VARIABLE_CLSW: { + match_results mr = Regexp::create_mr(); + if (Regexp::match(&mr, arg, L"(%c+)=(%c+)")) { + if (Str::get_first_char(arg) != '*') { + Errors::fatal("-variable names must begin with '*'"); + } else { + Str::copy(Dictionaries::create_text(pipeline_vars, mr.exp[0]), mr.exp[1]); + } + } else { + Errors::fatal("-variable should take the form 'name=value'"); + } + Regexp::dispose_of(&mr); + break; + } + case DOMAIN_CLSW: domain_path = Pathnames::from_text(arg); pipeline_as_text = NULL; break; + case TEMPLATE_CLSW: template_path = Pathnames::from_text(arg); pipeline_as_text = NULL; break; case TEST_CLSW: unit_test_file = Filenames::from_text(arg); break; } } @@ -79,22 +104,27 @@ void Main::add_file(int id, text_stream *arg, void *state) { @ = void Main::act(void) { - inter_repository *I = Inter::create(1, 32); - inter_file *IF; - LOOP_OVER(IF, inter_file) - if (Inter::Binary::test_file(IF->inter_filename)) - Inter::Binary::read(I, IF->inter_filename); - else - Inter::Textual::read(I, IF->inter_filename); - if (inter_processing_chain) { + if ((pipeline_as_file) || (pipeline_as_text)) { + if (NUMBER_CREATED(inter_file) > 0) + Errors::fatal("-pipeline and -pipeline-file cannot be combined with inter file parameters"); int NO_FS_AREAS = 0; pathname *pathname_of_i6t_files[1]; if (template_path) { NO_FS_AREAS = 1; pathname_of_i6t_files[0] = template_path; } - codegen_pipeline *SS = CodeGen::Pipeline::parse(inter_processing_chain, I"output.i6"); - CodeGen::Pipeline::run(domain_path, SS, I, NO_FS_AREAS, pathname_of_i6t_files, template_path, NULL); + codegen_pipeline *SS; + if (pipeline_as_file) SS = CodeGen::Pipeline::parse_from_file(pipeline_as_file, pipeline_vars); + else SS = CodeGen::Pipeline::parse(pipeline_as_text, pipeline_vars); + CodeGen::Pipeline::run(domain_path, SS, NO_FS_AREAS, pathname_of_i6t_files); } else if (unit_test_file) { UnitTests::run(unit_test_file); } else { + inter_repository *I = Inter::create(1, 32); + inter_file *IF; + LOOP_OVER(IF, inter_file) { + if (Inter::Binary::test_file(IF->inter_filename)) + Inter::Binary::read(I, IF->inter_filename); + else + Inter::Textual::read(I, IF->inter_filename); + } if (output_textually) { text_stream C_struct; text_stream *OUT = &C_struct; if (STREAM_OPEN_TO_FILE(OUT, output_textually, UTF8_ENC) == FALSE) diff --git a/inter/Contents.w b/inter/Contents.w index 057f405b5..1b2b8534d 100644 --- a/inter/Contents.w +++ b/inter/Contents.w @@ -18,7 +18,7 @@ Preliminaries Inform Primitives Inform Annotations Inform Organisation - Chains and Stages + Pipelines and Stages Chapter 1: Everything Basics diff --git a/inter/Preliminaries/Chains and Stages.w b/inter/Preliminaries/Chains and Stages.w deleted file mode 100644 index 41c36ea1b..000000000 --- a/inter/Preliminaries/Chains and Stages.w +++ /dev/null @@ -1,182 +0,0 @@ -Chains and Stages. - -Sequences of named code-generation stages are called chains. - -@h Stages and descriptions. -A processing stage is a step in code generation which acts on a repository -of inter in memory. Some stages change, add to or edit down that code, while -others leave it untouched but output a file based on it. - -Each stage can see an entire repository of inter code at a time, and is -not restricted to working through it in sequence. Those which read in or write -out a file also have a filename supplied to them as a parameter, but there -are otherwise no configuration options. It's not possible to tell a stage -to work on one specific function alone, for example. - -Stages are named, which are written without spaces, and conventionally use -hyphens: for example, |resolve-conditional-compilation|. Where a filename has -to be supplied, it appears after a colon. Thus |generate-inter:my.intert| -is a valid stage description. - -A "chain" is a comma-separated list of stage descriptions, and represents a -sort of program to follow: memory inter is passed through each stage in turn. -The special stage |stop| halts processing of the chain midway. At present -this is only useful for making experimental edits to chain descriptions -to see what just the first half does, without deleting the second half of -the description. - -@ There are three ways to use chains. One is from the command line of Inter: - - |$ inter/Tangled/inter FILE -inter 'CHAIN'| - -The other is to use two experimental features of Inform. This sentence: - ->> Use inter chain "STAGES". - -replaces the chain normally used for code generation with the one supplied. -(This may very well cause the compiler not to produce viable code, of course.) -Equivalently, a replacement chain can be specified at the Inform 7 command line: - - |$ inform7/Tangled/inform7 ... -inter 'CHAIN'| - -When using a chain within Inform, one further description syntax is allowed: -the filename |*| means "the filename Inform wants to use for the final -Inform 6 file". - -@h The code-generation stages. -The following are all experimental, and have probably not yet reached their -final form or names. But this briefly describes the stages which currently -exist in the code generator. In the description below, the "repository" is -the reservoir of memory inter code being worked on. - -Although one thinks of code generation as a process of turning inter into -Inform 6, in fact it goes both ways, because we also have to read in -the "template" of standing Inform 6 code. The early code generation stages -convert the template from Inform 6 into inter, merging it with the inter -already produced by the front end of the compiler. The later stages then -turn this merged repository into Inform 6 code. (Routines in the template, -therefore, are converted out of Inform 6 and then back into it again. This -sounds inefficient but is surprisingly fast, and enables many optimisations.) - -@ |link:T| reads in the I6T template file T, converts it to inter in a very -basic way (creating many splats), and merges it with the repository. Splats -are the unhappiest of inter statements, simply including verbatim snippets -of Inform 6 code. - -@ |parse-linked-matter| examines the splats produced by linking and annotates -them by what they seem to want to do. For example, - - |splat &"Global nitwit = 2;\n"| - -is recognised as an Inform 6 variable declaration, and annotated thus: - - |splat GLOBAL &"Global nitwit = 2;\n"| - -@ |resolve-conditional-compilation| looks for splats arising from Inform 6 -conditional compilation directives such as |#ifdef|, |#ifndef|, |#endif|; -it then detects whether the relevant symbols are defined, or looks at their -values, and deletes sections of code not to be compiled. At the end of this -stage, there are no conditional compilation splats left in the repository. -For example: - - |constant MAGIC K_number = 16339| - |splat IFTRUE &"#iftrue MAGIC == 16339;\n"| - |constant WIZARD K_number = 5| - |splat IFNOT &"#ifnot;\n"| - |constant MUGGLE K_number = 0| - |splat ENDIF &"#endif;\n"| - -is resolved to: - - |constant MAGIC K_number = 16339| - |constant WIZARD K_number = 5| - -@ |assimilate| aims to convert all remaining splats in the repository into -higher-level inter statements. For example, - - |splat STUB &"#Stub Peach 0;\n"| - |splat ATTRIBUTE &"Attribute marmorial;\n"| - -becomes: - - |constant Peach K_unchecked_function = Peach_B __assimilated=1| - |property marmorial K_truth_state __assimilated=1 __attribute=1 __either_or=1| - -At the end of this stage, there should be no splats left in the repository, -and the linking process is complete. - -@ |make-identifiers-unique| looks for symbols marked with the |MAKE_NAME_UNIQUE| -flag (represented in textual form by an asterisk after its name), This flag -means that Inform wants the symbol name to be globally unique in the repository. -For example, if Inform generates the symbol name |fruit*|, it's really telling -the code generator that it eventually wants this to have a name which won't -collide with anything else. - -What |make-identifiers-unique| does is to append |_U1|, |_U2|, ... to such -names across the repository. Thus |fruit*| might become |fruit_U176|, and it -is guaranteed that no other symbol has the same name. - -This stage is needed because whereas the inter language has namespces, so -that the same name can mean different things in different parts of the -program, Inform 6 (mostly) does not. There cannot be two functions with the -same name in any I6 program, for example. - -At the end of this stage, no symbol still has the |MAKE_NAME_UNIQUE| flag. - -@ |reconcile-verbs| is a short stage looking for clashes between any verbs (in -the parser interactive fiction sense) which have been assimilated from the -template, and verbs which have been defined in the main source text. For -example, suppose the source creates the command verb "abstract": this would -collide with the command meta-verb "abstract", intended for debugging, which -appears in the template. What this stage does is to detect such problems, -and if it finds one, to prefix the template verb with |!|. Thus we would end -up with two command verbs: |abstract|, with its source text meaning, and -|!abstract|, with its template meaning. - -At the end of this stage, all parser verbs have distinct textual forms. - -@ |eliminate-redundant-labels| performs peephole optimisation on all of -the functions in the repository to remove all labels which are declared -but can never be jumped to. - -At the end of this stage, all labels inside functions are targets of some -branch, either by |inv !jump| or in assembly language. - -@ |generate-inter:F| writes out the repository as a textual inter file |F|. -(By default, Inform doesn't do this: the inter ordinarily stays in memory -throughout.) - -This stage leaves the repository unchanged. - -@ |generate-inter-binary:F| writes out the repository as a binary inter -file |F|. (By default, Inform doesn't do this: the inter ordinarily stays in -memory throughout.) - -This stage leaves the repository unchanged. - -@ |generate-i6:F| translates the repository to an Inform 6 program. This is -normally the final stage in the Inform code generation chain. - -This stage leaves the repository unchanged. - -@h Diagnostic or non-working stages. - -@ |show-dependencies:F| and |log-dependencies| output a dependency graph of -the symbols in the current repository, one to a file, the other to the -debugging log. A dependency means that one can't be compiled without the -other: for example, if a function has a local variable of a given kind, then -the function depends on that kind. - -|eliminate-redundant-code| is a stage which removes all material from -the repository which the main routine is not dependent on. This can result -in many template routines being kicked out, and substantially reduces -story file sizes. The stage mostly works, but needs more refinement before -we could safely enable it by default with Inform. - -@ |summarise:F| is a very slow diagnostic stage showing the breakdown of the -current repository into packages, writing the output to file |F|. (Slow in -this sense means that it roughly triples compilation time.) - -@ |export:F| and |import:F| were part of an experiment to do with caching the -inter generated by the Standard Rules. This eventually worked, but was put on -ice while a better and more systematic solution was found. diff --git a/inter/Preliminaries/Pipelines and Stages.w b/inter/Preliminaries/Pipelines and Stages.w new file mode 100644 index 000000000..2659c5903 --- /dev/null +++ b/inter/Preliminaries/Pipelines and Stages.w @@ -0,0 +1,238 @@ +Pipelines and Stages. + +Sequences of named code-generation stages are called pipelines. + +@h Stages and descriptions. +A processing stage is a step in code generation which acts on a repository +of inter in memory. Some stages change, add to or edit down that code, while +others leave it untouched but output a file based on it. + +Each stage can see an entire repository of inter code at a time, and is +not restricted to working through it in sequence. + +Stages are named, which are written without spaces, and conventionally use +hyphens: for example, |resolve-conditional-compilation|. Where a filename has +to be supplied, it appears after a colon. Thus |generate-inter:my.intert| +is a valid stage description. + +A "pipeline" is a list of stage descriptions. If the pipeline is spelled +out textually on the command line, then commas are used to divide the stages: + + |$ inter/Tangled/inter -pipeline 'plugh, xyzzy, plover'| + +If the pipeline is in an external file, then one stage should appear on +each line, and the comma is not needed: + + |plugh| + |xyzzy| + |plover| + +@ A pipeline can work on up to 10 different repositories, called |0| to |9|, +which are initially empty (but see below). + +A pipeline description can make use of "variables". These hold only text, +and generally represent filenames. Variable names begin with a star |*|. +The pipeline cannot create variables: instead, the user of the pipeline has +to make them before use. For example, + + |$ inter/Tangled/inter -variable '*X=ex/why' -pipeline-file mypl.interpipeline| + +creates the variable |*X| with the textual contents |ex/why| before running +the given pipeline. Inside the pipeline, a line such as: + + |generate: inform6 -> *X| + +would then be read as: + + |generate: inform6 -> ex/why| + +After variable substitution like this, filenames inside the pipeline +description are interpreted as follows: + +(a) If a filename contains a slash character, it is considered a literal +filename. +(b) If not, it is considered to be a leafname inside the "domain" directory. +By default this is the current working directory, but using |-domain| at +the Inter command line changes that. + +The special variable |*log|, which always exists, means the debugging log. +A command to write a text file to |*log| is interpreted instead to mean +"spool the output you would otherwise write to the debugging log instead". +For example, + + |generate: inventory -> *log| + +Template filenames are a little different: those are searched for inside +a path of possible directories. By default there's no such path, but using +|-template T| at the Inter command line gives a path of just one directory. + +@h Pipelines run by Inform. +As the above implies, Inter pipelines normally begin with a clean slate: +no repositories, no variables. + +When a pipeline is being run by the main Inform 7 compiler, however, +repository |0| will be preloaded with the inter code Inform has generated +in memory. The variable |*out| is set to the filename to which final I6 code +needs to be written, and the "domain" is the directory containing that. +The template search path is set to the one used in Inform, that is, the +template file |Whatever.i6t| would be looked for first in the project's +|X.materials/I6T| directory, then in the user's |I6T| directory, and failing +that in Inform's built-in one. + +The pipeline is itself looked for in the same way. If you have a project +called |Strange.inform|, then Inform first looks for + + |Strange.materials/Inter/default.interpipeline| + +If it can't find this file, it next looks for |default.interpipeline| in +the user's folder, and then in Inform's built-in one. If you're curious to +read the pipeline normally used by a shipping version of Inform, the file +can be found here in the Github repository for Inform: + + |inform7/Internal/Inter/default.interpipeline| + +The best way to change the pipeline, then, is to put a new file in the +project's Materials folder. But there are also two other ways. + +1. This sentence: + +>> Use inter pipeline "PIPELINE". + +replaces the pipeline normally used for code generation with the one supplied. +(That may very well cause the compiler not to produce viable code, of course.) + +2. A replacement pipeline can be specified at the Inform 7 command line: + + |$ inform7/Tangled/inform7 ... -pipeline 'PIPELINE'| + +Exactly as with Inter, Inform 7 also responds to |-pipeline-file|: + + |$ inform7/Tangled/inform7 ... -pipeline-file FILE| + +@h Reading and generating. +The |read| stage reads Inter from a file into a repository in memory. +(Its previous contents, if any, are discarded.) This then becomes the +repository to which subsequent stages apply. The format is: + + |read REPOSITORY <- FILE| + +where |REPOSITORY| is |0| to |9|. Conventionally, we use |0| most of the time. +The |FILE| can contain either binary or textual Inter, and this is +automatically detected. + + |generate: FORMAT -> FILE| + +writes the contents of the current repository out into the given |FILE|. +There are several possible formats: |binary| and |text| mean a binary or +textual Inter file, |inventory| means a textual summary of the contents, +and |inform6| means an Inform 6 program. + +The |generate| stage leaves the repository unchanged, so it's possible +to generate multiple representations of the same repository into different +files. + +@h The code-generation stages. +The following are all experimental, and have probably not yet reached their +final form or names. + +Although one thinks of code generation as a process of turning inter into +Inform 6, in fact it goes both ways, because we also have to read in +the "template" of standing Inform 6 code. The early code generation stages +convert the template from Inform 6 into inter, merging it with the inter +already produced by the front end of the compiler. The later stages then +turn this merged repository into Inform 6 code. (Routines in the template, +therefore, are converted out of Inform 6 and then back into it again. This +sounds inefficient but is surprisingly fast, and enables many optimisations.) + +@ |link:T| reads in the I6T template file T, converts it to inter in a very +basic way (creating many splats), and merges it with the repository. Splats +are the unhappiest of inter statements, simply including verbatim snippets +of Inform 6 code. + +@ |parse-linked-matter| examines the splats produced by linking and annotates +them by what they seem to want to do. For example, + + |splat &"Global nitwit = 2;\n"| + +is recognised as an Inform 6 variable declaration, and annotated thus: + + |splat GLOBAL &"Global nitwit = 2;\n"| + +@ |resolve-conditional-compilation| looks for splats arising from Inform 6 +conditional compilation directives such as |#ifdef|, |#ifndef|, |#endif|; +it then detects whether the relevant symbols are defined, or looks at their +values, and deletes sections of code not to be compiled. At the end of this +stage, there are no conditional compilation splats left in the repository. +For example: + + |constant MAGIC K_number = 16339| + |splat IFTRUE &"#iftrue MAGIC == 16339;\n"| + |constant WIZARD K_number = 5| + |splat IFNOT &"#ifnot;\n"| + |constant MUGGLE K_number = 0| + |splat ENDIF &"#endif;\n"| + +is resolved to: + + |constant MAGIC K_number = 16339| + |constant WIZARD K_number = 5| + +@ |assimilate| aims to convert all remaining splats in the repository into +higher-level inter statements. For example, + + |splat STUB &"#Stub Peach 0;\n"| + |splat ATTRIBUTE &"Attribute marmorial;\n"| + +becomes: + + |constant Peach K_unchecked_function = Peach_B __assimilated=1| + |property marmorial K_truth_state __assimilated=1 __attribute=1 __either_or=1| + +At the end of this stage, there should be no splats left in the repository, +and the linking process is complete. + +@ |make-identifiers-unique| looks for symbols marked with the |MAKE_NAME_UNIQUE| +flag (represented in textual form by an asterisk after its name), This flag +means that Inform wants the symbol name to be globally unique in the repository. +For example, if Inform generates the symbol name |fruit*|, it's really telling +the code generator that it eventually wants this to have a name which won't +collide with anything else. + +What |make-identifiers-unique| does is to append |_U1|, |_U2|, ... to such +names across the repository. Thus |fruit*| might become |fruit_U176|, and it +is guaranteed that no other symbol has the same name. + +This stage is needed because whereas the inter language has namespces, so +that the same name can mean different things in different parts of the +program, Inform 6 (mostly) does not. There cannot be two functions with the +same name in any I6 program, for example. + +At the end of this stage, no symbol still has the |MAKE_NAME_UNIQUE| flag. + +@ |reconcile-verbs| is a short stage looking for clashes between any verbs (in +the parser interactive fiction sense) which have been assimilated from the +template, and verbs which have been defined in the main source text. For +example, suppose the source creates the command verb "abstract": this would +collide with the command meta-verb "abstract", intended for debugging, which +appears in the template. What this stage does is to detect such problems, +and if it finds one, to prefix the template verb with |!|. Thus we would end +up with two command verbs: |abstract|, with its source text meaning, and +|!abstract|, with its template meaning. + +At the end of this stage, all parser verbs have distinct textual forms. + +@ |eliminate-redundant-code| deletes all packages which Inter can prove +will not be used in the final code generated from the repository. For +example, functions never called, or arrays never referred to, are deleted. + +@ |eliminate-redundant-labels| performs peephole optimisation on all of +the functions in the repository to remove all labels which are declared +but can never be jumped to. + +At the end of this stage, all labels inside functions are targets of some +branch, either by |inv !jump| or in assembly language. + +@ The special stage |stop| halts processing of the pipeline midway. At present +this is only useful for making experimental edits to pipeline descriptions +to see what just the first half does, without deleting the second half of +the description. diff --git a/inter/Preliminaries/Using Inter.w b/inter/Preliminaries/Using Inter.w index 6db132f9d..79550bf97 100644 --- a/inter/Preliminaries/Using Inter.w +++ b/inter/Preliminaries/Using Inter.w @@ -19,22 +19,21 @@ or for future applications of inter code. @h Command-line usage. If you have compiled the standard distribution of the command-line tools for Inform then the Inter executable will be at |inter/Tangled/inter|. -The usage is: - |$ inter/Tangled/inter FILE1 FILE2 ... [OPTIONS]| +Inter has three basic modes. In the first, the command line specifies only +a single file: -Though multiple files can be supplied, it's usual to supply just one. + |$ inter/Tangled/inter INTERFILE| + +Inter simply verifies this file for correctness: that is, to see if the inter +code supplied conforms to the inter specification. It returns the exit code 0 +if all is well, and issues error messages and returns 1 if not. Such files can be in either textual or binary form, and Inter automatically detects which by looking at their contents. (Conventionally, such files have the filename extension |.intert| or |.interb| respectively, but that's not how Inter decides.) -@ Inter has three basic modes. In the first, when no options are supplied, -Inter simply verifies its input for correctness: that is, to see if the inter -code supplied conforms to the inter specification. It returns the exit code 0 -if all is well, and issues error messages and returns 1 if not. - @ In the second mode, Inter converts from textual to binary form or vice versa. The option |-binary X| writes a binary form of the inter to file |X|, and |-textual X| writes a text form. So, for example, @@ -47,24 +46,30 @@ converts |my.intert| (a textual inter file) to its binary equivalent |$ inter/Tangled/inter my.interb -textual my.intert| @ In the third and most flexible mode, Inter runs the supplied code through -a "chain" of processing stages. The chain, which must contain at least -one stage, is a textual list of comma-separated stage names. For example, +a pipeline of processing stages. The pipeline, which must contain at least +one stage, can be quite elaborate (see later), but for example: - |resolve-conditional-compilation,assimilate,make-identifiers-unique| + |read: 0 <- myfile.inter, resolve-conditional-compilation, generate: inform6 -> myfile.i6| -is a valid three-stage chain. The command to do this is then: +is a valid three-stage pipeline. The command to do this is then: - |$ inter/Tangled/inter my.intert -inter 'CHAIN'| + |$ inter/Tangled/inter -pipeline 'PIPELINE'| -where |CHAIN| is the chain description. +where |PIPELINE| is a textual description like the one above. In practice, +it may not be convenient to spell the pipeline out on the command line, so +one can also put it into a text file: -In practice, this will only be useful if you can access the result, so it's -normal for the final stage to output something: perhaps Inform 6 code, perhaps -textual inter. For example: + |$ inter/Tangled/inter -pipeline-file mypl.interpipeline| - |$ inter/Tangled/inter in.intert -inter 'parse-linked-matter, generate-inter:out.intert'| +Pipelines can contain variables, and their values can be set at the command +line with e.g.: -Two more options may be helpful to supplement this: |-domain D| sets the -directory |D| to be the default location for reading and writing inter files; -and |-template T| tells Inter that it can find the I6T template files at -the file system location |T|. (Some code-generation stages import these.) + |-variable '*out=myfile.i6'| + +It is also possible to set the default directory for reading and writing files: + + |-domain D| + +Finally, we can tell Inter where to find I6T template files: + + |-template T| diff --git a/inter/Tests/Assimilate/Assim.intert b/inter/Tests/General/Assim.intert similarity index 100% rename from inter/Tests/Assimilate/Assim.intert rename to inter/Tests/General/Assim.intert diff --git a/inter/Tests/Generations/Cons.intert b/inter/Tests/General/Cons.intert similarity index 100% rename from inter/Tests/Generations/Cons.intert rename to inter/Tests/General/Cons.intert diff --git a/inter/Tests/RCC/EasyRCC.intert b/inter/Tests/General/EasyRCC.intert similarity index 100% rename from inter/Tests/RCC/EasyRCC.intert rename to inter/Tests/General/EasyRCC.intert diff --git a/inter/Tests/RCC/IftrueRCC.intert b/inter/Tests/General/IftrueRCC.intert similarity index 100% rename from inter/Tests/RCC/IftrueRCC.intert rename to inter/Tests/General/IftrueRCC.intert diff --git a/inter/Tests/Generations/ObjKind.intert b/inter/Tests/General/ObjKind.intert similarity index 100% rename from inter/Tests/Generations/ObjKind.intert rename to inter/Tests/General/ObjKind.intert diff --git a/inter/Tests/PLM/PLM.intert b/inter/Tests/General/PLM.intert similarity index 100% rename from inter/Tests/PLM/PLM.intert rename to inter/Tests/General/PLM.intert diff --git a/inter/Tests/Generations/Predeclared.intert b/inter/Tests/General/Predeclared.intert similarity index 100% rename from inter/Tests/Generations/Predeclared.intert rename to inter/Tests/General/Predeclared.intert diff --git a/inter/Tests/Generations/Primitives.intert b/inter/Tests/General/Primitives.intert similarity index 100% rename from inter/Tests/Generations/Primitives.intert rename to inter/Tests/General/Primitives.intert diff --git a/inter/Tests/ERL/Redundancies.intert b/inter/Tests/General/Redundancies.intert similarity index 100% rename from inter/Tests/ERL/Redundancies.intert rename to inter/Tests/General/Redundancies.intert diff --git a/inter/Tests/Generations/SimpleKind.intert b/inter/Tests/General/SimpleKind.intert similarity index 100% rename from inter/Tests/Generations/SimpleKind.intert rename to inter/Tests/General/SimpleKind.intert diff --git a/inter/Tests/Generations/SimpleRoutines.intert b/inter/Tests/General/SimpleRoutines.intert similarity index 100% rename from inter/Tests/Generations/SimpleRoutines.intert rename to inter/Tests/General/SimpleRoutines.intert diff --git a/inter/Tests/General/_Pipelines/Assim.interpipeline b/inter/Tests/General/_Pipelines/Assim.interpipeline new file mode 100644 index 000000000..93be701ea --- /dev/null +++ b/inter/Tests/General/_Pipelines/Assim.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +assimilate +resolve-external-symbols +generate: text -> *out diff --git a/inter/Tests/General/_Pipelines/Cons.interpipeline b/inter/Tests/General/_Pipelines/Cons.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/Cons.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/General/_Pipelines/EasyRCC.interpipeline b/inter/Tests/General/_Pipelines/EasyRCC.interpipeline new file mode 100644 index 000000000..bb7bf9b2e --- /dev/null +++ b/inter/Tests/General/_Pipelines/EasyRCC.interpipeline @@ -0,0 +1,4 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +generate: text -> *out diff --git a/inter/Tests/General/_Pipelines/IftrueRCC.interpipeline b/inter/Tests/General/_Pipelines/IftrueRCC.interpipeline new file mode 100644 index 000000000..bb7bf9b2e --- /dev/null +++ b/inter/Tests/General/_Pipelines/IftrueRCC.interpipeline @@ -0,0 +1,4 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +generate: text -> *out diff --git a/inter/Tests/General/_Pipelines/ObjKind.interpipeline b/inter/Tests/General/_Pipelines/ObjKind.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/ObjKind.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/General/_Pipelines/PLM.interpipeline b/inter/Tests/General/_Pipelines/PLM.interpipeline new file mode 100644 index 000000000..a3f007dd9 --- /dev/null +++ b/inter/Tests/General/_Pipelines/PLM.interpipeline @@ -0,0 +1,3 @@ +read: 0 <- *in +parse-linked-matter +generate: text -> *out diff --git a/inter/Tests/General/_Pipelines/Predeclared.interpipeline b/inter/Tests/General/_Pipelines/Predeclared.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/Predeclared.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/General/_Pipelines/Primitives.interpipeline b/inter/Tests/General/_Pipelines/Primitives.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/Primitives.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/General/_Pipelines/Redundancies.interpipeline b/inter/Tests/General/_Pipelines/Redundancies.interpipeline new file mode 100644 index 000000000..04d724ce0 --- /dev/null +++ b/inter/Tests/General/_Pipelines/Redundancies.interpipeline @@ -0,0 +1,3 @@ +read: 0 <- *in +eliminate-redundant-labels +generate: text -> *out diff --git a/inter/Tests/General/_Pipelines/SimpleKind.interpipeline b/inter/Tests/General/_Pipelines/SimpleKind.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/SimpleKind.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/General/_Pipelines/SimpleRoutines.interpipeline b/inter/Tests/General/_Pipelines/SimpleRoutines.interpipeline new file mode 100644 index 000000000..34bc26d17 --- /dev/null +++ b/inter/Tests/General/_Pipelines/SimpleRoutines.interpipeline @@ -0,0 +1,5 @@ +read: 0 <- *in +parse-linked-matter +resolve-conditional-compilation +assimilate +generate: inform6 -> *out diff --git a/inter/Tests/Assimilate/_Results_Ideal/Assim.txt b/inter/Tests/General/_Results_Ideal/Assim.txt similarity index 100% rename from inter/Tests/Assimilate/_Results_Ideal/Assim.txt rename to inter/Tests/General/_Results_Ideal/Assim.txt diff --git a/inter/Tests/Generations/_Results_Ideal/Cons.txt b/inter/Tests/General/_Results_Ideal/Cons.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/Cons.txt rename to inter/Tests/General/_Results_Ideal/Cons.txt diff --git a/inter/Tests/RCC/_Results_Ideal/EasyRCC.txt b/inter/Tests/General/_Results_Ideal/EasyRCC.txt similarity index 100% rename from inter/Tests/RCC/_Results_Ideal/EasyRCC.txt rename to inter/Tests/General/_Results_Ideal/EasyRCC.txt diff --git a/inter/Tests/RCC/_Results_Ideal/IftrueRCC.txt b/inter/Tests/General/_Results_Ideal/IftrueRCC.txt similarity index 100% rename from inter/Tests/RCC/_Results_Ideal/IftrueRCC.txt rename to inter/Tests/General/_Results_Ideal/IftrueRCC.txt diff --git a/inter/Tests/Generations/_Results_Ideal/ObjKind.txt b/inter/Tests/General/_Results_Ideal/ObjKind.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/ObjKind.txt rename to inter/Tests/General/_Results_Ideal/ObjKind.txt diff --git a/inter/Tests/PLM/_Results_Ideal/PLM.txt b/inter/Tests/General/_Results_Ideal/PLM.txt similarity index 100% rename from inter/Tests/PLM/_Results_Ideal/PLM.txt rename to inter/Tests/General/_Results_Ideal/PLM.txt diff --git a/inter/Tests/Generations/_Results_Ideal/Predeclared.txt b/inter/Tests/General/_Results_Ideal/Predeclared.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/Predeclared.txt rename to inter/Tests/General/_Results_Ideal/Predeclared.txt diff --git a/inter/Tests/Generations/_Results_Ideal/Primitives.txt b/inter/Tests/General/_Results_Ideal/Primitives.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/Primitives.txt rename to inter/Tests/General/_Results_Ideal/Primitives.txt diff --git a/inter/Tests/ERL/_Results_Ideal/Redundancies.txt b/inter/Tests/General/_Results_Ideal/Redundancies.txt similarity index 100% rename from inter/Tests/ERL/_Results_Ideal/Redundancies.txt rename to inter/Tests/General/_Results_Ideal/Redundancies.txt diff --git a/inter/Tests/Generations/_Results_Ideal/SimpleKind.txt b/inter/Tests/General/_Results_Ideal/SimpleKind.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/SimpleKind.txt rename to inter/Tests/General/_Results_Ideal/SimpleKind.txt diff --git a/inter/Tests/Generations/_Results_Ideal/SimpleRoutines.txt b/inter/Tests/General/_Results_Ideal/SimpleRoutines.txt similarity index 100% rename from inter/Tests/Generations/_Results_Ideal/SimpleRoutines.txt rename to inter/Tests/General/_Results_Ideal/SimpleRoutines.txt diff --git a/inter/Tests/inter.intest b/inter/Tests/inter.intest index 51c4e6d2b..c475e5ed7 100644 --- a/inter/Tests/inter.intest +++ b/inter/Tests/inter.intest @@ -1,11 +1,7 @@ -cases [Valid] 'inter/Tests/Valid' -cases [Invalid] 'inter/Tests/Invalid' --cases [Generations] 'inter/Tests/Generations' --cases [RCC] 'inter/Tests/RCC' --cases [PLM] 'inter/Tests/PLM' --cases [Assimilate] 'inter/Tests/Assimilate' +-cases [General] 'inter/Tests/General' -cases [Units] 'inter/Tests/Units' --cases [ERL] 'inter/Tests/ERL' -recipe [Valid] @@ -50,9 +46,10 @@ -end --recipe [Generations] +-recipe [General] set: $O = $PATH/$CASE.intert + set: $P = $PATH/_Pipelines/$CASE.interpipeline set: $A = $PATH/_Results_Actual/$CASE.txt set: $I = $PATH/_Results_Ideal/$CASE.txt set: $T = $PATH/_Console/$CASE.txt @@ -61,91 +58,7 @@ mkdir: $PATH/_Results_Ideal mkdir: $PATH/_Console - step: inter/Tangled/inter $O -inter 'parse-linked-matter, resolve-conditional-compilation, assimilate, generate: inform6 -> $A' >$T 2>&1 - or: 'failed to produce output' $T - - show: $A - - match text: $A $I - or: 'produced incorrect output' - --end - --recipe [RCC] - - set: $O = $PATH/$CASE.intert - set: $A = $PATH/_Results_Actual/$CASE.txt - set: $I = $PATH/_Results_Ideal/$CASE.txt - set: $T = $PATH/_Console/$CASE.txt - - mkdir: $PATH/_Results_Actual - mkdir: $PATH/_Results_Ideal - mkdir: $PATH/_Console - - step: inter/Tangled/inter $O -inter 'parse-linked-matter, resolve-conditional-compilation, generate: text ->$A' >$T 2>&1 - or: 'failed to produce output' $T - - show: $A - - match text: $A $I - or: 'produced incorrect output' - --end - --recipe [PLM] - - set: $O = $PATH/$CASE.intert - set: $A = $PATH/_Results_Actual/$CASE.txt - set: $I = $PATH/_Results_Ideal/$CASE.txt - set: $T = $PATH/_Console/$CASE.txt - - mkdir: $PATH/_Results_Actual - mkdir: $PATH/_Results_Ideal - mkdir: $PATH/_Console - - step: inter/Tangled/inter $O -inter 'parse-linked-matter, generate: text ->$A' >$T 2>&1 - or: 'failed to produce output' $T - - show: $A - - match text: $A $I - or: 'produced incorrect output' - --end - --recipe [ERL] - - set: $O = $PATH/$CASE.intert - set: $A = $PATH/_Results_Actual/$CASE.txt - set: $I = $PATH/_Results_Ideal/$CASE.txt - set: $T = $PATH/_Console/$CASE.txt - - mkdir: $PATH/_Results_Actual - mkdir: $PATH/_Results_Ideal - mkdir: $PATH/_Console - - step: inter/Tangled/inter $O -inter 'eliminate-redundant-labels, generate: text ->$A' >$T 2>&1 - or: 'failed to produce output' $T - - show: $A - - match text: $A $I - or: 'produced incorrect output' - --end - --recipe [Assimilate] - - set: $O = $PATH/$CASE.intert - set: $A = $PATH/_Results_Actual/$CASE.txt - set: $I = $PATH/_Results_Ideal/$CASE.txt - set: $T = $PATH/_Console/$CASE.txt - - mkdir: $PATH/_Results_Actual - mkdir: $PATH/_Results_Ideal - mkdir: $PATH/_Console - - step: inter/Tangled/inter $O -inter 'parse-linked-matter, assimilate, resolve-external-symbols, generate: text ->$A' >$T 2>&1 + step: inter/Tangled/inter -variable '*in=$O' -variable '*out=$A' -pipeline-file $P >$T 2>&1 or: 'failed to produce output' $T show: $A diff --git a/inter/codegen-module/Chapter 1/Pipelines.w b/inter/codegen-module/Chapter 1/Pipelines.w index 497c55a3b..47edcc31c 100644 --- a/inter/codegen-module/Chapter 1/Pipelines.w +++ b/inter/codegen-module/Chapter 1/Pipelines.w @@ -18,6 +18,7 @@ typedef struct pipeline_step { struct pathname **the_PP; int the_N; int to_debugging_log; + int repository_argument; struct text_stream *text_out_file; struct inter_repository *repository; MEMORY_MANAGEMENT @@ -28,6 +29,7 @@ pipeline_step *CodeGen::Pipeline::new_step(void) { step->step_stage = NULL; step->step_argument = NULL; step->package_argument = NULL; + step->repository_argument = -1; CodeGen::Pipeline::clean_step(step); return step; } @@ -53,18 +55,22 @@ void CodeGen::Pipeline::write_step(OUTPUT_STREAM, pipeline_step *step) { if (step->step_stage->stage_arg != NO_STAGE_ARG) { if (step->package_argument) WRITE(" %S", step->package_argument); WRITE(":"); + if (step->repository_argument >= 0) WRITE(" %d <-", step->repository_argument); if (step->target_argument) WRITE(" %S ->", step->target_argument->target_name); WRITE(" %S", step->step_argument); } } -pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, text_stream *leafname) { +pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, dictionary *D) { CodeGen::Stage::make_stages(); CodeGen::Targets::make_targets(); pipeline_step *ST = CodeGen::Pipeline::new_step(); match_results mr = Regexp::create_mr(); - if (Regexp::match(&mr, step, L"(%c+?) *: *(%C*) *-> *(%c*)")) { - ST->step_argument = Str::new(); + if (Regexp::match(&mr, step, L"(%c+?) *: *(%d) *<- *(%c*)")) { + ST->repository_argument = Str::atoi(mr.exp[1], 0); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[2], D); + Str::copy(step, mr.exp[0]); + } else if (Regexp::match(&mr, step, L"(%c+?) *: *(%C*) *-> *(%c*)")) { code_generation_target *cgt; LOOP_OVER(cgt, code_generation_target) if (Str::eq(mr.exp[1], cgt->target_name)) @@ -73,18 +79,14 @@ pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, text_stream *leaf WRITE_TO(STDERR, "No such code generation target as '%S'\n", mr.exp[1]); internal_error("no such target"); } - Str::copy(ST->step_argument, mr.exp[2]); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[2], D); Str::copy(step, mr.exp[0]); - if (Str::eq(ST->step_argument, I"*")) Str::copy(ST->step_argument, leafname); } else if (Regexp::match(&mr, step, L"(%c+?) *: *(%c*)")) { - ST->step_argument = Str::new(); - Str::copy(ST->step_argument, mr.exp[1]); + ST->step_argument = CodeGen::Pipeline::read_parameter(mr.exp[1], D); Str::copy(step, mr.exp[0]); - if (Str::eq(ST->step_argument, I"*")) Str::copy(ST->step_argument, leafname); } if (Regexp::match(&mr, step, L"(%C+?) (%c+)")) { - ST->package_argument = Str::new(); - Str::copy(ST->package_argument, mr.exp[1]); + ST->package_argument = CodeGen::Pipeline::read_parameter(mr.exp[1], D); Str::copy(step, mr.exp[0]); } @@ -100,30 +102,65 @@ pipeline_step *CodeGen::Pipeline::read_step(text_stream *step, text_stream *leaf return ST; } +text_stream *CodeGen::Pipeline::read_parameter(text_stream *from, dictionary *D) { + if (Str::get_first_char(from) == '*') { + text_stream *find = Dictionaries::get_text(D, from); + if (find) return Str::duplicate(find); + WRITE_TO(STDERR, "No such pipeline variable as '%S'\n", from); + internal_error("no such pipeline variable"); + } + return Str::duplicate(from); +} + @h Pipelines. And then a pipeline is just a linked list of steps. = typedef struct codegen_pipeline { + struct dictionary *variables; + struct inter_repository *repositories[10]; struct linked_list *steps; /* of |pipeline_step| */ MEMORY_MANAGEMENT } codegen_pipeline; -codegen_pipeline *CodeGen::Pipeline::new(void) { +dictionary *CodeGen::Pipeline::basic_dictionary(text_stream *leafname) { + dictionary *D = Dictionaries::new(16, TRUE); + if (Str::len(leafname) > 0) Str::copy(Dictionaries::create_text(D, I"*out"), leafname); + Str::copy(Dictionaries::create_text(D, I"*log"), I"*log"); + return D; +} + +codegen_pipeline *CodeGen::Pipeline::new(dictionary *D) { codegen_pipeline *S = CREATE(codegen_pipeline); + S->variables = D; S->steps = NEW_LINKED_LIST(pipeline_step); + for (int i=0; i<10; i++) S->repositories[i] = NULL; return S; } -codegen_pipeline *CodeGen::Pipeline::parse(text_stream *instructions, text_stream *leafname) { - codegen_pipeline *S = CodeGen::Pipeline::new(); - CodeGen::Pipeline::parse_into(S, instructions, leafname); +codegen_pipeline *CodeGen::Pipeline::parse_from_file(filename *F, dictionary *D) { + TEMPORARY_TEXT(A); + TextFiles::read(F, FALSE, "can't open inter pipeline file", + TRUE, CodeGen::Pipeline::scan_line, NULL, (void *) A); + codegen_pipeline *S = CodeGen::Pipeline::new(D); + CodeGen::Pipeline::parse_into(S, A); + DISCARD_TEXT(A); return S; } -void CodeGen::Pipeline::parse_into(codegen_pipeline *S, text_stream *instructions, text_stream *leafname) { - if (instructions == NULL) - instructions = I"link:Output.i6t, parse-linked-matter, resolve-conditional-compilation, assimilate, reconcile-verbs, generate: inform6 -> *"; +void CodeGen::Pipeline::scan_line(text_stream *line, text_file_position *tfp, void *X) { + text_stream *A = (text_stream *) X; + if (Str::len(A) > 0) WRITE_TO(A, ", "); + WRITE_TO(A, "%S", line); +} + +codegen_pipeline *CodeGen::Pipeline::parse(text_stream *instructions, dictionary *D) { + codegen_pipeline *S = CodeGen::Pipeline::new(D); + CodeGen::Pipeline::parse_into(S, instructions); + return S; +} + +void CodeGen::Pipeline::parse_into(codegen_pipeline *S, text_stream *instructions) { TEMPORARY_TEXT(T); LOOP_THROUGH_TEXT(P, instructions) if (Characters::is_babel_whitespace(Str::get(P))) @@ -131,30 +168,35 @@ void CodeGen::Pipeline::parse_into(codegen_pipeline *S, text_stream *instruction else PUT_TO(T, Str::get(P)); match_results mr = Regexp::create_mr(); - while (Regexp::match(&mr, T, L" *(%c+?) *, *(%c*?) *")) { - pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], leafname); - ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps); + while (Regexp::match(&mr, T, L" *(%c+?) *,+ *(%c*?) *")) { + pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], S->variables); + if (ST) ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps); Str::copy(T, mr.exp[1]); } if (Regexp::match(&mr, T, L" *(%c+?) *")) { - pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], leafname); - ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps); + pipeline_step *ST = CodeGen::Pipeline::read_step(mr.exp[0], S->variables); + if (ST) ADD_TO_LINKED_LIST(ST, pipeline_step, S->steps); } } -void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, inter_repository *I, int N, pathname **PP, pathname *PM, pathname *FM) { - if (S == NULL) return; - clock_t start = clock(); +void CodeGen::Pipeline::set_repository(codegen_pipeline *S, inter_repository *I) { + S->repositories[0] = I; +} - CodeGen::Pipeline::prepare_to_run(I); +void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, int N, pathname **PP) { + if (S == NULL) return; + if (S->repositories[0] == NULL) S->repositories[0] = Inter::create(1, 32); + clock_t start = clock(); int step_count = 0, step_total = 0; pipeline_step *step; LOOP_OVER_LINKED_LIST(step, pipeline_step, S->steps) step_total++; - int active = TRUE; + int active = TRUE, current_repo = 0; + CodeGen::Pipeline::prepare_to_run(S->repositories[current_repo]); LOOP_OVER_LINKED_LIST(step, pipeline_step, S->steps) if (active) { + inter_repository *I = S->repositories[current_repo]; CodeGen::Pipeline::lint(I); CodeGen::Pipeline::clean_step(step); @@ -173,18 +215,17 @@ void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, inter_repository * (step->step_stage->stage_arg == TEXT_OUT_STAGE_ARG) || (step->step_stage->stage_arg == EXT_FILE_STAGE_ARG) || (step->step_stage->stage_arg == EXT_TEXT_OUT_STAGE_ARG)) { - if (Str::eq(step->step_argument, I"log")) { + if (Str::eq(step->step_argument, I"*log")) { step->to_debugging_log = TRUE; } else { + step->parsed_filename = Filenames::from_text(step->step_argument); int slashes = FALSE; LOOP_THROUGH_TEXT(pos, step->step_argument) if (Str::get(pos) == '/') slashes = TRUE; if (slashes) step->parsed_filename = Filenames::from_text(step->step_argument); - else if ((step->step_stage->stage_arg == EXT_FILE_STAGE_ARG) || - (step->step_stage->stage_arg == EXT_TEXT_OUT_STAGE_ARG)) - step->parsed_filename = Filenames::in_folder(FM, step->step_argument); else step->parsed_filename = Filenames::in_folder(P, step->step_argument); + LOG("Parsed %S == %f\n", step->step_argument, step->parsed_filename); } } @@ -213,6 +254,11 @@ void CodeGen::Pipeline::run(pathname *P, codegen_pipeline *S, inter_repository * (step->to_debugging_log == FALSE)) { STREAM_CLOSE(T); } + + if (step->repository_argument >= 0) { + current_repo = step->repository_argument; + CodeGen::Pipeline::prepare_to_run(S->repositories[current_repo]); + } } } diff --git a/inter/codegen-module/Chapter 1/Stages.w b/inter/codegen-module/Chapter 1/Stages.w index 47cf3785f..092f759c0 100644 --- a/inter/codegen-module/Chapter 1/Stages.w +++ b/inter/codegen-module/Chapter 1/Stages.w @@ -41,6 +41,7 @@ void CodeGen::Stage::make_stages(void) { if (stages_made == FALSE) { stages_made = TRUE; CodeGen::Stage::new(I"stop", CodeGen::Stage::run_stop_stage, NO_STAGE_ARG); + CodeGen::Stage::new(I"read", CodeGen::Stage::run_read_stage, FILE_STAGE_ARG); CodeGen::create_pipeline_stage(); CodeGen::Assimilate::create_pipeline_stage(); @@ -62,3 +63,12 @@ the pipeline: int CodeGen::Stage::run_stop_stage(pipeline_step *step) { return FALSE; } + +int CodeGen::Stage::run_read_stage(pipeline_step *step) { + filename *F = Filenames::from_text(step->step_argument); + if (Inter::Binary::test_file(F)) + Inter::Binary::read(step->repository, F); + else + Inter::Textual::read(step->repository, F); + return TRUE; +} diff --git a/inter/codegen-module/Chapter 2/Assimilate.w b/inter/codegen-module/Chapter 2/Assimilate.w index e3ed0e0e1..bd0201b34 100644 --- a/inter/codegen-module/Chapter 2/Assimilate.w +++ b/inter/codegen-module/Chapter 2/Assimilate.w @@ -143,9 +143,6 @@ void CodeGen::Assimilate::visitor3(inter_repository *I, inter_frame P, void *sta text_stream *suffix = NULL; inter_symbol *subpackage_type = plain_packagetype; - if (plm == ATTRIBUTE_PLM) trace_AME = TRUE; - else trace_AME = FALSE; - switch (plm) { case VERB_PLM: if (command_ptype_symbol) subpackage_type = command_ptype_symbol; diff --git a/inter/codegen-module/Chapter 4/Code Generation.w b/inter/codegen-module/Chapter 4/Code Generation.w index ce3755fe7..d0c1c6512 100644 --- a/inter/codegen-module/Chapter 4/Code Generation.w +++ b/inter/codegen-module/Chapter 4/Code Generation.w @@ -25,6 +25,7 @@ int CodeGen::run_pipeline_stage(pipeline_step *step) { internal_error("that's not a package name"); } } + code_generation *gen = CodeGen::new_generation(step, step->repository, which, step->target_argument); if (CodeGen::Targets::begin_generation(gen) == FALSE) { diff --git a/inter/gitignorescript.txt b/inter/gitignorescript.txt index 5400906a9..1af952cb3 100644 --- a/inter/gitignorescript.txt +++ b/inter/gitignorescript.txt @@ -5,19 +5,9 @@ inter-module/Woven/ inter.mk -Tests/Assimilate/_Results_Actual/ -Tests/Assimilate/_Console/ -Tests/Generations/_Results_Actual/ -Tests/Generations/_Console/ -Tests/Graph/_Results_Actual/ -Tests/Graph/_Console/ Tests/Invalid/_Results_Actual/ -Tests/PLM/_Results_Actual/ -Tests/PLM/_Console/ -Tests/RCC/_Results_Actual/ -Tests/RCC/_Console/ -Tests/ERL/_Results_Actual/ -Tests/ERL/_Console/ +Tests/General/_Results_Actual/ +Tests/General/_Console/ Tests/Valid/_Binary/ Tests/Valid/_Console/ Tests/Valid/_Textual/ diff --git a/scripts/makescript.txt b/scripts/makescript.txt index 1c307cca0..e8540f2a9 100644 --- a/scripts/makescript.txt +++ b/scripts/makescript.txt @@ -436,25 +436,6 @@ define clean-ebooks rm -f resources/Changes/Output/*.* endef -# ----------------------------------------------------------------------------- -# Target "csr" -# ----------------------------------------------------------------------------- -# "make csr" is for use while experimenting with Inter - it caches the Standard -# Rules as inter files, one for Z, one for Glulx. -# ----------------------------------------------------------------------------- - -.PHONY: csr -csr: - cp -f $(INFORM7WEB)/Home.txt $(INTESTWEB)/Workspace/T0/Example.inform/Source/story.ni - 'inform7/Tangled/inform7' '-format=z8' '-noprogress' '-fixtime' '-rng' '-sigils' '-clock' '-log' 'nothing' '-external' 'inform7/Tests' '-transient' 'intest/Workspace/T0/Transient' '-noindex' '-internal' 'inform7/Internal' '-project' 'intest/Workspace/T0/Example.inform' '-export' 'inform7/Internal/I6T/sr-Z.intert' '-inter' 'stop' - $(INTERTOOLWEB)/Tangled/inter inform7/Internal/I6T/sr-Z.intert -binary inform7/Internal/I6T/sr-Z.interb - cp -f inform7/Internal/I6T/sr-Z.intert $(INTERNAL)/I6T/sr-Z.intert - cp -f inform7/Internal/I6T/sr-Z.interb $(INTERNAL)/I6T/sr-Z.interb - 'inform7/Tangled/inform7' '-format=ulx' '-noprogress' '-fixtime' '-rng' '-sigils' '-clock' '-log' 'nothing' '-external' 'inform7/Tests' '-transient' 'intest/Workspace/T0/Transient' '-noindex' '-internal' 'inform7/Internal' '-project' 'intest/Workspace/T0/Example.inform' '-export' 'inform7/Internal/I6T/sr-G.intert' '-inter' 'stop' - $(INTERTOOLWEB)/Tangled/inter inform7/Internal/I6T/sr-G.intert -binary inform7/Internal/I6T/sr-G.interb - cp -f inform7/Internal/I6T/sr-G.intert $(INTERNAL)/I6T/sr-G.intert - cp -f inform7/Internal/I6T/sr-G.interb $(INTERNAL)/I6T/sr-G.interb - # ----------------------------------------------------------------------------- # Targets "integration" and "forceintegration" # ----------------------------------------------------------------------------- @@ -482,6 +463,7 @@ integration: \ $(INTERNAL)/Languages/English/Syntax.preform \ $(SRULESINPLACE) \ $(INTERNAL)/I6T/Main.i6t \ + $(INTERNAL)/Inter/default.interpipeline \ $(INTERNALEXEMPLUM) \ $(IMAGESEXEMPLUM) \ $(DOCEXEMPLUM) \ @@ -493,6 +475,7 @@ forceintegration: $(call transfer-preform) $(call transfer-standard-rules) $(call transfer-i6-template) + $(call transfer-inter-resources) $(call transfer-internal-tree) $(call transfer-images) $(call make-inapp-documentation) @@ -568,6 +551,15 @@ define transfer-i6-template cp -R -f inform7/Internal/I6T/*.i6t $(INTERNAL)/I6T endef +$(INTERNAL)/Inter/default.interpipeline: inform7/Internal/Inter/*.interpipeline + $(call transfer-inter-resources) + +define transfer-inter-resources + mkdir -p "$(INTERNAL)/Inter" + rm -f $(INTERNAL)/Inter/*.interpipeline + cp -R -f inform7/Internal/Inter/*.interpipeline $(INTERNAL)/Inter +endef + # (e) Copying internal resources into the app # The Internal tree also holds built-in extensions, web interpreters and so on.