-
Notifications
You must be signed in to change notification settings - Fork 65
/
New Use Option Requests.w
160 lines (138 loc) · 5.54 KB
/
New Use Option Requests.w
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
[NewUseOptions::] New Use Option Requests.
Special sentences for creating new use options.
@ Use options in Inform are akin to |#pragma| directives for the C family of
compilers: they are written in the source code of the program being compiled,
but they're not really part of that program, and are instead instructions to
the compiler to do something in a different way.[1]
Use options have natural-language names, and are created with sentences like:
>> Use American dialect translates as (- Constant DIALECT_US; -).
This syntax is now rather odd-looking, but most users never need it: it's used
mainly in the Basic Inform extension to create the standard set of use options.
Note the Inform 6 notation used for the Inter code between the |(-| and |-)|
brackets.
[1] The design of use options is arguably more muddled, because they do not all
correspond to compiler features: some affect the behaviour of Inter kits, and
some can be user-defined entirely.
@ A "... translates as ..." sentence has this special meaning if its SP and
OP match the following:
=
<use-translates-as-sentence-subject> ::=
use <np-unparsed> ==> { TRUE, RP[1] }
<use-translates-as-sentence-object> ::=
(- ### | ==> { -, - }
... ==> @<Issue PM_UseTranslatesNotI6 problem@>
@<Issue PM_UseTranslatesNotI6 problem@> =
StandardProblems::sentence_problem(Task::syntax_tree(),
_p_(PM_UseTranslatesNotI6),
"that translates into something which isn't a simple Inter inclusion",
"placed in '(-' and '-)' markers.");
==> { FALSE, - };
@ =
int NewUseOptions::use_translates_as_SMF(int task, parse_node *V, wording *NPs) {
wording SW = (NPs)?(NPs[0]):EMPTY_WORDING;
wording OW = (NPs)?(NPs[1]):EMPTY_WORDING;
switch (task) { /* "Use American dialect means ..." */
case ACCEPT_SMFT:
if ((<use-translates-as-sentence-object>(OW)) &&
(<use-translates-as-sentence-subject>(SW))) {
V->next = <<rp>>;
<np-unparsed>(OW);
V->next->next = <<rp>>;
return TRUE;
}
break;
case PASS_1_SMFT:
@<Create a new use option@>;
break;
}
return FALSE;
}
@ Use options correspond to instances of the following:
=
typedef struct use_option {
struct wording name; /* word range where name is stored */
struct wording expansion; /* definition as given in source */
struct parse_node *where_used; /* where the option is taken in the source */
struct parse_node *where_created;
int option_used; /* set if this option has been taken */
int source_file_scoped; /* scope is the current source file only? */
int minimum_setting_value; /* for those which are numeric */
int notable_option_code; /* or negative if not notable */
struct use_option_compilation_data compilation_data;
CLASS_DEFINITION
} use_option;
@<Create a new use option@> =
wording SP = Node::get_text(V->next);
wording OP = Node::get_text(V->next->next);
<use-setting>(SP); /* always passes */
int N = <<r>>;
use_option *uo = CREATE(use_option);
uo->name = GET_RW(<use-setting>, 1);
uo->expansion = OP;
uo->option_used = FALSE;
uo->minimum_setting_value = (N >= 0) ? N : -1;
uo->source_file_scoped = FALSE;
uo->notable_option_code = -1;
if (<notable-use-option-name>(uo->name)) uo->notable_option_code = <<r>>;
if (uo->notable_option_code == AUTHORIAL_MODESTY_UO) uo->source_file_scoped = TRUE;
uo->where_used = NULL;
uo->where_created = current_sentence;
uo->compilation_data = RTUseOptions::new_compilation_data(uo);
Nouns::new_proper_noun(uo->name, NEUTER_GENDER, ADD_TO_LEXICON_NTOPT,
MISCELLANEOUS_MC, Rvalues::from_use_option(uo), Task::language_of_syntax());
@ Having registered the use option names as miscellaneous, we need to parse
them back that way too:
=
use_option *NewUseOptions::parse_uo(wording OW) {
parse_node *p = Lexicon::retrieve(MISCELLANEOUS_MC, OW);
if (Rvalues::is_CONSTANT_of_kind(p, K_use_option)) return Rvalues::to_use_option(p);
return NULL;
}
@ The following sets an option.
=
void NewUseOptions::set(use_option *uo, int min_setting, source_file *from) {
if (uo->minimum_setting_value == -1) {
if (min_setting != -1)
StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UONotNumerical),
"that 'Use' option does not have a numerical setting",
"but is either used or not used.");
} else {
if (min_setting >= uo->minimum_setting_value)
uo->minimum_setting_value = min_setting;
}
if (uo->source_file_scoped) {
inform_extension *E = Extensions::corresponding_to(from);
if (E == NULL) { /* that is, if used in the main source text */
uo->option_used = TRUE;
uo->where_used = current_sentence;
}
} else {
uo->option_used = TRUE;
uo->where_used = current_sentence;
}
CompilationSettings::set(uo->notable_option_code,
uo->minimum_setting_value, from);
}
@ We can also meddle with the I6 memory settings which will be used to finish
compiling the story file. We need this because we have no practical way to
predict when our code will break I6's limits: the only reasonable way it can
work is for the user to hit the limit occasionally, and then raise that limit
by hand with a sentence in the source text.
=
typedef struct i6_memory_setting {
struct text_stream *ICL_identifier; /* see the DM4 for the I6 memory setting names */
int number; /* e.g., |50000| means "at least 50,000" */
CLASS_DEFINITION
} i6_memory_setting;
@ =
void NewUseOptions::memory_setting(text_stream *identifier, int n) {
i6_memory_setting *ms;
LOOP_OVER(ms, i6_memory_setting)
if (Str::eq(identifier, ms->ICL_identifier)) {
if (ms->number < n) ms->number = n;
return;
}
ms = CREATE(i6_memory_setting);
ms->ICL_identifier = Str::duplicate(identifier);
ms->number = n;
}