2019-02-04 22:26:45 +00:00
|
|
|
[Enumerations::] Enumerated Constants.
|
|
|
|
|
|
|
|
To define sequentially numbered values for families of constants.
|
|
|
|
|
|
|
|
@ The idea here is that each enumeration set is a sequence of named constants
|
2024-03-09 05:41:29 +00:00
|
|
|
with a given postfix: for example, [[HARRY_ST]], [[NEVILLE_ST]], [[ANGELINA_ST]]
|
|
|
|
form the [[*_ST]] set. By definition, the postfix part is the portion of the
|
|
|
|
name following the final underscore, so in this case [[ST]].
|
2019-02-04 22:26:45 +00:00
|
|
|
|
|
|
|
Each set of constants begins at a given value (typically 0) and then
|
|
|
|
increments sequentially in definition order.
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<*>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
typedef struct enumeration_set {
|
|
|
|
struct text_stream *postfix;
|
|
|
|
struct text_stream *stub;
|
|
|
|
int first_value;
|
|
|
|
int next_free_value;
|
|
|
|
struct source_line *last_observed_at;
|
2020-05-09 12:05:00 +00:00
|
|
|
CLASS_DEFINITION
|
2019-02-04 22:26:45 +00:00
|
|
|
} enumeration_set;
|
|
|
|
|
|
|
|
@ There won't be enough sets to make a hash table worth the overhead, so
|
|
|
|
compare all against all:
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<*>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
enumeration_set *Enumerations::find(text_stream *post) {
|
|
|
|
enumeration_set *es = NULL;
|
|
|
|
LOOP_OVER(es, enumeration_set)
|
|
|
|
if (Str::eq(post, es->postfix))
|
|
|
|
return es;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
@ The following is called when an enumeration is found. If [[from]] has a
|
2019-02-04 22:26:45 +00:00
|
|
|
sensible value, this is the start of a new enumeration set; otherwise it's
|
|
|
|
a further constant in what ought to be an existing set.
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<*>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
void Enumerations::define(OUTPUT_STREAM, text_stream *symbol,
|
|
|
|
text_stream *from, source_line *L) {
|
2020-06-27 22:03:14 +00:00
|
|
|
TEMPORARY_TEXT(pf)
|
2024-03-09 05:41:29 +00:00
|
|
|
<<Find the postfix in this symbol name>>;
|
2019-02-04 22:26:45 +00:00
|
|
|
enumeration_set *es = Enumerations::find(pf);
|
2024-03-09 05:41:29 +00:00
|
|
|
if (from == NULL) <<Continue existing set>>
|
|
|
|
else <<Begin new set>>;
|
2020-06-27 22:03:14 +00:00
|
|
|
DISCARD_TEXT(pf)
|
2019-02-04 22:26:45 +00:00
|
|
|
if (es) es->last_observed_at = L;
|
|
|
|
}
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
@ So for instance [[HARRY_ST]] to [[ST]]:
|
2019-02-04 22:26:45 +00:00
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<Find the postfix in this symbol name>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
match_results mr = Regexp::create_mr();
|
|
|
|
if (Regexp::match(&mr, symbol, L"%c*_(%C+?)")) Str::copy(pf, mr.exp[0]);
|
|
|
|
else {
|
|
|
|
Main::error_in_web(I"enumeration constants must belong to a _FAMILY", L);
|
|
|
|
WRITE_TO(pf, "BOGUS");
|
|
|
|
}
|
|
|
|
Regexp::dispose_of(&mr);
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<Continue existing set>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
if (es) {
|
|
|
|
if (es->stub) WRITE("(%S+", es->stub);
|
|
|
|
WRITE("%d", es->next_free_value++);
|
|
|
|
if (es->stub) WRITE(")");
|
|
|
|
} else Main::error_in_web(I"this enumeration _FAMILY is unknown", L);
|
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<Begin new set>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
if (es) Main::error_in_web(I"this enumeration _FAMILY already exists", L);
|
|
|
|
else {
|
|
|
|
es = CREATE(enumeration_set);
|
|
|
|
es->postfix = Str::duplicate(pf);
|
|
|
|
es->stub = NULL;
|
|
|
|
if ((Str::len(from) < 8) &&
|
|
|
|
((Regexp::match(NULL, from, L"%d+")) ||
|
|
|
|
(Regexp::match(NULL, from, L"-%d+")))) {
|
|
|
|
es->first_value = Str::atoi(from, 0);
|
|
|
|
es->next_free_value = es->first_value + 1;
|
|
|
|
} else {
|
|
|
|
es->stub = Str::duplicate(from);
|
|
|
|
es->first_value = 0;
|
|
|
|
es->next_free_value = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (es->stub) WRITE("(%S+", es->stub);
|
|
|
|
WRITE("%d", es->first_value);
|
|
|
|
if (es->stub) WRITE(")");
|
|
|
|
|
|
|
|
@ For each set, a further constant is defined to give the range; for example,
|
2024-03-09 05:41:29 +00:00
|
|
|
we would have [[NO_DEFINED_ST_VALUES]] set to 3. This is notionally placed in
|
|
|
|
the code at the last line on which an [[*_ST]] value was defined.
|
2019-02-04 22:26:45 +00:00
|
|
|
|
2024-03-09 05:41:29 +00:00
|
|
|
<<*>>=
|
2019-02-04 22:26:45 +00:00
|
|
|
void Enumerations::define_extents(OUTPUT_STREAM, tangle_target *target, programming_language *lang) {
|
2020-04-05 17:37:43 +00:00
|
|
|
enumeration_set *es;
|
|
|
|
LOOP_OVER(es, enumeration_set) {
|
2020-06-27 22:03:14 +00:00
|
|
|
TEMPORARY_TEXT(symbol)
|
|
|
|
TEMPORARY_TEXT(value)
|
2020-04-05 17:37:43 +00:00
|
|
|
WRITE_TO(symbol, "NO_DEFINED_%S_VALUES", es->postfix);
|
|
|
|
WRITE_TO(value, "%d", es->next_free_value - es->first_value);
|
|
|
|
LanguageMethods::start_definition(OUT, lang, symbol, value,
|
|
|
|
es->last_observed_at->owning_section, es->last_observed_at);
|
|
|
|
LanguageMethods::end_definition(OUT, lang,
|
|
|
|
es->last_observed_at->owning_section, es->last_observed_at);
|
2020-06-27 22:03:14 +00:00
|
|
|
DISCARD_TEXT(symbol)
|
|
|
|
DISCARD_TEXT(value)
|
2019-02-04 22:26:45 +00:00
|
|
|
}
|
|
|
|
}
|