On Sat, 14 Oct 2017, Allin Cottrell wrote:
genparse.h is where you insert a unique internal identifier for the
function
(e.g. F_NUMHESS), putting it into the functions "enum" in the right place.
Scanning the existing enum one should get an idea of what "the right place"
means. Basically: how many arguments does the new function take? -- other
than that it doesn't much matter where it goes.
The rule that Allin and I tend to follow is: if the new function "belongs
together" an existing one, put it near it; otherwise, stick it to the end
of the group it belongs to (1-arg, 2-arg, etc)
genlex.c is where you create a mapping from the function's
internal
identifier (e.g. F_NUMHESS) to the name under which users can call it (e.g.
"numhess"). Plenty of examples available there. The exact position of the new
entry doesn't matter.
See above.
geneval.c is where you actually "hook up" the hansl
function to its C
back-end. A hansl-function must have an entry in the function named "eval".
A word of caution. The "eval" function is quite large. It's several
hundreds lines of code, and it's basically a huge "switch" statements
which decides what has to be done for every hansl function (and more:
that, for example, where you handle all operators, like '+', '~', slicing
etc). Besides, it's very recursive (that is, it calls itself in various
places); so handle with care.
Another potentially confusing feature of the "eval" function is that it
operates on pointers on structures called "NODE"s and "parser"s.
Roughly
speaking, a NODE is an element of an "evaluation tree", which is what you
go through for producing the actual result (see for example
https://en.wikipedia.org/wiki/Binary_expression_tree#Algebraic_expressions).
A "parser", instead, is an auxiliary structure used for storing the
context in which the expression has to be evaluated: for example, the
actual hansl expression that was has to be processed, or the information
on the currently open dataset (which is something you need for thing like
$nobs etc).
So, again, handle with care :)
This entry should (usually) do some basic type-checking on the
arguments
provided by the user, then hand off to an implementer function. The best way
to grok this is to follow the path of execution for a hansl function that
you're familiar with. Ideally you want to find an existing function that is
as similar as possible to your new one, in terms of (a) what it returns, and
(b) the type of arguments it expects.
Absolutely. In order to get familiar with this, start with a function that
is close to what you need, and proceed by imitation. If, for example, you
wanted to write a function called "mymat()", which takes 2 scalars as
arguments and returns a matrix, your best course of action would be
looking at existing functions that have an analogous structure, such as
zeros() or ones().
One more word on this: practically all our matrix calculations depend on
functions that live in gretl_matrix.c and friends. Those functions work on
structures of the type "gretl_matrix", which is NOT a simple double array
of numbers (it's a structure with extra info, such as the matrix shape and
more). So, if you want to work with matrices, you'd better get acquainted
with that too. :-)
I hope this wasn't too off-putting!
-------------------------------------------------------
Riccardo (Jack) Lucchetti
Dipartimento di Scienze Economiche e Sociali (DiSES)
Università Politecnica delle Marche
(formerly known as Università di Ancona)
r.lucchetti(a)univpm.it
http://www2.econ.univpm.it/servizi/hpp/lucchetti
-------------------------------------------------------