1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-29 05:24:57 +03:00

Slightly clarified namespaces

This commit is contained in:
Graham Nelson 2022-10-13 23:15:49 +01:00
parent 1f81d09a58
commit baa615c76f
7 changed files with 105 additions and 21 deletions

View file

@ -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^";
];
-).

View file

@ -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

View file

@ -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;
}

View file

@ -84,8 +84,9 @@ So the above internal error cannot occur.
@<Interpret this as an identifier@> =
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<Str::len(name); i++)
if (Str::get_at(name, i) == '`')
add_namespace = FALSE;
@ -105,7 +106,10 @@ So the above internal error cannot occur.
if (S) goto Exit;
S = InterSymbolsTable::symbol_from_name(LargeScale::main_scope(I), name);
if (S) goto Exit;
S = InterNames::to_symbol(HierarchyLocations::find_by_name(I, seek));
if (add_namespace)
S = InterNames::to_symbol(HierarchyLocations::find_by_implied_name(I, name, finder.from_namespace));
else
S = InterNames::to_symbol(HierarchyLocations::find_by_name(I, seek));
Exit: ;
DISCARD_TEXT(N)
return S;

View file

@ -418,15 +418,24 @@ void Wiring::connect_plugs_to_sockets(inter_tree *I) {
last_tick = i;
}
if (last_tick >= 0) {
TEMPORARY_TEXT(N)
for (int i=last_tick+1; i<Str::len(name); i++)
PUT_TO(N, Str::get_at(name, i));
socket = Wiring::find_socket(I, N);
if (socket) {
LOGIF(INTER_CONNECTORS, "Wiring plug to socket with global name: $3\n", S);
Wiring::wire_plug(S, socket);
if ((Str::prefix_eq(name, I"implied`", 8)) ||
(Str::prefix_eq(name, I"main`", 5))) {
TEMPORARY_TEXT(N)
TEMPORARY_TEXT(NS)
for (int i=8; i<last_tick; i++)
PUT_TO(NS, Str::get_at(name, i));
if (Str::eq(NS, I"main")) Str::clear(NS);
for (int i=last_tick+1; i<Str::len(name); i++)
PUT_TO(N, Str::get_at(name, i));
socket = Wiring::find_socket(I, N);
if (socket) {
LOGIF(INTER_CONNECTORS, "Wire implied plug '%S' to socket with global name: $3\n",
name, S);
Wiring::wire_plug(S, socket);
}
DISCARD_TEXT(N)
DISCARD_TEXT(NS)
}
DISCARD_TEXT(N)
}
}
}

View file

@ -778,19 +778,36 @@ These have package types |_function| and |_code| respectively.
=
void CompileSplatsStage::apply_annotations(text_stream *A, text_stream *NS, inter_symbol *S) {
if (Str::len(NS) > 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<L; i++) PUT_TO(N, Str::get_at(NS, i));
LOGIF(INTER_CONNECTORS, "Assign namespace '%S' to $3\n", N, S);
InterSymbol::set_namespace(S, N);
DISCARD_TEXT(N)
}
if (Str::len(A) > 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.

View file

@ -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; i<Str::len(state->namespace); 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);