|
From: | Juergen Sauermann |
Subject: | Re: [Bug-apl] Request for feature: Back-channel interaction |
Date: | Thu, 02 Jan 2014 14:45:31 +0100 |
User-agent: | Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20130330 Thunderbird/17.0.5 |
Hello Elias,
1. Lets say your function is EE and you call it with a function number as axis argument like you did. (I believe this is a good convention). Then A EE[x] B in APL calls eval_AXB() in the shared library, EE[x] B in APL calls eval_XB() in the shared library, and so on. There are 12 such eval functions in total, but the native user defined APL operators require a very deep understanding of the GNU APL internals (if user-defiined functions are passed as operator arguments). So assume only eval_AXB() and eval_XB() are used. The arguments (A, X, and B for eval AXB() and X, and B for eval_XB are of type Value_P which are smart pointers to class Value. Don't touch (delete etc.) them but rather use them like const Value *. So you can use all const and static functions defined in Value.hh. The first thing is to check the incoming values, you can use is_empty(), is_skalar() and friends in Value.hh. get_shape() returns the shape of the values and so on. If something is wrong you can RANK_ERROR, LENGTH_ERROR, ... which are macros that terminate execution of the function and return the according APL error to the interpreter. At some point you want to access the ravel of the value with get_ravel(n) which is (,B)[n - ⎕IO]. We are in C++ so indexes start with 0. get_ravel() returns a Cell which is either an integer, a float, a complex number, a character, or another (nested) APL value. The different Cell types are derived from the same base class Cell (see cell.hh) that also has access functions to them (get_int_val(), get_real_val(), ...) If your function has one or two arguments then use eval_XB() or eval_AXB(). If it has more then you can use nested APL values, see fprintf() in file_io (to be committed). Next you do something specific to your functions and then create a result of class Token. This generally goes in 5 steps: a. create the shape for the result Value b. Value_P Z(shape, LOC); // create a value with proper shape but undefined ravel. c. set up ravel elements with placement new on either &Z->get_ravel() if the ravel is initialised in random order, or, more likely, with Z->next_ravel() and Z->done() if the ravel is initialised in sequence. For example, new (Z->next_ravel()) IntCell(42) sets the next ravel element to integer 42. d. call Z->check_value() unless you are sure that all elements of the ravel are initialised (you are not sure!). e. return Token(TOK_APL_VALUE1, Z); For common cases (skalars, vectors, strings) there are constructors in Value.hh that combine steps a and b, like: b1. Value_P Z(new Value(UCS_string, LOC)); The #include files in native/template.hh are the ones containing the above functions. It is essential that the Value_P object is created like described; don't take shortcuts on that! They would break the new smart pointer-based memory scheme. Note that your eval_XX() functions are now essentially new primitive APL functions. You can therefore look for existing primitive APL functions in PrimitiveFunctions.cc to see the typical design pattern for such functions. 2. Generally speaking you can start a thread in your native function and that thread can then access all data in the APL interpreter. None of the data structures in the interpreter is meant to be used by another tread so it could happen that they disappear without your thread noticing that. It can also happen that one of the functions you call throws an exception and returns without your lock being released (and then dead-locking the interpreter). Not good. What I would propose instead is a simple variable set by the interpreter that tells if the interpreter expects input (and is then guaranteed to not change its data structures until new input is received. Since you control the input in emacs mode, when you see the variable set and send no data to the interpreter then you are safe. 3. Yes. I believe you need to sign a few papers (see chapter 6 of http://www.gnu.org/prep/maintain/maintain.html) then. 4. right now the .so files are installed in a subdirectory apl of /usr/local/lib or /usr/lib. This is under the control of autoconf/automake and I believe the path to the parent directory of that subdirectory apl is known by the dynamic linker by some magic that I do not fully understand. I have also tried to not install the .a and .la files, but have not succeeded yet. Maybe a relative apl/ee,so works with ⎕FX - havent tried yet. If you have ideas - please let me know. Best Regards and a happy new year, Jürgen Sauermann On 01/02/2014 11:47 AM, Elias Mårtenson wrote:
|
[Prev in Thread] | Current Thread | [Next in Thread] |