diff options
Diffstat (limited to '')
-rw-r--r-- | LuaSL/src/LuaSL_LSL_tree.h | 75 | ||||
-rw-r--r-- | LuaSL/src/LuaSL_compile.c | 77 |
2 files changed, 103 insertions, 49 deletions
diff --git a/LuaSL/src/LuaSL_LSL_tree.h b/LuaSL/src/LuaSL_LSL_tree.h index 21fc696..d537948 100644 --- a/LuaSL/src/LuaSL_LSL_tree.h +++ b/LuaSL/src/LuaSL_LSL_tree.h | |||
@@ -29,16 +29,17 @@ | |||
29 | // http://w-hat.com/stackdepth is a useful discussion about some aspects of the LL parser. | 29 | // http://w-hat.com/stackdepth is a useful discussion about some aspects of the LL parser. |
30 | 30 | ||
31 | 31 | ||
32 | typedef struct _allowedTypes allowedTypes; | 32 | typedef struct _allowedTypes allowedTypes; |
33 | typedef struct _LSL_Token LSL_Token; | 33 | typedef struct _LSL_Token LSL_Token; |
34 | typedef struct _LSL_Leaf LSL_Leaf; | 34 | typedef struct _LSL_Leaf LSL_Leaf; |
35 | typedef struct _LSL_Parenthesis LSL_Parenthesis; | 35 | typedef struct _LSL_Parenthesis LSL_Parenthesis; |
36 | typedef struct _LSL_Identifier LSL_Identifier; | 36 | typedef struct _LSL_Identifier LSL_Identifier; |
37 | typedef struct _LSL_Statement LSL_Statement; | 37 | typedef struct _LSL_Statement LSL_Statement; |
38 | typedef struct _LSL_Block LSL_Block; | 38 | typedef struct _LSL_Block LSL_Block; |
39 | typedef struct _LSL_Function LSL_Function; | 39 | typedef struct _LSL_Function LSL_Function; |
40 | typedef struct _LSL_State LSL_State; | 40 | typedef struct _LSL_FunctionCall LSL_FunctionCall; |
41 | typedef struct _LSL_Script LSL_Script; | 41 | typedef struct _LSL_State LSL_State; |
42 | typedef struct _LSL_Script LSL_Script; | ||
42 | 43 | ||
43 | extern LSL_Token **tokens; | 44 | extern LSL_Token **tokens; |
44 | extern int lowestToken; | 45 | extern int lowestToken; |
@@ -108,6 +109,7 @@ typedef enum | |||
108 | OT_vectorRotation, | 109 | OT_vectorRotation, |
109 | OT_rotationRotation, | 110 | OT_rotationRotation, |
110 | OT_otherOther, | 111 | OT_otherOther, |
112 | OT_undeclared, | ||
111 | OT_invalid | 113 | OT_invalid |
112 | } opType; | 114 | } opType; |
113 | 115 | ||
@@ -148,30 +150,31 @@ struct _LSL_Token | |||
148 | 150 | ||
149 | struct _LSL_Leaf | 151 | struct _LSL_Leaf |
150 | { | 152 | { |
151 | LSL_Leaf *left; | 153 | LSL_Leaf *left; |
152 | LSL_Leaf *right; | 154 | LSL_Leaf *right; |
153 | LSL_Token *token; | 155 | LSL_Token *token; |
154 | #ifdef LUASL_DIFF_CHECK | 156 | #ifdef LUASL_DIFF_CHECK |
155 | Eina_Strbuf *ignorableText; | 157 | Eina_Strbuf *ignorableText; |
156 | #endif | 158 | #endif |
157 | int line, column, len; | 159 | int line, column, len; |
158 | opType basicType; | 160 | opType basicType; |
159 | union | 161 | union |
160 | { | 162 | { |
161 | float floatValue; | 163 | float floatValue; |
162 | float vectorValue[3]; | 164 | float vectorValue[3]; |
163 | float rotationValue[4]; | 165 | float rotationValue[4]; |
164 | int integerValue; | 166 | int integerValue; |
165 | LSL_Leaf *listValue; | 167 | LSL_Leaf *listValue; |
166 | const char *stringValue; | 168 | const char *stringValue; |
167 | opType operationValue; | 169 | opType operationValue; |
168 | LSL_Parenthesis *parenthesis; | 170 | LSL_Parenthesis *parenthesis; |
169 | LSL_Identifier *identifierValue; | 171 | LSL_Identifier *identifierValue; |
170 | LSL_Statement *statementValue; | 172 | LSL_Statement *statementValue; |
171 | LSL_Block *blockValue; | 173 | LSL_Block *blockValue; |
172 | LSL_Function *functionValue; | 174 | LSL_Function *functionValue; |
173 | LSL_State *stateValue; | 175 | LSL_FunctionCall *functionCallValue; |
174 | LSL_Script *scriptValue; | 176 | LSL_State *stateValue; |
177 | LSL_Script *scriptValue; | ||
175 | } value; | 178 | } value; |
176 | }; | 179 | }; |
177 | 180 | ||
@@ -216,6 +219,14 @@ struct _LSL_Function | |||
216 | LSL_Leaf *block; | 219 | LSL_Leaf *block; |
217 | }; | 220 | }; |
218 | 221 | ||
222 | struct _LSL_FunctionCall | ||
223 | { | ||
224 | LSL_Function *function; | ||
225 | Eina_Inarray params; // Eina Inarray has not been released yet (Eina 1.2). | ||
226 | Eina_Clist functionCall; | ||
227 | LSL_Leaf *call; | ||
228 | }; | ||
229 | |||
219 | struct _LSL_State | 230 | struct _LSL_State |
220 | { | 231 | { |
221 | const char *name; | 232 | const char *name; |
@@ -312,8 +323,10 @@ typedef struct | |||
312 | Eina_Strbuf *ignorableText; | 323 | Eina_Strbuf *ignorableText; |
313 | #endif | 324 | #endif |
314 | LSL_Leaf *lval; | 325 | LSL_Leaf *lval; |
315 | int column, line; | ||
316 | LSL_Block *currentBlock; | 326 | LSL_Block *currentBlock; |
327 | Eina_Clist danglingCalls; | ||
328 | int column, line; | ||
329 | int undeclared; | ||
317 | } LuaSL_compiler; | 330 | } LuaSL_compiler; |
318 | 331 | ||
319 | 332 | ||
diff --git a/LuaSL/src/LuaSL_compile.c b/LuaSL/src/LuaSL_compile.c index 06c55ef..a410152 100644 --- a/LuaSL/src/LuaSL_compile.c +++ b/LuaSL/src/LuaSL_compile.c | |||
@@ -185,6 +185,7 @@ allowedTypes allowed[] = | |||
185 | {OT_rotation, "rotation", (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_CONCATENATION | ST_ASSIGNMENT)}, // rotation rotation * / + - == != = += -= *= /= | 185 | {OT_rotation, "rotation", (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_CONCATENATION | ST_ASSIGNMENT)}, // rotation rotation * / + - == != = += -= *= /= |
186 | 186 | ||
187 | {OT_other, "other", (ST_NONE)}, // | 187 | {OT_other, "other", (ST_NONE)}, // |
188 | {OT_undeclared, "undeclared", (ST_NONE)}, // | ||
188 | {OT_invalid, "invalid", (ST_NONE)} // | 189 | {OT_invalid, "invalid", (ST_NONE)} // |
189 | }; | 190 | }; |
190 | 191 | ||
@@ -291,22 +292,6 @@ static LSL_Leaf *findVariable(LuaSL_compiler *compiler, const char *name) | |||
291 | return var; | 292 | return var; |
292 | } | 293 | } |
293 | 294 | ||
294 | // TODO - Damn, you can reference functions declared later. | ||
295 | LSL_Leaf *checkFunction(LuaSL_compiler *compiler, LSL_Leaf *identifier) | ||
296 | { | ||
297 | gameGlobals *game = compiler->game; | ||
298 | LSL_Leaf *func = findFunction(compiler, identifier->value.stringValue); | ||
299 | |||
300 | if (NULL == func) | ||
301 | PE("NOT found %s @ line %d column %d!", identifier->value.stringValue, identifier->line, identifier->column); | ||
302 | #ifdef LUASL_DEBUG | ||
303 | else | ||
304 | PI("Found %s!", identifier->value.stringValue); | ||
305 | #endif | ||
306 | |||
307 | return func; | ||
308 | } | ||
309 | |||
310 | LSL_Leaf *checkVariable(LuaSL_compiler *compiler, LSL_Leaf *identifier) | 295 | LSL_Leaf *checkVariable(LuaSL_compiler *compiler, LSL_Leaf *identifier) |
311 | { | 296 | { |
312 | gameGlobals *game = compiler->game; | 297 | gameGlobals *game = compiler->game; |
@@ -351,6 +336,11 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, | |||
351 | } | 336 | } |
352 | else | 337 | else |
353 | lType = left->basicType; | 338 | lType = left->basicType; |
339 | if (OT_undeclared == lType) | ||
340 | { | ||
341 | lval->basicType = OT_undeclared; | ||
342 | return lval; | ||
343 | } | ||
354 | if (OT_vector < lType) | 344 | if (OT_vector < lType) |
355 | lType = allowed[lType].result; | 345 | lType = allowed[lType].result; |
356 | } | 346 | } |
@@ -367,6 +357,11 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, | |||
367 | } | 357 | } |
368 | else | 358 | else |
369 | rType = right->basicType; | 359 | rType = right->basicType; |
360 | if (OT_undeclared == rType) | ||
361 | { | ||
362 | lval->basicType = OT_undeclared; | ||
363 | return lval; | ||
364 | } | ||
370 | if (OT_vector < rType) | 365 | if (OT_vector < rType) |
371 | rType = allowed[rType].result; | 366 | rType = allowed[rType].result; |
372 | } | 367 | } |
@@ -537,16 +532,35 @@ LSL_Leaf *addFunctionBody(LuaSL_compiler *compiler, LSL_Leaf *function, LSL_Leaf | |||
537 | 532 | ||
538 | LSL_Leaf *addFunctionCall(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf *open, LSL_Leaf *params, LSL_Leaf *close) | 533 | LSL_Leaf *addFunctionCall(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf *open, LSL_Leaf *params, LSL_Leaf *close) |
539 | { | 534 | { |
540 | LSL_Leaf *func = checkFunction(compiler, identifier); | 535 | LSL_Leaf *func = findFunction(compiler, identifier->value.stringValue); |
536 | LSL_FunctionCall *call = calloc(1, sizeof(LSL_FunctionCall)); | ||
541 | 537 | ||
542 | identifier->token = tokens[LSL_UNKNOWN - lowestToken]; | 538 | identifier->token = tokens[LSL_UNKNOWN - lowestToken]; |
543 | 539 | ||
544 | if (func) | 540 | if (func) |
545 | { | 541 | { |
546 | // TODO - Add some structure here to hold the params. | 542 | if (call) |
543 | { | ||
544 | call->function = func->value.functionValue; | ||
545 | eina_clist_element_init(&(call->functionCall)); | ||
546 | call->call = identifier; | ||
547 | } | ||
548 | identifier->value.functionCallValue = call; | ||
549 | // TODO - Put the params in call. | ||
547 | identifier->token = tokens[LSL_FUNCTION_CALL - lowestToken]; | 550 | identifier->token = tokens[LSL_FUNCTION_CALL - lowestToken]; |
548 | identifier->basicType = func->basicType; | 551 | identifier->basicType = func->basicType; |
549 | } | 552 | } |
553 | else | ||
554 | { | ||
555 | // It may be declared later, so store it and check later. | ||
556 | if (call) | ||
557 | { | ||
558 | eina_clist_add_tail(&(compiler->danglingCalls), &(call->functionCall)); | ||
559 | call->call = identifier; | ||
560 | } | ||
561 | identifier->basicType = OT_undeclared; | ||
562 | compiler->undeclared = TRUE; | ||
563 | } | ||
550 | 564 | ||
551 | return identifier; | 565 | return identifier; |
552 | } | 566 | } |
@@ -1235,6 +1249,7 @@ Eina_Bool compileLSL(gameGlobals *game, char *script, boolean doConstants) | |||
1235 | compiler.script.functions = eina_hash_stringshared_new(burnLeaf); | 1249 | compiler.script.functions = eina_hash_stringshared_new(burnLeaf); |
1236 | compiler.script.states = eina_hash_stringshared_new(burnLeaf); | 1250 | compiler.script.states = eina_hash_stringshared_new(burnLeaf); |
1237 | compiler.script.variables = eina_hash_stringshared_new(burnLeaf); | 1251 | compiler.script.variables = eina_hash_stringshared_new(burnLeaf); |
1252 | eina_clist_init(&(compiler.danglingCalls)); | ||
1238 | #ifdef LUASL_DIFF_CHECK | 1253 | #ifdef LUASL_DIFF_CHECK |
1239 | compiler.ignorableText = eina_strbuf_new(); | 1254 | compiler.ignorableText = eina_strbuf_new(); |
1240 | #endif | 1255 | #endif |
@@ -1274,6 +1289,32 @@ Eina_Bool compileLSL(gameGlobals *game, char *script, boolean doConstants) | |||
1274 | Parse (pParser, 0, compiler.lval, &compiler); | 1289 | Parse (pParser, 0, compiler.lval, &compiler); |
1275 | ParseFree(pParser, free); | 1290 | ParseFree(pParser, free); |
1276 | 1291 | ||
1292 | if (compiler.undeclared) | ||
1293 | { | ||
1294 | PI("A second pass will be needed to check if functions where declared after they where used. To avoid this second pass, don't do that."); | ||
1295 | if (eina_clist_count(&(compiler.danglingCalls))) | ||
1296 | { | ||
1297 | LSL_FunctionCall *call = NULL; | ||
1298 | |||
1299 | EINA_CLIST_FOR_EACH_ENTRY(call, &(compiler.danglingCalls), LSL_FunctionCall, functionCall) | ||
1300 | { | ||
1301 | LSL_Leaf *func = findFunction(&(compiler), call->call->value.stringValue); | ||
1302 | |||
1303 | if (func) | ||
1304 | { | ||
1305 | call->function = func->value.functionValue; | ||
1306 | call->call->value.functionCallValue = call; | ||
1307 | call->call->token = tokens[LSL_FUNCTION_CALL - lowestToken]; | ||
1308 | call->call->basicType = func->basicType; | ||
1309 | } | ||
1310 | else | ||
1311 | PE("Undeclared function %s called @ line %d, column %d!", call->call->value.stringValue, call->call->line, call->call->column); | ||
1312 | } | ||
1313 | } | ||
1314 | // TODO - Run through the expressions, cleaning up the function calls. | ||
1315 | PI("Second pass completed."); | ||
1316 | } | ||
1317 | |||
1277 | if (doConstants) | 1318 | if (doConstants) |
1278 | { | 1319 | { |
1279 | memcpy(&constants, &(compiler.script), sizeof(LSL_Script)); | 1320 | memcpy(&constants, &(compiler.script), sizeof(LSL_Script)); |