From ed743bbcb6acfbfd99b9d37d3978e1db9804b2d0 Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Fri, 14 Jul 2023 14:20:05 +0100 Subject: [PATCH] Ranges for literal notation parts not starting from 0 --- README.md | 2 +- build.txt | 4 +- docs/assertions-module/3-nlpr.html | 18 +-- docs/core-module/1-inaa.html | 7 + docs/runtime-module/2-ec.html | 10 +- docs/runtime-module/5-lp.html | 121 +++++++++++------- docs/values-module/3-lp.html | 82 +++++++----- inform7/Figures/memory-diagnostics.txt | 6 +- inform7/Figures/timings-diagnostics.txt | 14 +- .../Inter/Architecture16Kit/kit_metadata.json | 2 +- .../Inter/Architecture32Kit/kit_metadata.json | 2 +- .../Inter/BasicInformKit/kit_metadata.json | 2 +- .../Inter/CommandParserKit/kit_metadata.json | 2 +- .../EnglishLanguageKit/kit_metadata.json | 2 +- .../Inter/WorldModelKit/kit_metadata.json | 2 +- .../Chapter 3/New Literal Pattern Requests.w | 18 +-- .../Inform-Only Nodes and Annotations.w | 7 + .../Chapter 5/Literal Patterns.w | 117 ++++++++++------- .../Chapter 3/Literal Patterns.w | 80 ++++++++---- 19 files changed, 309 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index c0af22d16..8d53d659c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -[Version](notes/versioning.md): 10.2.0-beta+6W80 'Krypton' (13 July 2023) +[Version](notes/versioning.md): 10.2.0-beta+6W81 'Krypton' (14 July 2023) ## About Inform diff --git a/build.txt b/build.txt index 06edd56fd..e203d1503 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: beta -Build Date: 13 July 2023 -Build Number: 6W80 +Build Date: 14 July 2023 +Build Number: 6W81 diff --git a/docs/assertions-module/3-nlpr.html b/docs/assertions-module/3-nlpr.html index 87ee0493b..bc16bd72e 100644 --- a/docs/assertions-module/3-nlpr.html +++ b/docs/assertions-module/3-nlpr.html @@ -413,7 +413,7 @@ by a bracketed list of up to three options in any order. <lp-part> ==> { 0, RP[1] } <lp-part> ::= - <np-unparsed-bal> ( <lp-part-option-list> ) | ==> { 0, LPRequests::mark(RP[1], R[2], <<max_part_val>>) } + <np-unparsed-bal> ( <lp-part-option-list> ) | ==> { 0, LPRequests::mark(RP[1], R[2], <<min_part_val>>, <<max_part_val>>) } <np-unparsed-bal> ==> { 0, RP[1] } <lp-part-option-list> ::= @@ -430,7 +430,7 @@ by a bracketed list of up to three options in any order. with leading zeros | ==> { WITH_LEADING_ZEROS_LSO, - } without leading zeros | ==> { WITHOUT_LEADING_ZEROS_LSO, - } in <number-base> | ==> { BASE_LSO*R[1], - } - <cardinal-number> to <cardinal-number> | ==> <<max_part_val>> = R[2]; Apply range8.1; + <cardinal-number> to <cardinal-number> | ==> <<min_part_val>> = R[1]; <<max_part_val>> = R[2]; Apply range8.1; up to <cardinal-number> <number-base> digit/digits | ==> Apply based max digit count8.4; up to <cardinal-number> digit/digits | ==> Apply max digit count8.2; <cardinal-number> <number-base> digit/digits | ==> Apply based digit count8.5; @@ -442,11 +442,11 @@ by a bracketed list of up to three options in any order.

-    if (R[1] != 0)
+    if (R[1] > R[2])
         StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...),
-            "the range in a named part has to begin at 0",
-            "for the moment at least.");
-    ==> { MAXIMUM_LSO, - };
+            "the minimum value for a named part cannot be greater than the maximum",
+            "or it would be impossible for any value of this kind to exist.");
+    ==> { MINIMUM_LSO + MAXIMUM_LSO, - };
 

§8.2. Apply max digit count8.2 = @@ -527,6 +527,7 @@ by a bracketed list of up to three options in any order. define WITH_LEADING_ZEROS_LSO 0x00000004 define WITHOUT_LEADING_ZEROS_LSO 0x00000008 define MAXIMUM_LSO 0x00000010 +define MINIMUM_LSO 0x00000020 define BASE_LSO 0x00000100 define BASE_MASK_LSO 0x0000ff00 define MIN_DIGITS_LSO 0x00010000 @@ -535,10 +536,11 @@ by a bracketed list of up to three options in any order. define MAX_DIGITS_MASK_LSO 0x7f000000

-parse_node *LPRequests::mark(parse_node *A, int N, int M) {
+parse_node *LPRequests::mark(parse_node *A, int N, int MI, int MA) {
     if (A) {
         Annotations::write_int(A, lpe_options_ANNOT, N);
-        if (N & MAXIMUM_LSO) Annotations::write_int(A, lpe_max_ANNOT, M);
+        if (N & MINIMUM_LSO) Annotations::write_int(A, lpe_min_ANNOT, MI);
+        if (N & MAXIMUM_LSO) Annotations::write_int(A, lpe_max_ANNOT, MA);
     }
     return A;
 }
diff --git a/docs/core-module/1-inaa.html b/docs/core-module/1-inaa.html
index 7a1d98fc4..8430f3d71 100644
--- a/docs/core-module/1-inaa.html
+++ b/docs/core-module/1-inaa.html
@@ -528,6 +528,7 @@ which compilation unit the node belongs.
 enum evaluation_ANNOT  parse_node: result of evaluating the text
 enum explicit_gender_marker_ANNOT   int: used by PROPER NOUN nodes for evident genders
 enum lpe_options_ANNOT  int: options set for a literal pattern part
+enum lpe_min_ANNOT  int: value offset for a literal pattern part
 enum lpe_max_ANNOT  int: maximum value for a literal pattern part
 enum multiplicity_ANNOT  int: e.g., 5 for "five gold rings"
 enum new_relation_here_ANNOT  binary_predicate: new relation as subject of "relates" sentence
@@ -583,6 +584,8 @@ which compilation unit the node belongs.
     Annotations::declare_type(
         lpe_max_ANNOT, CoreSyntax::write_lpe_max_ANNOT);
     Annotations::declare_type(
+        lpe_min_ANNOT, CoreSyntax::write_lpe_min_ANNOT);
+    Annotations::declare_type(
         multiplicity_ANNOT, CoreSyntax::write_multiplicity_ANNOT);
     Annotations::declare_type(
         new_relation_here_ANNOT, CoreSyntax::write_new_relation_here_ANNOT);
@@ -637,6 +640,9 @@ which compilation unit the node belongs.
 void CoreSyntax::write_lpe_max_ANNOT(text_stream *OUT, parse_node *p) {
     WRITE(" {lpe max: %d}", Annotations::read_int(p, lpe_max_ANNOT));
 }
+void CoreSyntax::write_lpe_min_ANNOT(text_stream *OUT, parse_node *p) {
+    WRITE(" {lpe offset: %d}", Annotations::read_int(p, lpe_min_ANNOT));
+}
 void CoreSyntax::write_multiplicity_ANNOT(text_stream *OUT, parse_node *p) {
     if (Annotations::read_int(p, multiplicity_ANNOT))
         WRITE(" {multiplicity %d}", Annotations::read_int(p, multiplicity_ANNOT));
@@ -713,6 +719,7 @@ which compilation unit the node belongs.
     Annotations::allow(PROPER_NOUN_NT, defn_language_ANNOT);
     Annotations::allow(PROPER_NOUN_NT, lpe_options_ANNOT);
     Annotations::allow(PROPER_NOUN_NT, lpe_max_ANNOT);
+    Annotations::allow(PROPER_NOUN_NT, lpe_min_ANNOT);
     Annotations::allow(PROPER_NOUN_NT, multiplicity_ANNOT);
     Annotations::allow(UNPARSED_NOUN_NT, new_relation_here_ANNOT);
     Annotations::allow(PROPER_NOUN_NT, new_relation_here_ANNOT);
diff --git a/docs/runtime-module/2-ec.html b/docs/runtime-module/2-ec.html
index 2dd16c5aa..c921fc0b7 100644
--- a/docs/runtime-module/2-ec.html
+++ b/docs/runtime-module/2-ec.html
@@ -95,10 +95,10 @@ instruction last emitted, not after it.
 
  • EmitCode::up then returns us back to where we were.
  • -void EmitCode::up(void) {
    +void EmitCode::up(void) {
         Produce::up(Emit::tree());
     }
    -void EmitCode::down(void) {
    +void EmitCode::down(void) {
         Produce::down(Emit::tree());
     }
     
    @@ -145,7 +145,7 @@ start of a function.

    -void EmitCode::val_number(inter_ti N) {
    +void EmitCode::val_number(inter_ti N) {
         Produce::val(Emit::tree(), K_number, InterValuePairs::number(N));
     }
     
    @@ -177,7 +177,7 @@ start of a function.
         Produce::val_nothing(Emit::tree());
     }
     
    -void EmitCode::val_symbol(kind *K, inter_symbol *S) {
    +void EmitCode::val_symbol(kind *K, inter_symbol *S) {
         Produce::val_symbol(Emit::tree(), K, S);
     }
     
    @@ -284,7 +284,7 @@ in such cases, this function must exist in the kits somewhere.

    -void EmitCode::inv(inter_ti bip) {
    +void EmitCode::inv(inter_ti bip) {
         Produce::inv_primitive(Emit::tree(), bip);
     }
     
    diff --git a/docs/runtime-module/5-lp.html b/docs/runtime-module/5-lp.html
    index fc82d61bf..1246ee606 100644
    --- a/docs/runtime-module/5-lp.html
    +++ b/docs/runtime-module/5-lp.html
    @@ -232,11 +232,7 @@ the first function appears.)
                             EmitCode::up();
                             EmitCode::inv(EQ_BIP);
                             EmitCode::down();
    -                            EmitCode::inv(DIVIDE_BIP);
    -                            EmitCode::down();
    -                                EmitCode::val_symbol(K_value, value_s);
    -                                EmitCode::val_number((inter_ti) (lpe->element_multiplier));
    -                            EmitCode::up();
    +                            Evaluate LPE value to be printed4.1.1.3.2;
                                 EmitCode::val_number(0);
                             EmitCode::up();
                         EmitCode::up();
    @@ -256,11 +252,7 @@ the first function appears.)
                     EmitCode::inv(PRINTNUMBER_BIP);
                 }
                 EmitCode::down();
    -                EmitCode::inv(DIVIDE_BIP);
    -                EmitCode::down();
    -                    EmitCode::val_symbol(K_value, value_s);
    -                    EmitCode::val_number((inter_ti) (lpe->element_multiplier));
    -                EmitCode::up();
    +                Evaluate LPE value to be printed4.1.1.3.2;
                     if (lpe->number_base != 10)
                         EmitCode::val_number((inter_ti) (lpe->number_base));
                 EmitCode::up();
    @@ -294,15 +286,7 @@ the first function appears.)
                     EmitCode::inv(PRINTNUMBER_BIP);
                 }
                 EmitCode::down();
    -                EmitCode::inv(MODULO_BIP);
    -                EmitCode::down();
    -                    EmitCode::inv(DIVIDE_BIP);
    -                    EmitCode::down();
    -                        EmitCode::val_symbol(K_value, value_s);
    -                        EmitCode::val_number((inter_ti) (lpe->element_multiplier));
    -                    EmitCode::up();
    -                    EmitCode::val_number((inter_ti) (lpe->element_range));
    -                EmitCode::up();
    +                Evaluate LPE value to be printed4.1.1.3.2;
                     if (lpe->number_base != 10)
                         EmitCode::val_number((inter_ti) (lpe->number_base));
                 EmitCode::up();
    @@ -316,23 +300,23 @@ the first function appears.)
     
     
         if (lpe->print_with_leading_zeros) {
    +        int max_printable = lpe->element_range + lpe->element_offset;
    +        if (lpe->max_digits < 1000000) {
    +            int b = 1;
    +            for (int d = 1; d <= lpe->max_digits; d++)
    +                b = b * lpe->number_base;
    +            max_printable = b - 1;
    +        }
             int pow = 1;
    -        while (lpe->element_range > pow) pow = pow * lpe->number_base;
    +        while (max_printable > pow)
    +            pow = pow * lpe->number_base;
             for (; pow>1; pow = pow/lpe->number_base)
    -            if (lpe->element_range > pow) {
    +            if (max_printable > pow) {
                     EmitCode::inv(IF_BIP);
                     EmitCode::down();
                         EmitCode::inv(LT_BIP);
                         EmitCode::down();
    -                        EmitCode::inv(MODULO_BIP);
    -                        EmitCode::down();
    -                            EmitCode::inv(DIVIDE_BIP);
    -                            EmitCode::down();
    -                                EmitCode::val_symbol(K_value, value_s);
    -                                EmitCode::val_number((inter_ti) (lpe->element_multiplier));
    -                            EmitCode::up();
    -                            EmitCode::val_number((inter_ti) (lpe->element_range));
    -                        EmitCode::up();
    +                        Evaluate LPE value to be printed4.1.1.3.2;
                             EmitCode::val_number((inter_ti) (pow));
                         EmitCode::up();
                         EmitCode::code();
    @@ -347,21 +331,45 @@ the first function appears.)
         }
     
    +

    §4.1.1.3.2. Evaluate LPE value to be printed4.1.1.3.2 = +

    + +
    +    if (lpe->element_offset != 0) {
    +        EmitCode::inv(PLUS_BIP);
    +        EmitCode::down();
    +    }
    +    if (lpe->element_range >= 0) {
    +        EmitCode::inv(MODULO_BIP);
    +        EmitCode::down();
    +    }
    +    EmitCode::inv(DIVIDE_BIP);
    +    EmitCode::down();
    +        EmitCode::val_symbol(K_value, value_s);
    +        EmitCode::val_number((inter_ti) (lpe->element_multiplier));
    +    EmitCode::up();
    +    if (lpe->element_range >= 0) {
    +        EmitCode::val_number((inter_ti) (lpe->element_range));
    +        EmitCode::up();
    +    }
    +    if (lpe->element_offset != 0) {
    +        EmitCode::val_number((inter_ti) (lpe->element_offset));
    +        EmitCode::up();
    +    }
    +
    +

    §4.1.1.4. Truncate the printed form here if subsequent numerical parts are zero4.1.1.4 =

         if (oc == ec) {
    +        literal_pattern_element *lpe = &(lp->lp_elements[ec]);
             if (ec == 0) {
                 EmitCode::inv(IF_BIP);
                 EmitCode::down();
                     EmitCode::inv(EQ_BIP);
                     EmitCode::down();
    -                    EmitCode::inv(DIVIDE_BIP);
    -                    EmitCode::down();
    -                        EmitCode::val_symbol(K_value, value_s);
    -                        EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_multiplier));
    -                    EmitCode::up();
    +                    Evaluate LPE value to be printed4.1.1.3.2;
                         EmitCode::val_number(0);
                     EmitCode::up();
                     EmitCode::code();
    @@ -374,15 +382,7 @@ the first function appears.)
                 EmitCode::down();
                     EmitCode::inv(EQ_BIP);
                     EmitCode::down();
    -                    EmitCode::inv(MODULO_BIP);
    -                    EmitCode::down();
    -                        EmitCode::inv(DIVIDE_BIP);
    -                        EmitCode::down();
    -                            EmitCode::val_symbol(K_value, value_s);
    -                            EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_multiplier));
    -                        EmitCode::up();
    -                        EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_range));
    -                    EmitCode::up();
    +                    Evaluate LPE value to be printed4.1.1.3.2;
                         EmitCode::val_number(0);
                     EmitCode::up();
                     EmitCode::code();
    @@ -1289,13 +1289,42 @@ sets the parsed_number
             EmitCode::up();
         }
     
    -    if (lpe->element_index > 0) {
    +    if (lpe->element_offset != 0) {
    +        EmitCode::inv(STORE_BIP);
    +        EmitCode::down();
    +            EmitCode::ref_symbol(K_value, gprk.tot_s);
    +            EmitCode::inv(MINUS_BIP);
    +            EmitCode::down();
    +                EmitCode::val_symbol(K_value, gprk.tot_s);
    +                EmitCode::val_number((inter_ti) lpe->element_offset);
    +            EmitCode::up();
    +        EmitCode::up();
    +    }
    +
    +    if (lpe->element_range > 0) {
    +        inter_ti min_val = 0;
    +        inter_ti max_val = (inter_ti) (lpe->element_range);
    +        EmitCode::inv(IF_BIP);
    +        EmitCode::down();
    +            EmitCode::inv(LT_BIP);
    +            EmitCode::down();
    +                EmitCode::val_symbol(K_value, gprk.tot_s);
    +                EmitCode::val_number(min_val);
    +            EmitCode::up();
    +            EmitCode::code();
    +            EmitCode::down();
    +                EmitCode::inv(JUMP_BIP);
    +                EmitCode::down();
    +                    EmitCode::lab(failed_label);
    +                EmitCode::up();
    +            EmitCode::up();
    +        EmitCode::up();
             EmitCode::inv(IF_BIP);
             EmitCode::down();
                 EmitCode::inv(GE_BIP);
                 EmitCode::down();
                     EmitCode::val_symbol(K_value, gprk.tot_s);
    -                EmitCode::val_number((inter_ti) lpe->element_range);
    +                EmitCode::val_number(max_val);
                 EmitCode::up();
                 EmitCode::code();
                 EmitCode::down();
    diff --git a/docs/values-module/3-lp.html b/docs/values-module/3-lp.html
    index 69ba2fbfb..07da90a96 100644
    --- a/docs/values-module/3-lp.html
    +++ b/docs/values-module/3-lp.html
    @@ -202,6 +202,7 @@ The rightmost element \(e_{n-1}\) is the least significant numerically.
     
     typedef struct literal_pattern_element {
         int element_index;  the value \(i\) placing this within its LP, where \(0\leq i<n\)
    +    int element_offset;  amount by which outward values differ from stored ones
         int element_range;  the value \(r_i\) for this LP
         int element_multiplier;  the value \(m_i\) for this LP
     
    @@ -292,6 +293,7 @@ mass might also support "in kilograms" and "in grams", for instance.
     literal_pattern_element LiteralPatterns::lpe_new(int i, int r, int sgn) {
         literal_pattern_element lpe;
         if (i == 0) lpe.element_range = -1; else lpe.element_range = r;
    +    lpe.element_offset = 0;
         lpe.element_multiplier = 1;
         lpe.element_index = i;
         lpe.element_name = EMPTY_WORDING;
    @@ -660,8 +662,11 @@ on unusual platforms.
         while ((point_at > 0) && (point_at < digits_found)) {
             matched_scaledown *= lpe->number_base; point_at++;
         }
    -    if ((tot >= lpe->element_range) && (lpe->element_index > 0)) element_overflow_at = lpe;
    -    tot = (lpe->element_multiplier)*tot;
    +    if (lpe->element_range != -1) {  i.e., if the range of this LPE is finite
    +        if ((tot < lpe->element_offset) || (tot >= lpe->element_offset + lpe->element_range))
    +            element_overflow_at = lpe;
    +    }
    +    tot = (lpe->element_multiplier)*(tot - lpe->element_offset);
         if (tot > max_16_bit) overflow_16_bit_flag = TRUE;
         if (tot > max_32_bit) overflow_32_bit_flag = TRUE;
         tot = matched_number + tot;
    @@ -789,29 +794,31 @@ which is annoying. So we have a mechanism to suppress duplicates:
     

    -    int max = element_overflow_at->element_range - 1;
    +    int min_val = element_overflow_at->element_offset;
    +    int max_val = element_overflow_at->element_offset + element_overflow_at->element_range - 1;
         Problems::quote_source(1, current_sentence);
         Problems::quote_wording(2, W);
         Problems::quote_wording(3, lp->prototype_text);
    -    Problems::quote_number(4, &max);
    +    Problems::quote_number(4, &min_val);
    +    Problems::quote_number(5, &max_val);
         switch (element_overflow_at->element_index) {
    -        case 0: Problems::quote_text(5, "first"); break;
    -        case 1: Problems::quote_text(5, "second"); break;
    -        case 2: Problems::quote_text(5, "third"); break;
    -        case 3: Problems::quote_text(5, "fourth"); break;
    -        case 4: Problems::quote_text(5, "fifth"); break;
    -        case 5: Problems::quote_text(5, "sixth"); break;
    -        case 6: Problems::quote_text(5, "seventh"); break;
    -        case 7: Problems::quote_text(5, "eighth"); break;
    -        case 8: Problems::quote_text(5, "ninth"); break;
    -        case 9: Problems::quote_text(5, "tenth"); break;
    -        default: Problems::quote_text(5, "eventual"); break;
    +        case 0: Problems::quote_text(6, "first"); break;
    +        case 1: Problems::quote_text(6, "second"); break;
    +        case 2: Problems::quote_text(6, "third"); break;
    +        case 3: Problems::quote_text(6, "fourth"); break;
    +        case 4: Problems::quote_text(6, "fifth"); break;
    +        case 5: Problems::quote_text(6, "sixth"); break;
    +        case 6: Problems::quote_text(6, "seventh"); break;
    +        case 7: Problems::quote_text(6, "eighth"); break;
    +        case 8: Problems::quote_text(6, "ninth"); break;
    +        case 9: Problems::quote_text(6, "tenth"); break;
    +        default: Problems::quote_text(6, "eventual"); break;
         }
         StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ElementOverflow));
         Problems::issue_problem_segment(
             "In the sentence %1, you use the notation '%2' to write a constant value. "
    -        "But the notation was specified as '%3', which means that the %5 numerical "
    -        "part should range between 0 and %4.");
    +        "But the notation was specified as '%3', which means that the %6 numerical "
    +        "part should range between %4 and %5.");
         Problems::issue_problem_end();
         return NULL;
     
    @@ -1100,7 +1107,8 @@ note that the following uses the raw text of the word. literal_pattern_element *lpe = &(lp->lp_elements[ec]); int m = lpe->element_range; LiteralPatterns::write_val(OUT, m, - (v/(lpe->element_multiplier)) % m, lpe->number_base, lpe->print_with_leading_zeros); + (v/(lpe->element_multiplier)) % m + lpe->element_offset, + lpe->number_base, lpe->print_with_leading_zeros); if (ec == 0) Index the fractional part of the value23.3.1; } ec++; @@ -1399,7 +1407,7 @@ middle of either angle-escapes or the material in between. if (j == 0) { if (i > 0) { lpe_notation_pos to = { Wordings::first_wn(NW)+i-1, - Wide::len(Lexer::word_raw_text(Wordings::last_wn(NW)+i-1)) - 1 }; + Wide::len(Lexer::word_raw_text(Wordings::first_wn(NW)+i-1)) - 1 }; Compile unescaped notation between from and to25.7.2.2; } } else { @@ -1450,6 +1458,7 @@ material or else names for parts about which nothing else is said.

    +     LOG("Scan escape <%S>\n", angles);
         Str::trim_white_space(angles);
         wording AW = Feeds::feed_text(angles);
         if (<quoted-text>(AW)) {
    @@ -1485,7 +1494,9 @@ character ones.
     

    -    if ((from.wn < to.wn) || (from.char_pos <= to.char_pos)) {
    +     LOG("Scan word %W, %d to %W, %d\n",
    +    	Wordings::one_word(from.wn), from.char_pos, Wordings::one_word(to.wn), to.char_pos);
    +    if ((from.wn < to.wn) || ((from.wn == to.wn) && (from.char_pos <= to.char_pos))) {
             wording NW = Wordings::new(from.wn, to.wn);
             for (int i=0; i<Wordings::length(NW); i++) {
                 wchar_t *text_of_word = Lexer::word_raw_text(Wordings::first_wn(NW)+i);
    @@ -1634,7 +1645,8 @@ this is deferred until all elements exist, at which point we —
             if (Wordings::empty(lpe->element_name)) {
                 lpe->element_name = Node::get_text(p);
             } else if (Wordings::match(lpe->element_name, Node::get_text(p)) == FALSE) {
    -            LOG("Want %W have %W\n", lpe->element_name, Node::get_text(p));
    +            Log this literal pattern in full25.12;
    +            LOG("Here, want %W have %W\n", lpe->element_name, Node::get_text(p));
                 StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...),
                     "the part names after 'with' do not exactly match those named "
                     "in the specification itself",
    @@ -1656,9 +1668,10 @@ this is deferred until all elements exist, at which point we —
             if (O & MAX_DIGITS_MASK_LSO)
                 lpe->max_digits = ((O & MAX_DIGITS_MASK_LSO) / MAX_DIGITS_LSO);
             if (O & MAXIMUM_LSO) {
    -            lpe->element_range = Annotations::read_int(p, lpe_max_ANNOT) + 1;
    +            lpe->element_offset = Annotations::read_int(p, lpe_min_ANNOT);
    +            lpe->element_range = Annotations::read_int(p, lpe_max_ANNOT) - lpe->element_offset + 1;
                 if (O & MAX_DIGITS_MASK_LSO) {
    -                int n = lpe->element_range - 1;
    +                int n = lpe->element_offset + lpe->element_range - 1;
                     for (int i=1; i<=lpe->max_digits; i++) n = n/lpe->number_base;
                     if (n != 0)
                         StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...),
    @@ -1753,7 +1766,8 @@ optional, and it must not be the first.
                     else if ((lpe->min_digits > 1) || (lpe->max_digits < 1000000))
                         LOG("%d to %d digits ", lpe->min_digits, lpe->max_digits);
                     if (lpe->print_with_leading_zeros) LOG("printed with leading zeros ");
    -                if (lpe->element_range >= 0) LOG("range 0 to %d ", lpe->element_range);
    +                if (lpe->element_range >= 0) LOG("range %d to %d ",
    +                    lpe->element_offset, lpe->element_offset + lpe->element_range);
                     else LOG("range unlimited ");
                     LOG("(base %d) ", lpe->number_base);
                     LOG("- multiplier %d\n", lpe->element_multiplier);
    @@ -1764,7 +1778,7 @@ optional, and it must not be the first.
         }
         LOG("\n");
     
    -
    • This code is used in §25.
    +

    §26. Group names are created when first seen; the following recognises one which has been seen before.

    @@ -1921,13 +1935,18 @@ For instance, defining: id = Feeds::begin(); TEMPORARY_TEXT(print_rule_buff) + TEMPORARY_TEXT(offset_addition) + if (lpe->element_offset != 0) + WRITE_TO(offset_addition, " + %d", lpe->element_offset); if (i==0) - WRITE_TO(print_rule_buff, " (- ({full}/%d) -) ", lpe->element_multiplier); + WRITE_TO(print_rule_buff, " (- ({full}/%d%S) -) ", + lpe->element_multiplier, offset_addition); else if (lpe->element_multiplier > 1) - WRITE_TO(print_rule_buff, " (- (({full}/%d)%%%d) -) ", - lpe->element_multiplier, lpe->element_range); + WRITE_TO(print_rule_buff, " (- (({full}/%d)%%%d%S) -) ", + lpe->element_multiplier, lpe->element_range, offset_addition); else - WRITE_TO(print_rule_buff, " (- ({full}%%%d) -) ", lpe->element_range); + WRITE_TO(print_rule_buff, " (- ({full}%%%d%S) -) ", + lpe->element_range, offset_addition); Feeds::feed_text(print_rule_buff); XW = Feeds::end(id); if (Wordings::phrasual_length(XW) >= MAX_WORDS_PER_PHRASE + 5) @@ -1935,6 +1954,7 @@ For instance, defining: else Sentences::make_node(Task::syntax_tree(), XW, '.'); DISCARD_TEXT(print_rule_buff) + DISCARD_TEXT(offset_addition) }
    • This code is used in §29.
    @@ -1977,10 +1997,14 @@ For instance, the dollars-and-cents example compiles: WRITE_TO(print_rule_buff, " (- ("); for (int i=0; i<lp->no_lp_elements; i++) { literal_pattern_element *lpe = &(lp->lp_elements[i]); + if (lpe->element_offset != 0) + WRITE_TO(print_rule_buff, "("); if (i>0) WRITE_TO(print_rule_buff, "+"); if (lpe->element_multiplier != 1) WRITE_TO(print_rule_buff, "%d*", lpe->element_multiplier); WRITE_TO(print_rule_buff, "{part%d}", i); + if (lpe->element_offset != 0) + WRITE_TO(print_rule_buff, " - %d)", lpe->element_offset); } WRITE_TO(print_rule_buff, ") -) "); Feeds::feed_text(print_rule_buff); diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index 39cb95285..2ad626fbf 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -1,6 +1,6 @@ Total memory consumption was 138261K = 135 MB - ---- was used for 2115190 objects, in 374468 frames in 0 x 800K = 0K = 0 MB: + ---- was used for 2115191 objects, in 374469 frames in 0 x 800K = 0K = 0 MB: 30.5% inter_tree_node_array 60 x 8192 = 491520 objects, 43255680 bytes 19.1% text_stream_array 4813 x 100 = 481300 objects, 27106816 bytes @@ -143,7 +143,7 @@ Total memory consumption was 138261K = 135 MB ---- semver_range 42 objects, 4368 bytes ---- use_option 32 objects, 4352 bytes ---- either_or_property_data 62 objects, 3968 bytes - ---- parse_node_annotation_type 120 objects, 3840 bytes + ---- parse_node_annotation_type 121 objects, 3872 bytes ---- method_set 108 objects, 3456 bytes ---- definition 48 objects, 3456 bytes ---- property_setting_bp_data 86 objects, 3440 bytes @@ -269,5 +269,5 @@ Total memory consumption was 138261K = 135 MB ---- code generation workspace for objects 3488 bytes in 19 claims 0.1% emitter array storage 281184 bytes in 2006 claims --137.-4% was overhead - -194581688 bytes = -190021K = -185 MB +-137.-4% was overhead - -194581720 bytes = -190021K = -185 MB diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index 88dbecc3f..f6ed73e28 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,29 +1,29 @@ 100.0% in inform7 run - 67.5% in compilation to Inter - 44.6% in //Sequence::undertake_queued_tasks// + 67.9% in compilation to Inter + 45.0% in //Sequence::undertake_queued_tasks// 4.9% in //MajorNodes::pre_pass// 3.4% in //MajorNodes::pass_1// 1.9% in //ImperativeDefinitions::assess_all// 1.9% in //RTPhrasebook::compile_entries// 1.5% in //RTKindConstructors::compile// 1.1% in //Sequence::lint_inter// - 0.7% in //ImperativeDefinitions::compile_first_block// + 0.7% in //Sequence::undertake_queued_tasks// 0.3% in //CompletionModule::compile// + 0.3% in //ImperativeDefinitions::compile_first_block// 0.3% in //InferenceSubjects::emit_all// 0.3% in //MajorNodes::pass_2// 0.3% in //Sequence::undertake_queued_tasks// - 0.3% in //Sequence::undertake_queued_tasks// 0.3% in //World::stage_V// 5.0% not specifically accounted for 28.2% in running Inter pipeline 9.5% in step 14/15: generate inform6 -> auto.inf - 6.8% in step 5/15: load-binary-kits + 7.2% in step 5/15: load-binary-kits 6.1% in step 6/15: make-synoptic-module 1.9% in step 9/15: make-identifiers-unique 0.3% in step 12/15: eliminate-redundant-operations 0.3% in step 4/15: compile-splats 0.3% in step 7/15: shorten-wiring 0.3% in step 8/15: detect-indirect-calls - 2.3% not specifically accounted for + 1.9% not specifically accounted for 3.4% in supervisor - 0.8% not specifically accounted for + 0.4% not specifically accounted for diff --git a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json index 31a623324..c17a886fc 100644 --- a/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json +++ b/inform7/Internal/Inter/Architecture16Kit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "Architecture16Kit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "compatibility": "16-bit", "kit-details": { diff --git a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json index 4c6ce3a1b..0b6d9cfb8 100644 --- a/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json +++ b/inform7/Internal/Inter/Architecture32Kit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "Architecture32Kit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "compatibility": "32-bit", "kit-details": { diff --git a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json index 4e0310e40..6844389af 100644 --- a/inform7/Internal/Inter/BasicInformKit/kit_metadata.json +++ b/inform7/Internal/Inter/BasicInformKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "BasicInformKit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json index a2f5c1b1e..4bdc6ea72 100644 --- a/inform7/Internal/Inter/CommandParserKit/kit_metadata.json +++ b/inform7/Internal/Inter/CommandParserKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "CommandParserKit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json index de2c45446..6520ec095 100644 --- a/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json +++ b/inform7/Internal/Inter/EnglishLanguageKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "EnglishLanguageKit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "needs": [ { "need": { diff --git a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json index 1472fc06f..620e91c49 100644 --- a/inform7/Internal/Inter/WorldModelKit/kit_metadata.json +++ b/inform7/Internal/Inter/WorldModelKit/kit_metadata.json @@ -2,7 +2,7 @@ "is": { "type": "kit", "title": "WorldModelKit", - "version": "10.2.0-beta+6W80" + "version": "10.2.0-beta+6W81" }, "needs": [ { "need": { diff --git a/inform7/assertions-module/Chapter 3/New Literal Pattern Requests.w b/inform7/assertions-module/Chapter 3/New Literal Pattern Requests.w index fa329618e..163652982 100644 --- a/inform7/assertions-module/Chapter 3/New Literal Pattern Requests.w +++ b/inform7/assertions-module/Chapter 3/New Literal Pattern Requests.w @@ -284,7 +284,7 @@ by a bracketed list of up to three options in any order. ==> { 0, RP[1] } ::= - ( ) | ==> { 0, LPRequests::mark(RP[1], R[2], <>) } + ( ) | ==> { 0, LPRequests::mark(RP[1], R[2], <>, <>) } ==> { 0, RP[1] } ::= @@ -301,7 +301,7 @@ by a bracketed list of up to three options in any order. with leading zeros | ==> { WITH_LEADING_ZEROS_LSO, - } without leading zeros | ==> { WITHOUT_LEADING_ZEROS_LSO, - } in | ==> { BASE_LSO*R[1], - } - to | ==> <> = R[2]; @; + to | ==> <> = R[1]; <> = R[2]; @; up to digit/digits | ==> @; up to digit/digits | ==> @; digit/digits | ==> @; @@ -309,11 +309,11 @@ by a bracketed list of up to three options in any order. ...... ==> @ @ = - if (R[1] != 0) + if (R[1] > R[2]) StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...), - "the range in a named part has to begin at 0", - "for the moment at least."); - ==> { MAXIMUM_LSO, - }; + "the minimum value for a named part cannot be greater than the maximum", + "or it would be impossible for any value of this kind to exist."); + ==> { MINIMUM_LSO + MAXIMUM_LSO, - }; @ = if (R[1] < 1) @@ -370,6 +370,7 @@ literal_pattern_name *LPRequests::compose(literal_pattern_name *A, literal_patte @d WITH_LEADING_ZEROS_LSO 0x00000004 @d WITHOUT_LEADING_ZEROS_LSO 0x00000008 @d MAXIMUM_LSO 0x00000010 +@d MINIMUM_LSO 0x00000020 @d BASE_LSO 0x00000100 @d BASE_MASK_LSO 0x0000ff00 @d MIN_DIGITS_LSO 0x00010000 @@ -378,10 +379,11 @@ literal_pattern_name *LPRequests::compose(literal_pattern_name *A, literal_patte @d MAX_DIGITS_MASK_LSO 0x7f000000 = -parse_node *LPRequests::mark(parse_node *A, int N, int M) { +parse_node *LPRequests::mark(parse_node *A, int N, int MI, int MA) { if (A) { Annotations::write_int(A, lpe_options_ANNOT, N); - if (N & MAXIMUM_LSO) Annotations::write_int(A, lpe_max_ANNOT, M); + if (N & MINIMUM_LSO) Annotations::write_int(A, lpe_min_ANNOT, MI); + if (N & MAXIMUM_LSO) Annotations::write_int(A, lpe_max_ANNOT, MA); } return A; } diff --git a/inform7/core-module/Chapter 1/Inform-Only Nodes and Annotations.w b/inform7/core-module/Chapter 1/Inform-Only Nodes and Annotations.w index c6b5cf4cd..3e56822f9 100644 --- a/inform7/core-module/Chapter 1/Inform-Only Nodes and Annotations.w +++ b/inform7/core-module/Chapter 1/Inform-Only Nodes and Annotations.w @@ -416,6 +416,7 @@ void CoreSyntax::grant_L2_permissions(void) { @e evaluation_ANNOT /* |parse_node|: result of evaluating the text */ @e explicit_gender_marker_ANNOT /* |int|: used by PROPER NOUN nodes for evident genders */ @e lpe_options_ANNOT /* |int|: options set for a literal pattern part */ +@e lpe_min_ANNOT /* |int|: value offset for a literal pattern part */ @e lpe_max_ANNOT /* |int|: maximum value for a literal pattern part */ @e multiplicity_ANNOT /* |int|: e.g., 5 for "five gold rings" */ @e new_relation_here_ANNOT /* |binary_predicate|: new relation as subject of "relates" sentence */ @@ -466,6 +467,8 @@ void CoreSyntax::declare_L3_annotations(void) { lpe_options_ANNOT, CoreSyntax::write_lpe_options_ANNOT); Annotations::declare_type( lpe_max_ANNOT, CoreSyntax::write_lpe_max_ANNOT); + Annotations::declare_type( + lpe_min_ANNOT, CoreSyntax::write_lpe_min_ANNOT); Annotations::declare_type( multiplicity_ANNOT, CoreSyntax::write_multiplicity_ANNOT); Annotations::declare_type( @@ -521,6 +524,9 @@ void CoreSyntax::write_lpe_options_ANNOT(text_stream *OUT, parse_node *p) { void CoreSyntax::write_lpe_max_ANNOT(text_stream *OUT, parse_node *p) { WRITE(" {lpe max: %d}", Annotations::read_int(p, lpe_max_ANNOT)); } +void CoreSyntax::write_lpe_min_ANNOT(text_stream *OUT, parse_node *p) { + WRITE(" {lpe offset: %d}", Annotations::read_int(p, lpe_min_ANNOT)); +} void CoreSyntax::write_multiplicity_ANNOT(text_stream *OUT, parse_node *p) { if (Annotations::read_int(p, multiplicity_ANNOT)) WRITE(" {multiplicity %d}", Annotations::read_int(p, multiplicity_ANNOT)); @@ -597,6 +603,7 @@ void CoreSyntax::grant_L3_permissions(void) { Annotations::allow(PROPER_NOUN_NT, defn_language_ANNOT); Annotations::allow(PROPER_NOUN_NT, lpe_options_ANNOT); Annotations::allow(PROPER_NOUN_NT, lpe_max_ANNOT); + Annotations::allow(PROPER_NOUN_NT, lpe_min_ANNOT); Annotations::allow(PROPER_NOUN_NT, multiplicity_ANNOT); Annotations::allow(UNPARSED_NOUN_NT, new_relation_here_ANNOT); Annotations::allow(PROPER_NOUN_NT, new_relation_here_ANNOT); diff --git a/inform7/runtime-module/Chapter 5/Literal Patterns.w b/inform7/runtime-module/Chapter 5/Literal Patterns.w index 86c627f91..2469fcd16 100644 --- a/inform7/runtime-module/Chapter 5/Literal Patterns.w +++ b/inform7/runtime-module/Chapter 5/Literal Patterns.w @@ -151,11 +151,7 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { EmitCode::up(); EmitCode::inv(EQ_BIP); EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lpe->element_multiplier)); - EmitCode::up(); + @; EmitCode::val_number(0); EmitCode::up(); EmitCode::up(); @@ -175,11 +171,7 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { EmitCode::inv(PRINTNUMBER_BIP); } EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lpe->element_multiplier)); - EmitCode::up(); + @; if (lpe->number_base != 10) EmitCode::val_number((inter_ti) (lpe->number_base)); EmitCode::up(); @@ -213,15 +205,7 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { EmitCode::inv(PRINTNUMBER_BIP); } EmitCode::down(); - EmitCode::inv(MODULO_BIP); - EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lpe->element_multiplier)); - EmitCode::up(); - EmitCode::val_number((inter_ti) (lpe->element_range)); - EmitCode::up(); + @; if (lpe->number_base != 10) EmitCode::val_number((inter_ti) (lpe->number_base)); EmitCode::up(); @@ -231,23 +215,23 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { @ = if (lpe->print_with_leading_zeros) { + int max_printable = lpe->element_range + lpe->element_offset; + if (lpe->max_digits < 1000000) { + int b = 1; + for (int d = 1; d <= lpe->max_digits; d++) + b = b * lpe->number_base; + max_printable = b - 1; + } int pow = 1; - while (lpe->element_range > pow) pow = pow * lpe->number_base; + while (max_printable > pow) + pow = pow * lpe->number_base; for (; pow>1; pow = pow/lpe->number_base) - if (lpe->element_range > pow) { + if (max_printable > pow) { EmitCode::inv(IF_BIP); EmitCode::down(); EmitCode::inv(LT_BIP); EmitCode::down(); - EmitCode::inv(MODULO_BIP); - EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lpe->element_multiplier)); - EmitCode::up(); - EmitCode::val_number((inter_ti) (lpe->element_range)); - EmitCode::up(); + @; EmitCode::val_number((inter_ti) (pow)); EmitCode::up(); EmitCode::code(); @@ -261,18 +245,38 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { } } +@ = + if (lpe->element_offset != 0) { + EmitCode::inv(PLUS_BIP); + EmitCode::down(); + } + if (lpe->element_range >= 0) { + EmitCode::inv(MODULO_BIP); + EmitCode::down(); + } + EmitCode::inv(DIVIDE_BIP); + EmitCode::down(); + EmitCode::val_symbol(K_value, value_s); + EmitCode::val_number((inter_ti) (lpe->element_multiplier)); + EmitCode::up(); + if (lpe->element_range >= 0) { + EmitCode::val_number((inter_ti) (lpe->element_range)); + EmitCode::up(); + } + if (lpe->element_offset != 0) { + EmitCode::val_number((inter_ti) (lpe->element_offset)); + EmitCode::up(); + } + @ = if (oc == ec) { + literal_pattern_element *lpe = &(lp->lp_elements[ec]); if (ec == 0) { EmitCode::inv(IF_BIP); EmitCode::down(); EmitCode::inv(EQ_BIP); EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_multiplier)); - EmitCode::up(); + @; EmitCode::val_number(0); EmitCode::up(); EmitCode::code(); @@ -285,15 +289,7 @@ void RTLiteralPatterns::compilation_agent(compilation_subtask *t) { EmitCode::down(); EmitCode::inv(EQ_BIP); EmitCode::down(); - EmitCode::inv(MODULO_BIP); - EmitCode::down(); - EmitCode::inv(DIVIDE_BIP); - EmitCode::down(); - EmitCode::val_symbol(K_value, value_s); - EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_multiplier)); - EmitCode::up(); - EmitCode::val_number((inter_ti) (lp->lp_elements[ec].element_range)); - EmitCode::up(); + @; EmitCode::val_number(0); EmitCode::up(); EmitCode::code(); @@ -1168,13 +1164,42 @@ sets the |parsed_number| global to the value matched. EmitCode::up(); } - if (lpe->element_index > 0) { + if (lpe->element_offset != 0) { + EmitCode::inv(STORE_BIP); + EmitCode::down(); + EmitCode::ref_symbol(K_value, gprk.tot_s); + EmitCode::inv(MINUS_BIP); + EmitCode::down(); + EmitCode::val_symbol(K_value, gprk.tot_s); + EmitCode::val_number((inter_ti) lpe->element_offset); + EmitCode::up(); + EmitCode::up(); + } + + if (lpe->element_range > 0) { + inter_ti min_val = 0; + inter_ti max_val = (inter_ti) (lpe->element_range); + EmitCode::inv(IF_BIP); + EmitCode::down(); + EmitCode::inv(LT_BIP); + EmitCode::down(); + EmitCode::val_symbol(K_value, gprk.tot_s); + EmitCode::val_number(min_val); + EmitCode::up(); + EmitCode::code(); + EmitCode::down(); + EmitCode::inv(JUMP_BIP); + EmitCode::down(); + EmitCode::lab(failed_label); + EmitCode::up(); + EmitCode::up(); + EmitCode::up(); EmitCode::inv(IF_BIP); EmitCode::down(); EmitCode::inv(GE_BIP); EmitCode::down(); EmitCode::val_symbol(K_value, gprk.tot_s); - EmitCode::val_number((inter_ti) lpe->element_range); + EmitCode::val_number(max_val); EmitCode::up(); EmitCode::code(); EmitCode::down(); diff --git a/inform7/values-module/Chapter 3/Literal Patterns.w b/inform7/values-module/Chapter 3/Literal Patterns.w index 74867ae1b..7660493a4 100644 --- a/inform7/values-module/Chapter 3/Literal Patterns.w +++ b/inform7/values-module/Chapter 3/Literal Patterns.w @@ -112,6 +112,7 @@ The rightmost element $e_{n-1}$ is the least significant numerically. = typedef struct literal_pattern_element { int element_index; /* the value $i$ placing this within its LP, where $0\leq i 0) && (point_at < digits_found)) { matched_scaledown *= lpe->number_base; point_at++; } - if ((tot >= lpe->element_range) && (lpe->element_index > 0)) element_overflow_at = lpe; - tot = (lpe->element_multiplier)*tot; + if (lpe->element_range != -1) { /* i.e., if the range of this LPE is finite */ + if ((tot < lpe->element_offset) || (tot >= lpe->element_offset + lpe->element_range)) + element_overflow_at = lpe; + } + tot = (lpe->element_multiplier)*(tot - lpe->element_offset); if (tot > max_16_bit) overflow_16_bit_flag = TRUE; if (tot > max_32_bit) overflow_32_bit_flag = TRUE; tot = matched_number + tot; @@ -617,29 +622,31 @@ which is annoying. So we have a mechanism to suppress duplicates: @ The more specific problem of an internal overflow: @ = - int max = element_overflow_at->element_range - 1; + int min_val = element_overflow_at->element_offset; + int max_val = element_overflow_at->element_offset + element_overflow_at->element_range - 1; Problems::quote_source(1, current_sentence); Problems::quote_wording(2, W); Problems::quote_wording(3, lp->prototype_text); - Problems::quote_number(4, &max); + Problems::quote_number(4, &min_val); + Problems::quote_number(5, &max_val); switch (element_overflow_at->element_index) { - case 0: Problems::quote_text(5, "first"); break; - case 1: Problems::quote_text(5, "second"); break; - case 2: Problems::quote_text(5, "third"); break; - case 3: Problems::quote_text(5, "fourth"); break; - case 4: Problems::quote_text(5, "fifth"); break; - case 5: Problems::quote_text(5, "sixth"); break; - case 6: Problems::quote_text(5, "seventh"); break; - case 7: Problems::quote_text(5, "eighth"); break; - case 8: Problems::quote_text(5, "ninth"); break; - case 9: Problems::quote_text(5, "tenth"); break; - default: Problems::quote_text(5, "eventual"); break; + case 0: Problems::quote_text(6, "first"); break; + case 1: Problems::quote_text(6, "second"); break; + case 2: Problems::quote_text(6, "third"); break; + case 3: Problems::quote_text(6, "fourth"); break; + case 4: Problems::quote_text(6, "fifth"); break; + case 5: Problems::quote_text(6, "sixth"); break; + case 6: Problems::quote_text(6, "seventh"); break; + case 7: Problems::quote_text(6, "eighth"); break; + case 8: Problems::quote_text(6, "ninth"); break; + case 9: Problems::quote_text(6, "tenth"); break; + default: Problems::quote_text(6, "eventual"); break; } StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_ElementOverflow)); Problems::issue_problem_segment( "In the sentence %1, you use the notation '%2' to write a constant value. " - "But the notation was specified as '%3', which means that the %5 numerical " - "part should range between 0 and %4."); + "But the notation was specified as '%3', which means that the %6 numerical " + "part should range between %4 and %5."); Problems::issue_problem_end(); return NULL; @@ -893,7 +900,8 @@ note that the following uses the raw text of the word. literal_pattern_element *lpe = &(lp->lp_elements[ec]); int m = lpe->element_range; LiteralPatterns::write_val(OUT, m, - (v/(lpe->element_multiplier)) % m, lpe->number_base, lpe->print_with_leading_zeros); + (v/(lpe->element_multiplier)) % m + lpe->element_offset, + lpe->number_base, lpe->print_with_leading_zeros); if (ec == 0) @; } ec++; @@ -1145,7 +1153,7 @@ middle of either angle-escapes or the material in between. if (j == 0) { if (i > 0) { lpe_notation_pos to = { Wordings::first_wn(NW)+i-1, - Wide::len(Lexer::word_raw_text(Wordings::last_wn(NW)+i-1)) - 1 }; + Wide::len(Lexer::word_raw_text(Wordings::first_wn(NW)+i-1)) - 1 }; @; } } else { @@ -1191,6 +1199,7 @@ middle of either angle-escapes or the material in between. material or else names for parts about which nothing else is said. @ = + // LOG("Scan escape <%S>\n", angles); Str::trim_white_space(angles); wording AW = Feeds::feed_text(angles); if ((AW)) { @@ -1221,7 +1230,9 @@ word to play with, we optimise by making a word token instead of a run of character ones. @ = - if ((from.wn < to.wn) || (from.char_pos <= to.char_pos)) { + // LOG("Scan word %W, %d to %W, %d\n", + // Wordings::one_word(from.wn), from.char_pos, Wordings::one_word(to.wn), to.char_pos); + if ((from.wn < to.wn) || ((from.wn == to.wn) && (from.char_pos <= to.char_pos))) { wording NW = Wordings::new(from.wn, to.wn); for (int i=0; ielement_name)) { lpe->element_name = Node::get_text(p); } else if (Wordings::match(lpe->element_name, Node::get_text(p)) == FALSE) { - LOG("Want %W have %W\n", lpe->element_name, Node::get_text(p)); + @; + LOG("Here, want %W have %W\n", lpe->element_name, Node::get_text(p)); StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...), "the part names after 'with' do not exactly match those named " "in the specification itself", @@ -1364,9 +1376,10 @@ this is deferred until all elements exist, at which point we -- if (O & MAX_DIGITS_MASK_LSO) lpe->max_digits = ((O & MAX_DIGITS_MASK_LSO) / MAX_DIGITS_LSO); if (O & MAXIMUM_LSO) { - lpe->element_range = Annotations::read_int(p, lpe_max_ANNOT) + 1; + lpe->element_offset = Annotations::read_int(p, lpe_min_ANNOT); + lpe->element_range = Annotations::read_int(p, lpe_max_ANNOT) - lpe->element_offset + 1; if (O & MAX_DIGITS_MASK_LSO) { - int n = lpe->element_range - 1; + int n = lpe->element_offset + lpe->element_range - 1; for (int i=1; i<=lpe->max_digits; i++) n = n/lpe->number_base; if (n != 0) StandardProblems::sentence_problem(Task::syntax_tree(), _p_(...), @@ -1452,7 +1465,8 @@ optional, and it must not be the first. else if ((lpe->min_digits > 1) || (lpe->max_digits < 1000000)) LOG("%d to %d digits ", lpe->min_digits, lpe->max_digits); if (lpe->print_with_leading_zeros) LOG("printed with leading zeros "); - if (lpe->element_range >= 0) LOG("range 0 to %d ", lpe->element_range); + if (lpe->element_range >= 0) LOG("range %d to %d ", + lpe->element_offset, lpe->element_offset + lpe->element_range); else LOG("range unlimited "); LOG("(base %d) ", lpe->number_base); LOG("- multiplier %d\n", lpe->element_multiplier); @@ -1600,13 +1614,18 @@ To define which number is cents part of ( full - price ) : |(- ({full}%100) -)|. id = Feeds::begin(); TEMPORARY_TEXT(print_rule_buff) + TEMPORARY_TEXT(offset_addition) + if (lpe->element_offset != 0) + WRITE_TO(offset_addition, " + %d", lpe->element_offset); if (i==0) - WRITE_TO(print_rule_buff, " (- ({full}/%d) -) ", lpe->element_multiplier); + WRITE_TO(print_rule_buff, " (- ({full}/%d%S) -) ", + lpe->element_multiplier, offset_addition); else if (lpe->element_multiplier > 1) - WRITE_TO(print_rule_buff, " (- (({full}/%d)%%%d) -) ", - lpe->element_multiplier, lpe->element_range); + WRITE_TO(print_rule_buff, " (- (({full}/%d)%%%d%S) -) ", + lpe->element_multiplier, lpe->element_range, offset_addition); else - WRITE_TO(print_rule_buff, " (- ({full}%%%d) -) ", lpe->element_range); + WRITE_TO(print_rule_buff, " (- ({full}%%%d%S) -) ", + lpe->element_range, offset_addition); Feeds::feed_text(print_rule_buff); XW = Feeds::end(id); if (Wordings::phrasual_length(XW) >= MAX_WORDS_PER_PHRASE + 5) @@ -1614,6 +1633,7 @@ To define which number is cents part of ( full - price ) : |(- ({full}%100) -)|. else Sentences::make_node(Task::syntax_tree(), XW, '.'); DISCARD_TEXT(print_rule_buff) + DISCARD_TEXT(offset_addition) } @ And similarly, a packing phrase to calculate the value given its elements. @@ -1651,10 +1671,14 @@ To decide which price is price with dollars part ( part0 - a number ) cents part WRITE_TO(print_rule_buff, " (- ("); for (int i=0; ino_lp_elements; i++) { literal_pattern_element *lpe = &(lp->lp_elements[i]); + if (lpe->element_offset != 0) + WRITE_TO(print_rule_buff, "("); if (i>0) WRITE_TO(print_rule_buff, "+"); if (lpe->element_multiplier != 1) WRITE_TO(print_rule_buff, "%d*", lpe->element_multiplier); WRITE_TO(print_rule_buff, "{part%d}", i); + if (lpe->element_offset != 0) + WRITE_TO(print_rule_buff, " - %d)", lpe->element_offset); } WRITE_TO(print_rule_buff, ") -) "); Feeds::feed_text(print_rule_buff);