|
From: sfeam <eam...@gm...> - 2018-03-07 18:40:00
|
On Wednesday, 07 March 2018 19:40:58 Nikita Zlobin via gnuplot-info wrote: > Hello. > I'm writing gnuplot plugin, which allowes gnuplot to guide qalculate. > https://github.com/nick87720z/gnuplot-qalc-plugin > > I have question about some mean of variadic function arguments or as > alternative - generating of gnuplot functions by plugin with arbitrary > name/args. And second - about plugin finalization by gnuplot_fini(). > > However, i have trouble due to lack of any mean to have variadic > arguments - neither by itself, not by array argument. I is not problem, > to return value with type DATABLOCK. But if i try to use array of > values - i get "unsupported array operation" error in both when i > create "array arr = [.......]" and try to run some function with it, or > when for experiment i tried to return ARRAY, filling it for test with > INTGR values. Gnuplot's array data type is relatively new. The only operations currently implemented that take an array argument are the cardinality operator |Array| and the evaluate-an-element operator Array[element]. Rather than teach every piece of the evaluation code about arrays, the current implementation simply refuses to pass an array argument to other operations. This restriction could be relaxed if there is a coherent plan to guide how arrays are handled (see below). It is a good idea to use arrays to pass variadic arguments. I can see how that would be useful for plugin functions even though gnuplot's own code does not need the mechanism. The tricky part is that the internal implementation of expression evaluation uses pass-by-value rather than pass-by-reference. This is impractical for arrays (see long comment in eval.c about ARRAY_COPY_ON_REFERENCE). This limitation means there must be strict limitations on when or if the content of the array may be altered by a function. > Why i search for variadic arguments: in my plugin are functions - to > load function via text formula (takes name and expression str > arguments), delete (by name), list (using fictive argument, as gnuplot > doesn't allow to create functions with void arguments) and execute > functions... this is what i'm about. > > Exec function actually takes two parameters: > - name_or_id (accepts both > string and position in list, which should be got for that) > - numeric argument. If I understand your proposal, for your purpose it might be possible to treat the array contents as immutable. Is that correct? I am not sure how best to enforce that in the code. > For now, due to disluck, it supports only single arguments. Even > without variadic arguments - would be enough to have ability to > just generate gnuplot function - so, that if i run (for example): > gnuplot> qalc_hyperbola = qalc_ufunc_new('qalc_hyperbola', '1/x') > ...it could be called by just (lvalue has only name, without (x,y,etc)). > gnuplot> print qalc_hyperbola(4.5) # or > gnuplot> plot qalc_hyperbola(x) I do not fully understand this part of your description. > And another question: example plugin declares gnuplot_init() and > gnuplot_fini(), but doesn't define. I copied declaration without change > and defined both, but only gnuplot_init() is called automatically. I think those two definitions were included only as examples of how you might declare a plugin function prototype. As you say, the example code does not actually use them. > [snip] Gnuplot's built-in operations do not know what to do with an array argument, but if you want to experiment with passing a single array as a variable argument to your plugin it might be sufficient to change the int_error call in f_call() to int_warn. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/src/internal.c b/src/internal.c index b77ce4d..8eebc03 100644 --- a/src/internal.c +++ b/src/internal.c @@ -166,7 +166,7 @@ f_call(union argument *x) (void) pop(&(udf->dummy_values[0])); if (udf->dummy_values[0].type == ARRAY) - int_error(NO_CARET, "f_call: unsupported array operation"); + int_warn(NO_CARET, "f_call: unsupported array operation"); if (udf->dummy_num != 1) int_error(NO_CARET, "function %s requires %d variables", udf->udf_name, udf->dummy_num); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Or maybe not. I will experiment a bit. cheers, Ethan |