The Framepiler compiles Frame state machines to native targets (Python, TypeScript, GraphViz). It is written in Rust.
Start here:
- Developer guide: docs/HOW_TO.md
- Architecture: docs/framepiler_design/architecture.md
- Documentation index: docs/README.md
Current Version: v0.86.25 Branch: going_native Focus: Native‑first bodies, SOL‑anchored Frame statements in handlers, strong validation. LLVM is on indefinite hold.
Frame programs run atop two generated layers:
| Layer | Purpose |
|---|---|
| FrameRuntime | Implements language semantics (state machine scheduling, Frame collections, truthiness helpers). Emitted automatically per target; user code should never reference it directly. |
| FID + Native Modules | Frame Interface Definitions (FID) describe external capabilities (networking, filesystem, process control, timers, etc.), which are fulfilled by native modules in MixedBody regions for each target. |
Keep language behavior in the runtime, and use FID + native modules for capabilities. The historical FSL abstraction has been removed.
| Target | Package | Notes |
|---|---|---|
| Python | frame_runtime_py |
Generated Python files import from frame_runtime_py import FrameEvent, FrameCompartment; framec and frame_build drop the package automatically next to emitted code (single-file CLI runs embed a minimal fallback). |
| TypeScript | frame_runtime_ts |
Multi-file TypeScript builds emit import { … } from "./frame_runtime_ts"; the CLI and frame_build copy frame_runtime_ts/index.ts into the output directory, while single-file generation still embeds the bundle for convenience. |
-
Native bodies by default; MixedBody is authoritative only in event handlers.
-
Actions/operations are native‑only;
system.returnis supported for return assignment. -
SOL‑anchored Frame statements in handlers:
->,=> $^,$$[+/-],system.return. -
Per‑language body boundary via DPDAs (TS template/backtick‑aware, Py triple‑quote/f‑string‑aware).
-
Validation: transitions must be terminal (enforced), Python native policy, negative pattern checks.
-
LLVM runtime stores event payloads as typed
StateValues so queue replay, parent forwarding, and enter hooks preserve interface arguments. -
Builder surfaces interface metadata to
SystemSummary, enabling both handler generation and main-function calls to coerce arguments correctly. -
LLVM smoke suite expanded to 18 fixtures covering state/enter args, parent forwarding, event parameters, and multi-pop stack semantics.
-
Python and TypeScript suites remain green (895 specs) while native backend work stays Mac-first and fully integrated into CI.
-
LLVM Typed Events (v0.86.25): Runtime/FFI expose push/get helpers so interface parameters survive queued dispatch, parent forwards, and re-entry.
-
Main Call Support (v0.86.25): LLVM interface invocations in
mainaccept literal expressions and domain field references, automatically coercing to declared parameter kinds. -
Smoke Coverage (v0.86.25): Added
test_state_parameters_basic.frm,test_enter_args.frm,test_parent_forward_enter_args.frm,test_event_parameters.frm, andtest_state_stack_multi_pop.frm; suite now passes 18/18. -
LLVM Domain Actions (v0.86.22): The experimental LLVM backend now lowers actions, expands domain assignments, and supports string/bool initialisers so smoke tests cover real state mutations.
-
Async Runtime Parity (v0.86.21): Automatic detection of async systems now upgrades generated TypeScript dispatchers, interface methods, and kernel loops to
async/await, matching Python semantics for mixed sync/async event handlers. -
External API Alignment (v0.86.21): Python network/process specs now call the emitted action helpers instead of direct method names, eliminating runtime attribute errors while retaining the original behaviour.
-
Negative Suite Expansion (v0.86.21): Added a dedicated nested-function regression test to guarantee the parser rejects unsupported inner function declarations.
-
All-Green Test Runs (v0.86.21): Python (462) and TypeScript (433) suites now execute cleanly, including language-specific external API fixtures.
-
LLVM Backend (Phase 1 preview):
framec -l llvmemits LLVM IR with system structs, event dispatch, print lowering, and state transitions, providing a foundation for the native backend roadmap. -
LLVM Runtime (Week 8 scaffold):
runtime/llvmnow ships the minimal FrameRuntime ABI (frame_runtime_llvm) so the backend can link against shared event/compartment helpers while the kernel evolves.
- Going Native Roadmap: docs/framepiler_design/going_native/roadmap.md
cargo build --release
python3 framec_tests/runner/frame_test_runner.py --languages python typescript --framec ./target/release/framec- Bug #50 Resolution: Fixed misleading error messages that masked real parsing problems.
- Improved Error Reporting: Parser now highlights precise syntax issues instead of generic module-level errors.
- Complex File Support: Large Frame specifications (900+ lines) surface actionable diagnostics without test regressions.
- Cross-Language Fix: Improvements apply to Python, TypeScript, and GraphViz generation.
- TypeScript Actions: Generate complete implementations instead of TODO placeholders
- Frame Debugging Unblocked: VS Code extension debugging fully functional
- Try-Catch-Finally Support: Complete TypeScript translation for Frame exception handling
- 100% TypeScript Test Success: Perfect 426 of 426 TypeScript tests passing
- Feature Parity: Complete alignment between Python and TypeScript targets
- Frame Module Support: Frame modules generate proper TypeScript namespaces
- Multifile Compilation: Full support for multifile Frame programs in TypeScript
- Operator Coverage: All Frame operators (including In/NotIn) work correctly in TypeScript
- Production Ready: TypeScript code generation now fully production-ready
- Module Namespace Generation: Frame modules become TypeScript
export namespace - Runtime Class Management: Conditional generation prevents duplication in multifile projects
- Direct Function Returns: Module functions generate clean TypeScript with proper return statements
- Shared Runtime Optimization: Efficient runtime class sharing across multifile projects
- Enhanced Help Output: Target languages clearly listed in CLI help
- Language Options: Shows
python_3,typescript,graphviz,llvmwith descriptions - Better UX: Improved documentation directly in command-line interface
- New Target Language: Full TypeScript support for Frame state machines
- Complete Runtime: Event-driven state machine with FrameEvent and FrameCompartment classes
- Type-Safe Code: Generated TypeScript compiles with strict type checking
- All Core Features: States, transitions, events, actions, domain variables, and expressions
- Bug #47 Fixed: Resolved triple-mangling issue in generated Python code
- Simplified Naming Convention: Changed from double-underscore to simple prefix patterns
- Clean Internal Methods: Actions use
_action_, handlers use_handle_, runtime uses_frame_ - 100% Test Pass Rate: All 397 tests passing with improved code generation
- Bug #40 Fixed: Interface method source mappings now point to executable statements
- Bug #35 Fixed: Enhanced source mapping classification for statement types
- Debugger Integration: Improved VS Code debugging experience
- Bug #38 Fixed: Resolved string concatenation with escape sequences issue
- Enhanced Method Resolution: Improved conflict detection for method name ambiguity
- Robust String Operations: Better handling of escape sequences in generated Python code
- New Syntax:
system.interfaceMethod()for calling interface methods within systems - Multi-Context Support: Works in event handlers, actions, and non-static operations
- Validation: Prevents
self.interfaceMethodusage with helpful error messages - 2-Pass Parser Fix: Improved parser architecture for proper semantic validation
- Return Value Semantics: Complete implementation of Frame's return value precedence
- Default Values: Fixed interface method default values and handler precedence
- Test Coverage: Maintained 100% test compatibility with comprehensive validation
- 100% Statement Coverage: Every statement type now generates accurate source mappings
- Event Handler Debugging: Full debugging support inside event handlers restored
- Zero Active Bugs: All known source mapping issues resolved
- Comprehensive Fix: Added mappings to 20+ statement visitor methods
- Perfect Debugging: Breakpoints and step-through debugging work flawlessly
- Line-Aware Code Generation: Automatic tracking of every character and line
- No Manual Offsets: Eliminates all fragile +1/-1 adjustments
- Fragment Composition: Full support for non-linear code generation
- Perfect Mappings: Automatic source mapping maintenance
- PythonVisitorV2 Default: New visitor with CodeBuilder is now the default
- Legacy Support: Original visitor available via USE_PYTHON_V1 environment variable
- 100% Backward Compatible: Identical output with robust architecture
- Event Handler Mapping Fix: Corrected off-by-one error in event handler source mappings
- Removed Extra Blank Lines: Eliminated unnecessary newlines in state node generation
- Proper Offset Handling: Added correct offset for visual spacing
- Architecture Note: Current fix uses manual offsets (fragile); v0.75 will implement robust CodeBuilder
- Comprehensive Documentation: Complete source map architecture guide
- Marker File Linter: Validates intermediate files during compilation
- Bug Resolution: All known source mapping issues resolved
- Zero Active Bugs: Debugging infrastructure fully functional
- 100% Test Success: All 379 tests passing
- Removed ALL Backward Compatibility: No more feature flags or fallback logic
- 500+ Lines Deleted: Removed complex helper methods and tracking code
- Semantic Resolution Only: Parser's resolved types are the single source of truth
- 60% Complexity Reduction: Visitor methods dramatically simplified
- No Environment Variables: FRAME_SEMANTIC_RESOLUTION no longer needed
- Cleaner Architecture: Clear separation between parsing and code generation
- Simplified Code Generation: Leveraged v0.63's resolved types for clean visitor code
- New Handler Methods:
handle_call_with_resolved_type()replaced complex logic - Code Reduction: ~350 lines of complex call chain analysis simplified
- Performance Improvement: No redundant analysis during code generation
- Accurate Type Detection: Actions, Operations, and External calls correctly identified
- Context-Aware Resolution: Parser maintains system/class/function context throughout
- Symbol Table Integration: Direct lookups in actual symbol table data
- Verified Accuracy: Test output confirms correct resolution of all call types
- 100% Test Success: All 379 tests passing with improved resolution
- ResolvedCallType Enum: Comprehensive categorization of all call types (Action, Operation, SystemOperation, ClassMethod, ModuleFunction, External)
- SemanticAnalyzer Module: Dedicated semantic analysis during parser's second pass
- Enhanced AST: CallExprNode includes
resolved_typefield for semantic resolution - Feature Flag Control: Enable via
FRAME_SEMANTIC_RESOLUTION=1for gradual migration - Parser Integration: Resolution happens at all 5 CallExprNode creation points
- Architectural Improvement: Moves 350+ lines of complex logic from visitor to parser
- 100% Test Success: All existing tests pass with new architecture
- Comprehensive Analysis: Analyzed 350+ lines of complex call chain handling logic
- Refactoring Modules: Created foundation for future incremental improvements
- Documentation: Detailed architectural insights and refactoring strategy
- Lessons Learned: Understanding complexity before attempting to simplify
- 100% Test Success: Maintained stability throughout analysis and experimentation
- Double-Call Bug Fixed: Resolved critical issue where action calls in assignments generated incorrect double parameters
- Complete AST Serialization: Full JSON serialization of Frame AST for debugging and validation
- AST Summary Output: Concise overview with counts:
Systems (1): TestSystem (2 states), Functions (1): hello - Line Mapping: Hierarchical listing of all AST elements with accurate line numbers
- File Export: Save complete AST to JSON file for external analysis and validation
- Environment Variables:
FRAME_TRANSPILER_DEBUG=1,FRAME_AST_OUTPUT=filename.json - Enhanced Debugging: Foundation for advanced transpiler development and validation
- 100% Test Success: All 378 tests now passing with improved reliability
- Complete AST Coverage: All 122 AST nodes now have line tracking (100% coverage)
- Debug Output Mode: Generate JSON with transpiled code and source mappings via
--debug-outputflag - Full Line Mapping: Maps ALL Frame source lines to generated Python lines
- VSCode DAP Ready: Complete Debug Adapter Protocol support for IDE integration
- Enhanced JSON Output: Includes metadata with version, timestamp, and checksums
- Zero Performance Impact: Line tracking adds negligible overhead
- Bug Fix: Fixed dictionary comprehension key-value ordering issue
- Python Decorator Pass-Through: Support for Python decorators on classes
- Decorator Arguments: Decorators with parenthesized arguments supported
- Multiple Decorators: Stack multiple decorators on a single class
- Method Decorators Preserved:
@staticmethodand@propertycontinue working - Common Use Cases:
@dataclass,@total_ordering, custom decorators - Smart Parser: Context-aware parsing distinguishes class from method decorators
- Multi-System Generation: All systems in a Frame file are now generated
- Clean Output: Debug statements properly controlled by environment variable
- System Separation: Each system clearly labeled in concatenated output
- VSCode Ready: Clean DOT output for extension visualization
- Backward Compatible: Single system files work unchanged
- Frame File Imports: Import modules from other
.frmfiles - Three Import Syntaxes: Standard, aliased, and selective imports
- Dependency Resolution: Automatic discovery and compilation ordering
- Circular Detection: Identifies and reports circular dependencies
- Security Validation: Path traversal protection and validation
- Incremental Compilation: SHA-256 based caching for efficiency
- Module Access: Use
::for static access in Frame (transpiles to.in Python) - Separate File Generation: Generate individual Python files with
-oflag
- State Machines: Hierarchical state machines with enter/exit handlers
- Multi-Entity Support: Multiple functions and systems per module
- Module System: Named modules with qualified access (
module::function()) - Event Handlers: Named events, enter (
$>), and exit (<$) handlers - Transitions: State transitions with parameters and event forwarding
- Python Comments:
#for single-line comments (v0.40 - C-style removed) - Matrix Multiplication:
@and@=operators for NumPy arrays (v0.40) - Bitwise XOR:
^and^=operators (v0.40) - Floor Division:
//and//=operators (v0.40) - Python Numeric Literals: Binary (
0b), octal (0o), hex (0x) notation (v0.40) - Python Logical Operators:
and,or,notkeywords (v0.38) - All Compound Assignments:
+=,-=,*=,/=,%=,**=,&=,|=,^=,<<=,>>=,//=,@= - Bitwise Operators:
&,|,~,<<,>>,^ - Identity/Membership:
is,is not,in,not inoperators
- First-Class Functions: Functions as values - pass, return, and store functions
- Lambda Expressions: Anonymous functions with closure support
lambda x: x * 2 - Async/Await: Full async function and event handler support
- Slicing: Python-style slicing for strings and lists (
text[:5],list[::2]) - With Statements: Context manager support (
with/async with) - Import Statements: Native Python imports without backticks
- List Comprehensions: Python-style comprehensions
[x*2 for x in list] - Dictionary Comprehensions:
{k: v for k, v in items} - Exponent Operator: Right-associative
**for power operations - Collection Literals: Lists
[], dicts{}, sets{1,2}, tuples(), empty set{,}
- F-strings:
f"Hello {name}"- Formatted string literals with embedded expressions - Raw strings:
r"C:\path"- No escape sequence processing - Byte strings:
b"binary"- Binary data representation - Triple-quoted:
"""multi-line"""- Multi-line strings with preserved formatting - Percent formatting:
"Hello %s" % name- Classic Python string formatting
- Pattern Matching: Full match-case support with guards, OR patterns, star patterns
- Classes: Object-oriented programming with methods and variables
- Generators: Regular and async generators with yield expressions
- Type Annotations: Parameter and return type hints
- Property Decorators:
@propertyfor computed properties - Access Modifiers: Public/private/protected member visibility
- Assert Statements: Runtime assertion checking
- Try-Except: Exception handling with finally blocks
- Del Statement: Explicit deletion of variables
- Global Keyword: Explicit global variable access
- Multiple Assignment: Tuple unpacking and multiple variable declarations
- Star Expressions: Unpacking operators in assignments and calls
- State Parameters: States can receive and store parameters
- Enums: Custom values, string enums, iteration support
- Scope Resolution: LEGB scope rules with proper isolation
- Static Methods:
@staticmethoddecorator support - Interface Methods: Public system interfaces with async support
- Walrus Operator:
:=assignment expressions for inline variable creation - Numeric Literal Underscores:
1_000_000,0xFF_FFfor improved readability - Complex Numbers:
3+4j,2.5jimaginary number support - Type Aliases: Python 3.12+ style
type MyType = int - Scientific Notation:
1.23e10,6.022e23exponential notation
- 100% Success Rate: 374/374 tests passing 🎉
- UTF-8 Support: Full Unicode character support in source files
- Complete Feature Coverage: All Python operators and core language features fully tested
- Virtual Environment: Test suite includes NumPy support for matrix multiplication
- Clean Build: Zero warnings, zero deprecations with latest Rust toolchain
To learn more about the Frame language, please find Frame's official documentation on Read the Docs.
The Frame project is still early days but there are some resources and communities to help. You can download the VSCode extension to develop Frame programs on your desktop or experiment with Frame online at the Frame Playground.
You can also learn more about programming with automata at Reddit on the r/statemachines subreddit (I'm the mod).
Connect with me and other Frame enthusists on the Frame Discord channel - The Art of the State. You can also connect with me directly on LinkedIn.
Frame uses a unified testing framework that validates transpilation across all target languages.
./run_tests.sh --quick # Run core tests quickly./run_tests.sh # Run all tests for Python and TypeScript./run_tests.sh --python # Python tests only
./run_tests.sh --typescript # TypeScript tests only- Core: State machines, events, transitions (31 tests)
- Control Flow: Conditionals, loops (48 tests)
- Data Types: Collections, literals (66 tests)
- Systems: System definitions (197 tests)
- Total: 461 tests (432 common, 29 language-specific)
See framec_tests/README.md for detailed testing documentation.
Here's a simple multi-file Frame project example:
utils.frm:
module MathUtils {
fn add(a, b) {
return a + b
}
fn multiply(a, b) {
return a * b
}
}
main.frm:
import MathUtils from "./utils.frm"
fn main() {
var sum = MathUtils::add(5, 3) # Use :: for module access
var product = MathUtils::multiply(4, 7)
print("Sum: " + str(sum)) # Output: Sum: 8
print("Product: " + str(product)) # Output: Product: 28
}
main()
Compile:
# Option 1: Generate single concatenated file (default)
framec -m main.frm -l python_3 > output.py
python3 output.py
# Option 2: Generate separate Python files (NEW!)
framec -m main.frm -l python_3 -o ./output
python3 output/main.pyThe Frame Solution Depot is a Github repo and contains a growing body of examples and test specifications.
For now send issues to bugs@frame-lang.org while we get a better system in place. If you have a recommendation for a free bug tracker for open source communities please let me know!
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.
- Install Rust.
- Navigate to the framepiler/framec directory.
- Type
cargo build. 3.a You will see a bunch of warnings. Apologies but this is pre-alpha code. - Type
./target/debug/framec ../examples/HelloWorld.frm python_3. 4.a You should see a base class for a Frame controller generated to stdout. - If you want to generate a release build:
5.a Type
cargo build --release5.b Type./target/release/framec ../examples/HelloWorld.frm python_3 - You now have working debug and release Framepilers. Congratulations!
- You can try 6 other languages + Plant UML. Replace the
python_3above with any of these: 7.apython_37.bplantuml(try output at PlantUml site)
- Install Rust.
- Probably the same as MacOS but guessing you can figure it out if you know Linux and Rust. Still - please send me instructions on Discord and I will add to next release notes. Thanks!
- Install Rust.
- Help needed. Please send me instructions on Discord and I will add to next release notes. Thanks!
- Rust - Rust language
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.
Mark Truluck - Creator of Frame - LinkedIn
This project is licensed under the MIT License - see the LICENSE.md file for details
- Alan Turing - For inventing automata theory and helping end WWII. See The Imitation Game
- Dr. David Harel - Who invented Statecharts from which came Frame.