+ char *trueName = NULL;
+ int i;
+ int bFound = 0; // Used to keep nesting levels down
+ tSpiderObject *ret = ERRPTR;
+
+ // Handle namespaces
+ if( Function[0] == '.' ) {
+ trueName = (char*)&Function[1];
+ }
+ else if( !Script->CurNamespace ) {
+ trueName = (char*)Function;
+ }
+ else {
+ int len = strlen(Script->CurNamespace) + 1 + strlen(Function);
+ trueName = malloc( len + 1 );
+ strcpy(trueName, Script->CurNamespace);
+ strcat(trueName, ".");
+ strcat(trueName, Function);
+ }
+
+ // First: Find the function in the script
+ {
+ tAST_Function *fcn = Script->Script->Functions;
+ for( ; fcn; fcn = fcn->Next ) {
+ if( strcmp(fcn->Name, trueName) == 0 )
+ break;
+ }
+ // Execute!
+ if(fcn) {
+ tAST_BlockState bs;
+ bs.FirstVar = NULL; //< TODO: Parameters
+ bs.Parent = NULL;
+ bs.Script = Script;
+ {
+ tAST_Node *arg;
+ int i = 0;
+ for( arg = fcn->Arguments; arg; arg = arg->NextSibling, i++ )
+ {
+ // TODO: Type checks
+ Variable_Define(&bs, arg->DefVar.DataType, arg->DefVar.Name);
+ if( i >= NArguments ) break; // TODO: Return gracefully
+ Variable_SetValue(&bs, arg->DefVar.Name, Arguments[i]);
+ }
+ }
+ ret = AST_ExecuteNode(&bs, fcn->Code);
+ bFound = 1;
+ }
+ }
+
+ // Didn't find it in script?
+ if(!bFound)
+ {
+ // Second: Search the variant's exports
+ for( i = 0; i < Script->Variant->NFunctions; i ++ )
+ {
+ if( strcmp( Script->Variant->Functions[i].Name, trueName) == 0 )
+ break;
+ }
+ // Execute!
+ if(i < Script->Variant->NFunctions) {
+ ret = Script->Variant->Functions[i].Handler( Script, NArguments, Arguments );
+ bFound = 1;
+ }
+ }