blob: 217b0a6c8b1b4615d2c27f310c0c2434a756261f [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001CONCEPT
2 structs
3
4INTRODUCTION
5 structs are, next to arrays and mappings, a way to group a
6 collection of value together.
7
8 A struct holds a fixed number of values, called 'members', and
9 allows to access them by their given name. The name is resolved
10 when the LPC code is compiled, making struct member access as fast
11 as array member access.
12
13 structs are passed by reference.
14
15
16DEFINITION
17 A new struct type has to be defined at the top level of an
18 object. For example
19
20 struct Foo {
21 int one, *two;
22 struct Bar three;
23 };
24
25 defines the new struct 'Foo' with three members: integer 'one',
26 integer array 'two', and struct Bar 'three'
27
28 It is possible to 'inherit' structs from each other. Given above
29 definition of struct Foo, the following definition
30
31 struct Quux (Foo) {
32 int four;
33 };
34
35 is equivalent to the definition
36
37 struct Quux {
38 int one, *two;
39 struct Bar three;
40 int four;
41 };
42
43
44 The usual visibility modifiers apply, e.g.
45
46 protected struct Bang {...};
47
48
49 struct definitions are promoted through inheritance like functions,
50 with the difference that all structs live in the same flat namespace.
51 This means: a struct defined in a program is visible in _all_
52 inherited programs, regardless of how deep the inheritance is
53 nested. This also means that in one program there must not be
54 two structs, inherited or not, with the same name.
55
56
57 To declare a struct without defining it, write:
58
59 struct Quux;
60
61 This notation is useful if you have two structs referencing
62 each other:
63
64 struct Quux;
65
66 struct Bar {
67 struct Quux quux;
68 };
69 struct Quux {
70 struct Bar bar;
71 };
72
73
74USAGE
75 To use a struct, its definition must be visible - either because it
76 is defined in the object compiled, or it has been inherited.
77 (Note: #include'ing structs does not what you think it does: in
78 LPC it constructs a new struct type whereever it is included).
79
80
81 A variable to hold a struct is defined like this:
82
83 struct Foo var;
84
85 and similar for function arguments:
86
87 void fun (struct Foo arg)
88
89
90 Just writing 'struct Foo var' however does not _create_ a struct,
91 it just creates a variable capable of holding one. To assign a value
92 to the variable upon creation, assign it with a struct value, either
93 from another variable or from a literal struct:
94
95 struct Foo var = (<Foo>);
96
97
98 Literal structs are written using (<>) as delimiters:
99
100 (<Foo>)
101 creates an empty instance of struct Foo
102
103 (<Foo> 1, ({ 2 }), bar)
104 creates an instance of struct Foo, and assigns 1 to member
105 'one', ({ 2 }) to member 'two', and the content of variable
106 bar to member 'three'.
107
108 (<Foo> two: ({ 2 }) )
109 creates an instance of struct Foo which is all empty except
110 for member 'two' which is assigned the value ({ 2 }).
111
112 It is not possible to use both named and unnamed initializers
113 in the same literal.
114
115
116 A struct member is accessed using the -> operator:
117
118 struct Foo var = ...;
119
120 var->one = 1;
121
122
123 It is possible to compute struct lookups at runtime:
124
125 struct Foo bar = ...;
126 string member = "one";
127
128 bar->(member) = 1; // sets bar->one to 1
129 bar->(0) = 1; // sets bar->one to 1
130
131
132 When using struct values held in variables/expressions of type
133 'mixed', the 'mixed' value should to be casted to the struct
134 value. The cast can be omitted if the looked-up member exists
135 in only one struct (and its children) known to the compiler:
136
137 struct Foo { int one; };
138 struct Bar { int two; };
139 struct Baz { int two; };
140 mixed var;
141
142 var->one // looks up Foo->one
143 (struct Foo)var->one // looks up Foo->one
144 var->two // ERROR: ambiguous lookup
145 (struct Bar)var->one // looks up Bar->one
146
147
148USAGE IN CLOSURES
149 The #'(< operator can be used in lambda closures to create a
150 struct; the type of the struct is given by the 'template'
151 struct passed as first argument. The content of the template
152 struct is irrelevant, so an empty struct suffices. For
153 example, to create an instance of struct Foo:
154
155 ({ #'(<, (<Foo>), 1, ({ 2 }), (<Bar>) })
156
157 The order of the member values is the order in which they
158 appear in the struct definition.
159
160 To access a struct member in a lambda closure, use the #'->
161 operator with the name of the member as double-quoted symbol
162 or literal string:
163
164 ({ #'->, struct-expression, ''one })
165 ({ #'->, struct-expression, "one" })
166
167
168MISCELLANEOUS
169 Internally structs can be identified by the ID string
170 returned from get_type_info(). This string contains the name
171 of the struct, the name of the program its type was defined in,
172 and the ID number of the program. However, do not rely on
173 a particular format of this string!
174
175 Support for structs is signaled by the macro __LPC_STRUCTS__.
176
177 Since structs are tied to the program they are defined in,
178 re-compiling a program creates new struct types which are
179 in principle incompatible to the old ones. However, the LPC
180 compiler checks if the newly compiled structs have the same
181 structure as their older counterparts of the same name
182 (and defining program). If the structures conform, the existing
183 older struct types are used instead of the new ones. This way
184 an accidental of for example /std/types.c doesn't break
185 the whole mud.
186
187
188EXAMPLES
189 Suppose we have two objects: a monster, and a monster
190 coordinate tracker, and we want to use a struct to store the
191 coordinate:
192
193 -- monster_coordinate.c --
194 struct Coordinate { int x; int y; };
195
196 -- monster_tracker.c --
197 inherit "monster_coordinate";
198
199 void track (struct Coordinate coord) { ... }
200
201 -- monster.c --
202 inherit "monster_coordinate";
203
204 int move (..) {
205 ...
206 "monster_tracker"->track( (<Coordinate> my_x, my_y) );
207 }
208
209 Note that using '#include "monster_coordinate.c"' instead of inherit
210 won't work. While the objects would compile, the first call to
211 track() would cause a runtime error of the type
212
213 Illegal type to struct->(): struct Coordinate (/monster.c #234),
214 expected struct Coordinate
215 (/monster_tracker.c #552)
216
217
218HISTORY
219 structs were fully implemented first in LDMud 3.3.246.
220 The implementation was revised in LDMud 3.3.344.
221 The reactivation of unchanged structs in object updates was
222 implemented in LDMud 3.3.417.
223
224
225SEE ALSO
226 mappings(LPC), get_type_info(E), structp(E), to_mapping(E),
227 to_struct(E), struct_info(E), baseof(E)