Commit 462b6d18 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

raise version number


Thu Jun 16 17:40:29 2005  George Lebl <jirka@5z.com>

	* configure.in: raise version number

	* src/complil.c: compile symbolic_id and id for function nodes and
	  symbolic_id for global functions.

	* src/lexer.l, src/calc.c, src/eval.[ch], src/parse.y: SYNTAX CHANGE:
	  there is now an elt by elt addition and subtraction (.+ and .-)
	  which act like the old +,- when adding scalar to a matrix.  The +,-
	  now interpret A+x as A+x*I if A is a square matrix, and elt by elt
	  if A is a vector (row or column), else they error out.

	* src/funclib.c: the PolyToFunction now does 1 instead of x^0, since
	  this now works correctly for matrices.

	* src/lexer.l, src/calc.c, src/parse.y: make evalstack into
	  gel_parsestack since the naming was totally off

	* src/dict.h: on decompilation errors don't assert crash, just give
	  null as the function body.

	* src/geniustests.txt: add some tests and fix some old ones with
	  respect to the above syntax change.
parent c971dd1d
Thu Jun 16 17:40:29 2005 George Lebl <jirka@5z.com>
* configure.in: raise version number
* src/complil.c: compile symbolic_id and id for function nodes and
symbolic_id for global functions.
* src/lexer.l, src/calc.c, src/eval.[ch], src/parse.y: SYNTAX CHANGE:
there is now an elt by elt addition and subtraction (.+ and .-)
which act like the old +,- when adding scalar to a matrix. The +,-
now interpret A+x as A+x*I if A is a square matrix, and elt by elt
if A is a vector (row or column), else they error out.
* src/funclib.c: the PolyToFunction now does 1 instead of x^0, since
this now works correctly for matrices.
* src/lexer.l, src/calc.c, src/parse.y: make evalstack into
gel_parsestack since the naming was totally off
* src/dict.h: on decompilation errors don't assert crash, just give
null as the function body.
* src/geniustests.txt: add some tests and fix some old ones with
respect to the above syntax change.
Wed Jun 15 09:09:20 2005 George Lebl <jirka@5z.com>
* src/symbolic.c, src/calc.[ch], src/dict.c, src/eval.c,
......
AC_INIT(src/calc.c)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(genius,0.7.3)
AM_INIT_AUTOMAKE(genius,0.7.4)
dnl make sure we keep ACLOCAL_FLAGS around for maintainer builds to work
AC_SUBST(ACLOCAL_AMFLAGS, "$ACLOCAL_FLAGS")
......
......@@ -89,7 +89,7 @@ static gboolean got_end_too_soon = FALSE;
GHashTable *uncompiled = NULL;
/* stack ... has to be global:-( */
GSList *evalstack=NULL;
GSList *gel_parsestack=NULL;
/*error .. global as well*/
GeniusError error_num = NO_ERROR;
......@@ -602,8 +602,12 @@ appendoper(GelOutput *gelo, GelETree *n)
break;
case E_PLUS:
append_binaryoper(gelo,"+",n); break;
case E_ELTPLUS:
append_binaryoper(gelo,".+",n); break;
case E_MINUS:
append_binaryoper(gelo,"-",n); break;
case E_ELTMINUS:
append_binaryoper(gelo,".-",n); break;
case E_MUL:
append_binaryoper(gelo,"*",n); break;
case E_ELTMUL:
......@@ -1664,10 +1668,11 @@ compile_funcs_in_dict (FILE *outfile, GSList *dict, gboolean is_extra_dict)
}
if (func->type == GEL_USER_FUNC) {
fprintf (outfile,
"%c;%d;%s;%d;%d",
"%c;%d;%s;%s;%d;%d",
fs,
(int)strlen (body),
func->id->token,
func->symbolic_id ? func->symbolic_id->token : "*",
(int)func->nargs,
(int)func->vararg);
for (l = func->named_args; l != NULL; l = l->next) {
......@@ -1780,7 +1785,7 @@ load_compiled_fp (const char *file, FILE *fp)
while ( ! break_on_next && fgets (buf, buf_size, fp) != NULL) {
char *p;
char *b2;
GelToken *tok;
GelToken *tok, *symbolic_tok = NULL;
int size, nargs, vararg;
gboolean extra_dict = FALSE;
gboolean parameter = FALSE;
......@@ -1931,6 +1936,17 @@ load_compiled_fp (const char *file, FILE *fp)
tok = d_intern(p);
if (type == GEL_USER_FUNC) {
/*symbolic_id*/
p = strtok_r (NULL,";", &ptrptr);
if G_UNLIKELY (!p) {
gel_errorout (_("Badly formed record"));
continue;
}
if (strcmp (p, "*") == 0)
symbolic_tok = NULL;
else
symbolic_tok = d_intern (p);
/*nargs*/
p = strtok_r (NULL,";", &ptrptr);
if G_UNLIKELY (!p) {
......@@ -1983,7 +1999,6 @@ load_compiled_fp (const char *file, FILE *fp)
tok->parameter = 1;
}
/*the value*/
b2 = g_new(char,size+2);
if G_UNLIKELY (!fgets(b2,size+2,fp)) {
......@@ -2001,6 +2016,7 @@ load_compiled_fp (const char *file, FILE *fp)
if (type == GEL_USER_FUNC) {
func = d_makeufunc (tok, NULL, li, nargs, NULL);
func->vararg = vararg ? 1 : 0;
func->symbolic_id = symbolic_tok;
} else /*GEL_VARIABLE_FUNC*/ {
func = d_makevfunc (tok, NULL);
}
......@@ -2018,6 +2034,7 @@ load_compiled_fp (const char *file, FILE *fp)
if(type == GEL_USER_FUNC) {
func = d_makeufunc (tok, NULL, li, nargs, NULL);
func->vararg = vararg ? 1 : 0;
func->symbolic_id = symbolic_tok;
} else /*GEL_VARIABLE_FUNC*/ {
func = d_makevfunc(tok,NULL);
}
......@@ -2713,15 +2730,15 @@ do_exec_commands (const char *dirprefix)
ret = FALSE;
break;
case GEL_LOADFILE:
while (evalstack)
gel_freetree (stack_pop (&evalstack));
while (gel_parsestack)
gel_freetree (stack_pop (&gel_parsestack));
gel_load_file (dirprefix, arg, TRUE);
ret = TRUE;
break;
case GEL_LOADFILE_GLOB:
list = get_wordlist (arg);
while (evalstack)
gel_freetree (stack_pop (&evalstack));
while (gel_parsestack)
gel_freetree (stack_pop (&gel_parsestack));
for (li = list; li != NULL; li = li->next) {
gel_load_guess_file (dirprefix, li->data, TRUE);
if (interrupted)
......@@ -2733,8 +2750,8 @@ do_exec_commands (const char *dirprefix)
break;
case GEL_CHANGEDIR:
list = get_wordlist (arg);
while (evalstack)
gel_freetree (stack_pop (&evalstack));
while (gel_parsestack)
gel_freetree (stack_pop (&gel_parsestack));
for (li = list; li != NULL; li = li->next) {
our_chdir (dirprefix, li->data);
}
......@@ -2937,21 +2954,21 @@ gel_parseexp (const char *str, FILE *infile, gboolean exec_commands,
/*if we are testing and got an unfinished expression just report that*/
if(testparse && got_end_too_soon) {
while(evalstack)
gel_freetree(stack_pop(&evalstack));
while(gel_parsestack)
gel_freetree(stack_pop(&gel_parsestack));
if(finished) *finished = FALSE;
return NULL;
}
/*catch parsing errors*/
if(error_num!=NO_ERROR) {
while(evalstack)
gel_freetree(stack_pop(&evalstack));
while(gel_parsestack)
gel_freetree(stack_pop(&gel_parsestack));
if(finished) *finished = TRUE;
return NULL;
}
stacklen = g_slist_length(evalstack);
stacklen = g_slist_length(gel_parsestack);
if(stacklen==0) {
if(finished) *finished = FALSE;
......@@ -2960,22 +2977,22 @@ gel_parseexp (const char *str, FILE *infile, gboolean exec_commands,
/*stack is supposed to have only ONE entry*/
if(stacklen!=1) {
while(evalstack)
gel_freetree(stack_pop(&evalstack));
while(gel_parsestack)
gel_freetree(stack_pop(&gel_parsestack));
if G_UNLIKELY (!testparse)
gel_errorout (_("ERROR: Probably corrupt stack!"));
if(finished) *finished = FALSE;
return NULL;
}
replace_equals (evalstack->data, FALSE /* in_expression */);
replace_exp (evalstack->data);
fixup_num_neg (evalstack->data);
evalstack->data = gather_comparisons (evalstack->data);
try_to_do_precalc (evalstack->data);
replace_equals (gel_parsestack->data, FALSE /* in_expression */);
replace_exp (gel_parsestack->data);
fixup_num_neg (gel_parsestack->data);
gel_parsestack->data = gather_comparisons (gel_parsestack->data);
try_to_do_precalc (gel_parsestack->data);
if (finished != NULL)
*finished = TRUE;
return stack_pop (&evalstack);
return stack_pop (&gel_parsestack);
}
GelETree *
......
......@@ -134,7 +134,9 @@ gel_compile_node(GelETree *t,GString *gs)
case FUNCTION_NODE:
g_assert(t->func.func->type==GEL_USER_FUNC);
/*g_assert(t->func.func->id==NULL);*/
g_string_append_printf (gs, ";%d;%d;%d;%d",
g_string_append_printf (gs, ";%s;%s;%d;%d;%d;%d",
t->func.func->id ? t->func.func->id->token : "*",
t->func.func->symbolic_id ? t->func.func->symbolic_id->token : "*",
t->func.func->nargs,
t->func.func->vararg,
t->func.func->propagate_mod,
......@@ -183,6 +185,7 @@ static GelETree *
gel_decompile_node(char **ptrptr)
{
GelETree *n;
const char *id, *symbolic_id;
char *p;
int type = -1;
int nargs = -1;
......@@ -315,6 +318,20 @@ gel_decompile_node(char **ptrptr)
}
return n;
case FUNCTION_NODE:
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
if (strcmp (p, "*") == 0)
id = NULL;
else
id = p;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
if (strcmp (p, "*") == 0)
symbolic_id = NULL;
else
symbolic_id = p;
p = strtok_r (NULL,";", ptrptr);
if G_UNLIKELY (!p) return NULL;
nargs = -1;
......@@ -352,7 +369,9 @@ gel_decompile_node(char **ptrptr)
return NULL;
}
func = d_makeufunc(NULL,n,oli,nargs, NULL);
/* Note that d_intern handles NULL properly */
func = d_makeufunc (d_intern (id), n, oli, nargs, NULL);
func->symbolic_id = d_intern (symbolic_id);
func->context = -1;
func->vararg = vararg ? 1 : 0;
func->propagate_mod = propagate_mod ? 1 : 0;
......@@ -443,6 +462,7 @@ gel_decompile_tree (char *s)
t = gel_decompile_node (&ptrptr);
if G_UNLIKELY (t == NULL) {
printf ("FOO!\n");
gel_errorout (_("Bad tree record when decompiling"));
return NULL;
}
......
......@@ -474,12 +474,18 @@ d_lookup_only_global (GelToken *id)
GelToken *
d_intern (const char *id)
{
GelToken * tok = g_hash_table_lookup(dictionary,id);
if(!tok) {
tok = g_new0(GelToken,1);
tok->token = g_strdup(id);
g_hash_table_insert(dictionary,tok->token,tok);
GelToken * tok;
if (id == NULL)
return NULL;
tok = g_hash_table_lookup (dictionary, id);
if (tok == NULL) {
tok = g_new0 (GelToken, 1);
tok->token = g_strdup (id);
g_hash_table_insert (dictionary, tok->token, tok);
}
return tok;
}
......
......@@ -124,8 +124,10 @@ void d_add_named_args (GelEFunc *f, const char *args);
f->data.user = \
gel_decompile_tree (g_hash_table_lookup \
(uncompiled, f->id)); \
/* On error give null tree */ \
if (f->data.user == NULL) \
f->data.user = gel_makenum_null (); \
g_hash_table_remove (uncompiled, f->id); \
g_assert (f->data.user != NULL); \
} \
......
......@@ -193,7 +193,9 @@ branches (int op)
case E_PARAMETER: return 3;
case E_ABS: return 1;
case E_PLUS: return 2;
case E_ELTPLUS: return 2;
case E_MINUS: return 2;
case E_ELTMINUS: return 2;
case E_MUL: return 2;
case E_ELTMUL: return 2;
case E_DIV: return 2;
......@@ -1619,9 +1621,11 @@ op_two_nodes (GelCtx *ctx, GelETree *ll, GelETree *rr, int oper,
mpw_init(res);
switch(oper) {
case E_PLUS:
case E_ELTPLUS:
mpw_add(res,ll->val.value,rr->val.value);
break;
case E_MINUS:
case E_ELTMINUS:
mpw_sub(res,ll->val.value,rr->val.value);
break;
case E_MUL:
......@@ -1679,10 +1683,12 @@ op_two_nodes (GelCtx *ctx, GelETree *ll, GelETree *rr, int oper,
switch (oper) {
case E_PLUS:
case E_ELTPLUS:
res = lt || rt;
got_res = TRUE;
break;
case E_MINUS:
case E_ELTMINUS:
res = lt || ! rt;
got_res = TRUE;
break;
......@@ -1730,7 +1736,7 @@ op_two_nodes (GelCtx *ctx, GelETree *ll, GelETree *rr, int oper,
}
/*add, sub, mul, div*/
/*eltadd, eltsub, mul, div*/
static gboolean
matrix_scalar_matrix_op(GelCtx *ctx, GelETree *n, GelETree *l, GelETree *r)
{
......@@ -1784,6 +1790,59 @@ matrix_scalar_matrix_op(GelCtx *ctx, GelETree *n, GelETree *l, GelETree *r)
return TRUE;
}
/* add and sub using identity for square matrices and eltbyelt for vectors */
static gboolean
matrix_addsub_scalar_matrix_op (GelCtx *ctx, GelETree *n, GelETree *l, GelETree *r)
{
int i;
GelMatrixW *m;
GelETree *node;
int quote = 0;
if (l->type == MATRIX_NODE) {
m = l->mat.matrix;
quote = l->mat.quoted;
node = r;
} else {
m = r->mat.matrix;
quote = r->mat.quoted;
node = l;
}
/* If vector do the normal (element by element) scalar matrix operation */
if (gel_matrixw_width (m) == 1 || gel_matrixw_height (m) == 1)
return matrix_scalar_matrix_op (ctx, n, l, r);
if G_UNLIKELY (gel_matrixw_width (m) != gel_matrixw_height (m)) {
gel_errorout (_("Can't add/subtract a scalar to non-square matrix (A + x is defined as A + x*I)"));
return TRUE;
}
gel_matrixw_make_private(m);
for (i = 0; i < gel_matrixw_width (m); i++) {
GelETree *t = gel_matrixw_set_index(m,i,i);
/* Only for ADD/SUB so order is unimportant */
gel_matrixw_set_index (m, i, i) =
op_two_nodes (ctx,
t ? t : the_zero,
node, n->op.oper,
FALSE /* no_push */);
if (t != NULL)
gel_freetree (t);
}
n->op.args = NULL;
if (l->type == MATRIX_NODE) {
replacenode (n, l);
gel_freetree (r);
} else {
replacenode (n, r);
gel_freetree (l);
}
return TRUE;
}
static gboolean
matrix_absnegfac_op(GelCtx *ctx, GelETree *n, GelETree *l)
{
......@@ -1848,7 +1907,9 @@ pure_matrix_eltbyelt_op(GelCtx *ctx, GelETree *n, GelETree *l, GelETree *r)
if G_UNLIKELY ((gel_matrixw_width(m1) != gel_matrixw_width(m2)) ||
(gel_matrixw_height(m1) != gel_matrixw_height(m2))) {
if (n->op.oper == E_PLUS ||
n->op.oper == E_MINUS)
n->op.oper == E_ELTPLUS ||
n->op.oper == E_MINUS ||
n->op.oper == E_ELTMINUS)
gel_errorout (_("Can't add/subtract two matricies of different sizes"));
else
gel_errorout (_("Can't do element by element operations on two matricies of different sizes"));
......@@ -2757,6 +2818,26 @@ static const GelOper prim_table[E_OPER_LAST] = {
(GelEvalFunc)function_uni_op},
}},
/*E_PLUS*/
{{
{{GO_VALUE,GO_VALUE,0},(GelEvalFunc)numerical_add},
{{GO_MATRIX,GO_MATRIX,0},(GelEvalFunc)pure_matrix_eltbyelt_op},
{{GO_VALUE|GO_MATRIX,GO_VALUE|GO_MATRIX,0},
(GelEvalFunc)matrix_addsub_scalar_matrix_op},
{{GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_STRING,GO_STRING,0},
(GelEvalFunc)string_concat},
{{GO_STRING,GO_VALUE|GO_MATRIX|GO_FUNCTION|GO_STRING,0},
(GelEvalFunc)string_concat},
{{GO_FUNCTION|GO_IDENTIFIER,GO_FUNCTION|GO_IDENTIFIER,0},
(GelEvalFunc)function_bin_op},
{{GO_FUNCTION|GO_IDENTIFIER,GO_VALUE|GO_MATRIX,0},
(GelEvalFunc)function_something_bin_op},
{{GO_VALUE|GO_MATRIX,GO_FUNCTION|GO_IDENTIFIER,0},
(GelEvalFunc)something_function_bin_op},
{{GO_VALUE|GO_POLYNOMIAL,GO_VALUE|GO_POLYNOMIAL,0},
(GelEvalFunc)polynomial_add_sub_op},
{{GO_VALUE|GO_STRING|GO_BOOL,GO_VALUE|GO_STRING|GO_BOOL,0},(GelEvalFunc)boolean_add},
}},
/*E_ELTPLUS*/
{{
{{GO_VALUE,GO_VALUE,0},(GelEvalFunc)numerical_add},
{{GO_MATRIX,GO_MATRIX,0},(GelEvalFunc)pure_matrix_eltbyelt_op},
......@@ -2777,6 +2858,22 @@ static const GelOper prim_table[E_OPER_LAST] = {
{{GO_VALUE|GO_STRING|GO_BOOL,GO_VALUE|GO_STRING|GO_BOOL,0},(GelEvalFunc)boolean_add},
}},
/*E_MINUS*/
{{
{{GO_VALUE,GO_VALUE,0},(GelEvalFunc)numerical_sub},
{{GO_MATRIX,GO_MATRIX,0},(GelEvalFunc)pure_matrix_eltbyelt_op},
{{GO_VALUE|GO_MATRIX,GO_VALUE|GO_MATRIX,0},
(GelEvalFunc)matrix_addsub_scalar_matrix_op},
{{GO_VALUE|GO_POLYNOMIAL,GO_VALUE|GO_POLYNOMIAL,0},
(GelEvalFunc)polynomial_add_sub_op},
{{GO_FUNCTION|GO_IDENTIFIER,GO_FUNCTION|GO_IDENTIFIER,0},
(GelEvalFunc)function_bin_op},
{{GO_FUNCTION|GO_IDENTIFIER,GO_VALUE|GO_MATRIX,0},
(GelEvalFunc)function_something_bin_op},
{{GO_VALUE|GO_MATRIX,GO_FUNCTION|GO_IDENTIFIER,0},
(GelEvalFunc)something_function_bin_op},
{{GO_VALUE|GO_STRING|GO_BOOL,GO_VALUE|GO_STRING|GO_BOOL,0},(GelEvalFunc)boolean_sub},
}},
/*E_ELTMINUS*/
{{
{{GO_VALUE,GO_VALUE,0},(GelEvalFunc)numerical_sub},
{{GO_MATRIX,GO_MATRIX,0},(GelEvalFunc)pure_matrix_eltbyelt_op},
......@@ -5814,7 +5911,9 @@ iter_get_op_name(int oper)
case E_PARAMETER: break;
case E_ABS: name = g_strdup(_("Absolute value")); break;
case E_PLUS: name = g_strdup(_("Addition")); break;
case E_ELTPLUS: name = g_strdup(_("Element by element addition")); break;
case E_MINUS: name = g_strdup(_("Subtraction")); break;
case E_ELTMINUS: name = g_strdup(_("Element by element subtraction")); break;
case E_MUL: name = g_strdup(_("Multiplication")); break;
case E_ELTMUL: name = g_strdup(_("Element by element multiplication")); break;
case E_DIV: name = g_strdup(_("Division")); break;
......@@ -6028,7 +6127,9 @@ iter_operator_pre(GelCtx *ctx)
case E_ABS:
case E_PLUS:
case E_ELTPLUS:
case E_MINUS:
case E_ELTMINUS:
case E_MUL:
case E_ELTMUL:
case E_DIV:
......@@ -6301,7 +6402,9 @@ iter_operator_post (GelCtx *ctx, gboolean *repushed)
break;
case E_PLUS:
case E_ELTPLUS:
case E_MINUS:
case E_ELTMINUS:
case E_MUL:
case E_ELTMUL:
case E_DIV:
......@@ -7227,7 +7330,9 @@ try_to_precalc_op(GelETree *n)
case E_FACT: op_precalc_1(n,mpw_fac); return;
case E_DBLFACT: op_precalc_1(n,mpw_dblfac); return;
case E_PLUS: op_precalc_2(n,mpw_add); return;
case E_ELTPLUS: op_precalc_2(n,mpw_add); return;
case E_MINUS: op_precalc_2(n,mpw_sub); return;
case E_ELTMINUS: op_precalc_2(n,mpw_sub); return;
case E_MUL: op_precalc_2(n,mpw_mul); return;
case E_ELTMUL: op_precalc_2(n,mpw_mul); return;
case E_DIV: op_precalc_2(n,mpw_div); return;
......@@ -7240,7 +7345,7 @@ try_to_precalc_op(GelETree *n)
}
}
/* FIXME: try to also precalc things like 3*(10*foo) */
/* FIXME: try to also precalc things like 3*(10*foo), but be careful as to not change what the result is! */
void
try_to_do_precalc(GelETree *n)
{
......
......@@ -39,7 +39,9 @@ enum {
E_PARAMETER,
E_ABS,
E_PLUS,
E_ELTPLUS,
E_MINUS,
E_ELTMINUS,
E_MUL,
E_ELTMUL,
E_DIV,
......
......@@ -3462,18 +3462,15 @@ ptf_makenew_term(mpw_t mul, GelToken *id, int power)
{
GelETree *n;
/* we do the zero power the same as >1 so
* that we get an x^0 term. This may seem
* pointless but it allows evaluating matrices
* as it will make the constant term act like
* c*I(n) */
if (mpw_cmp_ui(mul,1)==0) {
if (power == 0) {
return gel_makenum (mul);
} else if (mpw_eql_ui (mul, 1)) {
n = ptf_makenew_power(id,power);
} else {
GET_NEW_NODE(n);
n->type = OPERATOR_NODE;
n->op.oper = E_MUL;
n->op.args = gel_makenum(mul);
n->op.args = gel_makenum (mul);
n->op.args->any.next = ptf_makenew_power(id,power);
n->op.args->any.next->any.next = NULL;
n->op.nargs = 2;
......
......@@ -79,7 +79,8 @@ function t(x)=(function t(x,y)=(x+y);t(x,2));t(5) 7
1#4 1
print(5);5+1;. 5
print(5);5+1; 5
.+1 ((null)+1)
. + 1 ((null)+1)
null + 1 ((null)+1)
if(5/0)then(1) (if (5/0) then 1)
k=5;while((20/k)>1)do(k=k-1) (while ((20/0)>1) do (k=(k-1)))
t=50;while(t>0)do(t=t-1);t 0
......@@ -448,7 +449,7 @@ q=5; function f(x) = ( q = 6; set(`q,x); q) ; f(10) ; q 10
l=9 ; if (l=9) then 1 1
l=9 ; if (l=10) then 1 else 2 2
l=9 ; if (l=10) then 1 else 2 ; l 9
A=[1,2;3,4];B=A+4;[A,0;0,B] [1,2,0,0;3,4,0,0;0,0,5,6;0,0,7,8]
A=[1,2;3,4];B=A+4;[A,0;0,B] [1,2,0,0;3,4,0,0;0,0,5,2;0,0,3,8]
sum n in ColumnsOf([1,2;3,4]) do n [3;7]
sum n in RowsOf([1,2;3,4]) do n [4,6]
function f(x) = `(l) = x+l; k=f(2);k(11) 13
......@@ -677,4 +678,6 @@ SymbolicDerivative(`(x)=10*x^3+x^2+88*x+100) (`(x)=((((10*(3*(x^2)))+(2*x))+88
function foo(f) = SymbolicDerivative(f) ; foo (sin) (`(x)=cos(x))
function foo(f) = SymbolicDerivative(f) ; foo (`(x)=x^2) (`(x)=(2*x))
SymbolicDerivative(f:=sin) (`(x)=cos(x))
[1,2;3,4]+2 [3,2;3,6]
[1,2;3,4;5,6]+2 ([1,2;3,4;5,6]+2)
load "longtest.gel" true
......@@ -38,7 +38,7 @@ int first_tok = STARTTOK;
int return_ret = FALSE;
int parenth_depth = 0;
int lex_init = TRUE;
extern GSList *evalstack;
extern GSList *gel_parsestack;
static int matrix_entry = 0;
static GSList *matrix_entry_stack = NULL;
......@@ -133,7 +133,7 @@ gel_lexer_close(FILE *fp)
^[ ]*load[ ]+<([^>]|\\>)*>[ ]*$ {
char *s;
char *end;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'<')+1; /*find the beginning*/
end=strrchr(yytext,'>'); /*find the end*/
s = unescape_string(s,end,NULL);
......@@ -145,7 +145,7 @@ gel_lexer_close(FILE *fp)
^[ ]*load[ ]+[^ ].*$ {
char *s;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'d')+1; /*move after the load*/
/*btw from the above RE we know this will work*/
while(*s==' ' || *s=='\t')
......@@ -157,7 +157,7 @@ gel_lexer_close(FILE *fp)
^[ ]*cd[ ]+[^ ].*$ {
char *s;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'d')+1; /*move after the cd*/
/*btw from the above RE we know this will work*/
while(*s==' ' || *s=='\t')
......@@ -169,7 +169,7 @@ gel_lexer_close(FILE *fp)
^[ ]*plugin[ ]+[^ ].*$ {
char *s;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'n')+1; /*move after the plugin*/
/*btw from the above RE we know this will work*/
while(*s==' ' || *s=='\t')
......@@ -180,14 +180,14 @@ gel_lexer_close(FILE *fp)
}
^[ ]*pwd[ ]*$ {
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
DO_RET;
return PWD;
}
^[ ]*ls[ ]+[^ ].*$ {
char *s;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'s')+1; /*move after the ls*/
/*btw from the above RE we know this will work*/
while(*s==' ' || *s=='\t')
......@@ -198,14 +198,14 @@ gel_lexer_close(FILE *fp)
}
^[ ]*ls[ ]*$ {
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
DO_RET;
return LS;
}
^[ ]*help[ ]+[^ ].*$ {
char *s;
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
s=strchr(yytext,'p')+1; /*move after the help*/
/*btw from the above RE we know this will work*/
while(*s==' ' || *s=='\t')
......@@ -216,7 +216,7 @@ gel_lexer_close(FILE *fp)
}
^[ ]*help[ ]*$ {
if(evalstack || parenth_depth) {REJECT;}
if(gel_parsestack || parenth_depth) {REJECT;}
DO_RET;
return HELP;
}
......@@ -451,6 +451,8 @@ null { DO_RET; return '.'; }
[ \t\r]+ ; /*ignore whitespace*/
\.\+ { DO_RET; return ELTELTPLUS; }
\.\- { DO_RET; return ELTELTMINUS; }
\.\* { DO_RET; return ELTELTMUL; }
\.\/ { DO_RET; return ELTELTDIV; }
\.\\ { DO_RET; return ELTELTBACKDIV; }
......
......@@ -34,7 +34,7 @@
#include "parseutil.h"
extern GSList *evalstack;
extern GSList *gel_parsestack;
extern int return_ret; /*should the lexer return on \n*/
extern char *loadfile;
......@@ -76,7 +76,7 @@ void yyerror(char *);
%token TRANSPOSE
%token ELTELTDIV ELTELTMUL ELTELTEXP ELTELTMOD DOUBLEFACT
%token ELTELTDIV ELTELTMUL ELTELTPLUS ELTELTMINUS ELTELTEXP ELTELTMOD DOUBLEFACT
%token EQ_CMP NE_CMP CMP_CMP LT_CMP GT_CMP LE_CMP GE_CMP
......@@ -107,7 +107,7 @@ void yyerror(char *);
%right ':'
%left '+' '-'
%left '+' ELTELTADD '-' ELTELTSUB
%left '*' ELTELTMUL '/' ELTELTDIV '\\' ELTELTBACKDIV '%' ELTELTMOD
%right '\'' TRANSPOSE
......@@ -145,14 +145,16 @@ expr: expr SEPAR expr { PUSH_ACT(E_SEPAR); }
mpw_init (i);
mpw_i (i);
gp_push_spacer();
stack_push(&evalstack,
stack_push(&gel_parsestack,
gel_makenum_use(i));
PUSH_ACT(E_MUL); }
| expr EQUALS expr { PUSH_ACT(E_EQUALS); }
| expr DEFEQUALS expr { PUSH_ACT(E_DEFEQUALS); }
| '|' expr '|' { PUSH_ACT(E_ABS); }
| expr '+' expr { PUSH_ACT(E_PLUS); }
| expr ELTELTPLUS expr { PUSH_ACT(E_ELTPLUS); }
| expr '-' expr { PUSH_ACT(E_MINUS); }
| expr ELTELTMINUS expr { PUSH_ACT(E_ELTMINUS); }
| expr '*' expr { PUSH_ACT(E_MUL); }
| expr ELTELTMUL expr { PUSH_ACT(E_ELTMUL); }
| expr '/' expr { PUSH_ACT(E_DIV); }
......@@ -256,7 +258,7 @@ expr: expr SEPAR expr { PUSH_ACT(E_SEPAR); }
| EXCEPTION { PUSH_ACT(E_EXCEPTION); }
| CONTINUE { PUSH_ACT(E_CONTINUE); }
| BREAK { PUSH_ACT(E_BREAK); }
| NUMBER { stack_push(&evalstack,
| NUMBER { stack_push(&gel_parsestack,
gel_makenum_use($<val>1)); }
| STRING { PUSH_CONST_STRING($<id>1); }
| '.' { gp_push_null(); }
......
......@@ -34,7 +34,7 @@
#include "parseutil.h"
extern GSList *evalstack;
extern GSList *gel_parsestack;
gboolean
......@@ -45,13 +45,13 @@ gp_push_func (gboolean vararg)
GSList * list = NULL;
int i = 0;
val = stack_pop(&evalstack);
val = stack_pop(&gel_parsestack);
if(!val)
return FALSE;
for(;;) {
tree = stack_pop(&evalstack);
tree = stack_pop(&gel_parsestack);
if(tree && tree->type==EXPRLIST_START_NODE) {
gel_freetree(tree);
break;
......@@ -76,7 +76,7 @@ gp_push_func (gboolean vararg)
tree->func.func->context = -1;
tree->func.func->vararg = vararg;
stack_push(&evalstack,tree);
stack_push(&gel_parsestack,tree);
return TRUE;
}
......@@ -91,19 +91,19 @@ gp_prepare_push_param (gboolean setfunc)
/* FIXME: setfunc not yet implemented */
g_assert ( ! setfunc);
val = stack_pop (&evalstack);
val = stack_pop (&gel_parsestack);
if (val == NULL)
return FALSE;
ident = stack_pop (&evalstack);