diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-05-23 20:44:09 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-05-23 20:44:09 -0400 |
| commit | d5421cb2dbc4d3b4d88493655bd102e9350fc274 (patch) | |
| tree | 4f0ded18fdd393c40e489e7dcb8a4a33695ab12e /docs | |
| parent | 871813e2df2aa50745536a0d8834875915276a67 (diff) | |
Preliminary spec for •FFI
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/spec/system.html | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/docs/spec/system.html b/docs/spec/system.html index 7469fa06..92933a1f 100644 --- a/docs/spec/system.html +++ b/docs/spec/system.html @@ -352,6 +352,7 @@ </tbody> </table> <h2 id="interface"><a class="header" href="#interface">Interface</a></h2> +<p>The function <code><span class='Function'>•SH</span></code> allows BQN to call other programs, as an operating system shell would. <code><span class='Function'>•FFI</span></code> allows it to call functions compiled by C or compatible languages—these are stored in files that traditionally have names like <code><span class='Value'>lib*.so</span></code> in Unix. In both cases the callee can run unrestricted code, so only trusted programs and functions should be called this way.</p> <table> <thead> <tr> @@ -364,9 +365,39 @@ <td><code><span class='Function'>•SH</span></code></td> <td>Execute shell command and return <code><span class='Value'>exitcode</span><span class='Ligature'>‿</span><span class='Value'>stdout</span><span class='Ligature'>‿</span><span class='Value'>stderr</span></code></td> </tr> +<tr> +<td><code><span class='Function'>•FFI</span></code></td> +<td>Load a native function from a shared object file</td> +</tr> </tbody> </table> <p>The argument to <code><span class='Function'>•SH</span></code> is a list of strings giving the command and its arguments (for example <code><span class='String'>"mv"</span><span class='Ligature'>‿</span><span class='String'>"old"</span><span class='Ligature'>‿</span><span class='String'>"new"</span></code>). The command is executed synchronously, and the result is a list of three elements: the command's exit code, text written to stdout, and text written to stderr. In both cases the text is a plain string containing all text emitted by the program. Text is interpreted as UTF-8, with an error if it's not valid UTF-8.</p> +<p>The arguments to <code><span class='Function'>•FFI</span></code> are a file path for <code><span class='Value'>𝕨</span></code> (interpreted relative to <code><span class='Value'>•path</span></code> if necessary, like <code><span class='Value'>•file</span></code> functions), and a function descriptor for <code><span class='Value'>𝕩</span></code>, which gives the function name, argument and result types, and information about how to convert these values. The format of <code><span class='Value'>𝕩</span></code> is described in the next section. The result is a BQN function that calls the specified function. This call can crash, mutate values, or invoke other unexpected behavior if the function interferes with memory used by BQN.</p> +<h3 id="foreign-function-interface"><a class="header" href="#foreign-function-interface">Foreign Function Interface</a></h3> +<p>In a call to <code><span class='Function'>•FFI</span></code>, <code><span class='Value'>𝕩</span></code> follows the pattern <code><span class='String'>"result"</span><span class='Ligature'>‿</span><span class='String'>"fn"</span><span class='Ligature'>‿</span><span class='String'>"arg0"</span><span class='Ligature'>‿</span><span class='String'>"arg1"</span><span class='Ligature'>‿</span><span class='Value'>...</span></code>, that is, a string for the <em>result type</em>, one for the <em>function name</em>, and any number of strings indicating <em>argument types</em>. <code><span class='Value'>𝕩</span></code> must always be a list.</p> +<p>The function name is an arbitrary string. In order to look up the appropriate function in shared object file <code><span class='Value'>𝕨</span></code>, it's encoded as UTF-8.</p> +<p>Types are to be interpreted according to the C ABI appropriate for the platform used. The grammar for a result or argument type is given below, using BNF as in the BQN grammar. Quoted values here are single characters: the type isn't tokenized and can't contain spaces. A <code><span class='Function'>•FFI</span></code> implementation does not need to support all combinations of types.</p> +<pre><span class='Value'>conv</span> <span class='Function'>=</span> <span class='Value'>type</span> <span class='Paren'>(</span> <span class='String'>":"</span> <span class='Value'>bqn</span> <span class='Paren'>)</span><span class='Head'>?</span> +<span class='Value'>type</span> <span class='Function'>=</span> <span class='Paren'>(</span> <span class='String'>"i"</span> <span class='Function'>|</span> <span class='String'>"u"</span> <span class='Function'>|</span> <span class='String'>"f"</span> <span class='Paren'>)</span> <span class='Value'>nat</span> <span class='Comment'># number +</span> <span class='Function'>|</span> <span class='String'>"a"</span> <span class='Comment'># BQN object +</span> <span class='Function'>|</span> <span class='String'>"*"</span> <span class='Comment'># opaque pointer +</span> <span class='Function'>|</span> <span class='Paren'>(</span> <span class='String'>"*"</span> <span class='Function'>|</span> <span class='String'>"&"</span> <span class='Paren'>)</span> <span class='Value'>type</span> <span class='Comment'># pointer +</span> <span class='Function'>|</span> <span class='String'>"["</span> <span class='Value'>nat</span> <span class='String'>"]"</span> <span class='Value'>type</span> <span class='Comment'># array +</span> <span class='Function'>|</span> <span class='String'>"{"</span> <span class='Paren'>(</span> <span class='Value'>conv</span> <span class='Paren'>(</span> <span class='String'>","</span> <span class='Value'>conv</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Paren'>)</span><span class='Head'>?</span> <span class='String'>"}"</span> <span class='Comment'># struct +</span><span class='Value'>bqn</span> <span class='Function'>=</span> <span class='Paren'>(</span> <span class='String'>"i"</span> <span class='Function'>|</span> <span class='String'>"u"</span> <span class='Function'>|</span> <span class='String'>"f"</span> <span class='Function'>|</span> <span class='String'>"c"</span> <span class='Paren'>)</span> <span class='Value'>nat</span> + +<span class='Value'>nat</span> <span class='Function'>=</span> <span class='Value'>digit</span><span class='Function'>+</span> +<span class='Value'>digit</span> <span class='Function'>=</span> <span class='String'>"0"</span> <span class='Function'>|</span> <span class='String'>"1"</span> <span class='Function'>|</span> <span class='String'>"2"</span> <span class='Function'>|</span> <span class='String'>"3"</span> <span class='Function'>|</span> <span class='String'>"4"</span> <span class='Function'>|</span> <span class='String'>"5"</span> <span class='Function'>|</span> <span class='String'>"6"</span> <span class='Function'>|</span> <span class='String'>"7"</span> <span class='Function'>|</span> <span class='String'>"8"</span> <span class='Function'>|</span> <span class='String'>"9"</span> +</pre> +<p>By default, the returned function takes a list of arguments <code><span class='Value'>𝕩</span></code>, requires <code><span class='Value'>𝕨</span></code> to be an empty list if present, and returns a value corresponding to the C result. Some argument-specific rules can change this:</p> +<ul> +<li>The result type may also be the empty string <code><span class='String'>""</span></code>, indicating a void or ignored result, or <code><span class='String'>"&"</span></code>, indicating an ignored result, using a mutable argument for the BQN result, as discussed below. It can't contain any instance of the pointer rule <code><span class='Paren'>(</span> <span class='String'>"*"</span> <span class='Function'>|</span> <span class='String'>"&"</span> <span class='Paren'>)</span> <span class='Value'>type</span></code>.</li> +<li>An argument type may be preceded by up to one <code><span class='Function'>></span></code>, and up to one <code><span class='Value'>𝕨</span></code> or <code><span class='Value'>𝕩</span></code>, in any order. Arguments with <code><span class='Value'>𝕨</span></code> are taken from <code><span class='Value'>𝕨</span></code> in order, and the others from <code><span class='Value'>𝕩</span></code>. If no arguments come from <code><span class='Value'>𝕨</span></code>, the BQN function may be called monadically. If an argument type contains <code><span class='Function'>></span></code>, it must be the only value in its BQN argument (<code><span class='Value'>𝕨</span></code> or <code><span class='Value'>𝕩</span></code>), and that argument will be treated not as a list but as an entire value.</li> +</ul> +<p>Beginning with the type declarations themselves, a <strong>number</strong> such as <code><span class='Value'>f32</span></code> corresponds to a C type with the given quality (<code><span class='Value'>i</span></code> for signed integer, <code><span class='Value'>u</span></code> for unsigned, <code><span class='Value'>f</span></code> for floating-point) and width in bits. The corresponding BQN value is a number, and should be converted exactly for integers and with rounding for decreasing-type conversions. For conversions to or from an integer type, attempting to convert a value to a type that can't contain it, or one outside of the exactly representable integer range (<code><span class='Function'>-</span><span class='Number'>2</span><span class='Function'>⋆</span><span class='Number'>53</span></code> to <code><span class='Number'>2</span><span class='Function'>⋆</span><span class='Number'>53</span></code> for IEEE doubles), results in an error.</p> +<p>A <strong>pointer</strong> such as <code><span class='Value'>*u8</span></code> comes from a BQN list. If the symbol <code><span class='Value'>&</span></code> is used rather than <code><span class='Value'>*</span></code>, the pointer is called <strong>mutable</strong> and its contents after the function call completes are also returned as an element of the result. If there is any mutable pointer, the result is a list, unless the result type is <code><span class='String'>"&"</span></code>, in which case there must be exactly one mutable pointer and the result is its value alone. These prefixes can only be used in arguments, meaning that a BQN value is provided, and this value determines the length of both the input and the mutable result.</p> +<p>The letter <code><span class='Value'>a</span></code> indicates that a <strong>BQN value</strong> is to be passed directly, interpreted in whatever way makes sense for the implementation. A plain <code><span class='Value'>*</span></code> indicates an <strong>opaque pointer</strong>, to be mapped to a BQN value of namespace type. The behavior of this value is not yet specified. The <strong>array</strong> and <strong>struct</strong> types indicate C structs and arrays, and correspond to BQN lists.</p> +<p>The <code><span class='Value'>bqn</span></code> value in a <code><span class='Value'>conv</span></code> term indicates a BQN element type to be used. It can be appear after the whole type, or any member of a struct, and applies to the final component (that is, <code><span class='Value'>type</span></code> term) of the type <em>and</em> one preceding <code><span class='Value'>*</span></code>, <code><span class='Value'>&</span></code>, or <code><span class='Value'>[n]</span></code> if present (if a type ends in <code><span class='Value'>**</span></code>, it applies to both <code><span class='Value'>*</span></code>s). This portion of the type corresponds to a BQN list of the given element type, interpreted much like <a href="#bitwise-operations">bitwise</a> conversion <code><span class='Value'>•bit.</span><span class='Modifier'>_conv</span></code>. The C type is treated as pure data, a stream of bits. For a prefix <code><span class='Value'>*</span></code> or <code><span class='Value'>&</span></code>, the data in question is the region of memory pointed to.</p> <h2 id="operation-properties"><a class="header" href="#operation-properties">Operation properties</a></h2> <table> <thead> |
