View Source cure_codegen (cure v0.1.0)

Cure Programming Language - BEAM Code Generator

The code generator transforms typed Cure AST into BEAM bytecode, enabling Cure programs to run on the Erlang Virtual Machine. It handles all Cure language features including dependent types, finite state machines, pattern matching, and integration with Erlang/OTP.

Features

Complete Language Support

  • Module Compilation: Full module support with imports/exports
  • Function Compilation: Regular and dependent function types
  • Expression Compilation: All Cure expressions to BEAM instructions
  • Pattern Matching: Efficient pattern compilation with optimization
  • Type Integration: Uses type information for optimizations

FSM Code Generation

  • Native FSM Support: Compiles FSMs to gen_statem behaviors
  • State Optimization: Optimizes state transitions and data access
  • Guard Compilation: Efficient guard expression compilation
  • Action Compilation: Action sequences to BEAM instructions

BEAM Integration

  • Bytecode Generation: Direct BEAM bytecode emission
  • Module Attributes: Proper module metadata generation
  • Export Lists: Correct function export handling
  • Debug Information: Optional debug info generation

Optimization Features

  • Configurable Levels: Multiple optimization levels (0-3)
  • Type-directed: Uses type information for better code
  • Dead Code Elimination: Removes unused code paths
  • Instruction Optimization: BEAM instruction-level optimizations

Compilation Pipeline

1. Program Compilation

%% Compile entire program
{ok, Modules} = cure_codegen:compile_program(AST),

%% With custom options
Options = [{optimize, 2}, {debug_info, true}],
{ok, Modules} = cure_codegen:compile_program(AST, Options).

2. Module Compilation

%% Compile single module
Module = #module_def{name = 'MyModule', exports = Exports, items = Items},
{ok, CompiledModule} = cure_codegen:compile_module(Module),

%% Generate BEAM file
cure_codegen:write_beam_module(CompiledModule, "MyModule.beam").

3. Function Compilation

%% Compile individual function
Func = #function_def{name = add, params = Params, body = Body},
{ok, CompiledFunc, State} = cure_codegen:compile_function(Func).

Code Generation Process

Phase 1: AST Analysis

  • Type Information: Extract and validate type annotations
  • Import Resolution: Process module imports and dependencies
  • Export Analysis: Validate and process export specifications
  • Dependency Analysis: Build function dependency graph

Phase 2: Instruction Generation

  • Expression Compilation: Convert expressions to BEAM instructions
  • Pattern Compilation: Generate efficient pattern matching code
  • Guard Compilation: Compile guard expressions
  • Control Flow: Generate conditionals, loops, and jumps

Phase 3: Optimization

  • Instruction Optimization: Peephole optimizations
  • Register Allocation: Efficient register usage
  • Jump Optimization: Minimize jumps and labels
  • Constant Folding: Compile-time constant evaluation

Phase 4: Module Assembly

  • Function Assembly: Combine compiled functions
  • Attribute Generation: Create module attributes
  • Export List: Generate proper export specifications
  • BEAM File: Produce final BEAM bytecode file

Compilation Options

Standard Options

Options = [
    {debug_info, true},      % Include debug information
    {optimize, 2},           % Optimization level 0-3
    {warnings, true},        % Enable compilation warnings
    {strict_types, true},    % Strict type checking
    {fsm_integration, true}  % Enable FSM features
].

Optimization Levels

  • Level 0: No optimizations (fastest compile, debugging)
  • Level 1: Basic optimizations (safe, minimal impact)
  • Level 2: Standard optimizations (default, balanced)
  • Level 3: Aggressive optimizations (maximum performance)

Expression Compilation

Literals

42          → {integer, 42}
"hello"     → {string, "hello"}
true        → {atom, true}
[1,2,3]     → {cons, {integer,1}, {cons, {integer,2}, ...}}

Function Calls

foo(x, y)   → {call, {atom, foo}, [VarX, VarY]}
Mod.func(x) → {call, {remote, {atom, 'Mod'}, {atom, func}}, [VarX]}

Pattern Matching

match value do
    {ok, x} -> x
    error -> 0
end

Compiles to efficient jump table with pattern tests.

FSM Compilation

Finite state machines compile to standard Erlang gen_statem:

fsm Counter do
    states: [idle, counting]
    initial: idle
    
    state idle do
        event start -> counting
    end
end

Generates:

  • init/1 callback for initialization
  • State callback functions for each state
  • Event handling with pattern matching
  • State data management

Error Handling

The code generator provides detailed error information:

  • Compilation Errors: Unsupported constructs, type mismatches
  • Generation Errors: BEAM instruction generation failures
  • Optimization Errors: Failed optimizations (non-fatal)
  • File I/O Errors: BEAM file writing errors

Integration with Type System

Uses type information for:

  • Type Erasure: Remove type annotations while preserving semantics
  • Optimization: Type-directed optimizations and specializations
  • Error Prevention: Catch type-related errors during compilation
  • Runtime Checks: Generate minimal runtime type checks where needed

BEAM Compatibility

Generates standard BEAM bytecode compatible with:

  • Erlang/OTP: Full compatibility with Erlang runtime
  • Elixir: Can be called from Elixir code
  • LFE/Gleam: Compatible with other BEAM languages
  • Standard Tools: Works with standard BEAM tools (debugger, profiler)

Performance Characteristics

  • Compilation Speed: Linear in program size for most constructs
  • Generated Code: Comparable performance to hand-written Erlang
  • Memory Usage: Efficient memory usage during compilation
  • Optimization Impact: 10-40% performance improvement at higher levels

Thread Safety

The code generator is stateless at the module level and can safely compile multiple modules concurrently. Individual function compilation maintains local state that is not shared between threads.

Summary

Functions

Compiles a Cure expression to BEAM instructions using default state.

Compiles a finite state machine definition to BEAM runtime functions.

Compiles a single Cure function to BEAM bytecode using default options.

Compiles a single Cure module to BEAM bytecode using default options.

Compiles a complete Cure program to BEAM bytecode using default options.

Generates a BEAM bytecode file from a compiled Cure module.

Writes a compiled Cure module to a BEAM file.

Functions

compile_expression(Expr)

Compiles a Cure expression to BEAM instructions using default state.

This is the main expression compilation entry point that handles conversion of all Cure expression types to equivalent BEAM bytecode instructions.

Arguments

  • Expr - Expression AST node (various expr record types)

Returns

  • {Instructions, State} - BEAM instructions and updated compilation state
  • {error, Reason} - Compilation error details

Example

Expr = #binary_op_expr{op = '+', left = {literal, 5}, right = {literal, 3}},
{Instructions, _State} = cure_codegen:compile_expression(Expr).

Supported Expression Types

  • Literals (integers, atoms, strings, booleans)
  • Identifiers (variables, function references)
  • Binary operations (arithmetic, logical, comparison)
  • Function calls (local and remote)
  • Control flow (if/else, pattern matching)
  • Data structures (lists, tuples, records)
  • Lambda expressions and blocks
  • String interpolation
  • Type annotations

Error Handling

Returns detailed error information for unsupported expressions, type mismatches, and compilation failures.

compile_expression(Expr, State)

compile_fsm_impl/2

Compiles a finite state machine definition to BEAM runtime functions.

This function transforms a Cure FSM definition into executable BEAM code that integrates with the FSM runtime system. It generates helper functions for spawning, controlling, and querying FSM instances.

Arguments

  • FSMDef - FSM definition AST node (#fsm_def{})
  • State - Current compilation state

Returns

  • {ok, {fsm, CompiledFSM}, NewState} - Successfully compiled FSM
  • {error, Reason} - Compilation error details

Generated Functions

For an FSM named Counter, generates:

  • Counter_spawn/0 - Spawn FSM with default initial state
  • Counter_spawn/1 - Spawn FSM with custom initial data
  • Counter_send/2 - Send event to FSM instance
  • Counter_state/1 - Get current state of FSM instance
  • Counter_stop/1 - Stop FSM instance gracefully
  • Counter_definition/0 - Get compiled FSM definition

Example

FSM = #fsm_def{
    name = 'Counter',
    states = [idle, counting],
    initial = idle,
    state_defs = [IdleState, CountingState]
},
{ok, {fsm, CompiledFSM}, NewState} = compile_fsm_impl(FSM, State).

FSM Runtime Integration

  • Compiles FSM to cure_fsm_runtime format
  • Generates proper BEAM bytecode for FSM operations
  • Integrates with gen_statem behavior patterns
  • Handles state transitions, events, and timeouts
  • Provides type-safe FSM interface functions

State Management

FSMs maintain state data through:

  • Initial state setup from spawn parameters
  • State data transformation during transitions
  • Event payload integration with state data
  • Timeout handling with state persistence

compile_function(FunctionAST)

Compiles a single Cure function to BEAM bytecode using default options.

This function handles standalone function compilation, primarily used for testing and development. In normal compilation, functions are compiled as part of module compilation.

Arguments

  • FunctionAST - Function AST node (function_def record or tuple format)

Returns

  • {ok, CompiledFunction, State} - Successfully compiled function with state
  • {error, Reason} - Compilation error details

Example

FuncAST = #function_def{
    name = add,
    params = [x, y],
    body = {binary_op, '+', {var, x}, {var, y}}
},
{ok, CompiledFunc, _State} = cure_codegen:compile_function(FuncAST).

Function Processing

  • Converts function parameters to BEAM registers
  • Compiles function body expressions to BEAM instructions
  • Handles pattern matching in parameters
  • Generates proper function entry and exit code
  • Applies function-level optimizations

Limitations

  • Creates minimal compilation state for standalone compilation
  • May not have access to full module context for imports/types
  • Primarily intended for testing individual functions

compile_function/2

compile_module(ModuleAST)

Compiles a single Cure module to BEAM bytecode using default options.

This function handles compilation of complete module definitions including exports, imports, function definitions, FSM definitions, and type definitions. It converts Cure module AST to BEAM-compatible Erlang forms.

Arguments

  • ModuleAST - Module AST node (module_def record or tuple format)

Returns

  • {ok, CompiledModule} - Successfully compiled module ready for BEAM
  • {error, Reason} - Compilation error with details

Example

ModuleAST = #module_def{
    name = 'MyModule',
    exports = [{foo, 2}, {bar, 1}],
    items = [FuncDef1, FuncDef2]
},
{ok, BeamModule} = cure_codegen:compile_module(ModuleAST),
cure_codegen:write_beam_module(BeamModule, "MyModule.beam").

Module Processing

  • Processes imports and builds import environment
  • Validates and converts export specifications
  • Compiles all module items (functions, FSMs, types)
  • Generates proper BEAM module structure with attributes
  • Handles both old and new AST formats for compatibility

Supported Module Items

  • Function definitions (regular and Erlang functions)
  • FSM definitions (compiled to gen_statem)
  • Record and type definitions
  • Import and export declarations

compile_module/2

compile_patterns_to_case_clauses(Patterns, State)

compile_program(AST)

Compiles a complete Cure program to BEAM bytecode using default options.

This is a convenience function that calls compile_program/2 with default compilation options.

Arguments

  • AST - List of top-level AST items (modules, functions, etc.)

Returns

  • {ok, Modules} - Successfully compiled modules
  • {error, {compilation_failed, Errors}} - Compilation failures

Example

AST = cure_parser:parse_file("program.cure"),
{ok, Modules} = cure_codegen:compile_program(AST),
lists:foreach(fun(Module) ->
    cure_codegen:write_beam_module(Module, filename(Module))
end, Modules).

Default Options

Uses standard compilation options: debug_info, optimization level 1, warnings enabled, strict types, and FSM integration.

compile_program(AST, Options)

compile_value_to_erlang_form(Value, Location)

convert_body_expression_to_erlang/2

convert_list_pattern_to_erlang_form/3

convert_pattern_to_erlang_form/2

convert_to_erlang_forms(Module)

default_options()

generate_beam_file(Module, OutputPath)

Generates a BEAM bytecode file from a compiled Cure module.

This function converts the internal compiled module representation to standard Erlang abstract forms, then uses the Erlang compiler to produce a BEAM bytecode file compatible with the Erlang Virtual Machine.

Arguments

  • Module - Compiled module data (map with functions, exports, etc.)
  • OutputPath - File path where BEAM file should be written

Returns

  • {ok, {ModuleName, OutputPath}} - Successfully generated BEAM file
  • {error, Reason} - Generation error details

Example

{ok, CompiledModule} = cure_codegen:compile_module(ModuleAST),
{ok, {MyModule, "MyModule.beam"}} = 
    cure_codegen:generate_beam_file(CompiledModule, "MyModule.beam").

Process Steps

  1. Form Conversion: Convert internal representation to Erlang forms
  2. Erlang Compilation: Use Erlang compiler to generate bytecode
  3. File Writing: Write binary BEAM data to specified path
  4. Error Handling: Provide detailed errors at each step

BEAM Compatibility

Generated BEAM files are fully compatible with:

  • Standard Erlang/OTP runtime
  • Elixir and other BEAM languages
  • BEAM development and debugging tools
  • Hot code reloading and distribution

Error Types

  • {write_failed, Reason} - File system errors
  • {compile_failed, Errors, Warnings} - Erlang compiler errors
  • Form conversion errors from convert_to_erlang_forms/1

generate_fsm_functions(FSMName, CompiledFSM, Location)

generate_module_attributes(State)

new_state()

validate_options(Options)

write_beam_module(Module, OutputPath)

Writes a compiled Cure module to a BEAM file.

This is a convenience function that calls generate_beam_file/2 to convert a compiled module to BEAM bytecode and write it to the specified path.

Arguments

  • Module - Compiled module data from compile_module/1,2
  • OutputPath - File path where BEAM file should be written

Returns

  • {ok, {ModuleName, OutputPath}} - Successfully written BEAM file
  • {error, Reason} - File writing or compilation error

Example

{ok, CompiledModule} = cure_codegen:compile_module(AST),
{ok, {MyModule, "MyModule.beam"}} = 
    cure_codegen:write_beam_module(CompiledModule, "MyModule.beam"),

%% Load and test the module
code:load_file(MyModule),
MyModule:function_name(args).

Use Cases

  • Final step in Cure compilation pipeline
  • Integration with build systems and tools
  • Deployment of Cure modules to BEAM environments
  • Testing and development workflows