prototype IR and parser
[henge/webcc.git] / src / apc / ir.h
1 /*!@file
2 \brief Intermediate Representation (IR) between Directory Structure and Engine Grammar
3 \details The IR serves as a storage structure that is populated during the
4 parsing of the input directory structure. After parsing is complete,
5 the IR will be condensed (removed of excess allocated space) and then
6 output as the Engine Grammar. In this file we describe the semantic actions
7 that are called at each step, and the memory buffers that they populate.
8 See parser.y for the description on how the input grammar is constructed,
9 and where/when semantic actions are called.
10 TODO: or just write it here.
11 \author Jordan Lavatai
12 \date Aug 2016
13 ----------------------------------------------------------------------------*/
14
15
16 #include <stdint.h>
17 //#include <apc/mem.h>TODO:
18
19 #define BUF_SIZE 256
20 #define MAX_SETS 256
21 #define MAX_ELES 256
22 #define MAX_QUADS 256
23 #define MAX_MODELS 256
24 #define MAX_POSTS 256
25 #define MAX_CLASS_DEPTH 256
26 #define MAX_CLASSES 256
27 #define MAX_FRAMES 256
28 /* All bufs are of pointers to their respective structs. When a buf is full */
29 /* (number of data structs pointers >= max number of data struct pointers), */
30 /* we need to allocate a more pointers for that buf. Allocate these */
31 /* pointers a page at a time (1024 = Page bytes (4096)/bytes per pointer(4)) */
32 /* TODO: Account for different page sizes in different system */
33 #define PTRS_IN_PAGE 1024
34
35 /* General: All information from the directory structure is stored in */
36 /* five buffers that comprise the IR: cdat_buf, odat_buf, vdat_buf, ref_buf */
37 /* and link_buf. Each buf corresponds to the data structure that it stores. */
38 /* The storage techique for all bufs (except cdat) is the same. Each bufs member first */
39 /* populates its struct and then allocates the space for the next member */
40 /* and increments the buf index. This means that we have to allocate the */
41 /* very first member of each buf at ir_init(), so that we don't segfault */
42 /* as the first member attempts to access memory that its previous member */
43 /* didn't allocate (because it doesnt exist). We access the buf members */
44 /* through standard array indexing but conceal the tediousness of array */
45 /* indexing with macros. E.g. without macros, acessing an elements name */
46 /* member would look like (split up to not go over line char limit): */
47 /* (*cdat_stackp)->set_list[(*cdat_stackp)->num_sets] */
48 /* .ele_list[(*cdat_stackp)->set_list[(*cdat_stackp->num_sets)].num_ele].name */
49
50 /* For cdats in cdat_buf, we allocate the memory for a cdat once a cdat
51 is recognized in the grammar. Cdat_buf is different from the other bufs
52 because cdats have a root cdat that all cdats are a subclass of. This root
53 cdat can have a set_list like other cdats. */
54
55
56
57
58 /* Elements: Ele stands for element and has two representations in the IR. */
59 /* In the cdat_buf eles store their name, cdat_idx (their classes index in */
60 /* the cdat_buf) and the ref_id (refer to ref ). In the odat_buf, eles store */
61 /* their object data (odat). At output time, the ref_id is dereferenced to */
62 /* determine the elements odat which is the data that the engine expects */
63 /* from an element. */
64
65 struct ele {
66 char name[32];
67 uint64_t ref_id;
68 int cdat_idx;
69 };
70
71 /* Sets: The set is similar to the ele, but it contains a list of its */
72 /* elements. The set is populated at parse time AFTER the elements are */
73 /* populated, due to the nature of bottom up parsing. */
74
75 struct set {
76 char name[32];
77 uint64_t ref_id;
78 int cdat_idx;
79 int num_ele;
80 struct ele ele_list[MAX_ELES];
81 };
82
83 /* Cdats: A cdat is a class data structure. Cdats serve as the central */
84 /* data types of the IR. At output, the cdat_buf is iterated through and */
85 /* each is written to the output file. For each cdat, sets and element */
86 /* ref_ids must be dereferenced to determine the odat information. Cdats */
87 /* contain pointers to their subclasses so that the relationship between */
88 /* classes can be determined, but the subclasses are not represented inside */
89 /* of the cdat itself but rather in the subsequent cdats in cdat_buf. We */
90 /* can determine the number of subclasses (the last index into cdat_buf */
91 /* that represents a subclass of some arbitrary cdat) each cdat has by */
92 /* incrementing num_classes during parse time. */
93 /* TODO: Should classes point to their parent class? */
94
95 struct cdat {
96 char name[32];
97 int idx;
98 int num_classes;
99 int num_sets;
100 struct cdat* class_list[MAX_CLASSES];
101 struct set set_list[MAX_SETS];
102 };
103
104 /* There are an unknown amount of cdats at compile time, so we maintain */
105 /* a cdat_buf of cdat pointers that can be expanded as needed. */
106 struct cdat* cdat_buf[PTRS_IN_PAGE];
107 int num_cdats = 0;
108 int curr_max_cdats = PTRS_IN_PAGE;
109
110 /* The cdat_stack is a stack pointers to cdat pointers, the top of which is
111 the cdat that is currently being parsed. Whenever a new cdat is recognized
112 by the grammar (CLOPEN), a cdat is pushed onto the cdat_stack, and we refer
113 to this cdat through the macro CURR_CDAT. By keeping a cdat_stack, we have
114 access to the current cdat so that the elements and sets can populate themselves
115 in the cdat accordingly. */
116
117 struct cdat* cdat_stack[PTRS_IN_PAGE];
118 struct cdat** cdat_stackp;
119
120 /* Refs: Each set/ele has a reference to its object data (odat) through a ref_id.
121 Ref_ids are unsigned 64 byte integers that map to the hex values RGBA. During
122 the construction of the directory structure, users can choose a RGBA value for
123 each object that any other object can refer to via links (see link). If a user
124 does not choose an RGBA value, then the object is given one from the system space.
125 We maintain a doubly linked list of refs in the ref_buf at parse time so that
126 links can be resolved after the parsing of the directory structure is complete.
127 For every 16th ref, we create a post so that we can reduce on the search time for
128 a random access. */
129
130 struct ref {
131 int type;
132 struct ref* nextref;
133 struct ref* lastref;
134 struct odat* odatp;
135 uint64_t ref_id; //0xFFFFFF->digit
136 };
137
138 /* Like the cdat_buf, ref_buf stores pointers to refs and can
139 increase in size */
140 struct ref* ref_buf[PTRS_IN_PAGE];
141 int num_refs = 0;
142 int curr_max_refs = PTRS_IN_PAGE;
143 uint64_t ss_ref_id = 0x00FFFFFF; /* system space for ref_ids */
144
145
146 /* posts for ref_buf */
147 struct ref posts[MAX_POSTS];
148 int num_posts;
149
150 /* Links: At parse time, a set/ele can include a link in their
151 grammar representation instead of the actual data and this signifies
152 to the APC that that set/ele wishes to use the data of another
153 set/ele, either its video data (vdat) or object data (odat). The link
154 itself contains the type of link it is, the ref_id OR name, and
155 which set/ele created the link. During parse time, links can be made
156 to o/vdats that have yet to be parsed. In order to accomodate for this,
157 we resolve all links AFTER parse time by iterating through the link_buf,
158 finding the ref_id that was stored for some object (if the ref_id exists),
159 and creating a relative pointer from the original object to the data that
160 was linked */
161
162 /* Svlinks stand for short vlink, which is a link to a vdat
163 TODO: diff btwn vlink*/
164
165 struct svlink {
166 uint64_t ref_id;
167 };
168
169 /* A vlink is what it sounds like, a link to a vdat
170 TODO: model link? */
171 struct vlink {
172 uint64_t ref_id;
173 char anim_name[32];
174 };
175
176 /* Olinks are links to odats */
177 struct olink {
178 uint64_t ref_id;
179 };
180
181 union link_t {
182 struct olink olink;
183 struct vlink vlink;
184 struct svlink svlink;
185 };
186
187 struct link {
188 int type; //1 = olink, 2 = vlink, 3 = svlink
189 union link_t link_t;
190 int cdat_idx;
191 int set_idx;
192 int ele_idx;
193 };
194 /* link_buf contains all the links that
195 we encountered during parse time that need
196 to be resolved to an offset at output time.
197 This does not include quad refs, because
198 those are already known to need to be resolved */
199 struct link* link_buf[PTRS_IN_PAGE];
200 int num_links = 0;
201 int curr_max_links = PTRS_IN_PAGE;
202
203
204 /* Odats: Odats consist of the object data necessary for
205 each object. Odats are sometimes referred to as archetypes
206 at compile-time, in order to distinguish the difference from
207 a runtime object and a compile-time object.
208 TODO: Need more info about objects at runtime, to described
209 the reasoning behind odat structure at compile-time*/
210
211 /* Each set has a quad_list or a list of quads. The quad_list
212 is the ? */
213 struct quad {
214 int x, y, z;
215 uint64_t ref_id; //rgba
216 };
217
218 struct root {
219 int x, y, z;
220 };
221
222 struct odat {
223 char name[32];
224 int vdat_id;
225 int cdat_idx;
226 int hitbox;
227 struct root root;
228 struct ref* refp; /* pointer to it's ref on ref_list */
229 int num_quads;
230 struct quad quad_list[MAX_QUADS];
231 };
232
233 /* Populated and allocated same way as other bufs */
234 struct odat* odat_buf[PTRS_IN_PAGE];
235 int curr_max_odats = PTRS_IN_PAGE;
236 int num_odats = 0;
237
238 /* A framesheet is a grouping of animation frames in
239 a single direction (N,W,S,E) */
240 struct framesheet {
241 int width;
242 int height;
243 int num_frames;
244 void* frames[MAX_FRAMES];
245 };
246
247 /* A model is a collection of framesheets for every
248 direction (N,W,S,E,NW,NE,SW,SE)*/
249 /* NAMED spritesheet */
250 struct model {
251 char name[32];
252 struct framesheet spritesheet[8]; //one for each
253 };
254
255 /* Vdat: Vdats are the video data of each object. They can not be
256 created as a stand alone object (because they consist solely
257 of animation information and not the skeleton on which the
258 animation manipulates). Vdats have a list of models for every
259 animation that the vdats odat can do for that vdat*/
260 struct vdat {
261 struct odat* creator; //pointer to odat that made this vdat
262 int num_models;
263 struct model model_list[MAX_MODELS];
264 };
265
266
267 struct vdat* vdat_buf[PTRS_IN_PAGE];
268 int curr_max_vdats = PTRS_IN_PAGE;
269 int num_vdats = 0;
270
271 /* The initalization function of the IR. Mallocs the
272 first c/v/odat and the first links and refs and
273 inits the cdat_stack */
274 void
275 ir_init(void);
276
277 /* mallocs memory for a new cdat. If the cdat_buf
278 is full, mallocs another 1024 cdat pointers. */
279 void
280 malloc_cdat(void);
281
282 /* Called after the cdat open operator has been recognized in grammar. Allocates
283 the space for a cdat on the cdat_buf, pushes that pointer onto
284 the cdat_stack */
285 void
286 push_cdat(char*);
287
288 /* Called after a cdat end operator has been recognized in grammar. Sets
289 top stack cdat ** to null and decrements stack pointer */
290 void
291 pop_cdat(void);
292
293 /* Called after an odat has been populated. Allocates memory for
294 the next odat. */
295 void
296 inc_odat(void);
297
298 /* Called after an vdat has been populated. Allocates memory for
299 the next vdat. */
300 void
301 inc_vdat(void);
302
303 void
304 inc_link(void);
305
306 void
307 inc_ref(void);
308
309 /* Called in the reduction of a set. While both odats (eles and sets)
310 have identical label terminals, we are unable to give a single grammatical rule
311 for both due to how we allocate odats in the odat buf. Due to the
312 nature of bottom up parsing, all the elements will be inserted into the
313 odat_buf first, and then the set that contains these element is inserted. Since
314 the sets label comes before the element list in the grammar, we would be giving an element
315 a set label in its respective odat, which would then be replaced by the
316 elements label. Instead, we store the label in the sets representation inside
317 CURR_CDAT and after we are done parsing the element_list and know that the CURR_ODAT
318 is the set, we populate the sets label members in CURR_ODAT with the values we stored
319 previously in CURR_CDAT. */
320 void
321 insert_set_label(char*, uint64_t);
322
323 /* Populate the sets representation in CURR_CDAT with a ref_id and insert a link
324 into the link_buf that will resolve the ref_id to an actual odat after parse time. */
325 void
326 insert_set_olink(uint64_t);
327
328 /* Put the vlink in the link_buf to be processed after parsetime */
329 void
330 insert_set_vlink(uint64_t, char*);
331
332 /* Put svlink in the link_buf to be processed after parsetime */
333 void
334 insert_set_svlink(uint64_t);
335
336 /* Called for every set reduction except for sets with olinks. Populates the
337 set data structures in the CDAT and in the ODAT. Uses the name and ref_id
338 from insert_set_label. Also inserts a ref into the ref_buf with the CURR_ODAT
339 pointer so that we can also resolve the odat from its ref_id. */
340 void
341 insert_set(void);
342
343 /* Insertion of eles is practically equivalent to how sets are inserted because both
344 share the same data type (ODAT). Like sets, eles have links, labels
345 and odats. Eles have the added notion of a parent set, and so must be inserted
346 into said parent set, but this is the only place they truly differ from sets. */
347
348 void
349 insert_ele_label(char*, uint64_t);
350
351 void
352 insert_ele_olink(uint64_t);
353
354 void
355 insert_ele_vlink(uint64_t, char*);
356
357 void
358 insert_ele_svlink(uint64_t);
359
360 void
361 insert_ele(void);
362
363 /* Created as a seperate function, instead of setting the ODATS vdat_id and
364 calling inc_vdat() inside of insert_set(), to account for the set reduction
365 where a vdat is not created (o/v/svlinks). Because insert_set/ele is always
366 called before insert_vdat, and thus increments the CURR_ODAT to be the next
367 ODAT to be populated, insert_vdat() targets the last ODAT that was populated,
368 via PREV_ODAT. */
369 void
370 insert_vdat(void);
371
372 /* Inserts the hitbox into the CURR_ODAT */
373 void
374 insert_hitbox(int);
375
376 /* Inserts the root into the CURR_ODAT */
377 void
378 insert_root(int, int, int);
379
380 /* Inserts a quad into the CURR_ODAT */
381 void
382 insert_quad(int, int, int, uint64_t);
383
384 void
385 insert_model(void);
386
387 void
388 insert_framesheet(char, char*, uint64_t, int, int, int);
389
390 void
391 insert_frame_pointer(char, void*);
392