You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: documentation/design-document.md
+59-1Lines changed: 59 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -119,5 +119,63 @@ This just declares a variable as being changable by the server, but not by users
119
119
120
120
This weird declaration is again related to documentation comments. The documentation for an `enum` is always generated, but if the `enum` is never used anywhere in code the comments become unattached and form part of the global documentation, instead of a symbol's documentation. This line just uses the enum in such as way to correctly attach the documentation to the correct symbol in the `.xml`, but not generate any additional output in the AMX.
121
121
122
-
It does however transpire that `enum`s have some minor issues when used for array indexes. While not all of the enums declared make sense for array indexes (think `KEY`, which is a bit-map), they have all none-the-less been converted to simple `const`s instead (at great cost in documentation complexity).
122
+
## Double declarations.
123
+
124
+
So most symbols are defined in `enum` for several reasons - to keep them grouped together, to collate things in the generated documentation, and for ease of declaration. So why are all the values re-declared a second time using `#define`? This is because different ways of declaring symbols work in different ways. Using `enum` for a set of related values puts them together in the documentation and allows for very efficient declarations - tags can be ommitted and values inferred, leading to much terser and clearer code. The downside to using `enum` is that it messes with arrays, since the slots will inherit the declared tags of each element, so this:
125
+
126
+
```pawn
127
+
new WEAPON:gWeapons[MAX_WEAPON_SLOTS];
128
+
```
129
+
130
+
Will produce unexpected results - the entries have the tag of `_:` not the tag of `WEAPON:`, because that's how the values inside the `WEAPON_SLOT` enum were declared.
131
+
132
+
Using `const` instead of `enum` solves this problem - there's no weird mixing of index tags and value tags, but the code is way more verbose, and the generated documentation is much more spread out; with unused values not even mentioned.
133
+
134
+
`#define` is slightly shorter than `const` in declaration length, since you only need tags once instead of twice, but they are not inserted in to the generated documentation at all. There's also one other weird quirk - `#define` is completely ignored by `#emit`, this:
135
+
136
+
```pawn
137
+
#define NUMBER 2
138
+
#emit CONST.pri NUMBER
139
+
```
140
+
141
+
Will give an undefined symbol error. But they're not only ignored by `#emit`, but completely invisible to it. Meanwhile, `const` and `enum` can be used by `#emit`, even if a `#define` with the same name would normally overwrite them:
142
+
143
+
```pawn
144
+
const NUMBER = 2;
145
+
#define NUMBER 2
146
+
#emit CONST.pri NUMBER
147
+
```
148
+
149
+
That code works, and uses the `const` in `#emit`, despite the fact that it should have been hidden by the `#define`. So we have the final solution, covering all use-cases. It is quite verbose, but you can just use the `enum`s to more easily read the code. This will generate compact and complete documentation, it makes reading the code easy if you only use the `enum` part, it works for `#emit` as well as normal code, and it doesn't produce weird side-effects in array declarations:
150
+
151
+
```pawn
152
+
enum WEAPON:MAX_WEAPONS
153
+
{
154
+
WEAPON_FIST = 0,
155
+
WEAPON_BRASSKNUCKLE,
156
+
WEAPON_GOLFCLUB,
157
+
WEAPON_NITESTICK,
158
+
WEAPON_NIGHTSTICK = WEAPON_NITESTICK,
159
+
WEAPON_KNIFE,
160
+
WEAPON_BAT,
161
+
WEAPON_SHOVEL,
162
+
WEAPON_POOLSTICK,
163
+
WEAPON_KATANA,
164
+
// ...
165
+
}
166
+
167
+
#define WEAPON_FIST (WEAPON:0)
168
+
#define WEAPON_BRASSKNUCKLE (WEAPON:1)
169
+
#define WEAPON_GOLFCLUB (WEAPON:2)
170
+
#define WEAPON_NITESTICK (WEAPON:3)
171
+
#define WEAPON_NIGHTSTICK (WEAPON:3)
172
+
#define WEAPON_KNIFE (WEAPON:4)
173
+
#define WEAPON_BAT (WEAPON:5)
174
+
#define WEAPON_SHOVEL (WEAPON:6)
175
+
#define WEAPON_POOLSTICK (WEAPON:7)
176
+
#define WEAPON_KATANA (WEAPON:8)
177
+
// ...
178
+
```
179
+
180
+
The enum names can't be used in the `#define`s as that would create an infinite loop in the compiler.
0 commit comments