From ed743bbcb6acfbfd99b9d37d3978e1db9804b2d0 Mon Sep 17 00:00:00 2001
From: Graham Nelson
- 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.
-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) }