A modern Rust implementation of a transpiler for the ROSY programming language, designed for scientific computing and beam physics applications.
Rosy is a complete transpiler toolchain that converts ROSY source code into native executable Rust programs. ROSY is a scientific programming language originally developed for the COSY INFINITY beam physics simulation environment, now reimplemented as a modern transpiler with several key design decisions:
Transpilation, Not Interpretation: Rather than executing scripts directly, Rosy generates self-contained Rust programs that compile to native binaries. This provides:
- Rust's memory safety guarantees without runtime overhead
- Performance comparable to hand-written Rust for numerical computing
- Zero runtime dependencies - generated binaries are fully standalone
- Compile-time type checking catches errors before execution
Registry-Based Type System: All operators use a TypeRule registry as the single source of truth for:
- Type compatibility validation during transpilation
- Runtime dispatch to optimized implementations
- Automatic test generation for comprehensive validation
Built for Scientific Computing: Native support for:
- Differential Algebra (DA/CD types) for automatic differentiation and Taylor series
- MPI parallelization with built-in
PLOOPconstructs for distributed computing - Multi-dimensional arrays with arbitrary dimensions
(RE ** 2 ** 3) - Complex numbers, vectors, and matrices as first-class types
- Strong type safety with compile-time checking of all operations
Test-Driven Development: Every language feature is validated against COSY INFINITY's reference implementation through automated output comparison, ensuring behavioral compatibility.
BEGIN;
{Function to add two numbers}
FUNCTION (RE) ADD_TWO a (RE) b (RE);
ADD_TWO := a + b;
ENDFUNCTION;
{Function to multiply and add}
FUNCTION (RE) COMPUTE x (RE) y (RE);
VARIABLE (RE) temp;
temp := x * y;
COMPUTE := temp + 10;
ENDFUNCTION;
{Procedure demonstrating conditionals}
PROCEDURE CONDITIONAL_DEMO;
VARIABLE (LO) is_true;
VARIABLE (LO) is_false;
is_true := TRUE;
is_false := FALSE;
IF is_true;
WRITE 6 "First condition is TRUE";
ELSEIF is_false;
WRITE 6 "Second condition is TRUE";
ELSE;
WRITE 6 "Neither condition is TRUE";
ENDIF;
IF is_false;
WRITE 6 "This should not print";
ELSE;
WRITE 6 "ELSE clause works!";
ENDIF;
ENDPROCEDURE;
{Procedure demonstrating vectors and arrays}
PROCEDURE VECTOR_DEMO;
VARIABLE (VE) vec;
VARIABLE (RE 2 3) matrix;
{Concatenate values into vector}
vec := 1 & 2 & 3 & 4 & 5;
WRITE 6 "Vector: " ST(vec);
{Access and assign array elements}
matrix[1, 2] := 42;
WRITE 6 "Matrix[1,2] = " ST(matrix[1, 2]);
ENDPROCEDURE;
{Procedure demonstrating loops}
PROCEDURE LOOP_DEMO;
VARIABLE (RE) sum;
sum := 0;
LOOP i 1 5;
sum := sum + i;
WRITE 6 "i = " ST(i) ", sum = " ST(sum);
ENDLOOP;
ENDPROCEDURE;
{Main entry point}
PROCEDURE RUN;
VARIABLE (RE) x;
VARIABLE (RE) y;
VARIABLE (RE) result;
x := 3;
y := 4;
result := ADD_TWO(x, y);
WRITE 6 "Adding " ST(x) " + " ST(y) " = " ST(result);
result := COMPUTE(x, y);
WRITE 6 "Computing " ST(x) " * " ST(y) " + 10 = " ST(result);
CONDITIONAL_DEMO;
VECTOR_DEMO;
LOOP_DEMO;
ENDPROCEDURE;
RUN;
END;
- Strong Static Typing:
(RE)real,(ST)string,(LO)logical/boolean,(CM)complex,(VE)vector,(DA)differential algebra,(CD)complex DA - Multi-dimensional Arrays:
(RE 2 3 4)declares a 2×3×4 array of reals - Concatenation Operator:
&builds vectors from scalars:1 & 2 & 3creates a vector - Extraction Operator:
|extracts vector length for iteration - Type Conversion:
ST()converts to string,CM()to complex,LO()to logical - Procedures & Functions: Procedures have no return value, functions return typed values
- Comments:
{This is a comment}using curly braces - Output:
WRITE 6 <expr>+writes to stdout (unit 6)
- Rust toolchain (1.70+): Install from rustup.rs
- (Optional) Nix: For reproducible development environment with MPI support
# Clone the repository
git clone https://github.com/yourusername/rosy.git
cd rosy
# Build the transpiler
cargo build --release
# The binary will be at target/release/rosy
# Optionally, install to your PATH
cargo install --path rosy# Enter the development shell with all dependencies
nix develop
# Build and run normally
cargo build --releaseThe Nix environment provides MPI libraries and LLVM required for full functionality.
The quickest way to test a script is with rosy run:
# Run a script directly (compiled binary stays in .rosy_output/)
rosy run examples/basic.rosy
# Run with optimizations
rosy run examples/basic.rosy --release
# Use custom build directory
rosy run examples/basic.rosy -d /tmp/my_build
# Enable verbose logging
RUST_LOG=info rosy run examples/basic.rosyTo create a standalone binary:
# Build and copy binary to current directory
rosy build examples/basic.rosy
# Creates ./basic executable
# Specify output name
rosy build examples/basic.rosy -o my_program
# Build with optimizations (slower compile, faster execution)
rosy build examples/basic.rosy --release
# Custom build directory
rosy build examples/basic.rosy -d /tmp/build- Write your ROSY source code (
.rosyextension) - Transpile with
rosy build script.rosy - Execute the generated binary
./script
The transpiler generates a complete Rust project in .rosy_output/, compiles it with cargo, and produces a self-contained executable.
The examples/ directory contains various demonstrations:
basic.rosy- Functions, procedures, loops, and vector operationsvectors_arrays.rosy- Multi-dimensional array indexing and manipulationif_statements.rosy- Conditional branching with IF/ELSEIF/ELSEda_test.rosy- Differential algebra for automatic differentiationploop.rosy- Parallel loops with MPI distributionglobal_vars.rosy- Variable scoping and closure capture
Run any example with:
rosy run examples/<example>.rosyThe project is organized as a Rust workspace with several interconnected crates:
rosy_transpiler/- Main transpiler binary that parses ROSY source and generates Rust coderosy_lib/- Runtime library providing ROSY data types and operations in Rustrosy_output/- Template target for generated Rust executablesrosy_ide_tools/- Development tools including VSCode syntax highlighting extension
- Read
manual.md- Find the operator/function definition in Appendix A, noting type tables (left type + right type → result type) and example usage - Grammar definition added to
rosy/assets/rosy.pest(either astermfor primaries orinfix_opfor binary operators) - Infix operators added to Pratt parser precedence table in
rosy/src/ast.rs - New struct created in
rosy/src/program/expressions/<name>.rswith parsing logic - Module declaration added to
rosy/src/program/expressions/mod.rs - Enum variant added to
ExprEnum - Pratt parser mapping implemented (
map_primaryfor terms,map_infixfor operators) - Traits implemented:
TranspileWithType,TypeOf, andTranspile - For operators:
TypeRuleregistry defined inrosy/src/rosy_lib/operators/<name>.rswith test values from manual - Build triggers codegen (
cargo build) to generate test files - COSY/ROSY output comparison validates behavior matches reference implementation
- PLOOP does not revert to LOOP behavior when
NP == 1 - Rosy offers a
BREAKstatement, while COSY does not
- Read
manual.md- Find the statement/procedure definition with syntax, arguments, and examples in the appropriate section - Grammar rule added to
rosy/assets/rosy.pestunderstatementproduction - New struct created in
rosy/src/program/statements/<name>.rs - Module declaration added to
rosy/src/program/statements/mod.rs - Enum variant added to
StatementEnum - Pattern matching case added to
Statement::from_ruleinmod.rs - Traits implemented:
FromRuleandTranspile - Integration tests added to
examples/directory - COSY/ROSY output comparison validates end-to-end behavior
All language features follow a strict TDD workflow:
- Test values embedded in
TypeRuleregistries (for operators) cargo buildauto-generates.rosyand.foxtest scripts- Transpile both ROSY and COSY INFINITY versions
- Output diff must be identical before merge (no approximations)
- Registry serves three purposes: type checking, runtime dispatch, and test generation
This repository will be filled out as the language stabilizes. Until then, stay tuned :)