This document provides comprehensive documentation for the Refal compiler, which translates Refal source code into WebAssembly (WASM), eBPF, and LLVM IR. The compiler is implemented in Rust and follows a modular design to support multiple compilation targets.
- Introduction to Refal
- Compiler Architecture
- Installation
- Usage
- Compilation Targets
- Examples
- Contributing
- References
Refal (REcursive Functions Algorithmic Language) is a functional programming language based on pattern matching and term rewriting. It was developed by Valentin Turchin in the 1960s at the Moscow Institute of Physics and Technology.
- Pattern Matching: Refal's primary computation mechanism is pattern matching against expressions.
- Term Rewriting: Programs are defined as sets of rewriting rules.
- Functional Paradigm: Refal is a pure functional language with no side effects.
- Dynamic Typing: Variables are dynamically typed.
- Variable Types: Refal has three types of variables:
- s-variables: Match single symbols
- e-variables: Match arbitrary expressions (including empty)
- t-variables: Match non-empty expressions
A Refal program consists of a set of functions, each containing pattern-matching sentences:
$ENTRY Go {
/* empty */ = <Prout 'Hello, World!'>;
}
Each sentence has a pattern on the left side of the equals sign and a result expression on the right side. The pattern is matched against the function's argument, and if it matches, the result expression is evaluated and returned.
The compiler follows a traditional multi-stage compilation pipeline:
Refal Source Code → Lexical Analysis → Parsing → AST →
Semantic Analysis → IR Generation → Target Code Generation → Output
- Lexer: Converts Refal source code into tokens
- Parser: Builds an Abstract Syntax Tree (AST) from tokens
- Semantic Analyzer: Performs type checking and semantic validation
- IR Generator: Converts AST to an intermediate representation
- Target Code Generators: Convert IR to WASM, eBPF, or LLVM IR
- CLI: Command-line interface for the compiler
refal/
├── src/
│ ├── main.rs # Entry point
│ ├── parser/ # Lexer and parser implementation
│ │ ├── mod.rs
│ │ ├── lexer.rs
│ │ ├── parser.rs
│ │ └── ast.rs # AST definitions
│ ├── compiler/ # Compiler implementation
│ │ ├── mod.rs
│ │ ├── ir.rs # Intermediate representation
│ │ ├── analyzer.rs # Semantic analyzer
│ │ ├── wasm/ # WebAssembly backend
│ │ │ ├── mod.rs
│ │ │ └── generator.rs
│ │ ├── ebpf/ # eBPF backend
│ │ │ ├── mod.rs
│ │ │ └── generator.rs
│ │ └── llvm/ # LLVM backend
│ │ ├── mod.rs
│ │ └── generator.rs
│ └── cli/ # Command-line interface
│ ├── mod.rs
│ └── options.rs
├── docs/ # Documentation
├── tests/ # Integration tests
└── examples/ # Example Refal programs
- Rust (1.56.0 or later)
- Cargo (comes with Rust)
- LLVM (for LLVM backend)
-
Clone the repository:
git clone https://github.com/larp-devs/refal.git cd refal -
Build the project:
cargo build --release -
The compiled binary will be available at
target/release/refal.
refal -i input.ref -o output.wasm -t wasm
-i, --input <FILE>: Input Refal file (required)-o, --output <FILE>: Output file (optional, defaults to input file with appropriate extension)-t, --target <TARGET>: Compilation target (wasm, ebpf, llvm, defaults to llvm)-l, --opt-level <LEVEL>: Optimization level (none, default, aggressive)-v, --verbose: Enable verbose output--help: Display help information
Compile a Refal program to WebAssembly:
refal -i examples/hello.ref -t wasm
Compile a Refal program to eBPF:
refal -i examples/hello.ref -t ebpf
Compile a Refal program to LLVM IR:
refal -i examples/hello.ref -t llvm
The WebAssembly backend generates WebAssembly Text Format (WAT) files that can be converted to binary WASM files using standard WebAssembly tools. The generated WebAssembly code can run in browsers, Node.js, and other WebAssembly runtimes.
- Pattern matching is implemented using WebAssembly's control flow constructs
- Memory management for Refal's dynamic data structures is handled through WebAssembly's linear memory
- Function calls are implemented using WebAssembly's function table
The eBPF backend generates eBPF bytecode that can be loaded into the Linux kernel or used with eBPF virtual machines. This enables Refal programs to run in sandboxed environments with minimal overhead.
- Pattern matching is adapted to eBPF's limited instruction set
- Memory access is carefully managed to comply with eBPF's constraints
- The generated code passes the eBPF verifier's checks
The LLVM backend generates LLVM Intermediate Representation (IR) that can be compiled to native code for various architectures. This provides the best performance and portability.
- Pattern matching is implemented using LLVM's control flow constructs
- Memory management leverages LLVM's memory operations
- Optimization passes improve the performance of the generated code
$ENTRY Go {
/* empty */ = <Prout 'Hello, World!'>;
}
$ENTRY Go {
/* empty */ = <Prout <Factorial 5>>;
}
Factorial {
0 = 1;
s.N = <Mul s.N <Factorial <Sub s.N 1>>>;
}
$ENTRY Go {
/* empty */ = <Prout <IsPalindrome 'racecar'>>;
}
IsPalindrome {
/* empty */ = 'True';
s.A = 'True';
s.A e.Middle s.A = <IsPalindrome e.Middle>;
e.Other = 'False';
}
Contributions to the Refal compiler are welcome! Here's how you can contribute:
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Commit your changes:
git commit -am 'Add feature' - Push to the branch:
git push origin feature-name - Submit a pull request
- Make sure tests pass:
cargo test - Format your code:
cargo fmt - Check for linting issues:
cargo clippy