From baa615c76f5e4bda5acef4852b9c9512458ef209 Mon Sep 17 00:00:00 2001 From: Graham Nelson Date: Thu, 13 Oct 2022 23:15:49 +0100 Subject: [PATCH] Slightly clarified namespaces --- inform7/Tests/Test Basic/Namespaces.txt | 17 +++++++++-- .../Test Basic/_Results_Ideal/Namespaces.txt | 6 ++-- .../Chapter 1/Hierarchy Locations.w | 14 +++++++++ .../Chapter 2/Identifier Finders.w | 8 +++-- inter/bytecode-module/Chapter 2/The Wiring.w | 25 +++++++++++----- .../Chapter 3/Compile Splats Stage.w | 26 +++++++++++++--- .../Chapter 3/Parsing Stages.w | 30 +++++++++++++++++-- 7 files changed, 105 insertions(+), 21 deletions(-) diff --git a/inform7/Tests/Test Basic/Namespaces.txt b/inform7/Tests/Test Basic/Namespaces.txt index 911db2400..458444928 100644 --- a/inform7/Tests/Test Basic/Namespaces.txt +++ b/inform7/Tests/Test Basic/Namespaces.txt @@ -7,6 +7,8 @@ Include (- [ greet; summon(); print "greet in Alpha^"; + ponder(); + main`ponder(); dismiss(); Beta`dismiss(); ]; @@ -15,21 +17,30 @@ Include (- print "dismiss in Alpha, where EXAMPLE = ", EXAMPLE, "^"; ]; + [ ponder; + print "ponder in Alpha^"; + ]; + +namespace(Beta); [ dismiss; print "dismiss in Beta^"; ]; -+namespace(); ++namespace(main); Constant EXAMPLE = 10; [ summon; - print "summon outside of namespace where Alpha`EXAMPLE = ", Alpha`EXAMPLE, "^"; + print "summon in main where Alpha`EXAMPLE = ", Alpha`EXAMPLE, "^"; ]; + [ dismiss; - print "dismiss outside of namespace^"; + print "dismiss in main^"; + ]; + + [ ponder; + print "ponder in main^"; ]; -). diff --git a/inform7/Tests/Test Basic/_Results_Ideal/Namespaces.txt b/inform7/Tests/Test Basic/_Results_Ideal/Namespaces.txt index 15bcd1b89..ce793b1a5 100644 --- a/inform7/Tests/Test Basic/_Results_Ideal/Namespaces.txt +++ b/inform7/Tests/Test Basic/_Results_Ideal/Namespaces.txt @@ -1,9 +1,11 @@ - summon outside of namespace where Alpha`EXAMPLE = 20 + summon in main where Alpha`EXAMPLE = 20 greet in Alpha + ponder in Alpha + ponder in main dismiss in Alpha, where EXAMPLE = 20 dismiss in Beta Here are the dismiss functions: dismiss in Alpha, where EXAMPLE = 20 dismiss in Beta - dismiss outside of namespace + dismiss in main The value of EXAMPLE here is 10 diff --git a/inter/building-module/Chapter 1/Hierarchy Locations.w b/inter/building-module/Chapter 1/Hierarchy Locations.w index 9270c90e5..372187ed5 100644 --- a/inter/building-module/Chapter 1/Hierarchy Locations.w +++ b/inter/building-module/Chapter 1/Hierarchy Locations.w @@ -534,3 +534,17 @@ inter_name *HierarchyLocations::find_by_name(inter_tree *I, text_stream *name) { } return try; } + +inter_name *HierarchyLocations::find_by_implied_name(inter_tree *I, text_stream *name, + text_stream *from_namespace) { + if (Str::len(name) == 0) internal_error("empty extern"); + inter_name *try = HierarchyLocations::name_to_iname(I, name); + if (try == NULL) { + TEMPORARY_TEXT(N) + WRITE_TO(N, "implied`%S`%S", from_namespace, name); + HierarchyLocations::con(I, -1, N, LocationRequirements::plug()); + try = HierarchyLocations::name_to_iname(I, N); + DISCARD_TEXT(N) + } + return try; +} diff --git a/inter/building-module/Chapter 2/Identifier Finders.w b/inter/building-module/Chapter 2/Identifier Finders.w index dfe0a4e25..387da099c 100644 --- a/inter/building-module/Chapter 2/Identifier Finders.w +++ b/inter/building-module/Chapter 2/Identifier Finders.w @@ -84,8 +84,9 @@ So the above internal error cannot occur. @ = text_stream *seek = name; TEMPORARY_TEXT(N) + int add_namespace = FALSE; if (Str::len(finder.from_namespace) > 0) { - int add_namespace = TRUE; + add_namespace = TRUE; for (int i=0; i= 0) { - TEMPORARY_TEXT(N) - for (int i=last_tick+1; i 0) { - LOGIF(INTER_CONNECTORS, "Assign namespace '%S' to $3\n", NS, S); - InterSymbol::set_namespace(S, NS); + int apply_private = NOT_APPLICABLE, L = Str::len(NS); + if (Str::get_last_char(NS) == '+') apply_private = FALSE; + if (Str::get_last_char(NS) == '-') apply_private = TRUE; + if (apply_private != NOT_APPLICABLE) L--; + if (L > 0) { + TEMPORARY_TEXT(N) + for (int i=0; i 0) { LOGIF(INTER_CONNECTORS, "Trying to apply '%S' to $3\n", A, S); for (I6_annotation *IA = I6Annotations::parse(A); IA; IA = IA->next) { if (Str::eq_insensitive(IA->identifier, I"private")) { if ((IA->terms == NULL) || (LinkedLists::len(IA->terms) == 0)) { - SymbolAnnotation::set_b(S, PRIVATE_IANN, TRUE); + if (apply_private == TRUE) + PipelineErrors::kit_error("the +private annotation is redundant here", NULL); + apply_private = TRUE; } else { PipelineErrors::kit_error("the +private annotation does not take any terms", NULL); } + } else if (Str::eq_insensitive(IA->identifier, I"public")) { + if ((IA->terms == NULL) || (LinkedLists::len(IA->terms) == 0)) { + if (apply_private == FALSE) + PipelineErrors::kit_error("the +public annotation is redundant here", NULL); + apply_private = FALSE; + } else { + PipelineErrors::kit_error("the +public annotation does not take any terms", NULL); + } } else if (Str::eq_insensitive(IA->identifier, I"replacing")) { text_stream *from = I"_"; if (IA->terms) { @@ -809,6 +826,7 @@ void CompileSplatsStage::apply_annotations(text_stream *A, text_stream *NS, inte } } } + if (apply_private == TRUE) SymbolAnnotation::set_b(S, PRIVATE_IANN, TRUE); } @h Plumbing. diff --git a/inter/pipeline-module/Chapter 3/Parsing Stages.w b/inter/pipeline-module/Chapter 3/Parsing Stages.w index 35e186676..9c34b2331 100644 --- a/inter/pipeline-module/Chapter 3/Parsing Stages.w +++ b/inter/pipeline-module/Chapter 3/Parsing Stages.w @@ -301,14 +301,40 @@ void ParsingStages::splat(text_stream *R, simple_tangle_docket *docket) { if ((IA) && (Str::eq_insensitive(IA->identifier, I"namespace"))) { rpi_docket_state *state = (rpi_docket_state *) docket->state; Str::clear(state->namespace); + int private = NOT_APPLICABLE; I6_annotation_term *term; - LOOP_OVER_LINKED_LIST(term, I6_annotation_term, IA->terms) + LOOP_OVER_LINKED_LIST(term, I6_annotation_term, IA->terms) { if (Str::eq_insensitive(term->key, I"_")) { WRITE_TO(state->namespace, "%S", term->value); + } else if (Str::eq_insensitive(term->key, I"access")) { + if (Str::eq_insensitive(term->value, I"private")) private = TRUE; + else if (Str::eq_insensitive(term->value, I"public")) private = FALSE; + else PipelineErrors::kit_error( + "the 'access' must be 'private' or 'public', not '%S'", term->value); } else { PipelineErrors::kit_error( - "the +replacing annotation does not take the term '%S'", term->key); + "the +namespace annotation does not take the term '%S'", term->key); } + } + int bad_name = FALSE; + for (int i=0; inamespace); i++) { + wchar_t c = Str::get_at(state->namespace, i); + if (i == 0) { + if (Characters::isalpha(c) == FALSE) bad_name = TRUE; + } else { + if ((Characters::isalnum(c) == FALSE) && (c != '_')) bad_name = TRUE; + } + } + if (bad_name) + PipelineErrors::kit_error( + "a namespace name should begin with a letter and contain " + "only alphanumeric characters or '_'", NULL); + if (Str::len(state->namespace) == 0) + PipelineErrors::kit_error( + "use '+namespace(main);' to return to the global namespace", NULL); + if (Str::eq(state->namespace, I"main")) Str::clear(state->namespace); + if (private == TRUE) PUT_TO(state->namespace, '-'); + if (private == FALSE) PUT_TO(state->namespace, '+'); } else { (*(docket->error_callback))( "this annotation seems not to apply to any directive: '%S'", A);