Frame is a markdown language for creating state machines (automata) in 7 programming languages as well as generating UML documentation.

Overview

Frame Language Transpiler v0.5.1

Hi! So very glad you are interested in Frame. Frame system design markdown language for software architects and engineers. It is an easy to learn textual language for defining system specifications that can generate both UML documentation as well as code in 7 langauges.

Purpose

This project contains the code for building the Frame Language Transpiler - the Framepiler. The Framepiler is written in Rust and transpiles Frame specification documents into 6 programming languages (more to come) and UML documentation.

New in this release

This release brings a slew of features focused on Rust, Frame's newest language. All of these new capabilites are only implemented in Rust, but will be rolled out to other languages as they gain users and build a community.

  1. Configurable code generation
  2. Rust formatting improvements
  3. Code conforms more closely to rustfmt guidelines.
  4. Added introspection - codegen to discover the current state
  5. Added interface call syntax iface() - call the interface from event handlers.
  6. Rust Transition hook - inject a call to al trait function to log transition data.

Resources

The Frame project is just getting started but there are some resources and communities to help. You can now download VSCode and Atom extensions to work with Frame in these popular free development applications.

An online version of the Framepiler is also available and provides examples and links to other resources. You can learn more about the Frame language at frame-lang.org as well as find general resources about programming with automata at Reddit re on the r/statemachines subreddit.

Communities exist at Gitter and Discord.

Frame Examples

The Framepiler itself has a number of examples baked into it but I also have started a Gitter Frame Examples channel for contributions. The Framepiler supports links to Gists so please create and share!

The Frame Solution Depot is a Github repo and growing body of examples and test specifications. This is useful in conjunction with the VSCode and Atom extensions.

Bugs and Problems

For now please report issues to the Gitter Bug Channel while we get a better system in place. If you have a recommendation please let me know there!

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

Installing

MacOS

  1. Install Rust.
  2. Navigate to the framepiler/framec directory.
  3. Type cargo build. 3.a You will see a bunch of warnings. Apologies but this is pre-alpha code.
  4. Type ./target/debug/framec ../examples/HelloWorld.frm c_sharp. 4.a You should see a base class for a Frame controller generated to stdout.
  5. If you want to generate a release build: 5.a Type cargo build --release 5.b Type ./target/release/framec ../examples/HelloWorld.frm c_sharp
  6. You now have working debug and release Framepilers. Congratulations!
  7. You can try 6 other languages + Plant UML. Replace the c_sharp above with any of these: 7.a javascript 7.b cpp 7.c gdscript 7.d java_8 7.e plantuml (try output at PlantUml site) 7.f python_3 7.g rust (experimental - only partially implemented)

Linux

  1. Install Rust.
  2. Probably the same as MacOS but guessing you can figure it out if you know Linux and Rust. Still - please send me instructions on Gitter Bug Channel and I will add to next release notes. Thanks!

Windows

  1. Install Rust.
  2. Help needed. Please send me instructions on Gitter Bug Channel and I will add to next release notes. Thanks!

Built With

  • Rust - Rust language

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Author

  • Mark Truluck - Creator of Frame - LinkedIn

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Acknowledgments

Comments
  • Code doesn't follow rust style guide

    Code doesn't follow rust style guide

    Currently the code doesn't follow the rust style guide so running cargo fmt to help automate styling results in modifications to a lot of files.

    Would be nice to make it conformant running cargo fmt once and cheking in the results to allow devs to use cargo fmt going forward

    opened by fdlg 6
  • Add derived traits for state enum.

    Add derived traits for state enum.

    This adds derived traits to the state enum type for the Rust backend.

    It adds one new configuration option and two new attributes:

    • The config option state_enum_traits is a string defining the traits to derive by default for the state enum in every state machine. In the default config, this is set to Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord. The rationale for the large set of traits in the default config is to derive as many standard traits as possible by default, following the advice here, but of course this is easy to change.

    • The attribute override_state_enum_traits is a string that overrides the new configuration option for a given state machine. This is useful, for example, if you want to provide a custom implementation of one of the standard traits.

    • The attribute extend_state_enum_traits is a string that extends the list of derived traits. This is useful, for example, if you want to derive all of the default traits plus some additional traits that are specific to this state machine.

    One thing to note is that the new configuration option is Rust-specific, while the existing configuration options are relatively backend-agnostic. Currently, there's not a good place (as far as I know) to put backend-specific configuration options, so the only place it can go is in the global configuration file.

    opened by walkie 4
  • System Parameters not handled message parameter

    System Parameters not handled message parameter

    I have found a bug in frame demos in system parameters. some code lines are missing. msg is not handled by code.

    params := make(map[string]interface{}) params["msg"] = msg;

    image

    bug 
    opened by deepaksharmaongraph 3
  • Add file name of source Frame spec to MachineInfo

    Add file name of source Frame spec to MachineInfo

    We have a scenario where we need to know the file name of the Frame spec that generated a particular state machine. This can easily be added to the MachineInfo struct available via the runtime system (in the Rust backend).

    It'd be easy to store the whole source file path there, but that might encourage some hacky/non-portable uses, so not sure whether that's a good idea... Maybe it's OK to provide it as long as it's just documented accordingly?

    enhancement 
    opened by walkie 3
  • Rust output incomplete - StateContext

    Rust output incomplete - StateContext

    I'm guessing this is already known as Rust support is incomplete, but I thought I'd drop an issue as it's one of the few remaining issues I'm seeing. Presently, I can compile Rust output from Frame files that don't include heirarchical state machines, but if there's hierarchy they fail on *_state() functions that include this line in interface event handler code:

    StateContext stateContext = null;
    

    Error: error: expected one of '!', '.', '::', ';', '?', '{', '}', or an operator, found 'stateContext'

    opened by bradnelson 3
  • Add event history to Rust runtime interface

    Add event history to Rust runtime interface

    For visualization and debugging, it could be useful to have access to the history of Frame events for a given state machine.

    This would be a bit more work than it seems because currently events live on the stack in the Rust backend, so we'd need to change the generated code to use Rc everywhere for events when the runtime system is enabled.

    opened by walkie 2
  • Disappearing `!` in conditions

    Disappearing `!` in conditions

    I've fixed a couple bugs related to this issue already, but it seems it's still around.

    This conditional:

    !mode_normal() || none_source() ? -> "Mode != Normal || Source == None" $Entry : :: ^
    

    Generates this code on v0.6.0:

                FrameMessage::FormingSourceChanged => {
                    if self.mode_normal() || self.none_source() {
                        // Start transition
                        // Mode != Normal || Source == None
    

    This case can probably be simplified a bit.

    Thanks to @fdlg for reporting.

    opened by walkie 2
  • New and improved configuration system

    New and improved configuration system

    This PR overhauls Frame's configuration system.

    Before

    Previously, Frame was configured via a config.yaml file in the current working directory. If this file was absent, Frame would copy a default_config.yaml file into the current working directory and proceed. If a configuration option was missing from config.yaml, Frame would default to false for Boolean options and the empty string for String options.

    Problems

    • The defaulting behavior combined with the auto-generated config.yaml was a constant source of confusion and pain whenever a new config option was added to Frame (which so far has been frequently!). After an update, Frame would silently generate code that wouldn't compile. The solution was to simply delete the local config.yaml to pull in the new defaults, but this was not obvious from the errors and it loses any local configuration you have done.

    • It was very difficult to have multiple different state machines generated with different configurations. This was especially a problem during testing since we were essentially only testing the "all-on" configuration.

    • The fundamental reliance on the file system broke the WASM interface, which hasn't worked since the config file was added.

    Now

    The new approach to configuration is defined in framec/src/frame_c/config.rs. A configuration is a value of the FrameConfig struct. The configuration used while compiling a Frame spec is built up in three stages:

    1. Initially, a default FrameConfig value is created using Rust's standard Default trait, i.e. FrameConfig::default().

    2. Any configuration options specified in a local config.yaml file will override the values in the default. The format of these config.yaml is almost identical to the format before this change. The only difference is that fields that were previously empty must now be set to {}.

    3. Configuration options can now be set directly in a Frame spec using Frame's existing attribute system.

    The name of the attribute for each option consists of a prefix and a path. The feature: prefix indicates a Boolean configuration option, while code: indicates a String configuration option. The path component of the name corresponds to the full path of the option in the corresponding YAML representation.

    For example, to enable the runtime_support feature, one could include the following attribute in the Frame spec:

    #[feature:codegen.rust.features.runtime_support="true"]
    

    The feature: and code: prefixes could easily be changed, but currently all Boolean options correspond to feature options, and all String options correspond to changing names involved in code-generation, and I thought these prefixes were nicer than bool: and string:. However, they may be less future-proof.

    I also added a new --generate-config (-g) option to the CLI, which generates a config.yaml file in the current working directory populated with the default settings. This recovers one of the nice aspects of the original solution, which is that you get a ready-to-edit config file.

    Advantages

    • A local config.yaml file is no longer required. This should fix the WASM interface.

    • Missing options in the local config.yaml file no longer cause compile errors since these now fallback on sane defaults.

    • This model supports sharing a set of configurations among several state machines (in a config.yaml) and also easily overriding some for individual state machines (via the attribute interface).

    • Frame can now be configured in the online Framepiler (once it's updated to this version) since config options can be set directly from Frame specs via attributes.

    • We can now actually test Frame with different combinations of features!

    Technical details

    The new config system is implemented using the Figment crate.

    It was super easy to implement the defaults and the YAML interface using this library. For the attribute interface, I wrote a custom Figment Provider implementation for SystemNode that extracts all attribute nodes from a Frame spec and updates the configuration accordingly.

    This should make it much easier to add configurability to other backends in the future. I was able to remove several hundred lines of code that were specific to the Rust backend, so this is now code that doesn't need to be duplicated in other backends.

    Heads up that I extended Frame's parser to recognize the attribute name syntax described above.

    Other changes

    Besides overhauling the config interface. This PR makes the following changes:

    • It restores the generate_hook_methods feature. Previously I removed this since the functionality overlaps with the runtime_support feature. However, after thinking about this some more (and seeing some ways folks in our team are using it), I realized there are compelling use cases for both approaches, and even both in tandem. It is disabled by default.

    • I disabled the runtime_support feature by default since it complicates the types in the generated code.

    • Added more tests and fixes now that we can locally configure test cases.

    opened by walkie 2
  • Stack Pop method not specify the return type

    Stack Pop method not specify the return type

    Need to specify the return type as currently handled through any

    func (s *Stack) Pop() any { -------------> compartment type??
    
        if s.stack.Len() == 0 {
            return nil
        }
        
        tail := s.stack.Back()
        val := tail.Value
        s.stack.Remove(tail)
        return val
    }
    
    golang 
    opened by deepaksharmaongraph 1
  • string literal not properly handled in golang

    string literal not properly handled in golang

    -domain- var tape:Log = `vec![]`

    results in:

    /Users/marktruluck/projects/frame_transpiler/target/debug/framec -l golang /Users/marktruluck/projects/frame-demos/go/v0.10.0_tests/scratch2.frm TODO: visit_literal_expression_node_to_string

    Process finished with exit code 0

    opened by frame-lang 1
  • System parameters don't throw errors

    System parameters don't throw errors

    If a system parameter is specified but there isn't a matching parameter or variable the parser doesn't throw an error.

    #SystemParams [msg:string]
    
    -domain-
    
    ##
    

    Should throw an error about missing domain variable.

    bug 
    opened by frame-lang 1
  • Compartment pointer are not deep copied in stack.

    Compartment pointer are not deep copied in stack.

    I have got an issue while pushing the compartment pointer in the stack when I update the value outside the stack, the pointer value changes inside the stack. Deep copy of pointer is not handled.

            sm.To_c()
    	sm.Inc()
    	sm.Inc()
    	sm.Inc()
    	sm.Push()
    	assert.Equal(t, StateContextStackState_C, x._compartment_.State)
    	assert.Equal(t, 30, sm.Value()) ------------------> push 30
    	sm.Inc()
    	assert.Equal(t, 40, sm.Value()) // forgotten --------------> change pointer value 40
    
    	sm.To_a()
    	sm.Inc()
    	assert.Equal(t, StateContextStackState_A, x._compartment_.State)
    	assert.Equal(t, 1, sm.Value())
    
    	sm.Pop()
    	assert.Equal(t, StateContextStackState_C, x._compartment_.State)
    	assert.Equal(t, 30, sm.Value())  // ---------------------------------> expected 30 but actual 40
    

    Reference files : click

    opened by deepaksharmaongraph 0
  • Issues w/ calls aliasing interface methods

    Issues w/ calls aliasing interface methods

    Look for this in parser:

    // TODO - need to check call args to confirm if matche at least number of params in interface

    Issue is what to do if there is an id match but not number of parameters? Currently it doesn't validate parameter count.

    Also, in the future type checking needs to be done if a statically typed target.

    enhancement 
    opened by frame-lang 0
  • Parser not catching transition parameter mismatches

    Parser not catching transition parameter mismatches

    Currently the transition from $S1 to $S0 does not error. There are a few other conditions that should be accounted for:

    #TransitionEventForwarding $[x:int] >[cycles:int]
    
        -machine-
    
        $S0 [x:int]
            |>| [y:int] ^
    
                
        $S1 [x:int]
            |e1| -> $S0 ^ --- should error as transition needs to supply the state and enter params
            |e11| -> (1) $S0(2) ^ --- is ok
            |e2| [y:int] -> => $S0 ^  --- is ok as forwarded event has state and enter params.
            |e3| -> => $S0 ^ --- should error as forwarded event does not have [y:int]
            |e4| -> (1) => $S0 ^ --- is ok as transition enter param is added
            |e5| [y:int] -> (2) => $S0(3) ^ --- should be permitted as both state and enter params are overridden.
    
    ##
    
    opened by frame-lang 0
  • Explore event forwarding parameter issues

    Explore event forwarding parameter issues

    Currently, an event forward disallows passing an enter event parameter during a forward. Not sure about state parameter, but it may be interesting to permit overrides of the forwarded parameters.

        $S1
            |>| [cycles:int] (2) -> (1) => $S0(3) ^
    
    opened by frame-lang 0
Releases(v0.10.0)
  • v0.10.0(Aug 31, 2022)

    Frame v0.10.0 brings a lot of exciting additions to the Frame language, adding both power and standardization to the notation. In addition, the transpiler now can read from stdin as well as still accepting file paths as in the past. This enables improved CI/CD processes involving Frame.

    New Language Features

    Note: The new language features are now supported in Golang, Javascript, Python3. Other languages will be supported in coming releases.

    • Compartments - v0.10 formalizes the idea of state closures called Compartments. Compartments are data structures that hold a state's local data as well as other metadata enabling new advanced features like Event Forwarding (see below).
    • Deferred transitions - deferred transitions address challenges with the previous approach of executing a transition immediately when called. Each immediate transition makes a function call and under certain situations, can blow up the stack if too many occur before returning to the caller. Deferred transitions avoid this situation and enable Frame controllers to make any number of sequential transitions. This architecture change enables Frame controllers to be launched as background daemons that run indefinitely until stopped as well as to be used to solve iterative problems.
    • System parameters - system parameters enable initializing the system in a more standardized, flexible and direct manner. This includes syntax for setting the start state parameters, the start state's enter parameters as well as override domain variable initialization. This change normalizes the start state to behave like all other states in the machine.
    • Event forwarding - event forwarding syntax enables passing events from one state to another. This capability enables system designers to easily receive events in one state and forward them on to other states that can handle them appropriately.
    • Persistance - A new system attribute enables code generation for Marshaling and Unmarshaling system data as JSON.

    Stdin support

    The CLI has been updated to support stdin:

    framec -language rust < HelloWorld.frm > HelloWorld.rs

    or

    cat HellowWorld.frm | framec -language golang > HellowWorld.go

    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Apr 9, 2022)

    Frame v0.9.0 brings a lot of exciting additions to the Frame language, adding both power and standardization to the notation. In addition, the transpiler now can read from stdin as well as still accepting file paths as in the past. This enables improved CI/CD processes involving Frame.

    New Language Features

    Note: The new language features are currently only supported in Golang. Other languages will be supported in coming releases.

    • Compartments - v0.9 formalizes the idea of state closures called Compartments. Compartments are data structures that hold a state's local data as well as other metadata enabling new advanced features like Event Forwarding (see below).
    • Deferred transitions - deferred transitions address challenges with the previous approach of executing a transition immediately when called. Each immediate transition makes a function call and under certain situations, can blow up the stack if too many occur before returning to the caller. Deferred transitions avoid this situation and enable Frame controllers to make any number of sequential transitions. This architecture change enables Frame controllers to be launched as background daemons that run indefinitely until stopped as well as to be used to solve iterative problems.
    • System parameters - system parameters enable initializing the system in a more standardized, flexible and direct manner. This includes syntax for setting the start state parameters, the start state's enter parameters as well as override domain variable initialization. This change normalizes the start state to behave like all other states in the machine.
    • Event forwarding - event forwarding syntax enables passing events from one state to another. This capability enables system designers to easily receive events in one state and forward them on to other states that can handle them appropriately.
    • Persistance - A new system attribute enables code generation for Marshaling and Unmarshaling system data as JSON.

    Stdin support

    The CLI has been updated to support stdin:

    framec -language rust < HelloWorld.frm > HelloWorld.rs

    or

    cat HellowWorld.frm | framec -language golang > HellowWorld.go

    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Feb 23, 2022)

    This release adds a new crate frame_build that provides a configurable build process for compiling Frame source files as part of building a larger Rust package.

    See the crate's documentation for instructions on how to use it and for some brief notes on how best to integrate Frame and Rust.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.5(Feb 9, 2022)

    This release makes information about the Frame specification file that was used to generate a state machine available via the runtime system for the Rust backend. Specifically, it adds the path to the .frm file passed to Framec, as well as a SHA-256 hash of that file, which can be used to verify that a state machine was generated by the expected version of the specification.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.4(Feb 7, 2022)

    This release adds golang as the latest Frame language target.

    Full Changelog: https://github.com/frame-lang/frame_transpiler/compare/v0.7.3...v0.7.4

    Source code(tar.gz)
    Source code(zip)
  • v0.7.3(Jan 5, 2022)

    This release refactors the runtime interface to reduce its impact on the types of generated code, and to make it easier to program against in a generic way. In particular:

    • The interface is no longer split into sync/unsync variants corresponding to whether the thread_safe feature is enabled or not. The traits instead contain associated types and type bounds that enable them to work with both variations of the generated code.

    • The runtime interface no longer requires a lifetime annotation on the machine type.

    The new trait bounds on the Machine type must often be propagated to use sites. Additionally callbacks must now own all their references, and the type annotations required on callback arguments have gotten a bit more complicated. See the frame_runtime documentation for details on these issues.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.2(Dec 8, 2021)

    This release adds a new feature to the Rust backend: codegen.rust.features.thread_safe.

    Generating Send- and Sync-compatible state machines

    When the new thread_safe feature is enabled, Framec will generate a state machine that implements Rust's standard Send and Sync traits, as long as all of declared domain variables also implement these traits.

    The feature is disabled by default.

    Impact on the runtime interface

    By far the biggest impact of the new thread_safe feature is on the runtime interface (see the Release Notes for v0.7.0 and v0.7.1), which has been split into two variants:

    • frame_runtime::sync, which is implemented by machines compiled with runtime_support=true and thread_safe=true

    • frame_runtime::unsync, which is implemented by machines compiled with runtime_support=true and thread_safe=false

    Note that the treatment of environments in the sync runtime interface is less efficient than in the unsync variant, and the sync variant also requires that all domain variables implement Clone. These issues/limitations may be resolved in the future.

    Source code(tar.gz)
    Source code(zip)
  • v0.7.1(Nov 23, 2021)

    This release adds a bunch of new functionality to the Rust runtime interface. As before, runtime support can be enabled by configuring Framec with codegen.rust.features.runtime_support=true.

    Live rendering of state machines to smcat

    Framec already supported rendering state machines can now be rendered to smcat. However, now this can be done for live state machines via the runtime interface. The advantage of doing this at runtime is that we can modify the visualization to reflect things like the currently active state and the last transition.

    The rendering interface includes a lot of configurability in the styling of generated smcat visualizations. Two built-in styles are provided: a SimpleStyle that embeds simple styling info directly in the smcat file (e.g. highlighting the active state by thick red lines), and a CssStyle that generates an smcat file where each element is annotated by CSS classes that can be styled in a separate CSS file.

    For more details, see the code and documentation at frame_runtime::smcat.

    New callback interface for events

    Frame events include interface method calls and state enter/exit events--basically, anything that can be handled in Frame by defining a corresponding handler associated with a state.

    You can now register callbacks to be notified of Frame events. Callbacks can be registered via two methods, both associated with the EventMonitor obtainable via the runtime interface from a state machine instance:

    • add_event_sent_callback -- Adds a callback that will be invoked whenever an event is sent.
    • add_event_handled_callback -- Adds a callback that will be invoked whenever an event has been completely handled.

    The sent callbacks will be invoked for events in the more intuitive order. For example, if calling method m triggers a transition from state A to state B, then the callbacks will be invoked for events "m" (the method call), "A:<" (old state exit event), and "B:>" (new state enter event), in that order. However, because the handler for m will not have terminated yet until the transition is complete, the event "m" received by the callback will not yet contain the return value of m (since it hasn't been computed yet).

    The handled callbacks will be invoked when the handlers for each event have completed. So, for the scenario above, the callbacks will be invoked in the order "A:<", "B:>", "m", since the handler for m doesn't terminate until after the transition. However, in this case, the event "m" received by the callback will contain the return value.

    In all cases, the events received by the callback are references wrapped in Rc<..>, so they can be freely saved. The return value for an event received via a sent callback will be updated when the handler terminates, so if this event is saved, it's return value will be accessible later.

    Most clients will probably want to be notified of events in the more intuitive order provided by add_event_sent_callback. However, add_event_handled_callback is provided in case the return value is needed at the time the callback is invoked.

    Configurable event and transition history

    The runtime interface (again via the EventMonitor) now maintains a history of recent events and transitions. The histories can be obtained via get_event_history and get_transition_history.

    The length of history maintained can be configured via set_event_history_capacity and set_transition_history_capacity, which take values of type Option<usize>. A None value indicates an unbounded history, while Some(n) indicates a history bounded to size n. The history feature can be disabled by setting the capacity to Some(0).

    By default, the history capacities are set to Some(0) (disabled) for the event history and Some(1) (maintain the last transition only) for the transition history. This minimizes memory impact if these features are not needed.

    The default values can be configured via the new Framec configuration options codegen.rust.runtime.event_history_capacity and codegen.rust.runtime.transition_history_capacity, configurable via YAML or the attribute system, as usual. As with the built-in defaults, these can be overridden at runtime using the set_ methods listed above.

    Events in the event history are listed in the order the events were sent. The history stores Rc<..> references to each event, which will be updated as the event is handled. In particular, the return value of an event (if any) will be set once the event has been fully handled.

    Smaller changes

    The runtime interface now provides the following additional features:

    • A method to get the initial state from a state machine.
    • A method to get all top-level states from a machine.
    • A unique ID is associated with each transition to enable disambiguating between multiple transitions between the same two states.
    • A convenience method to get the last transition from the transition history.
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Nov 1, 2021)

    This release includes two major new features and several small improvements and bug fixes.

    Runtime system for Rust

    The biggest new feature of this release is an optional Frame runtime system for Rust. The runtime system can be used by doing the following:

    1. Compile your Frame spec to Rust with the runtime_support feature enabled.
    2. Include the new frame_runtime crate in your project that uses the generated state machine.

    The runtime system provides comprehensive introspection of state machines generated by Frame, and some simple monitoring capabilities that will likely be expanded in the future. More specifically:

    • For any state machine generated by Frame:
      • Enumerate its states, domain variables, events, actions, and edges (potential transitions).
      • Get hierarchy information for states within a machine.
      • For each state: enumerate its parameters and variables, the handlers it defines, and its incoming and outgoing edges.
      • For each edge within the machine: get its kind (transition/change-state), source, target, triggering event, and label.
    • For a currently running state machine:
      • Get the current values of all domain variables.
      • Get the currently active state and the values of its parameters and variables.
      • Register callbacks to be notified of any transitions that occur.
      • For transition notifications, get access to the values of enter/exit arguments.

    New configuration system

    Frame's configuration system has been overhauled to make it simpler and more flexible to use going forward.

    Frame can still be configured using a config.yaml file in the current working directory, but this file is no longer mandatory and no longer needs to contain a complete set of configuration values. Instead, the file may contain only the values the user chooses to override.

    A default config.yaml file can be generated by running:

    framec --generate-config
    

    This file will contain a complete set of configuration options initialized to the default values.

    Additionally, Frame can now be configured through attributes embedded directly in Frame specifications. These attributes use the syntax #[path.to.config.option:type="value"] where path.to.config.option is the full path of the configuration option in config.yaml; type is one of bool, int, or str depending on the type of the configuration option; and value is the value to set it to.

    For example, to enable the new runtime_support feature for a particular state machine, one could either set the following option in config.yaml:

    codegen:
      rust:
        features:
          runtime_support: true
    

    Or include the following attribute setting at the top of the corresponding .frm file:

    #[codegen.rust.features.runtime_support:bool="true"]
    

    An advantage of the attribute interface is that it enables configuring two different state machines in the same project differently.

    Other fixes and improvements

    • (Feature) Added configurable style attributes to the output generated by the smcat backend.
    • (Bug fix) Can now directly invoke event handlers from within Frame, even in state machines that require a state context. Note that for now, direct handler invocations must occur as the last step in the calling handler. This constraint may be lifted in the future.
    • (Bug fix) State stacks now push a snapshot of the current state context rather than a reference. This means that changes after a state is pushed will not be reflected when that state is restored later by a pop.
    • (Code cleanup) Fixed or suppressed all outstanding cargo clippy warnings and added clippy to Github Actions to be applied on every push.
    • (Code cleanup) Simplified the visitor interface a bit, enabling the removal of over 3000 lines of code!
    • Lots of new tests!
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Sep 30, 2021)

    This release includes a lot of work on the Rust back-end:

    • New feature: the current state of the machine is stored as a value of a simple enum type, which can be accessed to determine the state of a running machine.

    • New feature: a new follow_rust_naming feature option has been added and enabled by default. This option significantly improves the conformance of generated code with Rust naming conventions and style guidelines.

    • New feature: a new generate_hook_methods feature option has been added that generates methods that are invoked on each transition or change-state. The names of these methods can be configured via config.yaml.

    • Completed feature: hierarchical state machines. This enables defining states as children of other states. Event handlers on child states may defer to the corresponding handler on a parent state by terminating the child handler with the "continue" terminator :>. The parent handler will be immediately invoked after a child handler that terminates in :>, if the child handler does not otherwise transition or return.

    • Completed feature: change-state transitions. Change-states (->>) are transitions that do not trigger the usual exit/enter events. Previously, this feature only worked for simple states (states without variables, parameters, or enter event arguments). Now it works in all expected scenarios.

    • Completed feature: state stacks/history. This feature enables pushing states (with corresponding state variables and arguments) to a stack. These states can later be returned to by a "pop transition" using the syntax -> $$[-]. This pops a state from the stack and restores the machine to that state.

    • Refactors and simplifies the generated code, particularly the representation of states and the initialization of state contexts.

    • More names in the generated code are now customizable via the config.yaml interface.

    • Significantly improved test coverage and corresponding bug fixes:

      • Initial states are now initialized correctly and may contain state variables and enter parameters.
      • Transitions inside of match or conditional statements now terminate the execution of a handler.
      • Negated conditional statements (?!) now work as expected.
      • ... and many more!
    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Aug 12, 2021)

    This version adds some powerful new features, but focused initially on Rust code generation. Over the coming releases they will be implemented in the other languages. These features include:

    1. Configurable code generation
    2. Rust formatting improvements
    3. Code conforms more closely to rustfmt guidelines.
    4. Added introspection - codegen to discover the current state
    5. Added interface call syntax iface() - call the interface from event handlers.
    6. Rust Transition hook - inject a call to a trait function to log transition data.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Jun 27, 2021)

  • v0.4.1(Jun 24, 2021)

    This release brings the Rust code generation into parity with the other languages as well as introducing new syntax for references (the & operator).

    It has been tested against the language feature examples in the solution depot repo: https://github.com/frame-lang/frame_solution_depot.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jun 1, 2021)

    The v0.4.0 release includes the following changes:

    1. Removed all compiler warnings.
    2. Added partial support for Rust.
    3. Added language support for language override attribute on system (#[language="python_3"])
    4. Fixed transpiler warnings bug with bad line numbers.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.48(Apr 29, 2021)

Owner
Mark Truluck
I am a software engineering manager with a passion for software modeling.
Mark Truluck
Cassette A simple, single-future, non-blocking executor intended for building state machines.

Cassette A simple, single-future, non-blocking executor intended for building state machines. Designed to be no-std and embedded friendly. This execut

James Munns 50 Jan 2, 2023
Provably optimal zero-copy parsers using nondeterministic finite automata.

inator: an evil parsing library You supply the evil plan; we supply the -inator! or, Provably Optimal Zero-Copy Parsers with Nondeterministic Finite A

Will Sturgeon 51 Oct 4, 2023
LIBFFM - field-aware factorization machines - in Rust

LIBFFM Rust LIBFFM - field-aware factorization machines - in Rust Getting Started LIBFFM Rust is available as a Rust library and a command line tool.

Andrew Kane 1 Jan 8, 2022
Symbolically Executable Stack Machines in Rust

Symbolically Executable Stack Machines in Rust Symbolic Stack Machines is a library for implementing symbolically executable stack-based virtual machi

TannrA 64 Dec 28, 2022
Envwoman is an application, to sync your .env-files across multiple machines

Envwoman is an application, to sync your .env-files across multiple machines. The main goal is to make Envwoman secure and trustworthy, so everything is open-source and the data will never in plain-text on the server. Encryption happens client-sided via aes-gcm.

Mawoka 3 Sep 28, 2022
Source code and documentation for our 'full stack on rust' meetup on 29-9-2022

Full stack on Rust This is the code and documentation repository for our 'Full stack on Rust' meetup on 29-9-2022. It includes step-by-step documentat

Baseflow 7 Oct 23, 2022
Achieve it! How you ask? Well, it's pretty simple; just use greatness!

Greatness! Achieve it! How you ask? Well, it's pretty simple; just use greatness! Disclaimer I do not believe that greatness is the best. It fits a me

Isacc Barker (Milo Banks) 107 Sep 28, 2022
Annoyed that Rust has many string types? Well it doesn't have to

generic-str The one true string type in Rust! This project intends to be a proof-of-concept for an idea I had a few months back. There is lots of unsa

Conrad Ludgate 40 Apr 9, 2022
tr-lang is a language that aims to bring programming language syntax closer to Turkish.

tr-lang Made with ❤️ in ???? tr-lang is a language that aims to bring programming language syntax closer to Turkish. tr-lang is a stack based language

Kerem Göksu 10 Apr 2, 2022
Generate markdown footer links.

WIP Generate markdown footer links.

Arijit Basu 8 Nov 20, 2022
Solutions of Advent of Code 2021 in Rust, and some other languages.

advent-of-rust Solutions of Advent of Code 2021 in Rust, and some other languages. Puzzles Puzzle Stars Languages Day 1: Sonar Sweep ⭐ ⭐ Rust Python D

rene-d 6 Jan 7, 2023
An upper-level course for CS majors on formal languages theory and compilers.

CS4100 Introduction to Formal Languages and Compilers Spring 2022 An upper-level course for CS majors on formal languages theory and compilers. Topics

null 2 May 28, 2022
Generating the nth Fibonacci number

Generating the nth Fibonacci number Per Wikipedia, "In mathematics, the Fibonacci numbers, commonly denoted Fn, form a sequence, called the Fibonacci

Charles 3 Dec 19, 2021
proc macros for generating mut and non-mut methods without duplicating code

mwt Hey! You! Read this before using! mwt was thrown together pretty quickly for personal use, because I couldn't find an existing crate that does thi

null 1 Dec 24, 2021
A library for parsing and generating ESP-IDF partition tables

esp-idf-part A library for parsing and generating ESP-IDF partition tables. Supports parsing from and generating to both CSV and binary formats. This

esp-rs 5 Nov 16, 2022
Web service generating images of Japanese (Riichi) Mahjong hands.

chombo-gen ChomboGen is a web service that allows to generate images of Japanese (Riichi) Mahjong hands. The hands are provided in a text format and a

Mateusz Maćkowski 5 May 2, 2023
The Solid-State Register Allocator

The Solid-State Register Allocator A simple, extremely fast, reverse linear scan register allocator. See the detailed write-up for an in-depth explana

Matt Keeter 66 Dec 13, 2022
Here are a few cargo-generate templates for use when creating bevy applications

Bevy-template-rs Here are a few cargo-generate templates for use when creating bevy applications. Templates Game This is a template for starting a new

Johnny Tidemand Vestergaard 19 Nov 4, 2022
Powerfull Discord Raid Bot written in Rust, use VPN / Proxy because creating 200 channels in 10s Will ratelimit you.

Harakiri-Rust This the first Discord Raid Bot made in RustLang I recommend you use with a VPN or a Proxy to evade Discord Ratelimit. If bot doesn't st

Marco 6 May 1, 2023