Guile Mailing List Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Guile Plug-In for Gnumeric
Hi, Mark.
Mark Probst <schani@unix.cslab.tuwien.ac.at> writes:
> one of the highlights of the plug-in is that it is able to operate
> not only on the values residing in the cells but also on the
> expressions. as examples of what is possible i have written a
> little expression simplifier (constant folding and simplification of
> things like x*1, a+0) and a symbolic differentiator. they are not
> neatly integrated with Gnumeric yet, however.
When I worked on a scheme spreadsheet I called these the raw and
cooked values, respectively. It sounds like you want to make each
cell visible from scheme, where the cell gives the programmer access
to the raw and cooked values.
> the plug-in exports two functions to Gnumeric: scm_eval and scm_apply.
> both do pretty much the obious. e.g.:
>
> =scm_eval("(+ 1 1)")
> =scm_apply("(lambda (a b) (if (> a b) a b))",1,2)
>
> one can of course write new Gnumeric functions in Scheme. examples
> can be found in plugins/guile/gnumeric_startup.scm.
Cool.
> my main concern is currently (apart from the trivial tasks) a smob
> wrapper for Gnumeric's ExprTrees (ExprTree is the data structure
> Gnumeric uses for internally storing expressions). the problems are:
>
> * ExprTrees are reference counted. Can be solved by increasing the
> refcount if an ExprTree is smobified. In order to avoid increasing
> the refcount more than once, a list of all smobified ExprTrees
> would need to be kept.
When you have a C data structure whose lifetime is determined in C,
(Xt Widgets are a good example), there are strategies you can use. I
have adapted some code I have to your example:
static struct {
long cell_type_tag;
} g;
typedef struct _Cell {
ExprTree expr_tree; /* raw value */
generic_ss_val val; /* cooked value */
int obj_init_p; /* obj has been initalized? */
SCM obj; /* scheme representation of this object */
} Cell;
static int
cell_p(SCM obj)
{
return(SCM_NIMP(obj) && SCM_CAR(obj) == g.cell_type_tag);
}
static Cell*
cell_unbox(SCM obj)
{
return((Cell*)SCM_CDR(obj));
}
static SCM
cell_box(Cell *cell)
{
if (!cell->obj_init_p) {
SCM_DEFER_INTS;
SCM_NEWCELL(cell->obj);
SCM_SETCAR(cell->obj, g.cell_type_tag);
SCM_SETCDR(cell->obj, (SCM)cell); /* put address of self in cdr */
SCM_ALLOW_INTS;
cell->obj_init_p++;
cell_increase_refcount(cell);
}
return cell->obj;
}
static scm_sizet
cell_sweep(SCM obj)
{
cell->obj_init_p = 0;
cell->obj = SCM_UNDEFINED;
cell_decrease_refcount(cell); /* this will only happen when the scheme */
/* object's lifetime ends */
}
> * ExprTrees are recursive. This means that if the user traverses the
> whole ExprTree from out of Guile, a smob for every node would need
> to be created. Is this ok?
My code above shows how to keep the consing to a minimum for this.
Only when a particular cell is exported to scheme is the cost of
preparing a scheme representation incurred. If the same cell is
exported to scheme twice, the scheme representation is reused.
> * CellRefs can be (and usually are) relative. This means that in
> order to evaluate an ExprTree its cell must be known in order to
> resolve the relative CellRefs. Thus, most functions dealing with
> ExprTrees would need to be passed the original CellRef. Another
> possibility would be to store the CellRef in the smob. Yet another
> solution would be to have a 'current CellRef' variable. Somehow,
> none of these solutions appeal to me. Suggestions, anyone?
Does my code above provide a potential solution? I think it does,
unless I don't quite understand your question.
I hope the above helps,
-russ
--
October. This is one of the peculiarly dangerous months to invest
in stocks. The others are July, January, September, April, November,
May, March, June, December, August, and February.
-- Mark Twain
Guile Home |
Main Index |
Thread Index