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(-)

(limited to 'LuaSL')

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