[genius] Fri Jul 24 16:01:28 2009 Jiri (George) Lebl <jirka 5z com>



commit e54271704eb0566d95895bc32efac506e1db3afc
Author: Jiri (George) Lebl <jirka 5z com>
Date:   Fri Jul 24 16:01:38 2009 -0500

    Fri Jul 24 16:01:28 2009  Jiri (George) Lebl <jirka 5z com>
    
    	* src/calc.c, src/compil.c: Correctly compile/decompile all the new
    	  function attributes
    
    	* src/calc.c: correctly print out the local stuff, handle local node
    	  correctly when outside of functions
    
    	* src/funclib.c, src/graphing.c: handle eof errors from parsing
    	  things correctly without dying.
    
    	* src/dict.c, src/eval.c, src/structs.h: is_local generally should
    	  not be moved around with the function.  Also correctly copy/free
    	  all the other attributes when needed as well.
    
    	* src/eval.c: Set arguments BEFORE extradict.  This should never
    	  be an issue, but it feels more correct.
    
    	* src/dict.c: when the subst list becomes empty, remove from subst
    	  list to avoid unnecessary lookups
    
    	* lib/*/*.gel: update and fix for the [] operator
    
    	* src/geniustests.txt: Add some testcases
    
    	* src/symbolic.c: just a comment change

 ChangeLog                             |   27 +++++
 TODO                                  |    7 +
 lib/calculus/differentiation.gel      |    6 +-
 lib/calculus/integration.gel          |    5 +-
 lib/calculus/limits.gel               |    8 +-
 lib/combinatorics/factorial.gel       |    2 +-
 lib/combinatorics/misc.gel            |    6 +-
 lib/linear_algebra/bilinear_forms.gel |    6 +-
 lib/symbolic/differentiation.gel      |    4 +-
 src/calc.c                            |  199 ++++++++++++++++++++++++++++++---
 src/compil.c                          |   61 +++++++++--
 src/dict.c                            |   71 ++++++++++--
 src/eval.c                            |   63 +++++------
 src/funclib.c                         |   28 ++++-
 src/geniustests.txt                   |   25 ++++
 src/graphing.c                        |    8 ++
 src/structs.h                         |    2 +
 src/symbolic.c                        |    1 +
 18 files changed, 439 insertions(+), 90 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 94093c8..5ad09a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+Fri Jul 24 16:01:28 2009  Jiri (George) Lebl <jirka 5z com>
+
+	* src/calc.c, src/compil.c: Correctly compile/decompile all the new
+	  function attributes
+
+	* src/calc.c: correctly print out the local stuff, handle local node
+	  correctly when outside of functions
+
+	* src/funclib.c, src/graphing.c: handle eof errors from parsing
+	  things correctly without dying.
+
+	* src/dict.c, src/eval.c, src/structs.h: is_local generally should
+	  not be moved around with the function.  Also correctly copy/free
+	  all the other attributes when needed as well.
+
+	* src/eval.c: Set arguments BEFORE extradict.  This should never
+	  be an issue, but it feels more correct.
+
+	* src/dict.c: when the subst list becomes empty, remove from subst
+	  list to avoid unnecessary lookups
+
+	* lib/*/*.gel: update and fix for the [] operator
+
+	* src/geniustests.txt: Add some testcases
+
+	* src/symbolic.c: just a comment change
+
 Thu Jul 23 18:35:28 2009  Jiri (George) Lebl <jirka 5z com>
 
 	* src/parse.y, src/eval.c, src/dict.c, src/structs.h: Add an optional
diff --git a/TODO b/TODO
index 1338faa..ac86184 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,10 @@
+-- check fourier stuff
+-- document new things in 1.0.7
+-- check modified functions in the library
+
+
+
+
 * Logfiles and/or save session
 * Whack the readline nonsense in the GUI
 * Native polynomial operation
diff --git a/lib/calculus/differentiation.gel b/lib/calculus/differentiation.gel
index 10b934f..874917b 100644
--- a/lib/calculus/differentiation.gel
+++ b/lib/calculus/differentiation.gel
@@ -128,7 +128,7 @@ function NumericalDerivative(f,x0) =
 (
     local *;
     # FIXME: perhaps check differentiability first, but then we're doing so many limits already
-    NumericalLimitAtInfinity (`(n)=(TwoSidedFivePointFormula(f,x0,2.0^(-n))),
+    NumericalLimitAtInfinity (`(n)[f,x0]=(TwoSidedFivePointFormula(f,x0,2.0^(-n))),
 			      Identity,
 			      DerivativeTolerance,
 			      DerivativeSFS,
@@ -141,7 +141,7 @@ NDerivative = NumericalDerivative
 function NumericalLeftDerivative(f,x0) =
 (
     local *;
-    NumericalLimitAtInfinity (`(n)=(OneSidedFivePointFormula(f,x0,-(2.0^(-n)))),
+    NumericalLimitAtInfinity (`(n)[f,x0]=(OneSidedFivePointFormula(f,x0,-(2.0^(-n)))),
 			      Identity,
 			      DerivativeTolerance,
 			      DerivativeSFS,
@@ -152,7 +152,7 @@ SetHelp("NumericalLeftDerivative","calculus","Attempt to calculate numerical lef
 function NumericalRightDerivative(f,x0) =
 (
     local *;
-    NumericalLimitAtInfinity (`(n)=(OneSidedFivePointFormula(f,x0,2.0^(-n))),
+    NumericalLimitAtInfinity (`(n)[f,x0]=(OneSidedFivePointFormula(f,x0,2.0^(-n))),
 			      Identity,
 			      DerivativeTolerance,
 			      DerivativeSFS,
diff --git a/lib/calculus/integration.gel b/lib/calculus/integration.gel
index 39cf3e6..537480e 100644
--- a/lib/calculus/integration.gel
+++ b/lib/calculus/integration.gel
@@ -65,4 +65,7 @@ SetHelp ("NumericalIntegralFunction", "parameters", "The function used for numer
 parameter NumericalIntegralFunction = `CompositeSimpsonsRule
 
 SetHelp ("NumericalIntegral", "calculus", "Integration by rule set in NumericalIntegralFunction of f from a to b using NumericalIntegralSteps steps")
-function NumericalIntegral(f,a,b) = (local *;NumericalIntegralFunction call (f,a,b,NumericalIntegralSteps))
+function NumericalIntegral(f,a,b) = (
+	local *;
+	NumericalIntegralFunction call (f,a,b,NumericalIntegralSteps)
+)
diff --git a/lib/calculus/limits.gel b/lib/calculus/limits.gel
index 9f717bc..fcb25b6 100644
--- a/lib/calculus/limits.gel
+++ b/lib/calculus/limits.gel
@@ -21,8 +21,8 @@
 
 # Limits:
 SetHelp ("NumericalLimitAtInfinity", "calculus", "Attempt to calculate the limit of f(step_fun(i)) as i goes from 1 to N")
-function NumericalLimitAtInfinity(_f,step_fun,tolerance,successive_for_success,N) =
-# this evaluates _f(step_fun(i)) as i goes from 1 to N.
+function NumericalLimitAtInfinity(f,step_fun,tolerance,successive_for_success,N) =
+# this evaluates f(step_fun(i)) as i goes from 1 to N.
 # If s_f_s of the pairwise successive differences are less than tolerance, then
 # it returns the last value; if this doesn't happen, it returns Null.
 # INPUT: N had better be at least 1
@@ -30,10 +30,10 @@ function NumericalLimitAtInfinity(_f,step_fun,tolerance,successive_for_success,N
 # bounded oscillation (like sin(x))
 (
     local *;
-    current_limit = _f(step_fun(1));
+    current_limit = f(step_fun(1));
     number_of_consecutive_differences_within_tolerance = 0;
     for i = 2 to N do (
-        new_limit = _f(step_fun(i));
+        new_limit = f(step_fun(i));
         if (|new_limit-current_limit| < tolerance) then (
             number_of_consecutive_differences_within_tolerance = number_of_consecutive_differences_within_tolerance+1
         ) else (
diff --git a/lib/combinatorics/factorial.gel b/lib/combinatorics/factorial.gel
index 934976e..9133087 100644
--- a/lib/combinatorics/factorial.gel
+++ b/lib/combinatorics/factorial.gel
@@ -96,7 +96,7 @@ function Multinomial(v,arg...) = (
 	else
 		m = [v, arg];
 
-	MatrixSum(m)!/MatrixProduct(ApplyOverMatrix(m,`(x)=x!))
+	MatrixSum(m)!/MatrixProduct(ApplyOverMatrix(m,`(x)[]=x!))
 )
 
 SetHelp("Pascal","combinatorics","Get the pascal's triangle as a matrix");
diff --git a/lib/combinatorics/misc.gel b/lib/combinatorics/misc.gel
index 15439f0..0ce24a3 100644
--- a/lib/combinatorics/misc.gel
+++ b/lib/combinatorics/misc.gel
@@ -14,13 +14,13 @@ function Hofstadter(n) = (
     	(error("Hofstadter: argument not a positive integer");bailout);
     # reason for doing this is that it's just plain faster then calling self
     # again
-    function _h (n) = (
+    function h (n) = (
     	if n <= 2 then
 		1
 	else
-		_h(n - _h(n-1)) + _h(n - _h(n-2))
+		h(n - h(n-1)) + h(n - h(n-2))
     );
-    _h (n)
+    h (n)
 )
 
 
diff --git a/lib/linear_algebra/bilinear_forms.gel b/lib/linear_algebra/bilinear_forms.gel
index 686cb50..2e5b8f1 100644
--- a/lib/linear_algebra/bilinear_forms.gel
+++ b/lib/linear_algebra/bilinear_forms.gel
@@ -30,10 +30,10 @@ function VectorAngle(v,w,B...) =
 
 #FIXME: check parameters
 SetHelp ("BilinearFormFunction", "linear_algebra", "Return a function that evaluates two vectors with respect to the bilinear form given by A")
-function BilinearFormFunction(A)=(`(v,w)=(v.'*A*w)@(1))
+function BilinearFormFunction(A)=(`(v,w)[A]=(v.'*A*w)@(1))
 
 SetHelp ("SesquilinearFormFunction", "linear_algebra", "Return a function that evaluates two vectors with respect to the sesquilinear form given by A")
-function SesquilinearFormFunction(A)=(`(v,w)=(v'*A*w)@(1))
+function SesquilinearFormFunction(A)=(`(v,w)[A]=(v'*A*w)@(1))
 
 # Projection onto a vector space
 # Projection of vector v onto subspace W given a sesquilinear form B
@@ -65,7 +65,7 @@ function GramSchmidt(v,B...) =
         # if you don't give anything, assume standard inner product
 	if IsNull(B) or IsNull(B@(1)) then P=HermitianProduct
 	# If it's a matrix, then use the sesquilinear form defined by that matrix
-	else if IsMatrix(B@(1)) then (function P(u,w)=SesquilinearForm(u,B@(1),w))
+	else if IsMatrix(B@(1)) then (function P(u,w)[B]=SesquilinearForm(u,B@(1),w))
 	# If B is just some function, assume that it's an inner product
         else if elements(B) > 1 or not IsFunction(B@(1)) then (error("GramSchmidt: argument B not a function or Matrix");bailout)
 	else P = B@(1);
diff --git a/lib/symbolic/differentiation.gel b/lib/symbolic/differentiation.gel
index d928e7c..59a0364 100644
--- a/lib/symbolic/differentiation.gel
+++ b/lib/symbolic/differentiation.gel
@@ -38,7 +38,7 @@ SetHelp("SymbolicNthDerivativeTry","symbolic","Attempt to symbolically different
 
 function SymbolicTaylorApproximationFunction(f,x0,n) =
 (
-	local f,df,c,n,k;
+	local *;
 	if not IsFunction(f) then
 		(error("SymbolicTaylorApproximationFunction: argument 1 must be a function");bailout)
 	else if not IsValue(x0) then
@@ -58,6 +58,6 @@ function SymbolicTaylorApproximationFunction(f,x0,n) =
 	        )
 	);
 	tp = PolyToFunction (c);
-	`(x) = (tp call (x - x0))
+	`(x)[tp,x0] = (tp call (x - x0))
 )
 SetHelp("SymbolicTaylorApproximationFunction","symbolic","Attempt to construct the taylor approximation function around x0 to the nth degree.");
diff --git a/src/calc.c b/src/calc.c
index 7dddd4a..7e3ac4a 100644
--- a/src/calc.c
+++ b/src/calc.c
@@ -1318,12 +1318,29 @@ append_func (GelOutput *gelo, GelEFunc *f)
 	if (f->vararg)
 		gel_output_string (gelo, "...");
 
-	if G_LIKELY (f->type==GEL_USER_FUNC) {
+	if G_LIKELY (f->type == GEL_USER_FUNC) {
 		gel_output_string(gelo,")=");
 		D_ENSURE_USER_BODY (f);
+		if (f->extra_dict != NULL ||
+		    f->local_all ||
+		    f->local_idents != NULL) {
+			gel_output_string(gelo,"(");
+		}
+		if (f->local_all) {
+			gel_output_string(gelo,"local *;");
+		} else if (f->local_idents != NULL) {
+			GSList *li;
+			gel_output_string(gelo,"local ");
+			for (li = f->local_idents; li != NULL; li = li->next) {
+				GelToken *tok = li->data;
+				if (li != f->local_idents)
+					gel_output_string(gelo,",");
+				gel_output_string (gelo, tok->token);
+			}
+			gel_output_string(gelo,";");
+		}
 		if (f->extra_dict != NULL) {
 			GSList *li;
-			gel_output_string(gelo,"(");
 			for (li = f->extra_dict; li != NULL; li = li->next) {
 				GelEFunc *ff = li->data;
 				gel_output_string (gelo, ff->id->token);
@@ -1337,7 +1354,9 @@ append_func (GelOutput *gelo, GelEFunc *f)
 			}
 		}
 		gel_print_etree (gelo, f->data.user, FALSE);
-		if (f->extra_dict != NULL) {
+		if (f->extra_dict != NULL ||
+		    f->local_all ||
+		    f->local_idents != NULL) {
 			gel_output_string(gelo,")");
 		}
 		gel_output_string(gelo,")");
@@ -1821,13 +1840,36 @@ compile_funcs_in_dict (FILE *outfile, GSList *dict, gboolean is_extra_dict)
 		}
 		if (func->type == GEL_USER_FUNC) {
 			fprintf (outfile,
-				 "%c;%d;%s;%s;%d;%d",
+				 "%c;%d;%s;%s;n%d;v%d;p%d;o%d;l%d;e%d;b%d",
 				 fs,
 				 (int)strlen (body),
 				 func->id->token,
 				 func->symbolic_id ? func->symbolic_id->token : "*",
 				 (int)func->nargs,
-				 (int)func->vararg);
+				 (int)func->vararg,
+				 (int)func->propagate_mod,
+				 (int)func->no_mod_all_args,
+				 (int)func->local_all,
+				 (int)func->never_on_subst_list,
+				 (int)func->built_subst_dict);
+			if (func->local_idents == NULL)
+				fprintf (outfile, ";-");
+			for (l = func->local_idents; l != NULL; l = l->next) {
+				GelToken *tok = l->data;
+				if (l != func->local_idents)
+					fprintf (outfile, ",%s", tok->token);
+				else
+					fprintf (outfile, ";%s", tok->token);
+			}
+			if (func->subst_dict == NULL)
+				fprintf (outfile, ";-");
+			for (l = func->subst_dict; l != NULL; l = l->next) {
+				GelToken *tok = l->data;
+				if (l != func->subst_dict)
+					fprintf (outfile, ",%s", tok->token);
+				else
+					fprintf (outfile, ";%s", tok->token);
+			}
 			for (l = func->named_args; l != NULL; l = l->next) {
 				GelToken *tok = l->data;
 				fprintf (outfile, ";%s", tok->token);
@@ -1902,6 +1944,8 @@ gel_compile_all_user_funcs (FILE *outfile)
 	g_slist_free (funcs);
 }
 
+/* FIXME: function reading is almost identical to that for FUNCTION_NODEs
+   in compile.c  We should really unify these! */
 static void
 load_compiled_fp (const char *file, FILE *fp)
 {
@@ -1939,7 +1983,9 @@ load_compiled_fp (const char *file, FILE *fp)
 		char *p;
 		char *b2;
 		GelToken *tok, *symbolic_tok = NULL;
-		int size, nargs, vararg;
+		int size, nargs, vararg, propagate_mod, no_mod_all_args;
+		int local_all, never_on_subst_list, built_subst_dict;
+		GSList *local_idents, *subst_dict;
 		gboolean extra_dict = FALSE;
 		gboolean parameter = FALSE;
 		int i;
@@ -2107,7 +2153,7 @@ load_compiled_fp (const char *file, FILE *fp)
 				continue;
 			}
 			nargs = -1;
-			sscanf(p,"%d",&nargs);
+			sscanf(p,"n%d",&nargs);
 			if G_UNLIKELY (nargs == -1) {
 				gel_errorout (_("Badly formed record"));
 				continue;
@@ -2120,12 +2166,109 @@ load_compiled_fp (const char *file, FILE *fp)
 				continue;
 			}
 			vararg = -1;
-			sscanf(p,"%d",&vararg);
+			sscanf(p,"v%d",&vararg);
 			if G_UNLIKELY (vararg == -1) {
 				gel_errorout (_("Badly formed record"));
 				continue;
 			}
 
+			/*propagate_mod*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			propagate_mod = -1;
+			sscanf(p,"p%d",&propagate_mod);
+			if G_UNLIKELY (propagate_mod == -1) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+
+			/*no_mod_all_args*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			no_mod_all_args = -1;
+			sscanf(p,"o%d",&no_mod_all_args);
+			if G_UNLIKELY (no_mod_all_args == -1) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+
+			/*local_all*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			local_all = -1;
+			sscanf(p,"l%d",&local_all);
+			if G_UNLIKELY (local_all == -1) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+
+			/*never_on_subst_list*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			never_on_subst_list = -1;
+			sscanf(p,"e%d",&never_on_subst_list);
+			if G_UNLIKELY (never_on_subst_list == -1) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+
+			/*built_subst_list*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			built_subst_dict = -1;
+			sscanf(p,"b%d",&built_subst_dict);
+			if G_UNLIKELY (built_subst_dict == -1) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+
+			/*local_idents*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if G_UNLIKELY (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			local_idents = NULL;
+			if (strcmp (p, "-") != 0) {
+				char **s;
+				s = g_strsplit (p, ",", -1);
+				for (i = 0; s[i] != NULL; i++) {
+					local_idents = g_slist_append (local_idents, d_intern (s[i]));
+				}
+				g_strfreev (s);
+			}
+
+			/*subst_dict*/
+			p = strtok_r (NULL,";", &ptrptr);
+			if G_UNLIKELY (p == NULL) {
+				gel_errorout (_("Badly formed record"));
+				continue;
+			}
+			subst_dict = NULL;
+			if (strcmp (p, "-") != 0) {
+				char **s;
+				s = g_strsplit (p, ",", -1);
+				for (i = 0; s[i] != NULL; i++) {
+					subst_dict = g_slist_append (subst_dict, d_intern (s[i]));
+				}
+				g_strfreev (s);
+			}
+
 			/*argument names*/
 			li = NULL;
 			for(i=0;i<nargs;i++) {
@@ -2170,6 +2313,13 @@ load_compiled_fp (const char *file, FILE *fp)
 				func = d_makeufunc (tok, NULL, li, nargs, NULL);
 				func->vararg = vararg ? 1 : 0;
 				func->symbolic_id = symbolic_tok;
+				func->propagate_mod = propagate_mod ? 1 : 0;
+				func->no_mod_all_args = no_mod_all_args ? 1 : 0;
+				func->local_all = local_all ? 1 : 0;
+				func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+				func->built_subst_dict = built_subst_dict ? 1 : 0;
+				func->subst_dict = subst_dict;
+				func->local_idents = local_idents;
 			} else /*GEL_VARIABLE_FUNC*/ {
 				func = d_makevfunc (tok, NULL);
 			}
@@ -2186,6 +2336,13 @@ load_compiled_fp (const char *file, FILE *fp)
 				func = d_makeufunc (tok, NULL, li, nargs, NULL);
 				func->vararg = vararg ? 1 : 0;
 				func->symbolic_id = symbolic_tok;
+				func->propagate_mod = propagate_mod ? 1 : 0;
+				func->no_mod_all_args = no_mod_all_args ? 1 : 0;
+				func->local_all = local_all ? 1 : 0;
+				func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+				func->built_subst_dict = built_subst_dict ? 1 : 0;
+				func->subst_dict = subst_dict;
+				func->local_idents = local_idents;
 			} else /*GEL_VARIABLE_FUNC*/ {
 				func = d_makevfunc(tok,NULL);
 			}
@@ -3140,18 +3297,32 @@ gel_parseexp (const char *str, FILE *infile, gboolean exec_commands,
 	
 	stacklen = g_slist_length(gel_parsestack);
 	
-	if(stacklen==0) {
-		if(finished) *finished = FALSE;
+	if (stacklen == 0) {
+		if (finished != NULL)
+			*finished = FALSE;
 		return NULL;
 	}
 
 	/*stack is supposed to have only ONE entry*/
-	if(stacklen!=1) {
-		while(gel_parsestack)
-			gel_freetree(gel_stack_pop(&gel_parsestack));
+	if (stacklen != 1) {
+		while (gel_parsestack != NULL)
+			gel_freetree (gel_stack_pop (&gel_parsestack));
 		if G_UNLIKELY (!testparse)
 			gel_errorout (_("ERROR: Probably corrupt stack!"));
-		if(finished) *finished = FALSE;
+		if (finished != NULL)
+			*finished = FALSE;
+		return NULL;
+	}
+	/* local nodes should not exist now, they should all
+	   have been eaten */
+	if (gel_get_local_node (gel_parsestack->data,
+			        FALSE /* first_arg */,
+				NULL,
+				NULL)) {
+		gel_freetree (gel_stack_pop (&gel_parsestack));
+		gel_errorout (_("ERROR: 'local' in a wrong place, can only be first statement in a function!"));
+		if (finished != NULL)
+			*finished = TRUE;
 		return NULL;
 	}
 	gel_replace_equals (gel_parsestack->data, FALSE /* in_expression */);
diff --git a/src/compil.c b/src/compil.c
index 8d84c05..0a6f630 100644
--- a/src/compil.c
+++ b/src/compil.c
@@ -136,23 +136,37 @@ gel_compile_node(GelETree *t,GString *gs)
 	case GEL_FUNCTION_NODE:
 		g_assert(t->func.func->type==GEL_USER_FUNC);
 		/*g_assert(t->func.func->id==NULL);*/
-		g_string_append_printf (gs, ";%s;%s;%d;%d;%d;%d;%d;",
+		g_string_append_printf (gs,
+					";%s;%s;n%d;v%d;p%d;o%d;l%d;e%d;b%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,
 					t->func.func->no_mod_all_args,
-					t->func.func->local_all);
+					t->func.func->local_all,
+					t->func.func->never_on_subst_list,
+					t->func.func->built_subst_dict);
+		/* Make sure to also update calc compile_funcs_in_dict
+		 * and related! */
 
 		if (t->func.func->local_idents == NULL)
-			g_string_append (gs, "-");
+			g_string_append (gs, ";-");
 		for (li = t->func.func->local_idents; li != NULL; li = li->next) {
 			GelToken *tok = li->data;
 			if (li != t->func.func->local_idents)
 				g_string_append_printf (gs, ",%s", tok->token);
 			else
-				g_string_append_printf (gs, "%s", tok->token);
+				g_string_append_printf (gs, ";%s", tok->token);
+		}
+		if (t->func.func->subst_dict == NULL)
+			g_string_append (gs, ";-");
+		for (li = t->func.func->subst_dict; li != NULL; li = li->next) {
+			GelToken *tok = li->data;
+			if (li != t->func.func->subst_dict)
+				g_string_append_printf (gs, ",%s", tok->token);
+			else
+				g_string_append_printf (gs, ";%s", tok->token);
 		}
 		for (li = t->func.func->named_args; li != NULL; li = li->next) {
 			GelToken *tok = li->data;
@@ -206,6 +220,8 @@ gel_decompile_node(char **ptrptr)
 	int propagate_mod = -1;
 	int no_mod_all_args = -1;
 	int local_all = -1;
+	int never_on_subst_list = -1;
+	int built_subst_dict = -1;
 	int quote;
 	int oper;
 	int i,j;
@@ -213,7 +229,7 @@ gel_decompile_node(char **ptrptr)
 	GelMatrixW *m;
 	GelETree *li = NULL;
 	GelETree *args;
-	GSList *oli, *local_idents;
+	GSList *oli, *local_idents, *subst_dict;
 	GelEFunc *func;
 	mpw_t tmp;
 
@@ -351,31 +367,41 @@ gel_decompile_node(char **ptrptr)
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (!p) return NULL;
 		nargs = -1;
-		sscanf(p,"%d",&nargs);
+		sscanf(p,"n%d",&nargs);
 		if G_UNLIKELY (nargs==-1) return NULL;
 
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (!p) return NULL;
-		sscanf(p,"%d",&vararg);
+		sscanf(p,"v%d",&vararg);
 		if G_UNLIKELY (vararg == -1) return NULL;
 
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (!p) return NULL;
-		sscanf(p,"%d",&propagate_mod);
+		sscanf(p,"p%d",&propagate_mod);
 		if G_UNLIKELY (propagate_mod == -1) return NULL;
 
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (!p) return NULL;
-		sscanf(p,"%d",&no_mod_all_args);
+		sscanf(p,"o%d",&no_mod_all_args);
 		if G_UNLIKELY (no_mod_all_args == -1) return NULL;
 
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (p == NULL) return NULL;
-		sscanf(p,"%d",&local_all);
+		sscanf(p,"l%d",&local_all);
 		if G_UNLIKELY (local_all == -1) return NULL;
 
 		p = strtok_r (NULL,";", ptrptr);
 		if G_UNLIKELY (p == NULL) return NULL;
+		sscanf(p,"e%d",&never_on_subst_list);
+		if G_UNLIKELY (never_on_subst_list == -1) return NULL;
+
+		p = strtok_r (NULL,";", ptrptr);
+		if G_UNLIKELY (p == NULL) return NULL;
+		sscanf(p,"b%d",&built_subst_dict);
+		if G_UNLIKELY (built_subst_dict == -1) return NULL;
+
+		p = strtok_r (NULL,";", ptrptr);
+		if G_UNLIKELY (p == NULL) return NULL;
 		local_idents = NULL;
 		if (strcmp (p, "-") != 0) {
 			char **s;
@@ -386,6 +412,18 @@ gel_decompile_node(char **ptrptr)
 			g_strfreev (s);
 		}
 
+		p = strtok_r (NULL,";", ptrptr);
+		if G_UNLIKELY (p == NULL) return NULL;
+		subst_dict = NULL;
+		if (strcmp (p, "-") != 0) {
+			char **s;
+			s = g_strsplit (p, ",", -1);
+			for (i = 0; s[i] != NULL; i++) {
+				subst_dict = g_slist_append (subst_dict, d_intern (s[i]));
+			}
+			g_strfreev (s);
+		}
+
 		oli = NULL;
 		for(i=0;i<nargs;i++) {
 			p = strtok_r (NULL,";", ptrptr);
@@ -412,7 +450,10 @@ gel_decompile_node(char **ptrptr)
 		func->propagate_mod = propagate_mod ? 1 : 0;
 		func->no_mod_all_args = no_mod_all_args ? 1 : 0;
 		func->local_all = local_all ? 1 : 0;
+		func->never_on_subst_list = never_on_subst_list ? 1 : 0;
+		func->built_subst_dict = built_subst_dict ? 1 : 0;
 		func->local_idents = local_idents;
+		func->subst_dict = subst_dict;
 
 		GEL_GET_NEW_NODE(n);
 		n->type = GEL_FUNCTION_NODE;
diff --git a/src/dict.c b/src/dict.c
index a2ff62e..617a90d 100644
--- a/src/dict.c
+++ b/src/dict.c
@@ -185,6 +185,7 @@ d_copyfunc(GelEFunc *o)
 	}
 	n->named_args = g_slist_copy (o->named_args);
 	n->local_idents = g_slist_copy (o->local_idents);
+	n->subst_dict = g_slist_copy (o->subst_dict);
 
 	n->extra_dict = g_slist_copy (o->extra_dict);
 	for (li = n->extra_dict; li != NULL; li = li->next)
@@ -206,6 +207,9 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
 
 	n = g_slice_dup (GelEFunc, o);
 
+	/* never copy is_local! */
+	n->is_local = 0;
+
 	n->id = id;
 	if (o->symbolic_id == NULL)
 		n->symbolic_id = o->id;
@@ -226,6 +230,7 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
 		o->extra_dict = NULL;
 		o->named_args = NULL;
 		o->local_idents = NULL;
+		o->subst_dict = NULL;
 		o->nargs = 0;
 	} else {
 		GSList *li;
@@ -234,6 +239,7 @@ d_makerealfunc(GelEFunc *o,GelToken *id, gboolean use)
 			li->data = d_copyfunc (li->data);
 		n->named_args = g_slist_copy (o->named_args);
 		n->local_idents = g_slist_copy (o->local_idents);
+		n->subst_dict = g_slist_copy (o->subst_dict);
 	}
 
 	if (n->on_subst_list) {
@@ -268,24 +274,34 @@ d_setrealfunc(GelEFunc *n,GelEFunc *fake, gboolean use)
 			n->data.user = gel_copynode(fake->data.user);
 	}
 
+	n->never_on_subst_list = fake->never_on_subst_list;
+	n->vararg = fake->vararg;
+	n->propagate_mod = fake->propagate_mod;
+	n->no_mod_all_args = fake->no_mod_all_args;
+	n->local_all = fake->local_all;
+	/* Never copy is_local */
+	n->built_subst_dict = fake->built_subst_dict;
+
 	if(use) {
 		n->named_args = fake->named_args;
 		n->local_idents = fake->local_idents;
+		n->subst_dict = fake->subst_dict;
 		n->nargs = fake->nargs;
 		fake->named_args = NULL;
 		fake->local_idents = NULL;
 		fake->nargs = 0;
-	} else {
-		n->named_args = g_slist_copy (fake->named_args);
-		n->local_idents = g_slist_copy (fake->local_idents);
-		n->nargs = fake->nargs;
-	}
+		fake->subst_dict = NULL;
 
-	if (use) {
 		n->extra_dict = fake->extra_dict;
 		fake->extra_dict = NULL;
 	} else {
 		GSList *li;
+
+		n->named_args = g_slist_copy (fake->named_args);
+		n->local_idents = g_slist_copy (fake->local_idents);
+		n->subst_dict = g_slist_copy (fake->subst_dict);
+		n->nargs = fake->nargs;
+
 		n->extra_dict = g_slist_copy (fake->extra_dict);
 		for (li = n->extra_dict; li != NULL; li = li->next)
 			li->data = d_copyfunc (li->data);
@@ -659,6 +675,7 @@ d_freefunc (GelEFunc *n)
 
 	g_slist_free (n->named_args);
 	g_slist_free (n->local_idents);
+	g_slist_free (n->subst_dict);
 
 	g_slice_free (GelEFunc, n);
 }
@@ -692,6 +709,7 @@ d_replacefunc(GelEFunc *old,GelEFunc *_new)
 
 	g_slist_free (old->named_args);
 	g_slist_free (old->local_idents);
+	g_slist_free (old->subst_dict);
 
 	for (li = old->extra_dict; li != NULL; li = li->next) {
 		d_freefunc (li->data);
@@ -721,9 +739,18 @@ d_set_ref(GelEFunc *n,GelEFunc *ref)
 	n->type = GEL_REFERENCE_FUNC;
 	g_slist_free (n->named_args);
 	g_slist_free (n->local_idents);
+	g_slist_free (n->subst_dict);
 	n->nargs = 0;
 	n->named_args = NULL;
-	n->local_idents = NULL;
+	n->subst_dict = NULL;
+
+	n->never_on_subst_list = 0;
+	n->vararg = 0;
+	n->propagate_mod = 0;
+	n->no_mod_all_args = 0;
+	n->local_all = 0;
+	/* don't touch is_local */
+	n->built_subst_dict = 0;
 	
 	n->data.ref = ref;
 }
@@ -740,10 +767,20 @@ d_set_value(GelEFunc *n,GelETree *value)
 	n->type = GEL_VARIABLE_FUNC;
 	g_slist_free (n->named_args);
 	g_slist_free (n->local_idents);
+	g_slist_free (n->subst_dict);
 	n->nargs = 0;
 	n->named_args = NULL;
 	n->local_idents = NULL;
-	
+	n->subst_dict = NULL;
+
+	n->never_on_subst_list = 0;
+	n->vararg = 0;
+	n->propagate_mod = 0;
+	n->no_mod_all_args = 0;
+	n->local_all = 0;
+	/* don't touch is_local */
+	n->built_subst_dict = 0;
+
 	n->data.user = value;
 }
 
@@ -776,7 +813,8 @@ d_popcontext (void)
 		GelContextFrame *of;
 
 		if (context.top != 0) {
-			for (li = subst; li != NULL; li = li->next) {
+			li = subst;
+			while (li != NULL) {
 				GelEFunc *func = li->data;
 				if (context.top == 1)
 					func->on_subst_list = 0;
@@ -799,9 +837,24 @@ d_popcontext (void)
 					if (func->context >= context.top)
 						func->context = context.top - 1;
 
+					/* If subst_dict goes to NULL, we no
+					 * longer need to keep this around on
+					 * the subst_lists */
+					if (func->subst_dict == NULL) {
+						if (substlast != NULL) {
+							substlast = g_slist_remove_link (substlast, li);
+							li = substlast->next;
+						} else {
+							subst = g_slist_remove_link (subst, subst);
+							li = subst;
+						}
+						continue;
+					}
+
 				}
 
 				substlast = li;
+				li = li->next;
 			}
 		}
 
diff --git a/src/eval.c b/src/eval.c
index aca3f90..22f7711 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1306,6 +1306,8 @@ get_func_call_node(GelEFunc *func, GelETree **args, int nargs)
 	GEL_GET_NEW_NODE(l);
 	l->type = GEL_FUNCTION_NODE;
 	l->func.func = d_copyfunc(func);
+	/* never copy is_local */
+	l->func.func->is_local = 0;
 	l->any.next = NULL;
 
 	GEL_GET_NEW_NODE(ret);
@@ -2600,6 +2602,8 @@ make_funccall (GelEFunc *a)
 	GEL_GET_NEW_NODE (nn);
 	nn->type = GEL_FUNCTION_NODE;
 	nn->func.func = d_copyfunc (a);
+	/* never copy is_local */
+	nn->func.func->is_local = 0;
 	if ( ! nn->func.func->on_subst_list)
 		nn->func.func->context = -1;
 
@@ -2798,6 +2802,8 @@ gel_function_from_function (GelEFunc *func, GelETree *l)
 	GEL_GET_NEW_NODE (n);
 	n->type = GEL_FUNCTION_NODE;
 	n->func.func = d_copyfunc (func);
+	/* never copy is_local */
+	n->func.func->is_local = 0;
 	if ( ! n->func.func->on_subst_list)
 		n->func.func->context = -1;
 
@@ -3310,17 +3316,11 @@ iter_do_var(GelCtx *ctx, GelETree *n, GelEFunc *f)
 
 		n->type = GEL_FUNCTION_NODE;
 		/* FIXME: are we ok with passing the token as well? */
-		n->func.func = d_makeufunc (f->id /* FIXME: does this need to be NULL */,
-					    gel_copynode (f->data.user),
-					    g_slist_copy (f->named_args),
-					    f->nargs,
-					    f->extra_dict);
-		n->func.func->context = -1;
-		n->func.func->vararg = f->vararg;
-		if ( ! f->never_on_subst_list &&
-		    f->on_subst_list &&
-		    d_curcontext () != 0)
-			d_put_on_subst_list (n->func.func);
+		n->func.func = d_copyfunc (f);
+		/* The function can no longer be local */
+		n->func.func->is_local = 0;
+		if ( ! f->on_subst_list)
+			n->func.func->context = -1;
 	} else if(f->type == GEL_BUILTIN_FUNC) {
 		GelETree *ret;
 		gboolean exception = FALSE;
@@ -3332,7 +3332,6 @@ iter_do_var(GelCtx *ctx, GelETree *n, GelEFunc *f)
 			n->func.func = d_makerealfunc(f,f->id,FALSE);
 			if ( ! n->func.func->on_subst_list)
 				n->func.func->context = -1;
-			n->func.func->vararg = f->vararg;
 			/* FIXME: no need for extra_dict right? */
 			return TRUE;
 		}
@@ -4549,30 +4548,20 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
 
 		d_addcontext (f);
 
-		EDEBUG("     USER FUNC CONTEXT PUSHED TO ADD EXTRA DICT");
-
-		/* add extra dictionary stuff */
-		for (li = f->extra_dict; li != NULL; li = li->next) {
-			GelEFunc *func = d_copyfunc (li->data);
-			func->context = d_curcontext ();
-			d_addfunc (func);
-		}
-
-		EDEBUG("     USER FUNC EXTRA DICT ADDED, TO PUSH ARGS ON CONTEXT STACK");
+		EDEBUG("     USER FUNC TO ADD ARGS TO DICT");
 
-		/*push arguments on context stack*/
+		/*add arguments to dictionary*/
 		li = f->named_args;
 		for(ali = n->op.args->any.next;
 		    ali != NULL;
 		    ali = ali->any.next) {
-			GelEFunc *vf;
 			if (li->next == NULL) {
 				last_arg = li->data;
 				if (f->vararg)
 					break;
 			}
 			if (ali->type == GEL_FUNCTION_NODE) {
-				vf = d_addfunc(d_makerealfunc(ali->func.func,li->data,FALSE));
+				d_addfunc(d_makerealfunc(ali->func.func,li->data,FALSE));
 			} else if(ali->type == GEL_OPERATOR_NODE &&
 				  ali->op.oper == GEL_E_REFERENCE) {
 				GelETree *t = ali->op.args;
@@ -4582,12 +4571,10 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
 					gel_errorout (_("Referencing an undefined variable %s!"), t->id.id->token);
 					goto funccall_done_ok;
 				}
-				vf = d_addfunc(d_makereffunc(li->data,rf));
+				d_addfunc(d_makereffunc(li->data,rf));
 			} else {
-				vf = d_addfunc(d_makevfunc(li->data,gel_copynode(ali)));
+				d_addfunc(d_makevfunc(li->data,gel_copynode(ali)));
 			}
-			if (f->local_all)
-				vf->is_local = 1;
 			li = li->next;
 			if (li == NULL)
 				break;
@@ -4596,7 +4583,6 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
 		EDEBUG("     USER FUNC ABOUT TO HANDLE VARARG");
 
 		if (f->vararg) {
-			GelEFunc *vf;
 			if (last_arg == NULL) {
 				li = g_slist_last (f->named_args);
 				g_assert (li != NULL);
@@ -4604,7 +4590,7 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
 			}
 			/* no extra argument */
 			if (n->op.nargs == f->nargs) {
-				vf = d_addfunc (d_makevfunc (last_arg, gel_makenum_null ()));
+				d_addfunc (d_makevfunc (last_arg, gel_makenum_null ()));
 			} else {
 				GelETree *nn;
 				GelMatrix *m;
@@ -4624,12 +4610,20 @@ iter_funccallop(GelCtx *ctx, GelETree *n, gboolean *repushed)
 				nn->mat.quoted = FALSE;
 				nn->mat.matrix = gel_matrixw_new_with_matrix (m);
 
-				vf = d_addfunc (d_makevfunc (last_arg, nn));
+				d_addfunc (d_makevfunc (last_arg, nn));
 			}
-			if (f->local_all)
-				vf->is_local = 1;
 		}
 
+		EDEBUG("     USER FUNC CONTEXT PUSHED TO ADD EXTRA DICT");
+
+		/* add extra dictionary stuff */
+		for (li = f->extra_dict; li != NULL; li = li->next) {
+			GelEFunc *func = d_copyfunc (li->data);
+			func->context = d_curcontext ();
+			d_addfunc (func);
+		}
+
+
 		EDEBUG("     CREATING LOCAL VARS");
 
 		for (li = f->local_idents;
@@ -6759,6 +6753,7 @@ build_extradict (GSList *funclist, GSList *toklist)
 		GelEFunc *func = d_lookup_global (id);
 		if G_LIKELY (func != NULL) {
 			GelEFunc *f = d_copyfunc (func);
+			/* note that local stays local! */
 			if ( ! f->on_subst_list)
 				f->context = -1;
 			funclist = g_slist_prepend (funclist, f);
diff --git a/src/funclib.c b/src/funclib.c
index c920727..45098c4 100644
--- a/src/funclib.c
+++ b/src/funclib.c
@@ -5679,18 +5679,26 @@ end_of_simpson:
 static GelETree *
 Parse_op (GelCtx *ctx, GelETree * * a, gboolean *exception)
 {
+	GelETree *r;
+
 	if (a[0]->type == GEL_NULL_NODE)
 		return gel_makenum_null ();
 
 	if G_UNLIKELY ( ! check_argument_string (a, 0, "Parse"))
 		return NULL;
 
-	return gel_parseexp (a[0]->str.str,
-			     NULL /* infile */,
-			     FALSE /* exec_commands */,
-			     FALSE /* testparse */,
-			     NULL /* finished */,
-			     NULL /* dirprefix */);
+	r = gel_parseexp (a[0]->str.str,
+			  NULL /* infile */,
+			  FALSE /* exec_commands */,
+			  FALSE /* testparse */,
+			  NULL /* finished */,
+			  NULL /* dirprefix */);
+
+	/* Have to reset the error here, else we may die */
+	gel_error_num = GEL_NO_ERROR;
+	gel_got_eof = FALSE;
+
+	return r;
 }
 
 static GelETree *
@@ -5711,6 +5719,14 @@ Evaluate_op (GelCtx *ctx, GelETree * * a, gboolean *exception)
 			   NULL /* finished */,
 			   NULL /* dirprefix */);
 
+	/* Have to reset the error here, else we may die */
+	gel_error_num = GEL_NO_ERROR;
+	gel_got_eof = FALSE;
+
+	if (et == NULL)
+		return NULL;
+
+
 	return gel_eval_etree (ctx, et);
 }
 
diff --git a/src/geniustests.txt b/src/geniustests.txt
index 3b420c6..167838b 100644
--- a/src/geniustests.txt
+++ b/src/geniustests.txt
@@ -689,7 +689,10 @@ false == 0							true
 |cos(pi+0.1i) +1| < 0.1						true
 |sin(pi+0.1i)| < 0.11						true
 NDerivative(`(x)=x^2,1)						2.0
+Derivative(`(x)=x^2,1)						2
 NDerivative(`(x)=x^2,10)					20.0
+Derivative(`(x)=x^2,10)						20
+Derivative(`(x)=float(x)^2,10)					20.0
 function f(x) = x^2 ; NDerivative(f,10)				20.0
 function _f(x) = x^2 ; NDerivative(_f,10)			20.0
 function f(x) = x^2 ; IsDifferentiable(f,10)			true
@@ -944,6 +947,28 @@ a=7;(function f(x)=(b=9));f(8);UndefineAll();UserVariables()+0	((null)+0)
 parameter FloatPrecision = 888					(parameter FloatPrecision = 888)
 parameter foo = 888						888
 y=9;(function g(x)[y]=(y+1));y=0;g(0)				10
+a=9;function f(x)[a]=(local *;x+a)				(`(x)=(local *;a=9;(x+a)))
+a=9;function f(x)[a]=(local x;x+a)				(`(x)=(local x;a=9;(x+a)))
+a=9;function f(x)[a]=(local x,h,g;x+a)				(`(x)=(local x,h,g;a=9;(x+a)))
+function f(x)=(local x,h,g;x+a)					(`(x)=(local x,h,g;(x+a)))
+function f(x)=(local *;x+a)					(`(x)=(local *;(x+a)))
+Parse("local *")						Parse("local *")
+Evaluate("local *")						Evaluate("local *")
+Parse("local *;x")						Parse("local *;x")
+Evaluate("local *;x")						Evaluate("local *;x")
+NumericalIntegral(`(x)=x^3,0,1)					0.25
+NumericalIntegral(`(x)=x^3,-1,1)+1				1.0
+NumericalLimitAtInfinity (atan,`(n)=2^n,10^(-20),10,10000)	1.57079632679
+LeftLimit (UnitStep,0)						0
+RightLimit (UnitStep,0)						1
+UnitStep(-1)							0
+UnitStep(1)							1
+Limit(UnitStep,0)+1						((null)+1)
+Limit(UnitStep,1)						1
+Limit(UnitStep,-1)						0
+Limit (cos,pi)							-1.0
+round(100*InfiniteSum(`(n)=2^(-n),1,1))				100
+func=1;start=2;inc=3;round(100*InfiniteSum(`(n)=inc-func-start+2^(-n),1,1))	100
 load "nullspacetest.gel"					true
 load "longtest.gel"						true
 load "testprec.gel"						true
diff --git a/src/graphing.c b/src/graphing.c
index 9b41b9f..8bc3318 100644
--- a/src/graphing.c
+++ b/src/graphing.c
@@ -4278,6 +4278,10 @@ function_from_expression (const char *e, const char *var, gboolean *ex)
 			      NULL /* dirprefix */);
 	g_free (ce);
 
+	/* Have to reset the error here, else we may die */
+	gel_error_num = GEL_NO_ERROR;
+	gel_got_eof = FALSE;
+
 	/* FIXME: if "x" (var) not used try to evaluate and if it returns a function use that */
 
 	if (value != NULL) {
@@ -4329,6 +4333,10 @@ function_from_expression2 (const char *e, gboolean *ex)
 			      NULL /* dirprefix */);
 	g_free (ce);
 
+	/* Have to reset the error here, else we may die */
+	gel_error_num = GEL_NO_ERROR;
+	gel_got_eof = FALSE;
+
 	/* FIXME: funcbody?  I think it must be done. */
 	got_x = gel_eval_find_identifier (value, d_intern ("x"), TRUE /*funcbody*/);
 	got_y = gel_eval_find_identifier (value, d_intern ("y"), TRUE /*funcbody*/);
diff --git a/src/structs.h b/src/structs.h
index fee271d..a41dbde 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -138,6 +138,8 @@ struct _GelEFunc {
 
 	/* did we already build the subst_list */
 	guint32 built_subst_dict:1;
+
+	/* NOTE: Make sure! to update d_setrealfunc and others */
 };
 
 typedef enum {
diff --git a/src/symbolic.c b/src/symbolic.c
index bcc5492..8903f3c 100644
--- a/src/symbolic.c
+++ b/src/symbolic.c
@@ -64,6 +64,7 @@ static GelEFunc *
 hack_parse_function (const char *expr)
 {
 	GelEFunc *f;
+	/* FIXME: parseexp could set gel_error_num! */
 	f = d_makeufunc (NULL /* id */,
 			 gel_parseexp(expr,
 				      NULL, FALSE, FALSE,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]