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;
void **data;
unsigned long int handle, refs;
hashtab_t *signals;
hashtab_t *signals, *vars;
llist_t *slots;
const char *handstr;
} gib_object_t;

View file

@ -43,14 +43,14 @@ typedef struct gib_function_s {
struct dstring_s *text;
struct gib_tree_s *program;
struct hashtab_s *globals;
struct llist_s *arglist;
unsigned int minargs;
qboolean exported;
} 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_Find (const char *name);
void GIB_Function_Prepare_Args (cbuf_t *cbuf, const char **args, unsigned int argc);
void GIB_Function_Prepare_Args_D (cbuf_t *cbuf, 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);
int GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, const char **args, unsigned int argc);
int GIB_Function_Execute_D (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
#endif

View file

@ -52,6 +52,7 @@ const char rcsid[] =
#include "QF/cmd.h"
#include "QF/cbuf.h"
#include "QF/hash.h"
#include "QF/llist.h"
#include "QF/dstring.h"
#include "QF/gib.h"
@ -174,24 +175,31 @@ static void
GIB_Function_f (void)
{
gib_tree_t *program;
gib_function_t *func;
int i;
if (GIB_Argc () != 3)
GIB_USAGE ("name program");
if (GIB_Argc () < 3)
GIB_USAGE ("name [arg1 arg2 ...] program");
else {
// Is the function program already tokenized?
if (GIB_Argm (2)->delim != '{') {
if (GIB_Argm (GIB_Argc()-1)->delim != '{') {
// 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!
GIB_Error ("parse", "Parse error while defining function '%s'.",
GIB_Argv (1));
return;
}
} else
program = GIB_Argm (2)->children;
GIB_Function_Define (GIB_Argv (1), GIB_Argv (2), program,
program = GIB_Argm (GIB_Argc()-1)->children;
func = GIB_Function_Define (GIB_Argv (1), GIB_Argv (GIB_Argc()-1), program,
GIB_DATA (cbuf_active)->script,
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;
}
directory = opendir (path);
if (!directory) {
GIB_Error ("file",
"%s: could not open directory %s: %s", GIB_Argv (0), path,
strerror (errno));
if (!directory)
return;
}
while ((entry = readdir (directory)))
if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..")
&& !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
GIB_bp1_f (void)
{
@ -1049,6 +1072,8 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("print", GIB_Print_f);
GIB_Builtin_Add ("class", GIB_Class_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 ("bp2", GIB_bp2_f);
GIB_Builtin_Add ("bp3", GIB_bp3_f);

View file

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

View file

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

View file

@ -53,22 +53,6 @@ const char rcsid[] =
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
*/
@ -95,6 +79,29 @@ GIB_Function_Free (void *ele, void *ptr)
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
@ -151,16 +158,32 @@ GIB_Function_Find (const char *name)
return (gib_function_t *) Hash_Find (gib_functions, name);
}
void
GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc)
static void
GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int
argc, llist_t *arglist)
{
static hashtab_t *zero = 0;
unsigned int i;
unsigned int i, ind;
gib_var_t *var;
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 =
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);
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
var->size = argc;
@ -173,16 +196,32 @@ GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc)
}
}
void
GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int argc)
static void
GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int
argc, llist_t *arglist)
{
static hashtab_t *zero = 0;
unsigned int i;
unsigned int i, ind;
gib_var_t *var;
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 =
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);
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
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
*/
void
int
GIB_Function_Execute (cbuf_t * cbuf, gib_function_t * func, const char ** args,
unsigned int argc)
{
if (argc < func->minargs)
return -1;
GIB_Tree_Ref (&func->program);
if (func->script)
func->script->refs++;
GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA (cbuf)->script = func->script;
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,
unsigned int argc)
{
if (argc < func->minargs)
return -1;
GIB_Tree_Ref (&func->program);
if (func->script)
func->script->refs++;
GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA (cbuf)->script = func->script;
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);
free ((void *) obj->handstr);
Hash_DelTable (obj->signals);
if (obj->vars)
Hash_DelTable (obj->vars);
llist_delete (obj->slots);
free (obj);
}
@ -316,9 +318,11 @@ void
GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char
**argv)
{
if (mesg.reply) {
mesg.reply (argc, argv, mesg.replydata);
GIB_Object_Decref (obj);
}
}
gib_object_t *
GIB_Object_Get (const char *id)

View file

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

View file

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