Add support for named arguments in GIB functions and methods, fix a few

bugs, allow subclasses of classes written in GIB to access the same set
of instance variables.
This commit is contained in:
Brian Koropoff 2003-10-19 00:51:47 +00:00
parent 389ead6f01
commit f4c174184d
9 changed files with 180 additions and 74 deletions

View file

@ -60,7 +60,7 @@ typedef struct gib_object_s {
hashtab_t *methods; hashtab_t *methods;
void **data; void **data;
unsigned long int handle, refs; unsigned long int handle, refs;
hashtab_t *signals; hashtab_t *signals, *vars;
llist_t *slots; llist_t *slots;
const char *handstr; const char *handstr;
} gib_object_t; } gib_object_t;

View file

@ -43,14 +43,14 @@ typedef struct gib_function_s {
struct dstring_s *text; struct dstring_s *text;
struct gib_tree_s *program; struct gib_tree_s *program;
struct hashtab_s *globals; struct hashtab_s *globals;
struct llist_s *arglist;
unsigned int minargs;
qboolean exported; qboolean exported;
} gib_function_t; } gib_function_t;
gib_function_t *GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals); gib_function_t *GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals);
gib_function_t *GIB_Function_Find (const char *name); gib_function_t *GIB_Function_Find (const char *name);
void GIB_Function_Prepare_Args (cbuf_t *cbuf, const char **args, unsigned int argc); int GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, const char **args, unsigned int argc);
void GIB_Function_Prepare_Args_D (cbuf_t *cbuf, dstring_t **args, unsigned int argc); int GIB_Function_Execute_D (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, const char **args, unsigned int argc);
void GIB_Function_Execute_D (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
#endif #endif

View file

@ -52,6 +52,7 @@ const char rcsid[] =
#include "QF/cmd.h" #include "QF/cmd.h"
#include "QF/cbuf.h" #include "QF/cbuf.h"
#include "QF/hash.h" #include "QF/hash.h"
#include "QF/llist.h"
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/gib.h" #include "QF/gib.h"
@ -174,24 +175,31 @@ static void
GIB_Function_f (void) GIB_Function_f (void)
{ {
gib_tree_t *program; gib_tree_t *program;
gib_function_t *func;
if (GIB_Argc () != 3) int i;
GIB_USAGE ("name program");
if (GIB_Argc () < 3)
GIB_USAGE ("name [arg1 arg2 ...] program");
else { else {
// Is the function program already tokenized? // Is the function program already tokenized?
if (GIB_Argm (2)->delim != '{') { if (GIB_Argm (GIB_Argc()-1)->delim != '{') {
// Parse on the fly // Parse on the fly
if (!(program = GIB_Parse_Lines (GIB_Argv (2), 0))) { if (!(program = GIB_Parse_Lines (GIB_Argv
(GIB_Argc()-1), 0))) {
// Error! // Error!
GIB_Error ("parse", "Parse error while defining function '%s'.", GIB_Error ("parse", "Parse error while defining function '%s'.",
GIB_Argv (1)); GIB_Argv (1));
return; return;
} }
} else } else
program = GIB_Argm (2)->children; program = GIB_Argm (GIB_Argc()-1)->children;
GIB_Function_Define (GIB_Argv (1), GIB_Argv (2), program, func = GIB_Function_Define (GIB_Argv (1), GIB_Argv (GIB_Argc()-1), program,
GIB_DATA (cbuf_active)->script, GIB_DATA (cbuf_active)->script,
GIB_DATA (cbuf_active)->globals); GIB_DATA (cbuf_active)->globals);
llist_flush (func->arglist);
for (i = 2; i < GIB_Argc()-1; i++)
llist_append (func->arglist, strdup (GIB_Argv(i)));
func->minargs = GIB_Argc()-2;
} }
} }
@ -855,12 +863,8 @@ GIB_File_Find_f (void)
glob = s + 1; glob = s + 1;
} }
directory = opendir (path); directory = opendir (path);
if (!directory) { if (!directory)
GIB_Error ("file",
"%s: could not open directory %s: %s", GIB_Argv (0), path,
strerror (errno));
return; return;
}
while ((entry = readdir (directory))) while ((entry = readdir (directory)))
if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..") if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..")
&& !fnmatch (glob, entry->d_name, 0)) && !fnmatch (glob, entry->d_name, 0))
@ -984,6 +988,25 @@ GIB_Emit_f (void)
} }
} }
static void
GIB_Exists_f (void)
{
if (GIB_Object_Get (GIB_Argv (1)))
GIB_Return ("1");
else
GIB_Return ("0");
}
static void
GIB_Error_f (void)
{
if (GIB_Argc() < 3) {
GIB_USAGE ("error_type explanation");
return;
} else
GIB_Error (GIB_Argv(1), "%s", GIB_Argv(2));
}
static void static void
GIB_bp1_f (void) GIB_bp1_f (void)
{ {
@ -1049,6 +1072,8 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("print", GIB_Print_f); GIB_Builtin_Add ("print", GIB_Print_f);
GIB_Builtin_Add ("class", GIB_Class_f); GIB_Builtin_Add ("class", GIB_Class_f);
GIB_Builtin_Add ("emit", GIB_Emit_f); GIB_Builtin_Add ("emit", GIB_Emit_f);
GIB_Builtin_Add ("exists", GIB_Exists_f);
GIB_Builtin_Add ("error", GIB_Error_f);
GIB_Builtin_Add ("bp1", GIB_bp1_f); GIB_Builtin_Add ("bp1", GIB_bp1_f);
GIB_Builtin_Add ("bp2", GIB_bp2_f); GIB_Builtin_Add ("bp2", GIB_bp2_f);
GIB_Builtin_Add ("bp3", GIB_bp3_f); GIB_Builtin_Add ("bp3", GIB_bp3_f);

View file

@ -526,11 +526,16 @@ typedef struct Scrobj_method_s {
static void * static void *
Scrobj_Construct (gib_object_t *obj) Scrobj_Construct (gib_object_t *obj)
{ {
Scrobj_t *new = malloc (sizeof (Scrobj_t)); //Scrobj_t *new = malloc (sizeof (Scrobj_t));
//
new->shared = GIB_Var_Hash_New (); //new->shared = GIB_Var_Hash_New ();
return new; //return new;
if (!obj->vars)
obj->vars = GIB_Var_Hash_New ();
return NULL;
} }
static void * static void *
@ -546,10 +551,10 @@ Scrobj_Class_Construct (gib_object_t *obj)
static void static void
Scrobj_Destruct (void *data) Scrobj_Destruct (void *data)
{ {
Scrobj_t *s = (Scrobj_t *) data; //Scrobj_t *s = (Scrobj_t *) data;
Hash_DelTable (s->shared); //Hash_DelTable (s->shared);
free (s); //free (s);
} }
static void static void
@ -569,14 +574,15 @@ Scrobj_Method_f (gib_object_t *obj, gib_method_t *method, void *data,
static hashtab_t *nhash = NULL; static hashtab_t *nhash = NULL;
gib_var_t *var; gib_var_t *var;
if (GIB_Function_Execute (thread, ((Scrobj_method_t *)method->data)->func,
mesg.argv, mesg.argc))
return -1;
GIB_DATA(thread)->dnotify = Scrobj_Thread_Died; GIB_DATA(thread)->dnotify = Scrobj_Thread_Died;
GIB_DATA(thread)->reply.obj = obj; GIB_DATA(thread)->reply.obj = obj;
GIB_DATA(thread)->reply.method = method; GIB_DATA(thread)->reply.method = method;
GIB_DATA(thread)->reply.mesg = mesg; GIB_DATA(thread)->reply.mesg = mesg;
GIB_Function_Execute (thread, ((Scrobj_method_t *)method->data)->func, GIB_DATA(thread)->globals = obj->vars;
mesg.argv, mesg.argc);
GIB_DATA(thread)->globals = ((Scrobj_t *)data)->shared;
var = GIB_Var_Get_Complex (&GIB_DATA(thread)->locals, &nhash, this, var = GIB_Var_Get_Complex (&GIB_DATA(thread)->locals, &nhash, this,
&ind, true); &ind, true);
if (obj->handle) if (obj->handle)
@ -633,16 +639,31 @@ GIB_Classes_Build_Scripted (const char *name, const char *parentname,
case TREE_T_CMD: case TREE_T_CMD:
if (!strcmp (line->children->str, if (!strcmp (line->children->str,
"function")) { "function")) {
gib_tree_t *cur, *last;
gib_methodtab_t *new = malloc (sizeof gib_methodtab_t *new = malloc (sizeof
(gib_methodtab_t)); (gib_methodtab_t));
Scrobj_method_t *data = malloc (sizeof Scrobj_method_t *data = malloc (sizeof
(Scrobj_method_t)); (Scrobj_method_t));
for (last =
line->children->next->next;
last->next; last =
last->next);
data->func = GIB_Function_Define data->func = GIB_Function_Define
(fname (fname
(line->children->next->str), (line->children->next->str),
line->children->next->next->str, last->str,
line->children->next->next->children, last->children,
script, NULL); script, NULL);
llist_flush (data->func->arglist);
data->func->minargs = 1;
for (cur = line->children->next->next;
cur != last; cur =
cur->next) {
llist_append
(data->func->arglist,
strdup (cur->str));
data->func->minargs++;
}
new->data = data; new->data = data;
new->name = line->children->next->str; new->name = line->children->next->str;
new->func = Scrobj_Method_f; new->func = Scrobj_Method_f;

View file

@ -339,10 +339,15 @@ GIB_Execute (cbuf_t * cbuf)
b->func (); b->func ();
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) { else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
cbuf_t *new = Cbuf_PushStack (&gib_interp); cbuf_t *new = Cbuf_PushStack (&gib_interp);
GIB_Function_Execute_D ( if (GIB_Function_Execute_D
new, f, (new, f,
cbuf->args->argv, cbuf->args->argc cbuf->args->argv,
); cbuf->args->argc))
GIB_Error ("syntax", "not "
"enough "
"arguments to "
"function '%s'",
cbuf->args->argv[0]->str);
} else { } else {
GIB_Execute_Generate_Composite (cbuf); GIB_Execute_Generate_Composite (cbuf);
if (Cmd_Command (cbuf->args)) if (Cmd_Command (cbuf->args))

View file

@ -53,22 +53,6 @@ const char rcsid[] =
hashtab_t *gib_functions = 0; hashtab_t *gib_functions = 0;
/*
GIB_Function_New
Builds a new function struct and returns
a pointer to it.
*/
static gib_function_t *
GIB_Function_New (const char *name)
{
gib_function_t *new = calloc (1, sizeof (gib_function_t));
new->text = dstring_newstr ();
new->name = strdup (name);
return new;
}
/* /*
Hashtable callbacks Hashtable callbacks
*/ */
@ -95,6 +79,29 @@ GIB_Function_Free (void *ele, void *ptr)
free (func); free (func);
} }
/*
GIB_Function_New
Builds a new function struct and returns
a pointer to it.
*/
static gib_function_t *
GIB_Function_New (const char *name)
{
gib_function_t *new = calloc (1, sizeof (gib_function_t));
static void
afree (void *data, void *unused)
{
free (data);
};
new->text = dstring_newstr ();
new->name = strdup (name);
new->arglist = llist_new (afree, NULL, NULL);
return new;
}
/* /*
GIB_Function_Define GIB_Function_Define
@ -151,16 +158,32 @@ GIB_Function_Find (const char *name)
return (gib_function_t *) Hash_Find (gib_functions, name); return (gib_function_t *) Hash_Find (gib_functions, name);
} }
void static void
GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc) GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int
argc, llist_t *arglist)
{ {
static hashtab_t *zero = 0; static hashtab_t *zero = 0;
unsigned int i; unsigned int i, ind;
gib_var_t *var; gib_var_t *var;
static char argss[] = "args"; static char argss[] = "args";
static qboolean
iterate (char *arg, llist_node_t *node)
{
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero,
arg, &ind, true);
if (!var->array[0].value)
var->array[0].value = dstring_newstr ();
dstring_copystr (var->array[0].value, args[i]);
i++;
return i < argc;
}
i = 1; llist_iterate (arglist, LLIST_ICAST (iterate));
var = var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true); GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss,
&ind, true);
var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc); var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc);
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s)); memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
var->size = argc; var->size = argc;
@ -173,16 +196,32 @@ GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc)
} }
} }
void static void
GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int argc) GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int
argc, llist_t *arglist)
{ {
static hashtab_t *zero = 0; static hashtab_t *zero = 0;
unsigned int i; unsigned int i, ind;
gib_var_t *var; gib_var_t *var;
static char argss[] = "args"; static char argss[] = "args";
static qboolean
iterate (char *arg, llist_node_t *node)
{
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero,
arg, &ind, true);
if (!var->array[0].value)
var->array[0].value = dstring_newstr ();
dstring_copystr (var->array[0].value, args[i]->str);
i++;
return i < argc;
}
i = 1; llist_iterate (arglist, LLIST_ICAST (iterate));
var = var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true); GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss,
&ind, true);
var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc); var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc);
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s)); memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
var->size = argc; var->size = argc;
@ -202,28 +241,34 @@ GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int argc)
a GIB function with certain arguments a GIB function with certain arguments
*/ */
void int
GIB_Function_Execute (cbuf_t * cbuf, gib_function_t * func, const char ** args, GIB_Function_Execute (cbuf_t * cbuf, gib_function_t * func, const char ** args,
unsigned int argc) unsigned int argc)
{ {
if (argc < func->minargs)
return -1;
GIB_Tree_Ref (&func->program); GIB_Tree_Ref (&func->program);
if (func->script) if (func->script)
func->script->refs++; func->script->refs++;
GIB_Buffer_Set_Program (cbuf, func->program); GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA (cbuf)->script = func->script; GIB_DATA (cbuf)->script = func->script;
GIB_DATA (cbuf)->globals = func->globals; GIB_DATA (cbuf)->globals = func->globals;
GIB_Function_Prepare_Args (cbuf, args, argc); GIB_Function_Prepare_Args (cbuf, args, argc, func->arglist);
return 0;
} }
void int
GIB_Function_Execute_D (cbuf_t * cbuf, gib_function_t * func, dstring_t ** args, GIB_Function_Execute_D (cbuf_t * cbuf, gib_function_t * func, dstring_t ** args,
unsigned int argc) unsigned int argc)
{ {
if (argc < func->minargs)
return -1;
GIB_Tree_Ref (&func->program); GIB_Tree_Ref (&func->program);
if (func->script) if (func->script)
func->script->refs++; func->script->refs++;
GIB_Buffer_Set_Program (cbuf, func->program); GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA (cbuf)->script = func->script; GIB_DATA (cbuf)->script = func->script;
GIB_DATA (cbuf)->globals = func->globals; GIB_DATA (cbuf)->globals = func->globals;
GIB_Function_Prepare_Args_D (cbuf, args, argc); GIB_Function_Prepare_Args_D (cbuf, args, argc, func->arglist);
return 0;
} }

View file

@ -240,6 +240,8 @@ GIB_Object_Finish_Destroy (int argc, const char **argv, void *data)
GIB_Handle_Free (obj->handle); GIB_Handle_Free (obj->handle);
free ((void *) obj->handstr); free ((void *) obj->handstr);
Hash_DelTable (obj->signals); Hash_DelTable (obj->signals);
if (obj->vars)
Hash_DelTable (obj->vars);
llist_delete (obj->slots); llist_delete (obj->slots);
free (obj); free (obj);
} }
@ -316,8 +318,10 @@ void
GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char
**argv) **argv)
{ {
mesg.reply (argc, argv, mesg.replydata); if (mesg.reply) {
GIB_Object_Decref (obj); mesg.reply (argc, argv, mesg.replydata);
GIB_Object_Decref (obj);
}
} }
gib_object_t * gib_object_t *

View file

@ -87,15 +87,21 @@ GIB_Semantic_Validate_Class (gib_tree_t * tokens)
"function.", "function.",
cmd->start); cmd->start);
return -1; return -1;
} else if (!cmd->next || !cmd->next->next || } else {
cmd->next->next->delim != '{' gib_tree_t *last;
|| !cmd->next->next->children) {
GIB_Parse_Error ("Malformed function " for (last = cmd; last->next; last = last->next);
"definition; name, "
"program block " if (!cmd->next || !last || last->delim != '{' ||
"expected.", !last->children) {
cmd->start); GIB_Parse_Error ("Malformed function "
return -1; "definition; name, "
"optional arg list, "
"program block "
"expected.",
cmd->start);
return -1;
}
} }
break; break;
default: default:

View file

@ -69,7 +69,7 @@ Carne_Execute_Script (const char *path, cbuf_args_t *args)
goto ERROR; goto ERROR;
} }
GIB_Function_Prepare_Args_D (mbuf, args->argv, args->argc); //GIB_Function_Prepare_Args_D (mbuf, args->argv, args->argc);
// Main loop // Main loop
while (1) { while (1) {