Jonathan Thornburg <jt...@ae...> writes:
> On Thu, 2 Jun 2005, Ethan Merritt wrote:
>
>> On Wednesday 25 May 2005 05:03 am, Lars Hecking wrote:
>>>
>>> may I ask to advance the #define'd compile-time parameter
>>> MAX_NUM_VAR
>>> in src/syscfg.h from 5 to something like 20 or so? :-)
>>
>> The arrays that use MAX_NUM_VAR are horribly wasteful,
>> particularly if we bump it up to a larger number.
>> e.g.: char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1];
>> would be reserving 20*50 chars of storage to hold what
>> is usually 2-3 instances of single-characters names like
>> "u", "v" or "w".
>>
>> How about changing these arrays to hold dynamically
>> allocated pointers instead. [[...]]
This reminds me of some work I had planned long ago (when I had time
to help out on gnuplot). A couple of thoughts...
- how are string literals in expressions represented ? When I was
deliberating over this area, I was tending towards having the notion
of a string pool associated with an exression. The pool would
survive for as long as the expression did, and if that meant the
expression was stored in a user-defined fn, then the string pool
would persist.
If that approach was used, then the names of the dummy variables
could be stored in that string pool.
- the other aspect of MAX_NUM_VAR is to actually have space for the
values during (recursive) expression parsing. My recollection is
that gnuplot used to have a fixed area for the parameter values, and
when recursing into a udf, would copy the old values into temporary
space, and put the new values into the globals. I don't know if this
is still how it works. But a much more elegant solution would be to
use an evaluation stack. (I work on java vm's these days, so it's
obvious where this idea comes from...)
Basically, there is one block of memory for estack. Each function
has a frame on the stack. When a fn is invoked, the frame of a
function overlaps the estack of the previous one.
eg
g(x,y,z)=x+y+z
f(x,y,z)=6 + g(x+2, y+3, 42)
gnuplot> show at f(10,11,12)
pushc 10
pushc 11
pushc 12
pushc 3
calln f
pushc 6
pushd1 f dummy
pushc 2
plus
pushd2 dummy
pushc 3
plus
pushc 42
pushc 3
calln g
pushd1 g dummy
pushd2 dummy
plus
pushc 2
pushd
plus
plus
consider estack growing from left to right.
push parameters
10 11 12
invoke f : I assume the 3 is a parameter count (ie linkage). This
becomes the start of the frame for f, with the parameter values still
on the bit of the stack belonging to the caller. (Or we could consider
this bit of the estack to be shared)
10 11 12 | 3 |
start interpreting f. The pushd1 (push dummy 1) reaches down in the
estack to retrieve the parameter values from the top of the estack of
the caller.
10 11 12 | 3 | 6 10 2
plus
10 11 12 | 3 | 6 12
so on until we invoke g
10 11 12 | 3 | 6 12 14 42 | 3 |
etc.
When a function exits, we merely take the value on top of the estack,
remove the linkage, and push the value back on top of the estack. so
the net effect is to pop the parameters and push the result.
dd
--
Dave Denholm <dde...@es...> http://www.esmertec.com
|