Guidelines for Libraries in GNU (and other) APL(s) ================================================== ================================================== 0. Terminology ============== The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119]. 1. Libraries ============ For the purpose of this document, a library shall be code in any language (but primarily APL and C/C++) that is made available by individual developers to a larger community. This document states requirements on such libraries in order to make them useful and usable. Different requirements may be in conflict, and then the following order (in decreasing relevance) shall be applied to resolve that, but in a pragmatic way: A. User friendliness and usability B. Portability C. Clear Code structure D. Performance ... 1.1 Intended audience --------------------- Libraries are primarily written for users of GNU APL. However portability to other APL interpreters shall always be kept in mind and achieved where possible. 1.2 How Libraries may be used ----------------------------- The standard way of using a library of APL code shall be a simple single command such as: )COPY lib However, the same library could be used in differen ways as well: - published on a web page - cut-and-paste (xterm middle mouse button or ^C/^V) between windows or browsers The file format MUST support all use cases above (which rules out file formats that use non-portable encodings). 1.3 Portability --------------- We foresee 3 levels of portability for libraries that contain APL code: L1: ISO portability. This means that the APL uses only APL contructs and commands defined in the ISO standard or are present (and identical) in all major APL interpreters. L2: basic portability: This means that non-standard functions can be used in APL code but only via wrapper functions in another librariy called 'base'. Portability is achieved by only porting the 'base' library to another interpreter and then all libraries with basic portability will run on that interpreter. This more or less means that all non-standard ⎕-functions are wrapped, e.g. ⎕CR becomes base∆CR, etc. L3: GNU APL portability: These libraries can only be used with GNU APL because they heavily use extensions GNU APL or are used to implement missing functions in GNU APL. The 'base' library itself is a (relatively simple) L3 library; its port to another interpreter may be complex. Another library foreseen is a 'meta' library that contains functions related to library managements (dependencies, revision numbers, copyrights etc). 'meta' is a L2 library (and as such must not )COPY a L3 library). Generally speaking, a L1 library must not depend on a L2 or L3 library and a L2 library must not depend on a L3 library. 1.4 Library types ----------------- We expect the following kinds of code: A. pure APL libraries B. mixed APL/C/C++ (and possibly other languages). C. Code using GNU APL like the ports to Javascript In A. the focus is on APL and this will most likely be a L2 or L1 lib. In B. the APL code will be a thin wrapper level. This will be a typical L2 lib. 2. Naming Convections ===================== The library concept described in this documents uses a number of nsming conventions as follows. 2.1 Library name ---------------- The library name SHALL be short, but still long enough to be easily remembered by the user. For example: sql for the SQL interface fio for the FILE_IO functions foo for an example library used in the following. ... 2.2 APL names ------------- In APL the functions and global variables of library 'foo' shall be named foo∆function_name or foo∆variable_name. Local variables, function arguments, and return values SHALL have the usual short names without the foo∆ prefix. A second prefix foo⍙ is used for functions related to meta information. These meta functions are not used by library user but by the management of libraries as explained further down. 2.3 Library Filename -------------------- The APL code for library foo MUST be contained in a file called foo.apl. 2.4 Library Directories ----------------------- A libraries can live in one of 10 directories that are selected to a 'library reference number' from 1-9, and a missing library number means 0. The library reference number is an optional argument of the )LOAD, )COPY and )SAVE commands like: )COPY 4 foo We propose that the first 3 library reference numbers, i.e 0-2, SHALL be left for the user (to organize them in a user/group/all fashion) and that the next 3 library numbers, i.e. 3, 4, and 5 resp, SHALL be used for L1, L2, and L3 libraries. The default directory naming in GNU APL follows IBM APL2 so that the directories 0-2 are named 'workspaces', 'wslib1', and 'wslib2'. This scheme is extended until 'wslib9'. Therefore the L1, L2, and L3 libraries shall live in directories 'wslib3', 'wslib4', and 'wslib5', 2.5 Library initialization -------------------------- The ')COPY 4 foo' command shall load all components of the library and perform the necessay initialization. It SHALL also perform dependency checking as needed, so that the user can use the functions installed by the library without any additional actions. The )COPY command can handle .apl files (i.e. other libraries) resursively. Therefore a library MUST load all libraries that it depends on. 2.6 Double Inclusion -------------------- The library shall normally be stateless, so that loading the same library twice is possible. 2,7 Library Components ---------------------- A library consists of 1, 2, or 3 components of different types: C1: APL code with the API towards the user C2: Native function implementation (C/C++) C3. Support function in GNU APL to be used by C2. L1 and L2 libraries have only a C1 component. L3 library typically have C1 with the API for the user, C2 for the function of the library itself, and C3 for function in the interpreter for creating and decoding APL values and other things. 2.7.1 C3 Components ------------------- C3 components are maintained the the GNU APL project itself. Access to the functions in C3 is provided via a header file. A C2 library (i.e. a native function uses dynamic linking via dlopen() to link with the C3 functions. V2.7.2 C2 Components -------------------- A C2 component is a dynamic library (typically an .so file) The name of that .so file is independent from the library name because different platforms have different naming conventions for their files. There are two sub-types of C2 components: A. In-tree components: The source code of these components lives in a subdirectory the the GNU APL 'src' directory. The component is compiled asnd installed together with GNU APL itself, taling into account the results of ./configure, in particular the $pkglibdir and $sysconfdir. In-tree components have a number of advantages: they are installed automatically, interface changes against the APL interpreter are immediately detected, They have disadvantages as well: the build-time increases, chances that a build fails increases, Also the maintenance of such components does not scale. B. Out-of-tree components Out-of-tree components can be compiled independent of the GNU APL sources and have to be installed separately. All that is needed from GNU APL is the header file that declares the functions in the interpreter that can be used by the component. V2.7.2 C1 Components -------------------- C1 components contain APL code relevant the user. 4. Coding Conventions ===================== 4.1 C1 library components are intended be )COPYd at the begining of the user code. 4.2 The 'base' and 'meta' libraries SHALL )SIC so that subsequent creation of functions is guaranteed to succeed. 4.3 A library must not (permanently) change the default values of system variables and must not create global objects with names other than foo∆... (more to come...) 5. The Meta library =================== The 'meta' contains helper functions that make the provisioning of meta information easier for the designers of other libraries, for example text of GPL and LGPL licenses, text formatting, etc. Meta information is provided (and required) in every library such as: - the author - license information - dependencies (provides/requires) - versioning - help information - ... The information is provided by niladic functions like: Z←foo⍙Author Z←foo⍙Author Z←foo⍙License Z←foo⍙Help The meta library contains functions that check if another library provides the required meta information. The details need to be worked out... 6. Documentation ================ The library MUST contain a file foo.README describing how to install and use the library. (more to come...) 7. File format for C1 Library Components ======================================== After having looked at different existing exchange formats, is looks like UTF8-encoded text files are the way to go of achieving the top-level requirements for C1 library components (i.e. for APL source files). Binary formats are slightly more efficient, but are lacking cut-and-past facilities. 7.1. Encoding ------------- The library shall be a text file containing only valid Unicode characters that are UTF-8 encoded. The first two characters of the text file MUST be #! for C3 components and ⍝! for C2 and C1 components 7.2. Correctness ---------------- The library shall contain correct APL code in the sense that it can be )LOADed into GNU APL without errors. APL Commands MAY be used, in particular )COPYing of other libraries. L1 library must only use commands defined in the ISO standard. Commands that MAY alter the default variables permanently (such as) LOAD) MUST NOT be used, 7.3 Representation of APL values -------------------------------- Generally speaking any sequence of APL expressions that produces a given APL value can be used in a library. For libraries originated in GNU APL, the )DUMP command or 10 ⎕CR can be used to create such expressions without side-effects. For libraries originated in other APL interpreters other functions may exist that have the desire effect of producing APL code that creates variables with a given value. 7.4 Representation of user-defined APL Functions ------------------------------------------------ There are currently 3 methods to create a user defined function in GNU APL: A. named direct functions, e.g. PLUS ← { ... } , or B. ⎕FX, e.g. ⎕FX 'Z←A PLUS B' 'Z←A + B', or C. The ∇-editor, e.g. ∇Z←A PLUS B Z←A + B ∇ Of these, A. is not portable because direct functions are non-standard. B. is difficult to read if a function gets longer, Therefore C. MUST be used for user-defined APL functions. 8. Packaging and Storing of Libraries ===================================== (more to come...)