modelverse_kernel.tex 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. \chapter{Modelverse Kernel}
  2. We will now consider the Modelverse Kernel (MvK), which is responsible for the execution of action code.
  3. Execution of action code causes changes to the PTM, which need to be handled by the MvS.
  4. As such, the Modelverse Kernel is responsible for the mapping between the user-level and the PTM.
  5. Users can create action code constructs directly, thus forming a direct interface to the MvS for the user.
  6. Alternatively, users can create models using a formalism which has action code constructs defined (\textit{e.g.}, to define the model semantics).
  7. As everything is modelled explicitly (\axiomModelEverything), both the execution context and instructions to execute are part of the MvS, and can thus be accessed by the MvK and ultimately the user.
  8. When executing an action language model, the execution context is modified in the MvS.
  9. Therefore, the MvK itself does not have any local state.
  10. By making all states and intermediate steps explicit, we obtain enhanced debugability and introspection.
  11. This furthermore contributes to \axiomForeverRunning, as it allows action code to modify other action code (\textit{i.e.}, self-modifiability).
  12. We first introduce the notion of transformations for our graph, subsequently called graph transformations
  13. \footnote{They are called graph transformations, though are different from the usual meaning of graph transformations in the literature. While the idea is similar, we provide a different mapping as we do not work on Typed Attributed Graphs (TAGs).}.
  14. Such transformations consist of a matching part, which we will use to determine if the execution context is well-defined, and a rewriting part, which we can use to define the action language semantics by defining transformations of the execution context.
  15. \section{Graph transformations}
  16. Before we can use graph transformations in our well-formedness check and semantical definition, we need to define them first.
  17. We need to bridge the gap between graph transformations and the CRUD operations defined by our MvS interface.
  18. For each transformation rule, it is possible to decompose it in four distinct (sequentially ordered) components.
  19. The first two are read operations, which are used for the matching, and the last two are create and delete operations, which are used for the rewriting.
  20. \begin{enumerate}
  21. \item \textbf{Positive read} operations are used for elements which are present before and after execution of the transformation rule.
  22. They are used for finding a possible match during the matching phase.
  23. Note that all elements need to be matched, even those that are about to be removed.
  24. All elements that are now matched, can be used during the rewriting phase.
  25. Elements that are simply required for the match, but without any changes to them, are visualized by black, solid lines.
  26. \item \textbf{Negative read} operations are used for the negative application conditions.
  27. Such elements should not be present before application of the transformation rule.
  28. If they are present in a match, the match is considered incorrect and another match is searched for.
  29. Elements which are searched for here, can of course not be used during the rewriting phase, as we explicitly required that they are absent.
  30. They are visualized by a red, dotted line.
  31. \item \textbf{Delete} operations are used for elements that need to be removed during the rewriting phase.
  32. Elements which should be removed, should also be matched in the positive read operation.
  33. These elements are visualized by a blue, dashed line.
  34. \item \textbf{Create} operations are used for elements that need to be created during the rewriting phase.
  35. Because the element is newly created, it does not need to be matched by a positive read operation.
  36. However, we do not require them to be absent either.
  37. They are visualized by a green, wide solid line.
  38. \end{enumerate}
  39. Each rule can be written in the following form, assuming success status, thus mapping to our previously defined formalization of the MvS.
  40. If an error is encountered, it is propagated to the user.
  41. \begin{center}
  42. \begin{tabular}{c}
  43. $PositiveRead_A(G)$ \\
  44. $NegativeRead_A(G)$ \\
  45. $G' = Create_A(G)$ \\
  46. $G'' = Delete_A(G')$ \\
  47. \hline
  48. $G \xrightarrow{step_A} G''$
  49. \end{tabular}
  50. \end{center}
  51. Each rule uses the matched elements, which get bound during application.
  52. As such, the $PositiveRead$ operation binds the variables, which are then used in the $NegativeRead$ to detect invalid matches, in the $Delete$ to delete elements, and in the $Create$ to create new elements.
  53. For conciseness, we define the shorthand notation for graph elements shown in Fig.~\ref{fig:shorthand_notation_a}, equivalent to Fig.~\ref{fig:shorthand_notation_b}, meaning:
  54. \begin{figure}
  55. \center
  56. \begin{subfigure}[c]{0.2\columnwidth}
  57. \includegraphics[width=\textwidth]{images/shorthand_notation.eps}
  58. \caption{Shorthand notation}
  59. \label{fig:shorthand_notation_a}
  60. \end{subfigure}
  61. \begin{subfigure}[c]{0.2\columnwidth}
  62. \includegraphics[width=\textwidth]{images/shorthand_notation_expanded.eps}
  63. \caption{Expanded notation}
  64. \label{fig:shorthand_notation_b}
  65. \end{subfigure}
  66. \caption{Shorthand notation and equivalent expanded notation.}
  67. \label{fig:shorthand_notation}
  68. \end{figure}
  69. \begin{gather*}
  70. (X_{node}, W_{link}, Y_{node}) \in E \\
  71. (W_{link}, e, W_{node}) \in E \\
  72. N_V(X_{node}) = X \\
  73. N_V(Y_{node}) = Y \\
  74. N_V(W_{node}) = W \\
  75. \end{gather*}
  76. If $X$, $Y$, or $W$ is not shown in the shorthand notation, then the $N_V$ mapping is unconstrained, and might not even exist.
  77. An example of the mapping between the shorthand notation and the previously defined semantics is given next.
  78. We explain the transformation shown in Figure~\ref{fig:example_transformation}.
  79. First, the \textit{success} status code is stored in $s$ (equation~\ref{eqn:status}), to shorten subsequent rules.
  80. All parts of the rule are assumed to result in a success status code.
  81. The positive read operations start at equation~\ref{eqn:positive_read}, followed by the negative read operation at equation~\ref{eqn:negative_read}.
  82. Now that all nodes and edges are bound, the create operation creates the necessary links starting from equation~\ref{eqn:create}.
  83. From equation~\ref{eqn:delete} to the end, operations try to match the edge to delete at a finer granularity and delete it in equation~\ref{eqn:delete_true}.
  84. \begin{figure}
  85. \center
  86. \includegraphics[width=0.2\textwidth]{images/example_transformation.eps}
  87. \caption{Example graph transformation which is expanded}
  88. \label{fig:example_transformation}
  89. \end{figure}
  90. \begin{center}
  91. \begin{tabular}{p{7cm}}
  92. {
  93. \begin{gather}
  94. s = (100, \_) \label{eqn:status}\\
  95. R_{dict}(G, a, "A") = (b, s) \label{eqn:positive_read}\\
  96. R_{dict}(G, a, "B") = (c, s) \\
  97. R_{dict}(G, a, "F") = (e, s) \\
  98. R_V(G, e) = ("E", s) \\
  99. \not \exists d : R_{dict}(G, d, "C") = (c, s) \label{eqn:negative_read}\\
  100. C_{NV}(G, "D") = (G', f, s) \label{eqn:create}\\
  101. C_E(G', b, c) = (G'', g, s) \\
  102. C_E(G'', g, f) = (G''', h, s) \\
  103. \langle V_1, s \rangle = R_O(G''', a, s) \label{eqn:delete}\\
  104. \langle V_2, s \rangle = R_I(G''', c, s) \\
  105. i \in V_1 \\
  106. i \in V_2 \\
  107. \langle V_3, s \rangle = R_O(G''', i, s) \\
  108. j \in V_3 \\
  109. R_E(G''', j) = ((i, k), s) \\
  110. R_V(G''', k) = ("B", s) \\
  111. D_E(G''', i) = (G'''', s) \label{eqn:delete_true}
  112. \end{gather}
  113. } \\
  114. \hline
  115. \centering $G \xrightarrow{step_{A}} G''''$
  116. \end{tabular}
  117. \end{center}
  118. Note that this does not explicitly remove all parts of the edge.
  119. Specifically, the node containing the data value still remains.
  120. This is because it might still be referenced from somewhere else, and deleting that might have serious repercussions.
  121. As a safety measure, only the link itself is removed.
  122. All elements that are no longer reachable from the root will later be removed in the garbage collection phase.
  123. The current notion of graph transformations should not be confused with the notion of model transformations, which the user can use.
  124. The graph transformations we have defined here, are merely a conceptual construct, used to formalize the semantics of action language constructs.
  125. It is therefore not mandatory for an MvK implementation to implement the semantics as if it were a graph transformation.
  126. On the other hand, model transformations, which are implemented on top of action language constructs, will be usable by the user, and as such are really implemented as transformations.
  127. Furthermore, model transformations will be at a level closer to the user (\textit{i.e.}, not on raw graphs), and will therefore be typed.
  128. We will not discuss model transformations any further in this technical report, as this is part of future work.
  129. \subsection{Performance}
  130. It is important to mention that our graph transformations do not use the notion of types.
  131. As we are working on simple graphs, which do not have a real notion of type, and it can therefore not be used.
  132. This implies that \emph{nodes} in the transformation rules can as well be edges, since the semantics of a point in the tranformation rules is simply an identifier from $IDS$.
  133. Conversely, this might imply a performance impact, as the only basis to determine a match is the use of primitive values, and edges between specific nodes.
  134. While this is a concern relating to \axiomScalability, it is not a fundamental problem for the following reasons:
  135. \begin{enumerate}
  136. \item We start from a pivot, which is the Modelverse Root previously defined.
  137. All MvK instances will know which node to use for this, and therefore there is already a place where the matching can start.
  138. \item At most one match exists.
  139. This means that we can already stop searching as soon as a single match is found.
  140. \item All edges have a constant on them, which needs to be unique.
  141. Therefore, no trackbacking is required as soon as the correct edge is found: each edge will be identifiable.
  142. \item A primitive operation exists to read out the aforementioned edges: the $R_{dict}$ operations.
  143. If this operation is implemented in $\mathcal{O}(1)$ (\textit{e.g.}, using hashmaps), this means that the complexity of finding a match is unrelated to the size of the host graph.
  144. \end{enumerate}
  145. Combining all of this information, we can write a simple algorithm for each rule, which starts from the Modelverse Root, and just performs a serie of $R_{dict}$ operations.
  146. As there is only one possible result for that operation, we do not need to rely on backtracking.
  147. Some exceptions exist to these findings though, such as the accessing of variables in the symbol table.
  148. These do not use values on the edge that are in $\mathbb{U}$, and therefore require more advanced algorithms.
  149. \section{Execution context}
  150. We specify the structure of the execution context by defining a graph that has to be matched.
  151. If the graph is matched, the execution context is valid and execution is possible if the current instruction is valid.
  152. If no match can be found for the specified user, the user's execution context is invalid and execution is impossible.
  153. If multiple matches are found, the execution context is also invalid, and results will be undefined.
  154. We make no distinction between \textit{no execution context} (\textit{i.e.}, nothing at all) and \textit{corrupt execution context} (\textit{e.g.}, a single missing link).
  155. In either case, no execution is possible.
  156. During normal operation, the user is unable to corrupt or remove its own execution context, as all action language primitives are guaranteed to keep the execution context in a valid state.
  157. But in case introspection or self-modifiability is used (\textit{i.e.}, if an intentional change is made by the user), it is possible to alter, and possibly corrupt, the execution context.
  158. This is possible because the execution context is itself again another model in the MvS, and it can be manipulated like any other.
  159. We do this to enable self-modifiability, introspection, reflection, and debugability, which can now be performed directly on the graph.
  160. For debugging it is even possible for another (privileged) user to debug the state of another user, or process.
  161. \begin{figure}
  162. \center
  163. \includegraphics[width=0.25\columnwidth]{images/execution_context.eps}
  164. \caption{Graph to match as execution context. Some nodes might be identical.}
  165. \label{fig:execution_context}
  166. \end{figure}
  167. A valid execution context is one that is matched by the structure in Fig.~\ref{fig:execution_context}.
  168. At the top of the structure sits the Modelverse root node, which is a node that is known to the MvK.
  169. From this root node, there is a link to all user root nodes, containing the name of the user.
  170. In our figure, \textit{username} has to be interpreted as a variable for the transformation.
  171. From the user root, there are links for \textit{input} and \textit{output} lists, and a \textit{``frame''} link.
  172. These input and output links come with both an initial link, and the \textit{last\_} variant, which points to the last element of the list.
  173. The last element will always be empty (have no value), but needs to be there to guard for the case of an empty list.
  174. Each element in such a list will have a \textit{``value''} link, which points to the actual value, and a \textit{``next''} link, which points to the next element in the list.
  175. The exception to this is the element pointed to by the \textit{``last\_''} element, which is the empty placeholder.
  176. The destination of the \textit{``frame''} link is the currently active execution frame for that user.
  177. Each execution frame has several outgoing links.
  178. First is the \textit{``symbols''} link, which points to the symbol table.
  179. A symbol table is a node which is interpreted as a dictionary, where all outgoing edges have a unique key.
  180. The symbol table can then be accessed using the $R_{dict}$ CRUD operation of the MvS.
  181. In this case, the key is the variable definition in the code being executed.
  182. The destination of the edge is the current value of the specified variable.
  183. It is not possible to save this variable in the executing code itself, as the code can possibly be executed by different users simultaneously (\axiomMultiUser).
  184. Second is the \textit{``IP''} link, which points to the current action code primitive being executed.
  185. It is similar to an Instruction Pointer, with the exception that it does not advance linearly, nor is there a default direction.
  186. Every instruction primitive is responsible to update the instruction pointer.
  187. Third is the \textit{``evalstack''} link, pointing to the evaluation stack.
  188. In this stack, instructions are stored, which need to be made in the same scope.
  189. Such a structure is necessary because we do not use compiled bytecodes which modify a stack.
  190. For example, for the execution of an \textit{If} construct, we first need to evaluate the condition.
  191. In such ``stack-based'' languages, the result of the condition is first put on the stack by the appropriate bytecodes.
  192. Only then a bytecode concerning the \textit{If} construct is encountered, which consumes the evaluated value on the stack.
  193. In our language, the \textit{If} is encountered first, which then explicitly states to evaluate the condition first (by moving the ``IP'' link), and come back as soon as it is evaluated (by putting it on the evaluation stack).
  194. There is also the \textit{``phase''} link, allowing for a distinction between the different sub-states in the evaluation of a primitive.
  195. For example in the \textit{If} construct, a distinction between the \textit{``evaluate condition''} and \textit{``branch on value''} phases is necessary.
  196. To make this possible, the phase keeps the current state of the evaluation of that specific execution primitive.
  197. Finally, there is the \textit{``returnvalue''} link, which links to a node which contains the value from the previous execution.
  198. Each instruction primitive can read and update this link.
  199. It is used for the exchange of temporary values between different instructions.
  200. In contrast to languages which use a stack, there is only one temporary variable in our language.
  201. This offers us a slightly more efficient implementation of most constructs, due to avoiding the use of a list.
  202. Some constructs get more complex (though not necessarily slower, performance-wise), such as those where it is natural to evaluate multiple values sequentially.
  203. Some additional links might be present on the frame, and their use is mandatory, though they are not required for a well-defined execution context.
  204. These links are the \textit{``prev''} and \textit{``variable''} links.
  205. The ``prev'' links to the previous execution frame, that is, the invoker of the function for which the frame is created.
  206. The ``variable'' link is used during assignment, as we need two evaluated elements at the same time: the variable to write to, and the value to assign.
  207. If these links are not present at the time where they are necessary, the execution context is considered to be corrupt.
  208. These optional links could be made mandatory, by setting making them point to an empty node if they are not necessary.
  209. The execution context is well-defined if exactly one such match is found for a given user.
  210. No matches means that there is no execution context with all required elements (\textit{i.e.}, either corrupt or completely missing).
  211. Multiple matches indicate non-determinism and are therefore not allowed.
  212. Additional elements, though not indicated here, are allowed, as they do not interfere with the match.
  213. These elements should be considered implementation-dependent and should not be used for the implementation of functional requirements.
  214. Apart from the user-specific execution context, there is also a global symbol table, stored as if it were the \textit{``\_\_global''} user.
  215. This symbol table is shared by all users, and is accessed if a variable could not be found in the local symbol table of the current execution frame.
  216. \section{Execution primitives}
  217. What remains is the semantics of each of the action language constructs.
  218. For each construct, defined in $\mathbb{A}$, the required modifications on the execution context needs to be defined.
  219. As proposed in previous sections, graph transformations are used to define the semantics.
  220. These graph transformation rules are defined such that there should always be exactly one possible match.
  221. If no matches can be found, this indicates that the execution context, the current action language primitive, or both, are invalid.
  222. If multiple matches are found, non-determinism is possible, which is disallowed.
  223. In the presence of multiple users (\axiomMultiUser), interleaving is necessary between them to guarantee fairness.
  224. This also prevents uninterruptible loops (\axiomForeverRunning), as another (privileged) user can then always halt the execution of another user.
  225. For performance reasons (\axiomScalability), an MvK can ignore updates to the execution context (\textit{e.g.}, by not propagating them to the MvS, or by implementing compiled operations).
  226. But this comes at the cost of debugability, introspection, and self-modifiability.
  227. Hybrid approaches are supported, meaning that some functions will be called without modifications to the execution context (\textit{e.g.}, primitive operations such as integer addition), whereas others modify to the execution context.
  228. A step function is defined for each user, which applies the only applicable rule.
  229. \begin{center}
  230. \begin{tabular}{c}
  231. $G \xrightarrow{step_A} G' \; \lor$ \\
  232. $G \xrightarrow{step_B} G' \; \lor$ \\
  233. $...$ \\
  234. \hline
  235. $G \xrightarrow{step} G'$ \\
  236. \end{tabular}
  237. \end{center}
  238. The interleaving of different users, and thus of different steps, is not specified, as long as there is some fairness between all users.
  239. This allows for the definition of primitive operations in the Modelverse Kernel, which consist of several (atomically executed) instructions.
  240. Such primitives can then be used for performance reasons (\axiomScalability), but also as a core function (\axiomModelEverything).
  241. In Table~\ref{table:well-formed}, we present an overview of all specified outgoing links for each primitive element.
  242. A construct is valid if all mandatory elements are present.
  243. Links which guide the instruction pointer, require the target of the link to be executable (\textit{i.e.}, be another primitive construct, $\in \mathbb{A}$).
  244. If that is not the case, execution will terminate.
  245. Normally, the action language constructs are created by a different tool, such as a HUTN MvI, which will guarantee that the constructs are well formed.
  246. But it is possible for users to access all parts of the MvS, thanks to \axiomModelEverything, and therefore to manually create (or alter) action language constructs.
  247. Such actions cannot automatically be checked for correctness, due to our lack of typing: there is no metamodel for the primitive action language constructs.
  248. And since there is no metamodel, there is no constraint on the graph.
  249. Although counter-intuitive, this is actually what we want: unconstrained modifications on the raw model representation, thus allowing model management operations.
  250. In the next chapter, we will add a layer on top of all this, which is typed and more constrained.
  251. Notwithstanding, it is possible to create a function which manually checks whether or not a construct is well-defined, using the information from Table~\ref{table:well-formed}.
  252. \begin{table}
  253. \center
  254. \begin{tabular}{lcccl}
  255. Construct & Name & Mandatory & Executable & Meaning (informal) \\
  256. \hline
  257. \hline
  258. \multirow{4}{*}{If} & cond & Yes & Yes & Condition \\
  259. & true & Yes & Yes & Block to execute if condition is True \\
  260. & false & No & Yes & Block to execute if condition is False \\
  261. & next & No & Yes & Next instruction after True/False block \\
  262. \hline
  263. \multirow{3}{*}{While} & cond & Yes & Yes & Condition \\
  264. & body & Yes & Yes & Body to execute while condition is True \\
  265. & next & No & Yes & Next instruction after condition is False \\
  266. \hline
  267. \multirow{1}{*}{Break} & while & Yes & Yes & While construct that should be broken \\
  268. \hline
  269. \multirow{1}{*}{Continue}& while & Yes & Yes & While construct that should be continued \\
  270. \hline
  271. \multirow{1}{*}{Access} & var & Yes & Yes & Variable to access \\
  272. \hline
  273. \multirow{1}{*}{Resolve}& var & Yes & No & Variable definition to access \\
  274. \hline
  275. \multirow{3}{*}{Assign} & var & Yes & Yes & Variable to assign to \\
  276. & value & Yes & Yes & Value to assign to variable \\
  277. & next & No & Yes & Next instruction after assignment \\
  278. \hline
  279. \multirow{4}{*}{Call} & func & Yes & Yes & Function signature to call \\
  280. & next & No & Yes & Next instruction after function call returned \\
  281. & params & Yes & No & First parameter, linking to a \textit{Parameter} \\
  282. & last\_param & Yes & No & Last parameter, linking to a \textit{Parameter} \\
  283. \hline
  284. \multirow{3}{*}{Parameter}& name & Yes & No & Name of the parameter, used to link with the formal parameters \\
  285. & value & Yes & Yes & Instructions to evaluate as parameter \\
  286. & next\_param & No & No & Next parameter to be evaluated (optional if this is the last parameter) \\
  287. \hline
  288. \multirow{1}{*}{Return} & value & No & Yes & Value to return \\
  289. \hline
  290. \multirow{1}{*}{Const} & node & Yes & No & Node containing the constant to access \\
  291. \hline
  292. \multirow{1}{*}{Input} & & N/A & N/A & N/A \\
  293. \hline
  294. \multirow{1}{*}{Output} & value & Yes & Yes & The node to output \\
  295. \end{tabular}
  296. \caption{Outgoing link specification.}
  297. \label{table:well-formed}
  298. \end{table}
  299. \clearpage
  300. \subsection{If}
  301. \begin{figure}[h!]
  302. \begin{subfigure}[b]{0.49\textwidth}
  303. \includegraphics[width=\textwidth]{images/rule_if__cond.eps}
  304. \caption{Evaluate condition}
  305. \label{fig:rule_if_a}
  306. \end{subfigure}
  307. \begin{subfigure}[b]{0.49\textwidth}
  308. \includegraphics[width=\textwidth]{images/rule_if__true.eps}
  309. \caption{Returned True}
  310. \label{fig:rule_if_b}
  311. \end{subfigure}
  312. \begin{subfigure}[b]{0.49\textwidth}
  313. \includegraphics[width=\textwidth]{images/rule_if__false-else.eps}
  314. \caption{Returned False and there is an 'else' block}
  315. \label{fig:rule_if_c}
  316. \end{subfigure}
  317. \begin{subfigure}[b]{0.49\textwidth}
  318. \includegraphics[width=\textwidth]{images/rule_if__false-nothing.eps}
  319. \caption{Returned False but there is no 'else' block}
  320. \label{fig:rule_if_d}
  321. \end{subfigure}
  322. \caption{If branch rules}
  323. \end{figure}
  324. The \textit{If} construct will first evaluate the condition (\textit{cond} link) by moving the instruction pointer there.
  325. It signals that it should be executed again afterwards, but now in phase \textit{cond}, by putting this on the evaluation stack (Figure~\ref{fig:rule_if_a}).
  326. As soon as the condition is evaluated, and the \textit{If} popped back from the stack, the return value (of the condition) can either be True or False.
  327. If it is True (Figure~\ref{fig:rule_if_b}), the \textit{then} link is executed, and the \textit{if} is pushed on the stack again, but now in the final phase \textit{finish}.
  328. This is the phase which signals to another rule that this operation has finished, and the next instruction can be loaded.
  329. If it is False, and there is an \textit{else} link (Figure~\ref{fig:rule_if_c}), it is executed, similar to the previous case.
  330. If it is False, but there is no \textit{else} link (Figure~\ref{fig:rule_if_d}), the \textit{If} is marked as completed immediately, without any subsequent actions.
  331. \clearpage
  332. \subsection{While}
  333. \begin{figure}[h!]
  334. \begin{subfigure}[b]{0.49\textwidth}
  335. \includegraphics[width=\textwidth]{images/rule_while__cond.eps}
  336. \caption{Evaluate the condition of the While}
  337. \label{fig:rule_while_a}
  338. \end{subfigure}
  339. \begin{subfigure}[b]{0.49\textwidth}
  340. \includegraphics[width=\textwidth]{images/rule_while__true.eps}
  341. \caption{Condition was true}
  342. \label{fig:rule_while_b}
  343. \end{subfigure}
  344. \begin{subfigure}[b]{0.49\textwidth}
  345. \includegraphics[width=\textwidth]{images/rule_while__false.eps}
  346. \caption{Condition was false}
  347. \label{fig:rule_while_c}
  348. \end{subfigure}
  349. \caption{While loop rules}
  350. \end{figure}
  351. The \textit{While} construct will first evaluate the condition (\textit{cond} link) by moving the instruction pointer there.
  352. It signals that it should be executed again afterwards, but now in phase \textit{cond}, by putting this on the stack (Figure~\ref{fig:rule_while_a}).
  353. As soon as the condition is evaluated, and the \textit{While} popped from the stack, the return value (of the condition) can either be True or False.
  354. If it is True (Figure~\ref{fig:rule_while_b}), the \textit{body} link is executed, and the \textit{While} is pushed on the stack again, but with its phase set to \textit{init}.
  355. This way, the while construct will again be executed after the body has terminated.
  356. By setting the phase to \textit{init}, we effectively cause looping, as the condition will again be evaluated, and, depending on the result, the body gets executed once more.
  357. If it is False (Figure~\ref{fig:rule_while_c}), the \textit{While} is immediately marked as finished and the body is not executed.
  358. \clearpage
  359. \subsection{Break}
  360. \begin{figure}[h!]
  361. \center
  362. \includegraphics[width=0.49\textwidth]{images/rule_break.eps}
  363. \caption{Break rule}
  364. \label{fig:rule_break}
  365. \end{figure}
  366. The \textit{Break} construct will move the instruction pointer back to the \textit{While} construct it belongs to (Figure~\ref{fig:rule_break}).
  367. The phase is set to \textit{finish} to indicate that the loop has finished.
  368. This prevents the condition evaluation and marks the end of the while loop.
  369. \subsection{Continue}
  370. \begin{figure}[h!]
  371. \center
  372. \includegraphics[width=0.49\textwidth]{images/rule_continue.eps}
  373. \caption{Continue rule}
  374. \label{fig:rule_continue}
  375. \end{figure}
  376. The \textit{Continue} construct will move the instruction pointer back to the \textit{While} construct to which it belongs (Figure~\ref{fig:rule_continue}).
  377. The phase is set to \textit{init} to indicate that the loop needs to continue.
  378. This causes the condition to be evaluated again, indicating the next iteration of the loop.
  379. \clearpage
  380. \subsection{Access}
  381. \begin{figure}[h!]
  382. \begin{subfigure}[b]{0.49\textwidth}
  383. \includegraphics[width=\textwidth]{images/rule_access__init.eps}
  384. \caption{Evaluate variable to access}
  385. \label{fig:rule_access_a}
  386. \end{subfigure}
  387. \begin{subfigure}[b]{0.49\textwidth}
  388. \includegraphics[width=\textwidth]{images/rule_access__eval.eps}
  389. \caption{Access evaluated variable}
  390. \label{fig:rule_access_b}
  391. \end{subfigure}
  392. \caption{Variable dereference rules}
  393. \end{figure}
  394. The \textit{Access} construct will move the instruction pointer to the variable which has to be resolved first (Figure~\ref{fig:rule_access_a}).
  395. It signals that it needs to be executed again after the variable was resolved, by putting itself on the evaluation stack.
  396. After resolution of the variable, the value of the variable is accessed and set as the new return value (Figure~\ref{fig:rule_access_b}).
  397. \clearpage
  398. \subsection{Resolve}
  399. \begin{figure}[h!]
  400. \begin{subfigure}[b]{0.49\textwidth}
  401. \includegraphics[width=\textwidth]{images/rule_resolve__no-attr.eps}
  402. \caption{Access the variable from the local symbol table}
  403. \label{fig:rule_resolve_c}
  404. \end{subfigure}
  405. \begin{subfigure}[b]{0.49\textwidth}
  406. \includegraphics[width=\textwidth]{images/rule_resolve__no-attr-global.eps}
  407. \caption{Access the variable from the global symbol table}
  408. \label{fig:rule_resolve_d}
  409. \end{subfigure}
  410. \caption{Resolution rules}
  411. \end{figure}
  412. With the \textit{resolve} rule, a variable is looked up in either the local (Figure~\ref{fig:rule_resolve_c}) or global (Figure~\ref{fig:rule_resolve_d}) symbol table.
  413. The variable in the symbol table will be set as the returnvalue.
  414. The local symbol table has priority over the global symbol table.
  415. Note that the returned value is only a reference, similar to the lvalue in parsers.
  416. A further \textit{Access} is required to read out the actual value.
  417. \clearpage
  418. \subsection{Assign}
  419. \begin{figure}[h!]
  420. \begin{subfigure}[b]{0.49\textwidth}
  421. \includegraphics[width=\textwidth]{images/rule_assign__init.eps}
  422. \caption{Resolve the variable to assign to}
  423. \label{fig:rule_assign_a}
  424. \end{subfigure}
  425. \begin{subfigure}[b]{0.49\textwidth}
  426. \includegraphics[width=\textwidth]{images/rule_assign__value.eps}
  427. \caption{Evaluate the value to assign}
  428. \label{fig:rule_assign_b}
  429. \end{subfigure}
  430. \begin{subfigure}[b]{0.49\textwidth}
  431. \includegraphics[width=\textwidth]{images/rule_assign__assign.eps}
  432. \caption{Assign the value to the variable}
  433. \label{fig:rule_assign_c}
  434. \end{subfigure}
  435. \caption{Assignment rules}
  436. \end{figure}
  437. The \textit{Assign} rule will first evaluate the variable (Figure~\ref{fig:rule_assign_a}), as it will first need to be resolved.
  438. After resolution (Figure~\ref{fig:rule_assign_b}), the found value is stored in a temporary link from the frame (\textit{variable} link).
  439. The instruction pointer is moved to the value that will be assigned, as it will also need to be evaluated.
  440. After the value is evaluated (Figure~\ref{fig:rule_assign_c}), the value link in the stored variable is changed to the evaluated value.
  441. \clearpage
  442. \subsection{Function call}
  443. \begin{figure}[h!]
  444. \begin{subfigure}[b]{0.49\textwidth}
  445. \includegraphics[width=\textwidth]{images/rule_call__resolve-no-params.eps}
  446. \caption{Resolve function without parameters}
  447. \label{fig:rule_call_a}
  448. \end{subfigure}
  449. \begin{subfigure}[b]{0.49\textwidth}
  450. \includegraphics[width=\textwidth]{images/rule_call__resolve-params.eps}
  451. \caption{Resolve function with parameters}
  452. \label{fig:rule_call_b}
  453. \end{subfigure}
  454. \begin{subfigure}[b]{0.49\textwidth}
  455. \includegraphics[width=\textwidth]{images/rule_call__call-no-params.eps}
  456. \caption{Execute call with no parameters}
  457. \label{fig:rule_call_c}
  458. \end{subfigure}
  459. \begin{subfigure}[b]{0.49\textwidth}
  460. \includegraphics[width=\textwidth]{images/rule_call__call-params.eps}
  461. \caption{Execute call with parameters}
  462. \label{fig:rule_call_d}
  463. \end{subfigure}
  464. \caption{Function call rules for resolution and execution}
  465. \end{figure}
  466. A \textit{Call} construct has different paths, depending on how many parameters there are.
  467. The distinct situations are:
  468. \begin{enumerate}
  469. \item \textbf{No parameters}: in this simple case, the method is first resolved by moving the instruction pointer there, and the call is already put on the stack (Figure~\ref{fig:rule_call_a}).
  470. After the function is resolved (Figure~\ref{fig:rule_call_c}), the call is made by creating a new execution frame and making it the active frame.
  471. \item \textbf{One parameter}: similar to the previous situation, the function is first resolved (Figure~\ref{fig:rule_call_b}), but instead of putting the \textit{call} on the stack, the first parameter is used.
  472. Afterwards (Figure~\ref{fig:rule_call_f}), the stack is created for the resolved function, the instruction pointer is set to evaluate the argument, and the \textit{call} is put on the stack.
  473. When the parameter is evaluated (Figure~\ref{fig:rule_call_d}), the result is put in the symbol table of the new execution frame and the new frame is made active.
  474. \item \textbf{Two parameters}: similar to a single parameter, the first parameter is again put on the stack for after the function resolution (Figure~\ref{fig:rule_call_c}).
  475. When evaluating the first parameter (Figure~\ref{fig:rule_call_e}), the \textit{next\_param} parameter is put on the stack, instead of the \textit{call} phase.
  476. The second parameter is already the last parameter, so we then put the \textit{call} on the stack (Figure~\ref{fig:rule_call_g}).
  477. Finally, the function is called as with only a single parameter (Figure~\ref{fig:rule_call_d}).
  478. \item \textbf{More than two parameters}: similar to two parameters, but with an iteration rule (Figure~\ref{fig:rule_call_h}) for all parameters except the first and last.
  479. This iteration rule simply evaluates the parameters in order of their \textit{next\_param} links.
  480. \end{enumerate}
  481. In all cases, the \textit{finish} is put on the stack during the call to the function.
  482. As soon as the called function has finished, it will invoke a return and thus pop the active execution frame.
  483. This will make the current frame active again, which will then progress towards the next instruction.
  484. Parameter passing happens through the use of both named variables and positional parameters.
  485. However, the positional parameters are only used to determine the evaluation order, and not for binding of actual to formal parameter.
  486. It is possible for a front-end to offer positional parameters, by automatically mapping them onto their formal parameters.
  487. \begin{figure}[t!]
  488. \begin{subfigure}[b]{0.49\textwidth}
  489. \includegraphics[width=\textwidth]{images/rule_call__params-first-multi.eps}
  490. \caption{Set first parameter of multiple}
  491. \label{fig:rule_call_e}
  492. \end{subfigure}
  493. \begin{subfigure}[b]{0.49\textwidth}
  494. \includegraphics[width=\textwidth]{images/rule_call__params-first-single.eps}
  495. \caption{Set first and only parameter}
  496. \label{fig:rule_call_f}
  497. \end{subfigure}
  498. \begin{subfigure}[b]{0.49\textwidth}
  499. \includegraphics[width=\textwidth]{images/rule_call__params-last.eps}
  500. \caption{Set last parameter of multiple}
  501. \label{fig:rule_call_g}
  502. \end{subfigure}
  503. \begin{subfigure}[b]{0.49\textwidth}
  504. \includegraphics[width=\textwidth]{images/rule_call__params-next.eps}
  505. \caption{Set next parameter}
  506. \label{fig:rule_call_h}
  507. \end{subfigure}
  508. \caption{Function call rules for parameter evaluation}
  509. \end{figure}
  510. \clearpage
  511. \subsection{Return}
  512. \begin{figure}[h!]
  513. \begin{subfigure}[b]{0.49\textwidth}
  514. \includegraphics[width=\textwidth]{images/rule_return__no-value.eps}
  515. \caption{Return without value}
  516. \label{fig:rule_return_a}
  517. \end{subfigure}
  518. \begin{subfigure}[b]{0.49\textwidth}
  519. \includegraphics[width=\textwidth]{images/rule_return__value.eps}
  520. \caption{Evaluate the value of the return}
  521. \label{fig:rule_return_b}
  522. \end{subfigure}
  523. \begin{subfigure}[b]{0.49\textwidth}
  524. \includegraphics[width=\textwidth]{images/rule_return__eval.eps}
  525. \caption{Return with the evaluated value}
  526. \label{fig:rule_return_c}
  527. \end{subfigure}
  528. \caption{Return rules}
  529. \end{figure}
  530. For the \textit{Return} construct, there are again two options: either there is a value to return, or there is none.
  531. If there is no return value (Figure~\ref{fig:rule_return_a}), the current execution frame is removed and the previous one is made active again, without touching the return value of the underlying frame.
  532. If there is a return value (Figure~\ref{fig:rule_return_b}), it is first evaluated by moving the instruction pointer there.
  533. After evaluation (Figure~\ref{fig:rule_return_c}), the evaluated value is stored in the returnvalue of the previous frame, and the current frame is deleted.
  534. \clearpage
  535. \subsection{Input and Output}
  536. \begin{figure}[h!]
  537. \begin{subfigure}[b]{0.49\textwidth}
  538. \includegraphics[width=\textwidth]{images/rule_output__init.eps}
  539. \caption{Output rule evaluates value}
  540. \label{fig:output_init}
  541. \end{subfigure}
  542. \begin{subfigure}[b]{0.49\textwidth}
  543. \includegraphics[width=\textwidth]{images/rule_output__output.eps}
  544. \caption{Output rule outputs value}
  545. \label{fig:output_output}
  546. \end{subfigure}
  547. \begin{subfigure}[b]{0.49\textwidth}
  548. \includegraphics[width=\textwidth]{images/rule_input.eps}
  549. \caption{Input rule consumes input}
  550. \label{fig:input}
  551. \end{subfigure}
  552. \end{figure}
  553. The \textit{Output} construct will first evaluate the element the 'value' link points to (Figure~\ref{fig:output_init}), and afterwards it puts the returnvalue in the output queue (Figure~\ref{fig:output_output}).
  554. The \textit{Input} construct will read the value that is in the input queue and put it in place of the returnvalue.
  555. No evaluation whatsoever is done on the values.
  556. \clearpage
  557. \subsection{Constant access}
  558. \begin{figure}[h!]
  559. \includegraphics[width=0.49\textwidth]{images/rule_const.eps}
  560. \caption{Constant access rule}
  561. \label{fig:rule_const}
  562. \end{figure}
  563. The \textit{Const} construct is used for constants, which are closely linked to the primitive data types presented in the Modelverse State.
  564. It is only used as an 'executable wrapper' for a literal: evaluation of this construct will yield the contained node (Figure~\ref{fig:rule_const}).
  565. The phase is also set to \textit{finish}, to indicate termination of the construct.
  566. \subsection{Helper rules}
  567. \begin{figure}[h!]
  568. \begin{subfigure}[b]{0.49\textwidth}
  569. \includegraphics[width=\textwidth]{images/rule_next__next.eps}
  570. \caption{Progress to the next instruction}
  571. \label{fig:rule_helper_a}
  572. \end{subfigure}
  573. \begin{subfigure}[b]{0.49\textwidth}
  574. \includegraphics[width=\textwidth]{images/rule_next__no-next.eps}
  575. \caption{Pop the next instruction from the stack}
  576. \label{fig:rule_helper_b}
  577. \end{subfigure}
  578. \caption{Next rules}
  579. \end{figure}
  580. When the instruction pointer points to an instruction which is marked as \textit{finish}ed, one of these helper rules becomes active.
  581. These are responsible for progressing towards the next instruction.
  582. Either there is a \textit{next} link (Figure~\ref{fig:rule_helper_a}), which links towards the next instruction to execute.
  583. If it is present, the instruction pointer is moved to this instruction, and the phase is reset to \textit{init} as it is the first time this construct is executed.
  584. In case no \textit{next} link exists (Figure~\ref{fig:rule_helper_b}), the next instruction is popped from the stack, together with its phase.
  585. This popping not only sets the instruction pointer, but also copies the saved phase, making it possible to progress where we left off.
  586. \clearpage
  587. \subsection{Declare}
  588. \begin{figure}[h!]
  589. \includegraphics[width=0.49\textwidth]{images/rule_declare__init.eps}
  590. \caption{Declare instruction}
  591. \label{fig:rule_declare__init}
  592. \end{figure}
  593. The Declare instruction will add the specified node to the symbol table, so that it can be assigned a value, or read out.
  594. As the declare does not take a value, the default value of the node is just an empty node.
  595. Future instructions can use the node connected to the Declare instruction to reference to the variable.
  596. \subsection{Global}
  597. \begin{figure}[h!]
  598. \includegraphics[width=0.49\textwidth]{images/rule_global__init.eps}
  599. \caption{Global declare instruction}
  600. \label{fig:rule_global__init}
  601. \end{figure}
  602. Apart from a declaration in the symbol table of the current user, it is also possible to declare it in the global namespace.
  603. This makes sure that other users can also find it and access the values.
  604. Its primary use will be function resolution though, as functions should be declared in a higher scope than the current scope.
  605. Nonetheless, it is possible to define everything else as a global too, making it accessible.
  606. \section{Primitive operations}
  607. As there are no special, built-in constructs for basic operations, such as mathematical operations, all of them have to map to a normal, user-level function.
  608. But these functions cannot implement the specified behaviour either, as the provided data values are MvS primitives.
  609. Such functions are primitive functions, which form the core of the MvK, and are hardcoded in the MvK implementation.
  610. Primitive functions are hardcoded functions in the MvK, which get loaded like normal operations (\textit{i.e.}, their parameters are evaluated and loaded on the stack).
  611. The execution of their body differs though, as it is executed without intermediate steps.
  612. As they cannot be written in Action Language, they do not have an implementation in the Action Language either.
  613. It is the MvK which recognizes that there is a primitive function available for the called function.
  614. If so, it calls the primitive instead of the (empty) body.
  615. To comply with our axioms (\axiomModelEverything), we need to model these functions explicitly.
  616. This can be done by taking the same approach as Squeak~\cite{Squeak}, where an interpreter is written in the interpreted language.
  617. Doing this, we can map the interpreted function (in the code being executed) to the primitive function of our used interpreter (in the implementation of the interpreter).
  618. Optionally, the interpreter could also be compiled, where these functions are then changed to primitive operations in the target language.
  619. The operations in Table~\ref{table:primitives_1} and~\ref{table:primitives_2} need to be defined as a primitive by all Modelverse Kernel implementations, with the specified semantics.
  620. None of them are allowed to modify any of the incoming parameters.
  621. Semantics are given in simple Python code.
  622. \begin{table}
  623. \center
  624. \begin{tabular}{llll}
  625. Name & Parameters & Returns & Semantics \\
  626. \hline
  627. \hline
  628. integer\_addition & $a$ : Integer; $b$ : Integer & $c$ : Integer & $c = a + b$ \\
  629. integer\_subtraction & $a$ : Integer; $b$ : Integer & $c$ : Integer & $c = a - b$ \\
  630. integer\_multiplication & $a$ : Integer; $b$ : Integer & $c$ : Integer & $c = a \times b$ \\
  631. integer\_division & $a$ : Integer; $b$ : Integer & $c$ : Integer & $c = a / b$ \\
  632. integer\_eq & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a == b$ \\
  633. integer\_neq & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a \neq b$ \\
  634. integer\_lt & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a < b$ \\
  635. integer\_lte & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a \leq b$ \\
  636. integer\_gt & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a > b$ \\
  637. integer\_gte & $a$ : Integer; $b$ : Integer & $c$ : Bool & $c = a \geq b$ \\
  638. integer\_neg & $a$ : Integer & $c$ : Bool & $c = -a$ \\
  639. \hline
  640. float\_addition & $a$ : Float; $b$ : Float & $c$ : Float & $c = a + b$ \\
  641. float\_subtraction & $a$ : Float; $b$ : Float & $c$ : Float & $c = a - b$ \\
  642. float\_multiplication & $a$ : Float; $b$ : Float & $c$ : Float & $c = a \times b$ \\
  643. float\_division & $a$ : Float; $b$ : Float & $c$ : Float & $c = a / b$ \\
  644. float\_eq & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a == b$ \\
  645. float\_neq & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a \neq b$ \\
  646. float\_lt & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a < b$ \\
  647. float\_lte & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a \leq b$ \\
  648. float\_gt & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a > b$ \\
  649. float\_gte & $a$ : Float; $b$ : Float & $c$ : Bool & $c = a \geq b$ \\
  650. float\_neg & $a$ : Float & $c$ : Bool & $c = -a$ \\
  651. \hline
  652. bool\_and & $a$ : Bool; $b$ : Bool & $c$ : Bool & $c = a \land b$ \\
  653. bool\_or & $a$ : Bool; $b$ : Bool & $c$ : Bool & $c = a \lor b$ \\
  654. bool\_not & $a$ : Bool & $c$ : Bool & $c = \neg a$ \\
  655. \hline
  656. list\_append & $a$ : Element; $b$ : Element & $a$ : Element & $a += b$ \\
  657. list\_insert & $a$ : Element; $b$ : Element; $c$ : Integer & $a$ : Element & $a.insert(b,c)$ \\
  658. list\_delete & $a$ : Element; $b$ : Integer & $a$ : Element & $a = a.pop(b)$ \\
  659. list\_len & $a$ : Element & $b$ : Integer & $b = len(a)$ \\
  660. \hline
  661. dict\_add & $a$ : Element; $b$ : Element, $c$ : Element & $a$ : Element & $a[b] = c$ \\
  662. dict\_delete & $a$ : Element; $b$ : Element & $a$ : Element & $delete~a[b]$ \\
  663. dict\_read & $a$ : Element; $b$ : Value & $c$ : Element & $c = a[b]$ \\
  664. dict\_read\_node& $a$ : Element; $b$ : Element & $c$ : Element & $c = a[b]$ \\
  665. dict\_len & $a$ : Element & $b$ : Integer & $b = len(a)$ \\
  666. dict\_in & $a$ : Element; $b$ : Value & $c$ : Boolean & $c = b in a$ \\
  667. dict\_in\_node & $a$ : Element; $b$ : Element & $c$ : Boolean & $c = b in a$ \\
  668. \hline
  669. string\_join & $a$ : String; $b$ : String & $c$ : String & $c = a . b$ \\
  670. string\_get & $a$ : String; $b$ : Integer & $c$ : String & $c = a[b]$ \\
  671. string\_substr & $a$ : String; $b$ : Integer; $c$ : Integer & $d$ : String & $d = a[b:c]$ \\
  672. string\_len & $a$ : String & $b$ : Integer & $b = len(a)$ \\
  673. \hline
  674. set\_add & $a$ : Element; $b$ : Element & $a$ : Element & $a.add(b)$ \\
  675. set\_pop & $a$ : Element & $b$ : Element & $b = a.pop()$ \\
  676. set\_remove & $a$ : Element; $b$ : Element & $a$ : Element & $a.remove(b)$ \\
  677. set\_in & $a$ : Element; $b$ : Element & $c$ : Boolean & $c = b in a$ \\
  678. \hline
  679. action\_eq & $a$ : Action; $b$ : Action & $c$ : Bool & $c = a == b$ \\
  680. action\_neq & $a$ : Action; $b$ : Action & $c$ : Bool & $c = a \neq b$ \\
  681. \hline
  682. type\_eq & $a$ : TypeType; $b$ : TypeType& $c$ : Bool & $c = a == b$ \\
  683. type\_neq & $a$ : TypeType; $b$ : TypeType& $c$ : Bool & $c = a \neq b$ \\
  684. \hline
  685. typeof & $a$ : Element & $b$ : TypeType & $b = type(a)$ \\
  686. \end{tabular}
  687. \caption{Primitive functions modifying primitive datavalues. If a Value is taken or returned, this refers to the value of the returned node.}
  688. \label{table:primitives_1}
  689. \end{table}
  690. \begin{table}
  691. \center
  692. \begin{tabular}{llll}
  693. Name & Parameters & Returns & Semantics \\
  694. \hline
  695. \hline
  696. cast\_i2f & $a$ : Integer & $b$ : Float & $b = float(a)$ \\
  697. cast\_i2s & $a$ : Integer & $b$ : String & $b = str(a)$ \\
  698. cast\_i2b & $a$ : Integer & $b$ : Bool & $b = bool(a)$ \\
  699. cast\_f2i & $a$ : Float & $b$ : Integer & $b = int(a)$ \\
  700. cast\_f2s & $a$ : Float & $b$ : String & $b = str(a)$ \\
  701. cast\_f2b & $a$ : Float & $b$ : Bool & $b = bool(a)$ \\
  702. cast\_s2i & $a$ : String & $b$ : Integer & $b = int(a)$ \\
  703. cast\_s2f & $a$ : String & $b$ : Float & $b = float(a)$ \\
  704. cast\_s2b & $a$ : String & $b$ : Bool & $b = bool(a)$ \\
  705. cast\_b2i & $a$ : Bool & $b$ : Integer & $b = int(a)$ \\
  706. cast\_b2f & $a$ : Bool & $b$ : Float & $b = float(a)$ \\
  707. cast\_b2s & $a$ : Bool & $b$ : String & $b = str(a)$ \\
  708. cast\_e2s & $a$ : Element & $b$ : String & $b = str(a)$ \\
  709. \hline
  710. create\_node & --- & $a$ : Element & create node and return ID \\
  711. create\_edge & $a$ : Element; $b$ : Element & $c$ : Edge & create edge from $a$ to $b$ and return ID \\
  712. create\_value & $a$ : Value & $b$ : Element & create node with value $a$ and return ID \\
  713. \hline
  714. is\_edge & $a$ : Element & $b$ : Boolean & return whether $a$ is an edge or not \\
  715. read\_nr\_out & $a$ : Element & $b$ : Integer & return number of outgoing links from $a$ \\
  716. read\_out & $a$ : Element; $b$ : Integer & $c$ : Element & return the $b$th element which has an outgoing link from $a$ \\
  717. read\_nr\_in & $a$ : Element & $b$ : Integer & return number of incoming links from $a$ \\
  718. read\_in & $a$ : Element; $b$ : Integer & $c$ : Element & return the $b$th element which has an incoming link from $a$ \\
  719. read\_edge\_src & $a$ : Edge & $b$ : Element & return the source of edge $a$ \\
  720. read\_edge\_dst & $a$ : Edge & $b$ : Element & return the destination of edge $a$ \\
  721. \hline
  722. delete\_element & $a$ : Element & $a$ : Boolean & delete element $a$ \\
  723. element\_eq & $a$ : Element; $b$ : Element & $c$ : Boolean & return whether or not $a$ and $b$ are exactly equal \\
  724. \hline
  725. deserialize & $a$ : String & $b$ : Element & merge serialized graph with current and return initial node \\
  726. \hline
  727. import\_node & $a$ : String & $b$ : Element & import a previously exported node \\
  728. export\_node & $a$ : String; $b$ : Element & $b$ : Element & export a node so it can be imported \\
  729. \hline
  730. \end{tabular}
  731. \caption{Lower-level primitive functions to implement. If a Value is taken or returned, this refers to the value of the returned node.}
  732. \label{table:primitives_2}
  733. \end{table}
  734. An MvK is free to implement additional functions as primitives, as long as each primitive instruction is guaranteed to terminate and does not violate the fairness between different users (\axiomMultiUser).
  735. Additionally, all additional functions need to have an equivalent implementation in Action Language for interoperability between different MvKs (\axiomInteroperability).
  736. To enforce this fairness, and guarantee that all users have a fairly low response time, an upper bound is placed on the time allocated for such a primitive.
  737. If the operation times out, the operations done by the primitive are ignored and the function is interpreted as usual.
  738. The mandatory primitive operations should never time out due to their simplicity.
  739. Modelled functions can therefore be compiled to new primitives for performance reasons (\axiomScalability): they get mapped to native code, and they no longer need to update the execution context after every instruction.
  740. As the execution context is not updated, primitive operations cannot be debugged easily.
  741. For debugging, the user needs to be able to toggle an \textit{interpreter-only} flag, which forces the Modelverse Kernel to execute in interpreter mode, bypassing all possible optimizations.
  742. This flag also requires the Modelverse Kernel to continuously update the execution context, as described in the previous sections.
  743. Execution of the primitives defined in Table~\ref{table:primitives_1} and~\ref{table:primitives_2} will still be through their hardcoded implementation though.
  744. As almost everything is a function call, including mathematical operations, no order of operations is imposed, apart from the one in the function calls.
  745. Instead, the user is required to expand this to the correct function call.
  746. Most users, however, will use an MvI with a parsed concrete syntax, which can generate an automatically modified abstract syntax graph from this.
  747. Therefore, the user might still be able to write $d = a + b * c$, as long as the MvI expands this to $d = integer\_add(a, integer\_mul(b, c))$, taking into account the typing and order of evaluation during parsing.
  748. This offloads the work required for the implementation of a MvK.
  749. Several primitive operations require some additional explanation:
  750. \begin{itemize}
  751. \item \textbf{float} operations only work on floats and not on integers, due to possible loss of accuracy.
  752. To get the desired results, explicit type conversions are required using the \textit{cast} operations.
  753. \item \textbf{string} operations work on both strings and characters, as a character is a string of length 1.
  754. \item \textbf{type} will return the type of the provided element.
  755. This is possible as types of primitives are primitive data values too.
  756. \item \textbf{cast} operations are used to switch between types.
  757. Casts from a string will try to parse the result, whereas casting to a string will pretty-print the value.
  758. Boolean True is equal to integers or floats different from 0 or 0.0, respectively.
  759. Conversion from float to integer is rounded \textit{down} if necessary.
  760. \item \textbf{create} operations are a one-to-one mapping with the MvS CRUD interface.
  761. \item \textbf{read\_nr\_(out/in)} returns the number of outgoing and incoming edges, respectively.
  762. \item \textbf{read\_(out/in)} returns the specified outgoing or incoming edge, respectively.
  763. \item \textbf{read\_dict} is a one-to-one mapping with the $R_{dict}$ MvS CRUD operation, thus reading out from the dictionary based on value in the node.
  764. \item \textbf{read\_dict} is a one-to-one mapping with the $R_{dict\_node}$ MvS CRUD operation, thus reading out from the dictionary based on the actual node.
  765. \item The \textbf{delete} operation will automatically determine the correct MvS delete operation to call.
  766. \end{itemize}
  767. \section{Interface}
  768. Since the MvK is not an autonomous process, it requires input from the user, and needs to forward output to the user when required.
  769. Therefore, an interface towards the MvI is required, which offers only two functions: add something to the input queue, and pop something from the output queue.
  770. This interface is sufficient to execute all operations, as the input value can be any element in the modelverse, for example a function signature or name to resolve and subsequently execute.
  771. While this makes the interface very minimal, it pushes all API definitions to the MvK itself, thus explicitly modelling parts that were normally hardcoded.
  772. Another advantage of this very versatile API, is that the MvK can be customized per-user.
  773. The running process of the user will just have to function as the API itself, and process all incoming messages.
  774. It also makes sure that all desired functionality is present, as users can manually implement it if necessary.
  775. We now formalize the behaviour of these two functions (\texttt{set\_input} and \texttt{get\_output}) just like the execution rules.
  776. It should be noted however, that these rules are not executed when they are applicable, but only when they are invoked through the API.
  777. The rules also reference elements that are passed to the invoking API call, and returns the marked node.
  778. \begin{figure}[h!]
  779. \begin{subfigure}[b]{0.49\textwidth}
  780. \includegraphics[width=\textwidth]{images/api_input.eps}
  781. \caption{API rule for input processing}
  782. \label{fig:api_input}
  783. \end{subfigure}
  784. \begin{subfigure}[b]{0.49\textwidth}
  785. \includegraphics[width=\textwidth]{images/api_output.eps}
  786. \caption{API rule for output processing}
  787. \label{fig:api_output}
  788. \end{subfigure}
  789. \caption{API rules}
  790. \end{figure}