Browse Source

Add documentation on types of functions

Yentl Van Tendeloo 3 years ago
parent
commit
67436b9c41
1 changed files with 55 additions and 11 deletions
  1. 55 11
      doc/primitives.rst

+ 55 - 11
doc/primitives.rst

@@ -1,26 +1,70 @@
 Functions
 =========
 
-Explain the different types of functions in the Modelverse.
+The Modelverse distinguishes three types of function.
+For the modeller, it is transparent which type the function is, although it is not possible to dig down in primitive functions.
+We now present these three types of functions.
 
 Primitive functions
 -------------------
 
-Explain primitive functions:
-hardcoded in kernel, no AL equivalent
-minimal set of functions to be ported for new kernel
+The primitive functions are functions that are implemented directly for the platform, such as in Python.
+While the function is written in that language, there are still various bindings with the Modelverse, as the function makes the requested changes in the MvS directly.
+As such, the function also makes use of the yield infrastructure presented previously.
+
+For example, the *integer_addition* is one such function, which must be implemented in the platform.
+Its definition is as follows::
+
+    def integer_addition(a, b, **remainder):
+        if 'value' not in a:
+            a['value'], = yield [("RV", [a['id']])]
+        if 'value' not in b:
+            b['value'], = yield [("RV", [b['id']])]
+        yield [("RETURN", [{'value': a['value'] + b['value']}])]
+
+We see that there are two parameters: *a* and *b*.
+Additionally, a dictionary of other parameters is also passed, although these are not necessary most of the time.
+All alphabetic parameters are those originally passed to the function in the action language, and are represented as a dictionary containing a *value* and *id* key.
+The *value* key contains the value of the node, stored in a representation that is compatible with the platform.
+The *id* key stores the id of the element in the Modelverse.
+When a *value* is defined without an *id*, this means that the value was never stored in the Modelverse to begin with.
+When an *id* is defined without a *value*, this means that the value of the ID was never read out of the Modelverse.
+
+It is easy to see that we can switch between both.
+To create a value if only an id is present, we read the node::
+
+    a['value'], = yield [("RV", [a['id']])]
+
+To create an id if only a value is present, we create the value in the Modelverse::
+
+    a['id'], = yield [("CNV", [a['value']])]
+
+As such, the primitive functions will have to check which of the two representations is there, and if the required one is not there, it must be converted.
+This explains the first four lines of the function: the function checks whether the value is already read from the Modelverse, and reuses it where possible.
+Finally, we return an element of similar structure as the input values.
+Again, it is possible for us to just return a *value* entry, meaning that the value is not stored in the Modelverse yet.
+It is every functions responsibility to check for the correct type of input, and the output function should only contain either *value* or *id*.
+
+The primitive functions are hardcoded in the tool, and have no explicitly modelled counterpart.
+They are essentially to be seen as part of the specification.
+While a handle to these functions exists in the Modelverse, when the function is invoked, the instruction pointer is merely pointing at an empty node.
+During bootstrapping, however, this node was bound to the primitive python function.
+As this is the only option for these functions, all these functions **MUST** be ported if the Modelverse is to be ported to a different domain.
 
 Compiled functions
 ------------------
 
-Explain compiled functions:
-hardcoded in kernel, but AL equivalent
-can be ported for efficiency fo the resulting kernel, but not required
+In addition to the primitive functions, which must be implemented directly for the platform, some functions can also be precompiled by the user for performance reasons.
+Essentially, these functions are the same as the primitive functions, but their definition is stored in *kernel/modelverse_kernel/compiled.py*.
+The definition of these functions is identical, and they are automatically detected at startup.
+Nonetheless, they differ in that a Modelverse definition must also exist, which must have identical behaviour to the implemented function.
+When such a function is executed in the Modelverse, it is up to the Modelverse to decide which version is to be used.
+In case the platform provides a pre-compiled function, that one is normally used, otherwise the action language is directly executed.
+
+Through its JIT compiler, the Modelverse actually dynamically creates compiled functions for the platform all the time.
+As such, all functions are actually written out as platform code, and only sporadically is an actual piece of action language still directly executed.
 
 Normal functions
 ----------------
 
-Explain normal functions:
-completely in AL, no compiled equivalent
-can still be implemented by kernel as compiled for performance, though not required
-functions are likely to be flexible
+All other functions are normal functions, but as mentioned before, these functions are often even compiled behind the scenes by the JIT compiler.