From 4ef9d7848f126f1c982a5aae7cb27e18ab2b8aa3 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sat, 21 Jan 2012 18:50:51 +1000 Subject: More function call, and first part of dealing with using functions before declaring them. --- LuaSL/src/LuaSL_LSL_tree.h | 75 +++++++++++++++++++++++++------------------- 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 @@ // http://w-hat.com/stackdepth is a useful discussion about some aspects of the LL parser. -typedef struct _allowedTypes allowedTypes; -typedef struct _LSL_Token LSL_Token; -typedef struct _LSL_Leaf LSL_Leaf; -typedef struct _LSL_Parenthesis LSL_Parenthesis; -typedef struct _LSL_Identifier LSL_Identifier; -typedef struct _LSL_Statement LSL_Statement; -typedef struct _LSL_Block LSL_Block; -typedef struct _LSL_Function LSL_Function; -typedef struct _LSL_State LSL_State; -typedef struct _LSL_Script LSL_Script; +typedef struct _allowedTypes allowedTypes; +typedef struct _LSL_Token LSL_Token; +typedef struct _LSL_Leaf LSL_Leaf; +typedef struct _LSL_Parenthesis LSL_Parenthesis; +typedef struct _LSL_Identifier LSL_Identifier; +typedef struct _LSL_Statement LSL_Statement; +typedef struct _LSL_Block LSL_Block; +typedef struct _LSL_Function LSL_Function; +typedef struct _LSL_FunctionCall LSL_FunctionCall; +typedef struct _LSL_State LSL_State; +typedef struct _LSL_Script LSL_Script; extern LSL_Token **tokens; extern int lowestToken; @@ -108,6 +109,7 @@ typedef enum OT_vectorRotation, OT_rotationRotation, OT_otherOther, + OT_undeclared, OT_invalid } opType; @@ -148,30 +150,31 @@ struct _LSL_Token struct _LSL_Leaf { - LSL_Leaf *left; - LSL_Leaf *right; - LSL_Token *token; + LSL_Leaf *left; + LSL_Leaf *right; + LSL_Token *token; #ifdef LUASL_DIFF_CHECK - Eina_Strbuf *ignorableText; + Eina_Strbuf *ignorableText; #endif - int line, column, len; - opType basicType; + int line, column, len; + opType basicType; union { - float floatValue; - float vectorValue[3]; - float rotationValue[4]; - int integerValue; - LSL_Leaf *listValue; - const char *stringValue; - opType operationValue; - LSL_Parenthesis *parenthesis; - LSL_Identifier *identifierValue; - LSL_Statement *statementValue; - LSL_Block *blockValue; - LSL_Function *functionValue; - LSL_State *stateValue; - LSL_Script *scriptValue; + float floatValue; + float vectorValue[3]; + float rotationValue[4]; + int integerValue; + LSL_Leaf *listValue; + const char *stringValue; + opType operationValue; + LSL_Parenthesis *parenthesis; + LSL_Identifier *identifierValue; + LSL_Statement *statementValue; + LSL_Block *blockValue; + LSL_Function *functionValue; + LSL_FunctionCall *functionCallValue; + LSL_State *stateValue; + LSL_Script *scriptValue; } value; }; @@ -216,6 +219,14 @@ struct _LSL_Function LSL_Leaf *block; }; +struct _LSL_FunctionCall +{ + LSL_Function *function; + Eina_Inarray params; // Eina Inarray has not been released yet (Eina 1.2). + Eina_Clist functionCall; + LSL_Leaf *call; +}; + struct _LSL_State { const char *name; @@ -312,8 +323,10 @@ typedef struct Eina_Strbuf *ignorableText; #endif LSL_Leaf *lval; - int column, line; LSL_Block *currentBlock; + Eina_Clist danglingCalls; + int column, line; + int undeclared; } LuaSL_compiler; 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[] = {OT_rotation, "rotation", (ST_MULTIPLY | ST_ADD | ST_SUBTRACT | ST_EQUALITY | ST_CONCATENATION | ST_ASSIGNMENT)}, // rotation rotation * / + - == != = += -= *= /= {OT_other, "other", (ST_NONE)}, // + {OT_undeclared, "undeclared", (ST_NONE)}, // {OT_invalid, "invalid", (ST_NONE)} // }; @@ -291,22 +292,6 @@ static LSL_Leaf *findVariable(LuaSL_compiler *compiler, const char *name) return var; } -// TODO - Damn, you can reference functions declared later. -LSL_Leaf *checkFunction(LuaSL_compiler *compiler, LSL_Leaf *identifier) -{ - gameGlobals *game = compiler->game; - LSL_Leaf *func = findFunction(compiler, identifier->value.stringValue); - - if (NULL == func) - PE("NOT found %s @ line %d column %d!", identifier->value.stringValue, identifier->line, identifier->column); -#ifdef LUASL_DEBUG - else - PI("Found %s!", identifier->value.stringValue); -#endif - - return func; -} - LSL_Leaf *checkVariable(LuaSL_compiler *compiler, LSL_Leaf *identifier) { gameGlobals *game = compiler->game; @@ -351,6 +336,11 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, } else lType = left->basicType; + if (OT_undeclared == lType) + { + lval->basicType = OT_undeclared; + return lval; + } if (OT_vector < lType) lType = allowed[lType].result; } @@ -367,6 +357,11 @@ LSL_Leaf *addOperation(LuaSL_compiler *compiler, LSL_Leaf *left, LSL_Leaf *lval, } else rType = right->basicType; + if (OT_undeclared == rType) + { + lval->basicType = OT_undeclared; + return lval; + } if (OT_vector < rType) rType = allowed[rType].result; } @@ -537,16 +532,35 @@ LSL_Leaf *addFunctionBody(LuaSL_compiler *compiler, LSL_Leaf *function, LSL_Leaf LSL_Leaf *addFunctionCall(LuaSL_compiler *compiler, LSL_Leaf *identifier, LSL_Leaf *open, LSL_Leaf *params, LSL_Leaf *close) { - LSL_Leaf *func = checkFunction(compiler, identifier); + LSL_Leaf *func = findFunction(compiler, identifier->value.stringValue); + LSL_FunctionCall *call = calloc(1, sizeof(LSL_FunctionCall)); identifier->token = tokens[LSL_UNKNOWN - lowestToken]; if (func) { - // TODO - Add some structure here to hold the params. + if (call) + { + call->function = func->value.functionValue; + eina_clist_element_init(&(call->functionCall)); + call->call = identifier; + } + identifier->value.functionCallValue = call; + // TODO - Put the params in call. identifier->token = tokens[LSL_FUNCTION_CALL - lowestToken]; identifier->basicType = func->basicType; } + else + { + // It may be declared later, so store it and check later. + if (call) + { + eina_clist_add_tail(&(compiler->danglingCalls), &(call->functionCall)); + call->call = identifier; + } + identifier->basicType = OT_undeclared; + compiler->undeclared = TRUE; + } return identifier; } @@ -1235,6 +1249,7 @@ Eina_Bool compileLSL(gameGlobals *game, char *script, boolean doConstants) compiler.script.functions = eina_hash_stringshared_new(burnLeaf); compiler.script.states = eina_hash_stringshared_new(burnLeaf); compiler.script.variables = eina_hash_stringshared_new(burnLeaf); + eina_clist_init(&(compiler.danglingCalls)); #ifdef LUASL_DIFF_CHECK compiler.ignorableText = eina_strbuf_new(); #endif @@ -1274,6 +1289,32 @@ Eina_Bool compileLSL(gameGlobals *game, char *script, boolean doConstants) Parse (pParser, 0, compiler.lval, &compiler); ParseFree(pParser, free); + if (compiler.undeclared) + { + 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."); + if (eina_clist_count(&(compiler.danglingCalls))) + { + LSL_FunctionCall *call = NULL; + + EINA_CLIST_FOR_EACH_ENTRY(call, &(compiler.danglingCalls), LSL_FunctionCall, functionCall) + { + LSL_Leaf *func = findFunction(&(compiler), call->call->value.stringValue); + + if (func) + { + call->function = func->value.functionValue; + call->call->value.functionCallValue = call; + call->call->token = tokens[LSL_FUNCTION_CALL - lowestToken]; + call->call->basicType = func->basicType; + } + else + PE("Undeclared function %s called @ line %d, column %d!", call->call->value.stringValue, call->call->line, call->call->column); + } + } +// TODO - Run through the expressions, cleaning up the function calls. + PI("Second pass completed."); + } + if (doConstants) { memcpy(&constants, &(compiler.script), sizeof(LSL_Script)); -- cgit v1.1