Changeset: d97f81eb4ddc for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d97f81eb4ddc Modified Files: monetdb5/extras/jaql/jaql.c monetdb5/extras/jaql/jaql.h monetdb5/extras/jaql/jaql.mal monetdb5/extras/jaql/jaql.y monetdb5/extras/jaql/jaqlgencode.c Branch: jacqueline Log Message:
variables: implemented assigning and referencing variables Variables (JSON snippets) are kept in the jc struct now, which is now hooked into the Client struct. Until we implement proper scenarios, we leak the variable stack upon client exit. diffs (truncated from 373 to 300 lines): diff --git a/monetdb5/extras/jaql/jaql.c b/monetdb5/extras/jaql/jaql.c --- a/monetdb5/extras/jaql/jaql.c +++ b/monetdb5/extras/jaql/jaql.c @@ -36,6 +36,7 @@ extern int yyparse(jc *j); void freetree(tree *j); +str getContext(Client c, jc **j); /* assign the output of action (a 1 or more stage pipe) to ident, if * ident is NULL, the result should be outputted to the screen, if @@ -525,26 +526,53 @@ freetree(tree *j) } } +void +freevars(jvar *v) { + jvar *n; + while (v != NULL) { + GDKfree(v->vname); + BBPdecref(v->kind, TRUE); + BBPdecref(v->string, TRUE); + BBPdecref(v->integer, TRUE); + BBPdecref(v->doble, TRUE); + BBPdecref(v->array, TRUE); + BBPdecref(v->object, TRUE); + BBPdecref(v->name, TRUE); + + n = v->next; + GDKfree(v); + v = n; + } +} + str JAQLexecute(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { - jc j; + jc *j = NULL; int *ret = (int *)getArgReference(stk, pci, 0); str jaql = *(str *)getArgReference(stk, pci, 1); + str err; (void)mb; + + if ((err = getContext(cntxt, &j)) != MAL_SUCCEED) + GDKfree(err); - memset(&j, '\0', sizeof(jc)); - j.buf = jaql; + if (j == NULL) { + j = GDKzalloc(sizeof(jc)); + cntxt->state[MAL_SCENARIO_OPTIMIZE] = j; + } - yylex_init_extra(&j, &j.scanner); - yyparse(&j); - yylex_destroy(j.scanner); - if (j.err[0] != '\0') - throw(MAL, "jaql.execute", "%s", j.err); + j->buf = jaql; + yylex_init_extra(j, &j->scanner); + yyparse(j); + yylex_destroy(j->scanner); - switch (j.explain) { + if (j->err[0] != '\0') + throw(MAL, "jaql.execute", "%s", j->err); + + switch (j->explain) { case 0: { str err; /* normal (execution) mode */ @@ -553,30 +581,156 @@ JAQLexecute(Client cntxt, MalBlkPtr mb, /* we do not return anything */ setVarType(prg->def, 0, TYPE_void); setVarUDFtype(prg->def, 0); - (void)dumptree(&j, prg->def, j.p); + (void)dumptree(j, prg->def, j->p); pushEndInstruction(prg->def); - if (j.err[0] != '\0') { - freetree(j.p); - throw(MAL, "jaql.execute", "%s", j.err); + if (j->err[0] != '\0') { + freetree(j->p); + throw(MAL, "jaql.execute", "%s", j->err); } chkProgram(cntxt->nspace, prg->def); printFunction(cntxt->fdout, prg->def, 0, LIST_MAL_STMT); err = (str)runMAL(cntxt, prg->def, 1, 0, 0, 0); - resetMalBlk(prg->def, prg->def->stop); + freeMalBlk(prg->def); if (err != MAL_SUCCEED) { - freetree(j.p); + freetree(j->p); return err; } } break; case 1: /* explain */ case 2: /* plan */ - printtree(j.p, 0, j.explain == 1); + printtree(j->p, 0, j->explain == 1); break; /* case 3: trace? */ } - freetree(j.p); + freetree(j->p); + /* reset all but vars */ + j->p = NULL; + j->esc_depth = 0; + j->buf = NULL; + j->err[0] = '\0'; + j->scanner = NULL; + j->explain = 0; + /* freevars(j->vars); should do only on client destroy */ *ret = 0; return MAL_SUCCEED; } + +str +getContext(Client cntxt, jc **c) +{ + *c = ((jc *) cntxt->state[MAL_SCENARIO_OPTIMIZE]); + if (*c == NULL) + throw(MAL, "jaql.context", "JAQL environment not found"); + return MAL_SUCCEED; +} + +str +JAQLgetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + jc *j; + str msg = getContext(cntxt, &j); + int *j1 = (int *)getArgReference(stk, pci, 0); + int *j2 = (int *)getArgReference(stk, pci, 1); + int *j3 = (int *)getArgReference(stk, pci, 2); + int *j4 = (int *)getArgReference(stk, pci, 3); + int *j5 = (int *)getArgReference(stk, pci, 4); + int *j6 = (int *)getArgReference(stk, pci, 5); + int *j7 = (int *)getArgReference(stk, pci, 6); + str var = *(str *)getArgReference(stk, pci, 7); + jvar *t; + + (void)mb; + + if (msg != MAL_SUCCEED) + return msg; + + for (t = j->vars; t != NULL; t = t->next) { + if (strcmp(t->vname, var) == 0) { + *j1 = t->kind; + *j2 = t->string; + *j3 = t->integer; + *j4 = t->doble; + *j5 = t->array; + *j6 = t->object; + *j7 = t->name; + break; + } + } + if (t == NULL) + throw(MAL, "jaql.getVar", "no such variable: %s", var); + + /* incref for MAL interpreter ref */ + BBPincref(t->kind, TRUE); + BBPincref(t->string, TRUE); + BBPincref(t->integer, TRUE); + BBPincref(t->doble, TRUE); + BBPincref(t->array, TRUE); + BBPincref(t->object, TRUE); + BBPincref(t->name, TRUE); + return MAL_SUCCEED; +} + +str +JAQLsetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + jc *j; + str msg = getContext(cntxt, &j); + int *ret = (int *)getArgReference(stk, pci, 0); + str var = *(str *)getArgReference(stk, pci, 1); + int *j1 = (int *)getArgReference(stk, pci, 2); + int *j2 = (int *)getArgReference(stk, pci, 3); + int *j3 = (int *)getArgReference(stk, pci, 4); + int *j4 = (int *)getArgReference(stk, pci, 5); + int *j5 = (int *)getArgReference(stk, pci, 6); + int *j6 = (int *)getArgReference(stk, pci, 7); + int *j7 = (int *)getArgReference(stk, pci, 8); + jvar *t; + + (void)mb; + + if (msg != MAL_SUCCEED) + return msg; + + t = j->vars; + if (t == NULL) { + t = j->vars = GDKzalloc(sizeof(jvar)); + } else { + while (t->next != NULL) { + if (strcmp(t->vname, var) == 0) + break; + t = t->next; + } + if (t->next != NULL || strcmp(t->vname, var) == 0) { + GDKfree(t->vname); + BBPdecref(t->kind, TRUE); + BBPdecref(t->string, TRUE); + BBPdecref(t->integer, TRUE); + BBPdecref(t->doble, TRUE); + BBPdecref(t->array, TRUE); + BBPdecref(t->object, TRUE); + BBPdecref(t->name, TRUE); + } else { + t = t->next = GDKzalloc(sizeof(jvar)); + } + } + t->vname = GDKstrdup(var); + t->kind = *j1; + t->string = *j2; + t->integer = *j3; + t->doble = *j4; + t->array = *j5; + t->object = *j6; + t->name = *j7; + BBPincref(t->kind, TRUE); + BBPincref(t->string, TRUE); + BBPincref(t->integer, TRUE); + BBPincref(t->doble, TRUE); + BBPincref(t->array, TRUE); + BBPincref(t->object, TRUE); + BBPincref(t->name, TRUE); + + *ret = 0; + return MAL_SUCCEED; +} diff --git a/monetdb5/extras/jaql/jaql.h b/monetdb5/extras/jaql/jaql.h --- a/monetdb5/extras/jaql/jaql.h +++ b/monetdb5/extras/jaql/jaql.h @@ -32,6 +32,18 @@ #define jaql_export extern #endif +typedef struct _jvar { + char *vname; + int kind; + int string; + int integer; + int doble; + int array; + int object; + int name; + struct _jvar *next; +} jvar; + typedef struct _jc { struct _tree *p; int esc_depth; @@ -39,6 +51,7 @@ typedef struct _jc { char err[1024]; void *scanner; char explain; + jvar *vars; } jc; enum treetype { @@ -103,6 +116,8 @@ void printtree (tree *t, int level, char jaql_export str JAQLexecute(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +jaql_export str JAQLgetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); +jaql_export str JAQLsetVar(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci); #endif diff --git a/monetdb5/extras/jaql/jaql.mal b/monetdb5/extras/jaql/jaql.mal --- a/monetdb5/extras/jaql/jaql.mal +++ b/monetdb5/extras/jaql/jaql.mal @@ -25,3 +25,10 @@ pattern x(jaql:str):void address JAQLexecute comment "execute() alias for the lazy"; +pattern getVar(nme:str)(kind:bat[:oid,:chr],string:bat[:oid,:str],integer:bat[:oid,:lng],double:bat[:oid,:dbl],array:bat[:oid,:oid],object:bat[:oid,:oid],name:bat[:oid,:str]) +address JAQLgetVar +comment "Retrieve value of JSON variable"; + +pattern setVar(nme:str, kind:bat[:oid,:chr],string:bat[:oid,:str],integer:bat[:oid,:lng],double:bat[:oid,:dbl],array:bat[:oid,:oid],object:bat[:oid,:oid],name:bat[:oid,:str]):void +address JAQLsetVar +comment "Set or overwrite value of JSON variable"; diff --git a/monetdb5/extras/jaql/jaql.y b/monetdb5/extras/jaql/jaql.y --- a/monetdb5/extras/jaql/jaql.y +++ b/monetdb5/extras/jaql/jaql.y @@ -93,7 +93,7 @@ jaql: jaqlpipe {$$ = ap ; jaqlpipe: _IDENT opt_actions {$$ = append_jaql_pipe(make_varname($1), $2);} - | _ARRAY actions {$$ = append_jaql_pipe(make_json($1), $2);} _______________________________________________ Checkin-list mailing list Checkin-list@monetdb.org http://mail.monetdb.org/mailman/listinfo/checkin-list