Dirk Laurie on Fri, 15 Jun 2012 08:52:10 +0200


Re: gp_read_str

2012/6/14 Bill Allombert <Bill.Allombert@math.u-bordeaux1.fr>:

> I am still not quite clear on what you need.

The explanation in terms of Lua was mainly _why_ I need it.  _What_
I need can more easily be explained in C.  Let me try again, in terms
of the way I think Pari works.  (After I wrote this, I found that doing
so has answered my question.  But I'll still keep in this explanation
of the basics because maybe someone else is also as stupid as I am.
Since it will appear in the list archive, please correct my errors.)

Pari, by and large, is a system that works with anonymous values.
The implied variable in a polynomial has a number, not a name.
Names are the user's language, not the system's.  The same GEN
that prints now as "a+b+c" will print as "c+a+b" if way back in
my code, before the first "a" appears, I add a statement that
involves "c".  Yes, deep down there is a table that says in what
order I introduced the names, but Pari uses it only on the surface;
you could say it speaks my language only when it needs to communicate
with me.

The Pari evaluator can be thought of as a stripped-down GP without the
stuff mainly of interest to the human at the keyboard.  The way you
get a name into Pari's table of variables is to actually use that name
in an expression or as an lvalue.  No other way.  But the evaluator can
also use that name for some other value that the Pari system has calculated.
You distinguish between the two values inside a GP expression by putting
an apostrophe to say "use the original, basic meaning of this name as
a monomial with only one factor".

C is a language that works with names at compile-time.  You have to
tell it what type of value you will be associating with which name.
When working with the Pari library, one's program has lots of names whose
associated value will be of type GEN.  Sometimes, the only available
reference to some GEN is stored in a C variable; the Pari evaluator has
no name for it.  This GEN has been computed during the current run, not
read in as binary from a file, so the internal variables in it still have
the same names as when first used.  No other code has touched its contents.

But such a value is not accessible by the Pari evaluator.  One can freely
use it in the C code, e.g. when calling routines from the Pari library,
but one can't use that GEN in a GP expression â you can use only values
associated with names that GP knows.  GP has three sources of names: names
with which it was born, names that you have used in the past when calling
the evaluator, and names that have added to it using `pari_add_function`.

You absolutely may not, must not, tamper in any way with GP's names
and the GEN objects associated with them except by calling the Pari

So the only way of using the C API to teach GP a new name requires that
the name refers to a function, not a value.  (I most certainly did not
have this insight during my previous post.)

I am now in a position to understand the following suggestion. :-)

> Maybe you could add an extra function to the GP interpretor that returns
> the value of the Lua pointer:
>    gp_read_str("b=fromlua(\"b\")");

I can't do that.  Lua's C API gives you access to the value of an
object, not to its name.  (Names in Lua are extremely context-dependent;
Lua has the notion of `_ENV` which allows a switch from one set of names
to another with a single assignment statment.)

But you have given me the germ of a solution: I can shove the Lua values
into a C location before calling `gp_read_str` and use such an extra
function to retrieve them.

Basically I have to mimic what the interactive GP does when making
a reference to a GEN on the stack. (That part of GP is not available
for library use.)  Thus:

1. Lua> setarg{p,q,r}
   -- makes the C program store those GEN's in a static array PARAM.
2. The Pari evaluator will know a function `param(k)` that returns
   `PARAM[k-1]` having range-checked `k` of course.
3. Lua> f=gen"$1*($2-$3)"
   -- The "gen" function translates `$1` to `param(1)` etc before passing
   -- the string to `gp_read_str`.

I use `$`, not `%`, because `%` also means `modulo`.

> And it was completely changed between 2.3 and 2.5.

Some homework for me to do, then.