.. include:: /std/localtoc.irst ======================================================= [DRAFT] Integration a FSM in CastleCode (experimenting) ======================================================= .. post:: :category: Castle, Language, rough :tags: Castle, DesignStudy, FSM As demanded by :need:`U_FSM_Syntax`, we need a syntax to define FSMs directly in CastleCode. The behavior of a FSM is defined by the its “rules”. But to use a FSM we need to “call” that FSM; it needs to proces events, either by *single stepping* or in a *for-ever-loop*. This is typically a details that most developers like to controll. |BR| And so we need a bit of syntax (and semantics) for it. A few experiments are already given in :ref:`FSM-rules-tries` -- which focus on the rules; and are mostly “internal” to the FSM. In this blog we focus and experiments on how to integrate the FSM with the “rest of the CastleCode”. |BR| Unlike the ‘states’ -- which are internal details of the FSM--, the events and actions are external -- its are the inputs and outputs of the FSM. So, the need to exist both ‘in’ and ‘outside’ the FSM. Intro ***** This blog shows a few possible implementations of a simle, well-known *Turnstile* FSM, to experiment with syntax options. We use a basic version, and we will extend it -- to show wat it does with the code. Questions ========= The experiments -- how to intergrade an FSM into CCastle focus around the following questions. .. include:: FSM-questions.irst Turnstile demo ============== We use a very simple -- 2 states, 2 events, 4 actions-- FSM called “Turnstile”. It has only 4 “rules”, and is easy to understand. |BR| Later, we will add more stated (requesting 2 coins) and/or non-FSM behavior, like counting the (total number of) coins .. include:: FSM-Turnstile.isrt Experimenting ************* .. caution:: Most of the shown CastleCode syntax is provisional. * Here, we use basic rule synax of :ref:`FSM-rules-try-1`, * I use ``@FSM`` (see: “:ref:`Rewriters`”) as a kind of (Python) (`decorator `__) or CPP2 [#cpp2]_ metafunction `(video-link) `__ * I use some “ad hoc syntax, for trivial thinks, I did’t design yet (e.g. Enum). * The order of names and typs are not consistent ``name ‘:’ type [‘:=’ value]`` vs ``type ‘:’ name`` -- sorry for that; my tought are not final, and my fingers type differently:-) .. _FSM_component: FSM as Component ================ When an component is implemented as an FSM (using the “:ref:`Rewriters`”: `@FSM`) the in-ports are used as FSM-inputs and the out-port can be used for actions. So, “calling” the FSM is like “calling” any other component: send signals over the connections. |BR| Note: There is no need to that alls FSM-inputs (nor it outputs) match 1:1 to the protocol of one port -- the can originate from multiple in-ports and protocols. .. include:: FSM-Turnstile-Basics.irst As you can see in the code above, *only* in the (component) implement it is shown it is (implemented as/with) an FSM. This a future implementation may be differently, without any change to it users. Eval (Component) ---------------- I like this variant! The Turnstile FSM shows that a basic FSM in this style is very clean, and simple. Later, we will it’s expandable to; see: :ref:`CountingTurnstile`. .. _FSM_function: FSM as function =============== As a FSM has *state* it can’t be a “`pure function `__” -- like a math-function: always returning the same answers on the same input, without side-effects. Pure function have great benefits for concurent computing. However, most programming “functions” are (typical) not pure, and “procedures” would be better name, most language uses the term function. |BR| In line with that, we use the term ‘function’ too; in a general way. In that view, having state is not an issue. Programming-functions can have “state”, by example by having a `static (local) variable `__, as in e.g. C/C++. |BR| The state of a FSM-as-functions is like a static. And as we can see below, it results in quite easy syntax. .. literalinclude:: code/Turnstile_FunSyntax.Castle :language: ReasonML There are some complication with this concept, however! When rewriting this FSM-function to a regular-function with a local static variable, there is **only one** (memory) place to store the state, even when that FSM is used at multiple places. |BR| So, we need a kind of variable-instance pro use of the same function -- that is what we typically call a class (see: `FSM_class`_, below). Another tough questions is how to use “call” it, and what does it return? |BR| Conceptually, a FSM does not “return” anything, so it would be a void function. We could return the action to be called -- which is a bit strange, but making the FSM call them is strange too. Simular, when calling: what parameter(s) to pass? |BR| In the example above, we pass the list of signals (as a Protocol), not the “current signal”. That “list” is needed as the rules use it -- we can’t compile (aka: verify) the transactions without the list. Again, this can solved in a class-alike setting, e.g. by introducing a “step” method; which passes the current signal. Eval (typical function) ----------------------- As shown above, using a FSM as a (classical) function is problematic. The syntax is easy to read & write, but the semantics are complicated. And even when it is possible, it not easy to use. So, this approach is *turned down*. Function syntax, to build a (local) component. ============================================== Another approach to use the function-syntax is to consider a FSM as a (kind of) iterator. Then the FSM-function becomes a `generator `__, as by example in Python. And the function --roughly as shown above-- returns an object that *is* the FSM. |BR| This solves most (all?) of the described complications. Returning a class-object ------------------------ In most languages an *iterator* is (like a) class-instance. So, it can store the state. When Calling the FSM-function twice, two independent FSMs “instance” --each with it own state-- are returned. |BR| Given the (returned) FSM is an instance, “calling” it becomes simple. We can have several (build-in) methods, like ``fsm.step()``. Admitting it solves the “calling” and some practical problems, other complications still arise. Like how to call the actions -- are the called by the FSM, or by the code that called the FSM? Both are possible, but not perfect. |BR| Another disadvantage is introducing “classes” (aslo see below). Classe are fine in most languages, but Castle is build around “components” -- more active, And with clean interface at the “backside”. And luckily, the is a better solution ... Returning a component-element ----------------------------- When the FSM-function returns a component-element (instead of a class-instance) all uncertainties are solved! After calling that FSM-function, we have a normal component (element) with input- and output-ports (both passed as parameter). Those port can be connected to other ports, or an input can be triggered like any component. And as the element is *active*, the actions of the FSM result in triggering other components/ports. The semantics of a FSM-function are exactly the same as for the FSM-component. Actually, the rewriter for a FSM-function will transform it to a “normal” FSM-component (and instantiate it). |BR| Mark that a FSM-component is also rewritten. So the FSM-function is rewritten twice. Both by the same @FSM rewriter. That however, is an implementation detail. It may be clear that there is no loop -- above we already shown that rewriting a FSM-component result is “base code”. The only questions is: **why?** (and which one) |BR| As the FSM-function and the FSM-component result in the same element, which one should we select? Or should we allow both? In many modern languages it is possible to define code in two (or more) ways. For example in python we can define functions with the ‘def’ keyword (the usual way), or as a nameless “lambda”. The same aplies to “classes”, and is valid in many languages. |BR| Typically, there is a “standard way”, for typical use. And a “shortcut” for small, only uses once case. The same can be useful for Castle, as we can see in a :ref:`CountingTurnstile` example. Eval (component-building function) ---------------------------------- It is possible use the function-syntax, when it results in a component-element. Although the syntax differs from the FSM-component (syntax), it has the same semantics. It have a certain beauty, but I’m not (yet) convinced that it has advantages to allow both syntaxes. And as the component one is closer to components (sic), the function variant is an option for now. Not more, not less. |BR| When I add it, there is no need to implement it in the “bootstrap” compilers. .. _FSM_class: FSM as (Data)Class ================== .. error:: Class? Of Data-Classes? Or Struct’s Until now, “classes” are hardly used in CCastle -- they are kind-of replace by Components. Components however are always “active”, and we may/probably need passive “data-clases” too -- e.g the AIGR has only data-clases. .. hint:: As an FSM has state and behavior, a class sounds better then a Data-Class/Structure. But is it .. hint:: As an FSM has *state*, it needs “memory”, and is typically implemented as a instantiated class in many language. .. Caution:: Some design-patterns use classes (with no data; and hardly an instance) for “hold” the callables for each state. That is more namespace then a class. And surely not a data-class Eval (Data/Class) ------------------ ToDo FSM is not a statement ======================= In the initial list of questions, I added the option “FSM as statement”. But in the analyse (above) it become clear that that doesn't is a valid option. Neither the syntax, nor the semantics are clear nor have any advantages. ------- .. rubric:: footnotes .. [#cpp2] CPP2 is a language-study by Herb Sutter, see https://herbsutter.com/?s=cpp2 and https://github.com/hsutter/cppfront, to make a “better, safer” C++. |BR| It has some goals that are comparable with my CCastle goals -- but restrics itself to be C++ (with good arguments). Herb has a lot of experience and deep-tought; and so is a good inspiration. ===== .. _CountingTurnstile: Counting Turnstile ********************* Using the Turnstile as a sub ============================ .. tabs:: .. tab:: interface .. literalinclude:: code/CountingTurnstile.Moat :language: ReasonML .. tab:: sub Turnstile .. literalinclude:: code/CountingTurnstile-sub.Castle :language: ReasonML .. tab:: Function syntax .. literalinclude:: code/CountingTurnstile-fun.Castle :language: ReasonML