From 2cca448105dc5cfa2e4117f724b3905a6e1fc82c Mon Sep 17 00:00:00 2001
From: Graham Nelson §49. Functional Programming. Here we have the ability to use the name of a function as a value, and to
apply such a function.
diff --git a/docs/building-module/2-is.html b/docs/building-module/2-is.html
index c36ea63d80..514a20e070 100644
--- a/docs/building-module/2-is.html
+++ b/docs/building-module/2-is.html
@@ -413,6 +413,7 @@
To decide which list of Ks is list of (name of kind of value K)
that/which/whom (R - relation of Ks to values of kind L) relates
(documented at ph_leftdomain):
- (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -).
+ (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -).
To decide which list of Ls is list of (name of kind of value L)
to which/whom (R - relation of values of kind K to Ls) relates
(documented at ph_rightdomain):
- (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -).
To decide which list of Ls is list of (name of kind of value L)
that/which/whom (R - relation of values of kind K to Ls) relates to
(documented at ph_rightdomain):
- (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -).
To decide which list of Ks is list of (name of kind of value K) that/which/who
relate to (Y - L) by (R - relation of Ks to values of kind L)
(documented at ph_leftlookuplist):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -).
+ (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -).
To decide which list of Ls is list of (name of kind of value L) to which/whom (X - K)
relates by (R - relation of values of kind K to Ls)
(documented at ph_rightlookuplist):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -).
To decide which list of Ls is list of (name of kind of value L)
that/which/whom (X - K) relates to by (R - relation of values of kind K to Ls)
(documented at ph_rightlookuplist):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -).
To decide whether (name of kind of value K) relates to (Y - L) by
(R - relation of Ks to values of kind L)
(documented at ph_ifright):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -).
+ (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -).
To decide whether (X - K) relates to (name of kind of value L) by
(R - relation of values of kind K to Ls)
(documented at ph_ifleft):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -).
To decide which K is (name of kind of value K) that/which/who relates to
(Y - L) by (R - relation of Ks to values of kind L)
(documented at ph_leftlookup):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -).
+ (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -).
To decide which L is (name of kind of value L) to which/whom (X - K)
relates by (R - relation of values of kind K to Ls)
(documented at ph_rightlookup):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -).
To decide which L is (name of kind of value L) that/which/whom (X - K)
relates to by (R - relation of values of kind K to Ls)
(documented at ph_rightlookup):
- (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -).
+ (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -).
enum indexing_routine_ISINC
enum strong_kind_ISINC
enum weak_kind_ISINC
+enum object_kind_ISINC
enum backspace_ISINC
enum erase_ISINC
enum open_brace_ISINC
@@ -441,6 +442,8 @@
enum unprotect_ISINC
enum copy_ISINC
enum initialise_ISINC
+enum match_right_relation_domain_ISINC
+enum match_left_relation_domain_ISINC
enum matches_description_ISINC
enum now_matches_description_ISINC
enum arithmetic_operation_ISINC
diff --git a/docs/building-module/2-tkn.html b/docs/building-module/2-tkn.html
index 14a12e0521..68917e3a0d 100644
--- a/docs/building-module/2-tkn.html
+++ b/docs/building-module/2-tkn.html
@@ -356,6 +356,8 @@
c = strong_kind_ISINC;
} else if (Str::eq_wide_string(t->command, U"weak-kind")) {
c = weak_kind_ISINC;
+ } else if (Str::eq_wide_string(t->command, U"object-kind")) {
+ c = object_kind_ISINC;
} else if (Str::eq_wide_string(t->command, U"backspace")) {
c = backspace_ISINC;
} else if (Str::eq_wide_string(t->command, U"erase")) {
@@ -414,6 +416,10 @@
c = initialise_ISINC;
} else if (Str::eq_wide_string(t->command, U"matches-description")) {
c = matches_description_ISINC;
+ } else if (Str::eq_wide_string(t->command, U"match-right-relation-domain")) {
+ c = match_right_relation_domain_ISINC;
+ } else if (Str::eq_wide_string(t->command, U"match-left-relation-domain")) {
+ c = match_left_relation_domain_ISINC;
} else if (Str::eq_wide_string(t->command, U"now-matches-description")) {
c = now_matches_description_ISINC;
} else if (Str::eq_wide_string(t->command, U"arithmetic-operation")) {
diff --git a/docs/imperative-module/2-cv.html b/docs/imperative-module/2-cv.html
index c17712ab5a..5a3a4ca0e4 100644
--- a/docs/imperative-module/2-cv.html
+++ b/docs/imperative-module/2-cv.html
@@ -163,7 +163,7 @@
void CompileValues::to_code_val(parse_node *value) {
CompileValues::to_code_val_inner(value, NULL, COMPILE_SPEC_AS_VALUE);
}
-void CompileValues::to_code_val_of_kind(parse_node *value, kind *K) {
+void CompileValues::to_code_val_of_kind(parse_node *value, kind *K) {
CompileValues::to_code_val_inner(value, K, COMPILE_SPEC_AS_VALUE);
}
void CompileValues::to_fresh_code_val_of_kind(parse_node *value, kind *K) {
diff --git a/docs/imperative-module/4-cp.html b/docs/imperative-module/4-cp.html
index f59449f81b..d288b93ced 100644
--- a/docs/imperative-module/4-cp.html
+++ b/docs/imperative-module/4-cp.html
@@ -270,7 +270,7 @@
-void CompilePropositions::to_make_true_about(pcalc_prop *prop, parse_node *t) { +void CompilePropositions::to_make_true_about(pcalc_prop *prop, parse_node *t) { Binding::substitute_var_0_in(prop, t); TypecheckPropositions::type_check(prop, TypecheckPropositions::tc_no_problem_reporting()); @@ -354,7 +354,7 @@internal_error("no way to compile this without deferral"); } -void CompilePropositions::to_test_if_matches(parse_node *in, parse_node *desc) { +void CompilePropositions::to_test_if_matches(parse_node *in, parse_node *desc) { if (Deferrals::defer_if_matches(in, desc)) return; internal_error("no way to compile this without deferral"); } diff --git a/docs/imperative-module/5-ca.html b/docs/imperative-module/5-ca.html index aebe503245..f8be850d30 100644 --- a/docs/imperative-module/5-ca.html +++ b/docs/imperative-module/5-ca.html @@ -77,7 +77,7 @@
-void CompileArithmetic::perform_arithmetic_emit(int op, equation *eqn, +void CompileArithmetic::perform_arithmetic_emit(int op, equation *eqn, parse_node *X, equation_node *EX, kind *KX, parse_node *Y, equation_node *EY, kind *KY) { int binary = TRUE; diff --git a/docs/imperative-module/5-cii.html b/docs/imperative-module/5-cii.html index 09f467834c..4309cbd884 100644 --- a/docs/imperative-module/5-cii.html +++ b/docs/imperative-module/5-cii.html @@ -1004,6 +1004,7 @@if (C == previous_routine_ISINC) Inline command "previous-routine"6.3.4; if (C == strong_kind_ISINC) Inline command "strong-kind"6.3.8; if (C == weak_kind_ISINC) Inline command "weak-kind"6.3.9; + if (C == object_kind_ISINC) Inline command "object-kind"6.3.10;
- This code is used in §6.
§6.3.1. The following produces a new value of the given kind. If it's stored as a @@ -1141,6 +1142,21 @@
return;
§6.3.10. Inline command "object-kind"6.3.10 = +
+ ++ kind *K = CSIInline::parse_bracing_operand_as_kind(ist->operand, + Node::get_kind_variable_declarations(inv)); + if (K) { + if (Kinds::Behaviour::is_object(K)) + EmitCode::val_iname(K_value, RTKindDeclarations::iname(K)); + else + EmitCode::val_number(0); + } else Issue an inline no-such-kind problem6.3.1.2; + return; ++
§6.3.1.2. Issue an inline no-such-kind problem6.3.1.2 =
@@ -1149,7 +1165,7 @@§6.4. Typographic commands. These rather clumsy commands are a residue from earlier forms of the markup language, really. {-open-brace} and {-close-brace} are handled for us elsewhere, so we need do nothing. The other two have actually been withdrawn. @@ -1361,11 +1377,13 @@
§6.6.1. The {-my:name} command creates a local variable for use in the invocation, @@ -1712,14 +1730,70 @@
§6.6.5. The next command generates code able to test if a token in the invocation, +
§6.6.5. These are needed to apply stricter kind-checking to phrases like "the X +which relates to Y by R". For example, if R relates containers to doors then +"the vehicle which relates to the oak door by R" is unsafe because what relates +to the oak door may be a container which is not a vehicle. +
+ +There are two forms according to which domain is implied. +
+ +Inline command "match-left-relation-domain"6.6.5 = +
+ ++ kind *X = CSIInline::parse_bracing_operand_as_kind(ist->operand, Node::get_kind_variable_declarations(inv)); + parse_node *R = CSIInline::parse_bracing_operand_as_identifier(ist->operand2, idb, tokens, my_vars); + kind *KR = Specifications::to_kind(R); + if (Kinds::get_construct(KR) == CON_relation) { + kind *K = NULL; kind *unwanted = NULL; + Kinds::binary_construction_material(KR, &K, &unwanted); + Check there is strict conformance on this domain6.6.5.1; + } + return; ++
§6.6.6. Inline command "match-right-relation-domain"6.6.6 = +
+ ++ kind *X = CSIInline::parse_bracing_operand_as_kind(ist->operand, Node::get_kind_variable_declarations(inv)); + parse_node *R = CSIInline::parse_bracing_operand_as_identifier(ist->operand2, idb, tokens, my_vars); + kind *KR = Specifications::to_kind(R); + if (Kinds::get_construct(KR) == CON_relation) { + kind *unwanted = NULL; kind *K = NULL; + Kinds::binary_construction_material(KR, &unwanted, &K); + Check there is strict conformance on this domain6.6.5.1; + } + return; ++
§6.6.5.1. Check there is strict conformance on this domain6.6.5.1 = +
+ ++ if (Kinds::conforms_to(K, X) == FALSE) { + Problems::quote_source(1, current_sentence); + Problems::quote_kind(2, X); + Problems::quote_kind(3, KR); + Problems::quote_kind(4, K); + StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationDomainWrongKind)); + Problems::issue_problem_segment( + "You wrote %1, but the kinds here do not quite match: what we " + "have is %3, and %4 is not necessarily %2."); + Problems::issue_problem_end(); + } ++ +
§6.6.7. The next command generates code able to test if a token in the invocation, or an Inter variable, matches a given description — which need not be constant. For example, if the phrase prototype includes the token (OS - description of objects) then the bracing {-matches-description:1:OS} compiles a condition testing whether the object in variable {-my:1} matches the description or not.
-Inline command "matches-description"6.6.5 = +
Inline command "matches-description"6.6.7 =
@@ -1741,11 +1815,11 @@return;
§6.6.6. This is the same, except that it compiles code to assert that the given +
§6.6.8. This is the same, except that it compiles code to assert that the given variable matches the given description.
-Inline command "now-matches-description"6.6.6 = +
Inline command "now-matches-description"6.6.8 =
@@ -1768,7 +1842,7 @@return;
§6.6.7. Inline command "arithmetic-operation"6.6.7 = +
§6.6.9. Inline command "arithmetic-operation"6.6.9 =
@@ -1777,12 +1851,12 @@if (Kinds::Dimensions::arithmetic_op_is_unary(op)) binary = FALSE; parse_node *X = NULL, *Y = NULL; kind *KX = NULL, *KY = NULL; - Read the operands and their kinds6.6.7.1; + Read the operands and their kinds6.6.9.1; CompileArithmetic::perform_arithmetic_emit(op, NULL, X, NULL, KX, Y, NULL, KY); return;
§6.6.7.1. Read the operands and their kinds6.6.7.1 = +
§6.6.9.1. Read the operands and their kinds6.6.9.1 =
@@ -1795,15 +1869,15 @@-KY = Specifications::to_kind(Y); }
§6.6.8. This prints a token or variable using the correct format for its kind. The +
§6.6.10. This prints a token or variable using the correct format for its kind. The code below optimises this so that constant text is printed directly, rather than stored as a constant text value and printed by a call to TEXT_TY_Say: this saves 2 words of memory and a function call at print time. But the result would be the same without the optimisation.
-Inline command "say"6.6.8 = +
Inline command "say"6.6.10 =
@@ -1817,9 +1891,9 @@kind *K = CSIInline::parse_bracing_operand_as_kind(ist->operand2, Node::get_kind_variable_declarations(inv)); - if (Kinds::eq(K, K_text)) Inline say text6.6.8.1; - if (Kinds::eq(K, K_number)) Inline say number6.6.8.2; - if (Kinds::eq(K, K_unicode_character)) Inline say unicode character6.6.8.3; + if (Kinds::eq(K, K_text)) Inline say text6.6.10.1; + if (Kinds::eq(K, K_number)) Inline say number6.6.10.2; + if (Kinds::eq(K, K_unicode_character)) Inline say unicode character6.6.10.3; if (K) { EmitCode::call(RTKindConstructors::printing_fn_iname(K)); EmitCode::down(); @@ -1829,7 +1903,7 @@
return;
§6.6.8.1. Inline say text6.6.8.1 = +
§6.6.10.1. Inline say text6.6.10.1 =
@@ -1854,11 +1928,11 @@-} return;
§6.6.8.2. Numbers are also handled directly... +
§6.6.10.2. Numbers are also handled directly...
-Inline say number6.6.8.2 = +
Inline say number6.6.10.2 =
@@ -1872,8 +1946,8 @@-EmitCode::up(); return;
§6.6.8.3. And similarly for Unicode characters. It would be tidier to abstract this +
§6.6.10.3. And similarly for Unicode characters. It would be tidier to abstract this with a function call, but it would cost a function call.
@@ -1881,7 +1955,7 @@Inline say unicode character6.6.8.3 = +
Inline say unicode character6.6.10.3 =
@@ -1903,12 +1977,12 @@-} return;
§6.6.9. This is for debugging purposes only: it does the equivalent of the "showme" +
§6.6.11. This is for debugging purposes only: it does the equivalent of the "showme" phrase applied to the named variable.
-Inline command "show-me"6.6.9 = +
Inline command "show-me"6.6.11 =
@@ -2153,7 +2227,7 @@- +ist->owner->parent_schema->converted_from, "I don't know any local variable called '%4'.");
§8. Parsing the invocation operands. Two ways. First, as an identifier name, which stands for a local Inter variable or for a token in the phrase being invoked. There are three ways we can write this: @@ -2166,7 +2240,7 @@
-parse_node *CSIInline::parse_bracing_operand_as_identifier(text_stream *operand, id_body *idb, +parse_node *CSIInline::parse_bracing_operand_as_identifier(text_stream *operand, id_body *idb, tokens_packet *tokens, local_variable **my_vars) { local_variable *lvar = NULL; if ((Str::get_at(operand, 1) == 0) && @@ -2209,7 +2283,7 @@(- return {-new:return-kind}; -).
-kind *CSIInline::parse_bracing_operand_as_kind(text_stream *operand, +kind *CSIInline::parse_bracing_operand_as_kind(text_stream *operand, kind_variable_declaration *kvd) { if (Str::eq_wide_string(operand, U"return-kind")) return Frames::get_kind_returned(); @@ -2403,7 +2477,7 @@
-void CSIInline::emit_showme(parse_node *spec) { +void CSIInline::emit_showme(parse_node *spec) { TEMPORARY_TEXT(OUT) if (Node::is(spec, PROPERTY_VALUE_NT)) spec = Lvalues::underlying_property(spec); diff --git a/docs/knowledge-module/3-spr2.html b/docs/knowledge-module/3-spr2.html index 07ff5280f9..0a15f53024 100644 --- a/docs/knowledge-module/3-spr2.html +++ b/docs/knowledge-module/3-spr2.html @@ -250,7 +250,6 @@
void SettingPropertyRelations::set_property_BP_schemas(binary_predicate *bp, property *prn) { - LOG("set_property_BP_schemas sees property %n of kind %u\n", RTProperties::iname(prn), ValueProperties::kind(prn)); if (Kinds::Behaviour::uses_block_values(ValueProperties::kind(prn))) { bp->task_functions[TEST_ATOM_TASK] = Calculus::Schemas::new("ComparePV(*1.%n, *2) == 0", RTProperties::iname(prn)); diff --git a/inform7/Figures/memory-diagnostics.txt b/inform7/Figures/memory-diagnostics.txt index c5567e26af..07b927fed4 100644 --- a/inform7/Figures/memory-diagnostics.txt +++ b/inform7/Figures/memory-diagnostics.txt @@ -1,6 +1,6 @@ -Total memory consumption was 153422K = 150 MB +Total memory consumption was 153352K = 150 MB - ---- was used for 2279849 objects, in 402729 frames in 0 x 800K = 0K = 0 MB: + ---- was used for 2279726 objects, in 402705 frames in 0 x 800K = 0K = 0 MB: 28.9% inter_tree_node_array 63 x 8192 = 516096 objects, 45418464 bytes 19.9% text_stream_array 5555 x 100 = 555500 objects, 31285760 bytes @@ -18,7 +18,7 @@ Total memory consumption was 153422K = 150 MB 1.4% inter_name_generator_array 55 x 1000 = 55000 objects, 2201760 bytes 1.2% package_request 22153 objects, 1949464 bytes 1.2% vocabulary_entry_array 168 x 100 = 16800 objects, 1886976 bytes - 1.1% dict_entry_array 561 x 100 = 56100 objects, 1813152 bytes + 1.1% dict_entry_array 560 x 100 = 56000 objects, 1809920 bytes 0.9% inter_symbols_table 27946 objects, 1564976 bytes 0.9% i6_schema_array 25 x 100 = 2500 objects, 1500800 bytes 0.9% match_trie_array 11 x 1000 = 11000 objects, 1496352 bytes @@ -119,7 +119,7 @@ Total memory consumption was 153422K = 150 MB ---- adjective_iname_holder 337 objects, 13480 bytes ---- booking_list 417 objects, 13344 bytes ---- web_bibliographic_datum 203 objects, 12992 bytes - ---- uniqueness_count 509 objects, 12216 bytes + ---- uniqueness_count 486 objects, 11664 bytes ---- inter_construct 32 objects, 11008 bytes ---- md_doc_state 2 objects, 10480 bytes ---- heading_tree 33 objects, 10296 bytes @@ -271,7 +271,7 @@ Total memory consumption was 153422K = 150 MB 100.0% was used for memory not allocated for objects: - 64.4% text stream storage 101245812 bytes in 579773 claims + 64.4% text stream storage 101241876 bytes in 579750 claims 3.9% dictionary storage 6168192 bytes in 8263 claims ---- sorting 20984 bytes in 2656 claims 4.5% source text 7200000 bytes in 3 claims @@ -280,7 +280,7 @@ Total memory consumption was 153422K = 150 MB ---- linguistic stock array 81920 bytes in 2 claims ---- small word set array 105600 bytes in 22 claims 3.1% inter symbols storage 4905872 bytes in 29425 claims - 10.7% inter bytecode storage 16841636 bytes in 15 claims + 10.6% inter bytecode storage 16773620 bytes in 15 claims 3.9% inter links storage 6222976 bytes in 11 claims 0.1% inter tree location list storage 191232 bytes in 32 claims 1.7% instance-of-kind counting 2715904 bytes in 1 claim @@ -289,5 +289,5 @@ Total memory consumption was 153422K = 150 MB ---- code generation workspace for objects 3616 bytes in 19 claims 0.1% emitter array storage 295200 bytes in 2112 claims --140.-2% was overhead - -220277832 bytes = -215115K = -210 MB +-140.-2% was overhead - -220274048 bytes = -215111K = -210 MB diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index 797d40593d..2af8da7332 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,8 +1,8 @@ 100.0% in inform7 run 66.5% in compilation to Inter - 44.1% in //Sequence::undertake_queued_tasks// - 4.1% in //MajorNodes::pre_pass// - 3.4% in //MajorNodes::pass_1// + 43.7% in //Sequence::undertake_queued_tasks// + 4.4% in //MajorNodes::pre_pass// + 3.7% in //MajorNodes::pass_1// 2.0% in //RTKindConstructors::compile// 1.7% in //ImperativeDefinitions::assess_all// 1.3% in //RTPhrasebook::compile_entries// @@ -15,7 +15,7 @@ 0.3% in //Sequence::undertake_queued_tasks// 0.3% in //Sequence::undertake_queued_tasks// 0.3% in //Task::make_built_in_kind_constructors// - 4.8% not specifically accounted for + 4.5% not specifically accounted for 26.2% in running Inter pipeline 8.6% in step 14/15: generate inform6 -> auto.inf 6.8% in step 5/15: load-binary-kits @@ -26,5 +26,5 @@ 0.3% in step 7/15: shorten-wiring 0.3% in step 8/15: detect-indirect-calls 1.8% not specifically accounted for - 6.5% in supervisor - 0.7% not specifically accounted for + 6.8% in supervisor + 0.4% not specifically accounted for diff --git a/inform7/Internal/Extensions/Graham Nelson/Basic Inform.i7xd/Source/Basic Inform.i7x b/inform7/Internal/Extensions/Graham Nelson/Basic Inform.i7xd/Source/Basic Inform.i7x index 48cb51a3b7..e46922e94c 100644 --- a/inform7/Internal/Extensions/Graham Nelson/Basic Inform.i7xd/Source/Basic Inform.i7x +++ b/inform7/Internal/Extensions/Graham Nelson/Basic Inform.i7xd/Source/Basic Inform.i7x @@ -1249,57 +1249,57 @@ To decide which number is number of steps via (R - relation of objects) To decide which list of Ks is list of (name of kind of value K) that/which/whom (R - relation of Ks to values of kind L) relates (documented at ph_leftdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -). To decide which list of Ls is list of (name of kind of value L) to which/whom (R - relation of values of kind K to Ls) relates (documented at ph_rightdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [1] To decide which list of Ls is list of (name of kind of value L) that/which/whom (R - relation of values of kind K to Ls) relates to (documented at ph_rightdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [2] To decide which list of Ks is list of (name of kind of value K) that/which/who relate to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_leftlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -). To decide which list of Ls is list of (name of kind of value L) to which/whom (X - K) relates by (R - relation of values of kind K to Ls) (documented at ph_rightlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [1] To decide which list of Ls is list of (name of kind of value L) that/which/whom (X - K) relates to by (R - relation of values of kind K to Ls) (documented at ph_rightlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [2] To decide whether (name of kind of value K) relates to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_ifright): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -). To decide whether (X - K) relates to (name of kind of value L) by (R - relation of values of kind K to Ls) (documented at ph_ifleft): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -). + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -). To decide which K is (name of kind of value K) that/which/who relates to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_leftlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -). To decide which L is (name of kind of value L) to which/whom (X - K) relates by (R - relation of values of kind K to Ls) (documented at ph_rightlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [1] To decide which L is (name of kind of value L) that/which/whom (X - K) relates to by (R - relation of values of kind K to Ls) (documented at ph_rightlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [2] Chapter 7 - Functional Programming diff --git a/inform7/Tests/Test Cases/ContainmentScanning.txt b/inform7/Tests/Test Cases/ContainmentScanning.txt index 88d37b2a8a..7d776cd99e 100644 --- a/inform7/Tests/Test Cases/ContainmentScanning.txt +++ b/inform7/Tests/Test Cases/ContainmentScanning.txt @@ -12,9 +12,9 @@ To say relations for (item - a thing): showme the containment relation; To describe (R - a relation of objects) for (item - a thing): - say "[item]: [the list of things to which item relates by R with indefinite articles]."; - if a thing to which item relates by R is a thing: - say "[The item] [verb rendering applied to a random verb that means R] [the list of things to which item relates by R with indefinite articles]. [run paragraph on]" + say "[item]: [the list of objects to which item relates by R with indefinite articles]."; + if an object to which item relates by R is a thing: + say "[The item] [verb rendering applied to a random verb that means R] [the list of objects to which item relates by R with indefinite articles]. [run paragraph on]" To decide which text is the rendering of (V - verb) (this is verb rendering): decide on "[adapt V]". diff --git a/inform7/Tests/Test Problems/PM_RelationDomainWrongKind--I.txt b/inform7/Tests/Test Problems/PM_RelationDomainWrongKind--I.txt new file mode 100644 index 0000000000..856374f674 --- /dev/null +++ b/inform7/Tests/Test Problems/PM_RelationDomainWrongKind--I.txt @@ -0,0 +1,11 @@ +Inform 7 v10.2.0 has started. +I've now read your source text, which is 66 words long. +I've also read version 10.2.0 of Basic Inform by Graham Nelson, which is 10687 words long. +I've also read version 10.2.0 of English Language by Graham Nelson, which is 2330 words long. +I've also read version 10.2.0 of Standard Rules by Graham Nelson, which is 35526 words long. +Problem__ PM_RelationDomainWrongKind + >--> You wrote 'showme the vehicle that relates to s1 by the regard relation' + (source text, line 10), but the kinds here do not quite match: what we have + is a relation of containers to supporters, and a container is not + necessarily a vehicle. +Inform 7 has finished. diff --git a/inform7/Tests/Test Problems/PM_RelationDomainWrongKind.txt b/inform7/Tests/Test Problems/PM_RelationDomainWrongKind.txt new file mode 100644 index 0000000000..ff7885fa8a --- /dev/null +++ b/inform7/Tests/Test Problems/PM_RelationDomainWrongKind.txt @@ -0,0 +1,14 @@ +Problem: PM_RelationDomainWrongKind + +Regard relates one container to one supporter. +The verb to respect means the regard relation. + +s1 is a supporter. +c1 is a container. +x1 is a vehicle. +c1 respects s1. + +when play begins: + showme the vehicle that relates to s1 by the regard relation; + showme the thing that relates to s1 by the regard relation; + showme the container that relates to s1 by the regard relation; diff --git a/inform7/extensions/basic_inform/Sections/Phrase Definitions.w b/inform7/extensions/basic_inform/Sections/Phrase Definitions.w index f0defe8d42..f923a440c0 100644 --- a/inform7/extensions/basic_inform/Sections/Phrase Definitions.w +++ b/inform7/extensions/basic_inform/Sections/Phrase Definitions.w @@ -1507,57 +1507,57 @@ To decide which number is number of steps via (R - relation of objects) To decide which list of Ks is list of (name of kind of value K) that/which/whom (R - relation of Ks to values of kind L) relates (documented at ph_leftdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of K}, RLIST_ALL_X) -). To decide which list of Ls is list of (name of kind of value L) to which/whom (R - relation of values of kind K to Ls) relates (documented at ph_rightdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [1] To decide which list of Ls is list of (name of kind of value L) that/which/whom (R - relation of values of kind K to Ls) relates to (documented at ph_rightdomain): - (- RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LIST, {-new:list of L}, RLIST_ALL_Y) -). [2] To decide which list of Ks is list of (name of kind of value K) that/which/who relate to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_leftlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_X, {Y}, {-new:list of K}) -). To decide which list of Ls is list of (name of kind of value L) to which/whom (X - K) relates by (R - relation of values of kind K to Ls) (documented at ph_rightlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [1] To decide which list of Ls is list of (name of kind of value L) that/which/whom (X - K) relates to by (R - relation of values of kind K to Ls) (documented at ph_rightlookuplist): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ALL_Y, {X}, {-new:list of L}) -). [2] To decide whether (name of kind of value K) relates to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_ifright): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_CAN_GET_X) -). To decide whether (X - K) relates to (name of kind of value L) by (R - relation of values of kind K to Ls) (documented at ph_ifleft): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -). + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_CAN_GET_Y) -). To decide which K is (name of kind of value K) that/which/who relates to (Y - L) by (R - relation of Ks to values of kind L) (documented at ph_leftlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -). + (- {-match-left-relation-domain:K:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {Y}, RLANY_GET_X) -). To decide which L is (name of kind of value L) to which/whom (X - K) relates by (R - relation of values of kind K to Ls) (documented at ph_rightlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [1] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [1] To decide which L is (name of kind of value L) that/which/whom (X - K) relates to by (R - relation of values of kind K to Ls) (documented at ph_rightlookup): - (- RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [2] + (- {-match-right-relation-domain:L:R}RelationTest({-by-reference:R}, RELS_LOOKUP_ANY, {X}, RLANY_GET_Y) -). [2] @h Functional Programming. Here we have the ability to use the name of a function as a value, and to diff --git a/inform7/imperative-module/Chapter 5/Compile Invocations Inline.w b/inform7/imperative-module/Chapter 5/Compile Invocations Inline.w index 5929ce70ae..430915c65f 100644 --- a/inform7/imperative-module/Chapter 5/Compile Invocations Inline.w +++ b/inform7/imperative-module/Chapter 5/Compile Invocations Inline.w @@ -771,6 +771,7 @@ We'll start with a suite of details about kinds: if (C == previous_routine_ISINC) @; if (C == strong_kind_ISINC) @ ; if (C == weak_kind_ISINC) @ ; + if (C == object_kind_ISINC) @ ; @ The following produces a new value of the given kind. If it's stored as a word value, this will just be the default value, so |{-new:time}| will output @@ -863,6 +864,17 @@ proposition. else @ ; return; +@ = + kind *K = CSIInline::parse_bracing_operand_as_kind(ist->operand, + Node::get_kind_variable_declarations(inv)); + if (K) { + if (Kinds::Behaviour::is_object(K)) + EmitCode::val_iname(K_value, RTKindDeclarations::iname(K)); + else + EmitCode::val_number(0); + } else @ ; + return; + @ = StandardProblems::inline_problem(_p_(PM_InlineNew), idb, ist->owner->parent_schema->converted_from, @@ -1014,6 +1026,8 @@ a command, which is why it isn't here.) if (C == unprotect_ISINC) @ ; if (C == copy_ISINC) @ ; if (C == initialise_ISINC) @ ; + if (C == match_right_relation_domain_ISINC) @ ; + if (C == match_left_relation_domain_ISINC) @ ; if (C == matches_description_ISINC) @ ; if (C == now_matches_description_ISINC) @ ; if (C == arithmetic_operation_ISINC) @ ; @@ -1293,6 +1307,48 @@ story title). return; } +@ These are needed to apply stricter kind-checking to phrases like "the X +which relates to Y by R". For example, if R relates containers to doors then +"the vehicle which relates to the oak door by R" is unsafe because what relates +to the oak door may be a container which is not a vehicle. + +There are two forms according to which domain is implied. + +@ = + kind *X = CSIInline::parse_bracing_operand_as_kind(ist->operand, Node::get_kind_variable_declarations(inv)); + parse_node *R = CSIInline::parse_bracing_operand_as_identifier(ist->operand2, idb, tokens, my_vars); + kind *KR = Specifications::to_kind(R); + if (Kinds::get_construct(KR) == CON_relation) { + kind *K = NULL; kind *unwanted = NULL; + Kinds::binary_construction_material(KR, &K, &unwanted); + @ ; + } + return; + +@ = + kind *X = CSIInline::parse_bracing_operand_as_kind(ist->operand, Node::get_kind_variable_declarations(inv)); + parse_node *R = CSIInline::parse_bracing_operand_as_identifier(ist->operand2, idb, tokens, my_vars); + kind *KR = Specifications::to_kind(R); + if (Kinds::get_construct(KR) == CON_relation) { + kind *unwanted = NULL; kind *K = NULL; + Kinds::binary_construction_material(KR, &unwanted, &K); + @ ; + } + return; + +@ = + if (Kinds::conforms_to(K, X) == FALSE) { + Problems::quote_source(1, current_sentence); + Problems::quote_kind(2, X); + Problems::quote_kind(3, KR); + Problems::quote_kind(4, K); + StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_RelationDomainWrongKind)); + Problems::issue_problem_segment( + "You wrote %1, but the kinds here do not quite match: what we " + "have is %3, and %4 is not necessarily %2."); + Problems::issue_problem_end(); + } + @ The next command generates code able to test if a token in the invocation, or an Inter variable, matches a given description -- which need not be constant. For example, if the phrase prototype includes the token |(OS - description of objects)| diff --git a/inform7/knowledge-module/Chapter 3/Setting Property Relation.w b/inform7/knowledge-module/Chapter 3/Setting Property Relation.w index 73be4c0887..23eaa484ad 100644 --- a/inform7/knowledge-module/Chapter 3/Setting Property Relation.w +++ b/inform7/knowledge-module/Chapter 3/Setting Property Relation.w @@ -159,7 +159,6 @@ and simplicity. = void SettingPropertyRelations::set_property_BP_schemas(binary_predicate *bp, property *prn) { - LOG("set_property_BP_schemas sees property %n of kind %u\n", RTProperties::iname(prn), ValueProperties::kind(prn)); if (Kinds::Behaviour::uses_block_values(ValueProperties::kind(prn))) { bp->task_functions[TEST_ATOM_TASK] = Calculus::Schemas::new("ComparePV(*1.%n, *2) == 0", RTProperties::iname(prn)); diff --git a/inter/building-module/Chapter 2/Inter Schemas.w b/inter/building-module/Chapter 2/Inter Schemas.w index 416302a198..0a1a65697a 100644 --- a/inter/building-module/Chapter 2/Inter Schemas.w +++ b/inter/building-module/Chapter 2/Inter Schemas.w @@ -329,6 +329,7 @@ inter_schema_token *InterSchemas::new_token(int type, text_stream *material, @e indexing_routine_ISINC @e strong_kind_ISINC @e weak_kind_ISINC +@e object_kind_ISINC @e backspace_ISINC @e erase_ISINC @e open_brace_ISINC @@ -357,6 +358,8 @@ inter_schema_token *InterSchemas::new_token(int type, text_stream *material, @e unprotect_ISINC @e copy_ISINC @e initialise_ISINC +@e match_right_relation_domain_ISINC +@e match_left_relation_domain_ISINC @e matches_description_ISINC @e now_matches_description_ISINC @e arithmetic_operation_ISINC diff --git a/inter/building-module/Chapter 2/Tokenisation.w b/inter/building-module/Chapter 2/Tokenisation.w index 9b784adaff..c15a3a1db0 100644 --- a/inter/building-module/Chapter 2/Tokenisation.w +++ b/inter/building-module/Chapter 2/Tokenisation.w @@ -257,6 +257,8 @@ a bracing. c = strong_kind_ISINC; } else if (Str::eq_wide_string(t->command, U"weak-kind")) { c = weak_kind_ISINC; + } else if (Str::eq_wide_string(t->command, U"object-kind")) { + c = object_kind_ISINC; } else if (Str::eq_wide_string(t->command, U"backspace")) { c = backspace_ISINC; } else if (Str::eq_wide_string(t->command, U"erase")) { @@ -315,6 +317,10 @@ a bracing. c = initialise_ISINC; } else if (Str::eq_wide_string(t->command, U"matches-description")) { c = matches_description_ISINC; + } else if (Str::eq_wide_string(t->command, U"match-right-relation-domain")) { + c = match_right_relation_domain_ISINC; + } else if (Str::eq_wide_string(t->command, U"match-left-relation-domain")) { + c = match_left_relation_domain_ISINC; } else if (Str::eq_wide_string(t->command, U"now-matches-description")) { c = now_matches_description_ISINC; } else if (Str::eq_wide_string(t->command, U"arithmetic-operation")) { diff --git a/resources/Documentation/Examples/RelevantRelations.txt b/resources/Documentation/Examples/RelevantRelations.txt index d8ca7eb6bf..b485cd9cc6 100644 --- a/resources/Documentation/Examples/RelevantRelations.txt +++ b/resources/Documentation/Examples/RelevantRelations.txt @@ -63,9 +63,9 @@ The following uses what is, strictly speaking, a piece of internal machinery not Before printing the name of something (called mentioned target) while writing a paragraph about something: add the mentioned target to the current paragraph, if absent. - To describe (R - a relation of objects) for (item - a thing): - if a thing to which item relates by R is a thing: - say "[The item with pronoun] [verb rendering applied to a random verb that means R] [the list of things to which item relates by R with indefinite articles]. [run paragraph on]" + To describe (R - a relation of objects) for (item - an object): + if an object to which item relates by R is a thing: + say "[The item with pronoun] [verb rendering applied to a random verb that means R] [the list of objects to which item relates by R with indefinite articles]. [run paragraph on]" To decide which text is the rendering of (V - verb) (this is verb rendering): decide on "[adapt V]".