Karim BELABAS on Tue, 2 Jul 2002 02:07:19 +0200 (MEST) |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: Bug in parsing of local() |
On Mon, 1 Jul 2002, Ilya Zakharevich wrote: > ? ff(x)=local(y=x);x=177;print(y) > ? ff(12) > 12 > ? gg(x)=local(y=x);x='x;x=177;print(y) > ? gg(12) > 177 > > I think the answers should be the same... The problem may be due to > the following difference in the assignment of variables and > parameters: > > for (i=0; i<narg; i++) copyvalue(*p++, *arg++); > for (i=0; i<nloc; i++) pushvalue(*p++, make_arg(*loc++)); > > (the difference between copy and push). And what make_arg() magic is doing > there? 1) make_arg(): parameters with default values are evaluated when the function is called [ was: when the function is defined (long time ago), see COMPAT-2.2 ] Hence default values are really formal expressions [character strings], which are evaluated to bona fide GENs by make_arg(). [ btw, make_arg() was unnecessarily complicated, I simplified it ] 2) copy: clone the value push: store the address of the value Values of arguments are cloned, values of local variables are pushed (the initial value is assumed not to vary while we evaluate the function). 3) In both cases above, I would expect SEGV (but then, I know how the thing is implemented...). Strangely enough, I couldn't produce one in a deterministic way. This is a long standing problem related to TODO entry 5 life of GP variables too short in pathological cases: v = [0,0]; v + [v=0,v=0] --> SEGV u = Mod(x*Mod(1,2), polcyclo(25)*Mod(1,2)); sum(i=1,4,u=u^32) --> SEGV I've modified the [string to GEN] routines (lisexpr and variants) so that they never return a clone: it is almost certain that this is a variable value, which may be destroyed anytime [we don't have reference couting]. The patch fixes all the bug mentioned above. I'm not 100% sure it fixes all instances of the problem. It shouldn't be detrimental to efficiency in any case, please check your GP scripts [esp. the badly written ones]... Cheers, Karim. P.S: we have a major performance problem with argument passing. It would be so much simpler if there were a way to pass variables by reference. Currently, in user functions, it's much more efficient to use global variables than to pass structs as arguments [ the latter are cloned; if they are large and the routine is used often, we're dead ]. It's been in my personal TODO list for a long time to check whether a function definition like f(&x, y) = ... would break anything. Here, x is a reference, y is a value. Modifying x in the function body would modify x in the calling frame. Modifying y would modify a copy (current behaviour). Not sure about the calling, syntax. Maybe f(x,y), or f(&x, y) to emphasize we're passing a reference. Probably the former. It would be very easy to add, would not introduce ambiguities, and would be _very_ useful. The most important use would be that it would at last be possible to write (relatively) efficient user functions without using global variables. -- Karim Belabas Tel: (+33) (0)1 69 15 57 48 Dép. de Mathematiques, Bat. 425 Fax: (+33) (0)1 69 15 60 19 Université Paris-Sud Email: Karim.Belabas@math.u-psud.fr F-91405 Orsay (France) http://www.math.u-psud.fr/~belabas/ -- PARI/GP Home Page: http://www.parigp-home.de/