View Source Cure Language Features Reference
Version: Current Implementation Status
Last Updated: November 22, 2025
This document provides a comprehensive reference for all Cure language features, including current implementation status, syntax examples, and usage patterns.
Table of Contents
- Core Language Syntax
- Data Types and Type System
- Finite State Machines
- Type Classes and Constraints
- Advanced Features
- Standard Library Integration
- CLI and Build System
- Compilation and Runtime
- Testing Infrastructure
- Performance and Optimization
Core Language Syntax
Module System
module ModuleName do
import Std [abs/1, sqrt/1, Option, Result]
import Std.Math [sin/1, cos/1]
export [main/0, demo_function/1]
# Module contents...
endFunction Definitions
# Simple function
def add(x: Int, y: Int): Int = x + y
# Function with complex body
def demo(): Unit =
let result = calculate_something()
println("Result: " <> show(result))
0
# Helper function
def helper(x: Int): String = int_to_string(x)Lambda Expressions
# Simple lambda
let double = fn(x) -> x * 2 end
# Lambda with pattern matching instead of if-then-else
let safe_div = fn(x, y) ->
match y == 0 do
true -> error("Division by zero")
false -> ok(x / y)
end
end
# Lambda with multiple parameters
let fold_sum = fold(numbers, 0, fn(x, acc) -> x + acc end)Pattern Matching
match expression do
Ok(value) -> handle_success(value)
Error(msg) -> handle_error(msg)
end
match list do
[] -> "empty"
[x] -> "single: " <> show(x)
[x | rest] -> "head: " <> show(x) <> ", rest: " <> show(rest)
end
match option do
Some(found) -> "Found: " <> show(found)
None -> "Not found"
endCase Expressions
Cure supports case expressions as an alternative to match (they are semantically identical):
# Case with 'of' keyword
case expression of
Ok(value) -> handle_success(value)
Error(msg) -> handle_error(msg)
end
# Functionally equivalent to match
match expression do
Ok(value) -> handle_success(value)
Error(msg) -> handle_error(msg)
endNote: Cure does not have if-then-else expressions. Use match or case for conditional logic.
Let Bindings
# Simple let
let x = 42
# Let with complex expression
let result = calculate()
|> map(fn(x) -> x * 2 end)
|> filter(fn(x) -> x > 10 end)Pipe Operations
result = input
|> transform1()
|> transform2(argument)
|> final_transform()Data Types and Type System
Primitive Types
Int: 64-bit signed integersFloat: 64-bit IEEE floating-point numbersString: UTF-8 encoded text stringsBool: Boolean values (true,false)Atom: Symbolic constants (:atom_name)Binary: Byte sequencesUnit: Unit type for functions with no return valueNat: Natural numbers (Int >= 0) - refinement typePos: Positive integers (Int > 0) - refinement typePid: BEAM process identifier
Composite Types
List(T) # Homogeneous lists
List(T, n) # Length-indexed lists (dependent type)
Tuple(T1, T2, ...) # Fixed-size tuples
Result(T, E) # Error handling without exceptions
Option(T) # Nullable valuesConstructor Types
Ok(value) # Success result
Error(message) # Error result
Some(value) # Present optional value
None # Absent optional valueDependent Types
# Length-indexed types
Vector(T, n: Nat) # Fixed-length vector
List(T, n: Nat) # List with compile-time known length
Matrix(rows: Nat, cols: Nat, T) # 2D matrix with dimensions
# Constraint-based types
{x: Int | x > 0} # Positive integers
{x: Float | x >= 0.0} # Non-negative floats
{xs: List(T) | length(xs) > 0} # Non-empty lists
# Function-dependent types
def replicate(n: Nat, x: T): List(T, n) # Return type depends on argument
def safe_head(xs: List(T, n)): T when n > 0 # Precondition constraintOperators
Binary Operators
- Arithmetic:
+,-,*,/,% - Comparison:
==,!=,<,>,<=,>= - String:
<>(concatenation) List:
|(cons operator, used in[h | t]syntax)- Pipe:
|>(function composition)
Unary Operators
- Arithmetic:
+x,-x - Logical:
not(expr)
Literals
Numbers
42 # Integer
3.14 # Float
-5 # Negative integerStrings
"Hello, World!" # Simple string
"Line 1\nLine 2" # String with escape sequences
"Quote: \"text\"" # String with escaped quotesLists
[] # Empty list
[1, 2, 3] # List of integers
["a", "b", "c"] # List of stringsTuples
Tuples use curly brace {} syntax:
{} # Empty tuple (Unit)
{42} # Single element tuple
{1, "hello", true} # Multi-element tuple
{:ok, "success"} # Tagged tuple (atom + value)
{:error, "failed"} # Error tuple (atom + value)Note: Tuple pattern matching is fully supported:
match point do
{x, y} when x > 0.0 and y > 0.0 -> "First quadrant"
{x, y} when x == 0.0 and y == 0.0 -> "Origin"
_ -> "Other quadrant"
endAtoms
:atom_name
:increment
:okFinite State Machines
Cure provides first-class support for finite state machines with compile-time verification, state-dependent data, and integration with the BEAM actor model.
Basic FSM Definition
Cure FSMs use a record-based payload system with arrow transition syntax:
# Define a payload record to track FSM data
record TrafficPayload do
cycles_completed: Int
timer_events: Int
emergency_stops: Int
end
# FSM with initial payload values
fsm TrafficPayload{cycles_completed: 0, timer_events: 0, emergency_stops: 0} do
Red --> |timer| Green
Red --> |emergency| Red # Self-transition
Green --> |timer| Yellow
Green --> |emergency| Red
Yellow --> |timer| Red
Yellow --> |emergency| Red
endKey Points:
- First state in transitions is the initial state (Red in this example)
- Transitions use
-->arrow with|event|syntax - Must define a payload record even if fields are unused
FSM Runtime Operations
FSMs compile to BEAM gen_statem processes:
import Std.Fsm [fsm_spawn/2, fsm_cast/2, fsm_advertise/2, fsm_state/1]
import Std.Pair [pair/2]
# Spawn an FSM instance with initial data
let initial_data = TrafficPayload{cycles_completed: 0, timer_events: 0, emergency_stops: 0}
let fsm_pid = fsm_spawn(:TrafficPayload, initial_data)
# Give the FSM a name for easy reference
let adv_result = fsm_advertise(fsm_pid, :traffic_light)
# Send events to the FSM
let empty_list = []
let event = pair(:timer, empty_list)
let cast_result = fsm_cast(:traffic_light, event)
# Query current state
let current_state = fsm_state(:traffic_light) # Returns current state atomFSM Implementation Notes
Cure FSMs compile to Erlang gen_statem behaviors with the following features:
Compile-Time Verification:
- State machine structure validated at compile time
- Transition completeness checked
- Event type checking
Runtime Integration:
- Native BEAM process integration
- Mailbox-based event handling
- OTP supervision tree compatible
- Hot code reloading support
Current Implementation:
- Simple arrow-based transition syntax (
State1 --> |event| State2) - Record-based payload data tracking
- Event casting with atom-based event names
- State querying via FSM references
Records and Dependent Types
Record Definitions
record Person do
name: String
age: Nat
email: String
end
# Creating records
let person = Person{name: "Alice", age: 30, email: "alice@example.com"}
# Pattern matching on records
match person do
Person{name: name, age: age} when age >= 18 ->
"Hello, adult " <> name <> "!"
Person{name: name} ->
"Hello, young " <> name <> "!"
endDependent Types
# Length-indexed types
Vector(T, n: Nat) # Fixed-length vector
List(T, n: Nat) # List with known length
Range(min: Int, max: Int) # Integer range type
# Matrix with dimension checking
record Matrix(rows: Nat, cols: Nat, T) do
data: Vector(Vector(T, cols), rows)
end
# Refinement types
type NonEmptyList(T) = List(T, n) when n > 0
def head(list: NonEmptyList(T)): T =
match list do
[x|_] -> x
# No need for empty case - type system guarantees non-empty
endAdvanced Features
Function Imports with Arity
import ModuleName [
function1/1, # Function with 1 parameter
function2/2, # Function with 2 parameters
TypeName, # Type import
constructor # Constructor import
]Complex Nested Expressions
# Nested lambdas in higher-order functions
processed = data
|> filter(fn(item) -> not(is_empty(item)) end)
|> map(fn(item) ->
process_item(item)
|> validate()
|> transform()
end)
|> collect_results()Match vs Case
Both match and case are supported and functionally equivalent:
# Case expression with 'of' keyword (alternative to match)
case expression of
Ok(value) -> handle_success(value)
Error(msg) -> handle_error(msg)
end
case list of
[] -> "empty"
[x] -> "single: " <> show(x)
[x | rest] -> "head: " <> show(x)
endPattern Matching with Guards
match value do
x when x > 0 -> "positive"
x when x < 0 -> "negative"
_ -> "zero"
end
# Guards in case expressions
case number do
n when n > 100 -> "large"
n when n > 10 -> "medium"
_ -> "small"
endFunction-Level Guards ✅ Complete Implementation
Cure supports guards on function definitions with when clauses, enabling elegant multi-clause functions with preconditions:
# Basic guard on function parameter
def is_positive(x: Int): Bool when x > 0 = true
def is_positive(_x: Int): Bool = false
# Multi-clause function with guards
def abs(x: Int): Int when x >= 0 = x
def abs(x: Int): Int = 0 - x
# Sign function with complete coverage
def sign(x: Int): Int when x > 0 = 1
def sign(x: Int): Int when x == 0 = 0
def sign(x: Int): Int = -1
# Guards with AND/OR sequences
def in_range(x: Int, min: Int, max: Int): Bool
when x >= min and x <= max = true
def in_range(_x: Int, _min: Int, _max: Int): Bool = false
def is_extreme(x: Int): Bool
when x > 100 or x < -100 = true
def is_extreme(_x: Int): Bool = false
# Real-world example: tax brackets
def tax_rate(income: Int): Float when income <= 10000 = 0.0
def tax_rate(income: Int): Float
when income > 10000 and income <= 40000 = 0.1
def tax_rate(income: Int): Float
when income > 40000 and income <= 100000 = 0.2
def tax_rate(_income: Int): Float = 0.3Guard Features:
- All comparison operators:
>,<,>=,<=,==,!= - Logical combinations:
and,or - Type refinement: Guards narrow parameter types in function bodies
- SMT verification: Guards verified for completeness and consistency
- Coverage analysis: Compiler detects unreachable clauses
- Optimization: Guard-specific optimizations for performance
Example: Comprehensive Guards Demo
See examples/06_comprehensive_guards_demo.cure for a complete demonstration including:
- Basic comparisons with all operators
- Multi-clause functions
- Guard sequences (AND/OR combinations)
- Type refinement examples
- Real-world applications (discounts, tax brackets, shipping costs)
- Recursive functions with guards
- Performance-ordered guard clauses
Error Handling Patterns
Result Types
def safe_operation(input: Int): Result(Int, String) =
match input < 0 do
true -> error("Negative input not allowed")
false -> ok(input * 2)
endOption Types
def find_item(list: List(String), target: String): Option(String) =
match search(list, target) do
found when found != "" -> Some(found)
_ -> None
endBest Practices
Function Composition
Use pipe operators for readable data transformations:
result = input
|> validate_input()
|> process_data()
|> format_output()Error Handling
Use Result types for operations that can fail:
def divide(x: Float, y: Float): Result(Float, String) =
match y == 0.0 do
true -> error("Division by zero")
false -> ok(x / y)
endPattern Matching
Prefer pattern matching for control flow:
# Good - using pattern matching
match result do
Ok(value) -> use_value(value)
Error(msg) -> handle_error(msg)
end
# Also good - using case
case result of
Ok(value) -> use_value(value)
Error(msg) -> handle_error(msg)
endType Classes and Constraints
Cure supports type classes for ad-hoc polymorphism and constraint-based programming.
Type Class Definition
typeclass Ord(T) where
def compare(x: T, y: T): Ordering
def (<)(x: T, y: T): Bool = compare(x, y) == LT
def (<=)(x: T, y: T): Bool = compare(x, y) != GT
end
typeclass Show(T) where
def show(x: T): String
end
typeclass Functor(F) where
def map(f: A -> B, fa: F(A)): F(B)
endType Class Instances
# Manual instances
instance Ord(Int) where
def compare(x, y) =
if x < y then LT
else if x > y then GT
else EQ
end
end
# Automatic derivation
derive Ord for List(T) when Ord(T)
derive Show for Option(T) when Show(T)
derive Functor for List
derive Functor for OptionConstraint-Based Programming
# Generic sorting with constraints
def sort(xs: List(T)): List(T) where Ord(T) =
quicksort_impl(xs)
# Pretty printing with constraints
def debug_print(x: T): Unit where Show(T) =
print(show(x))
# Functor mapping
def transform(f: A -> B, container: F(A)): F(B) where Functor(F) =
map(f, container)Advanced Features
Pi Types (Dependent Functions)
# Function types that depend on their arguments
def replicate(n: Nat, x: T): List(T, n) =
if n == 0 then [] else x :: replicate(n-1, x)Sigma Types (Dependent Pairs)
# Pairs where the second type depends on the first value
{x: Nat, Vector(Int, x)} # Pair of number and vector of that lengthRefinement Types
# Types with predicates
{x: Int | x > 0} # Positive integers
{x: List(T) | length(x) > 0} # Non-empty listsIndexed Types
# Types parameterized by values
Vector(T, n: Nat) # Vector of type T with length n
Matrix(rows: Nat, cols: Nat, T) # Matrix with compile-time dimensionsCLI and Build System
Cure provides a sophisticated command-line interface with wrapper script automation and intelligent build management.
Wrapper Script Commands
# Special wrapper script commands
cure build # Execute 'make all' to build compiler
cure test # Execute 'make test' to run test suite
cure clean # Execute 'make clean' to clean build artifacts
cure shell # Start Erlang development shell with modules loaded
File Compilation
# Basic compilation
cure input.cure # Compile with defaults
cure input.cure -o output.beam # Specify output file
cure input.cure --verbose # Verbose compilation
cure input.cure --no-optimize # Disable optimizations
Automatic Standard Library Management
- Import Detection: Automatically detects if source files need stdlib imports
- Smart Imports: Adds common stdlib imports to files without explicit module/import declarations
- Conflict Avoidance: Skips automatic imports for files with explicit module definitions or imports
- Partial Failure Handling: Reports detailed errors when stdlib compilation partially fails
Module Detection and Validation
- Required Modules Check: Validates presence of all required BEAM compiler modules
- Missing Module Reporting: Provides detailed error messages for missing components
- Build Automation: Automatically triggers 'make all' when modules are missing
- Error Recovery: Graceful error handling with instructions for resolution
Standard Library Compilation
- Automatic Compilation: Compiles stdlib modules as needed during user file compilation
- Dependency Resolution: Handles stdlib dependencies and compilation order
- Partial Failure Recovery: Attempts individual file compilation when batch compilation fails
- Path Conversion: Converts BEAM paths to source paths for error reporting
Standard Library Integration
Cure includes a comprehensive standard library implemented in Cure itself with Erlang runtime support.
Core Standard Library Modules
# Import common types and functions
import Std [Result, Option, ok, error, some, none]
import Std [map/2, filter/2, fold_left/3, fold_right/3]
# Mathematical operations
import Std.Math [abs/1, sqrt/1, sin/1, cos/1, pi, e]
# String operations
import Std.String [length/1, concat/2, split/2, trim/1]
# FSM utilities
import Std.FSM [create/2, send_event/2, get_state/1]Result and Option Types
# Chainable error handling
result = safe_divide(x, y)
|> map_ok(fn(val) -> val * 2 end)
|> and_then(fn(doubled) -> safe_sqrt(doubled) end)
match result do
Ok(final_value) -> println("Success: " <> show(final_value))
Error(msg) -> println("Error: " <> msg)
end
# Optional value handling
opt_value = find_in_list(items, predicate)
|> map(fn(item) -> process(item) end)
|> filter(fn(processed) -> is_valid(processed) end)Testing Infrastructure
Cure includes comprehensive testing infrastructure covering all aspects of the compiler and standard library.
Comprehensive Test Suites
# Master test runner for all new CLI and stdlib tests
erl -pa _build/ebin -pa test -s run_all_new_tests run -s init stop
# Individual comprehensive test suites
erl -pa _build/ebin -pa test -s cli_wrapper_comprehensive_test run -s init stop
erl -pa _build/ebin -pa test -s cure_wrapper_script_test run -s init stop
CLI and Wrapper Testing
- Build Command Testing: Verifies wrapper script correctly executes 'make all' for build command
- Missing Module Detection: Tests wrapper script detection and reporting of missing BEAM modules
- Error Message Validation: Ensures proper error reporting with helpful instructions
- Script Logic Verification: Tests all wrapper script conditional logic and edge cases
Standard Library Testing
- Automatic Import Testing: Validates CLI automatic stdlib import addition and detection
- Import Conflict Detection: Tests detection of explicit modules/imports to prevent conflicts
- Compilation Failure Testing: Tests stdlib compilation partial failure reporting
- Performance Testing: Benchmarks Std.List.length function with large datasets (up to 50k elements)
Test Coverage Areas
- Lexical Analysis: Token recognition and error handling
- Parsing: AST construction and syntax validation
- Type System: Inference, checking, and unification
- Code Generation: BEAM instruction generation
- FSM Runtime: State transitions and event handling
- CLI Functionality: Complete wrapper script and CLI module coverage
- Error Handling: Comprehensive error message formatting and reporting
Testing Features
- EUnit Integration: All tests use EUnit assertions for reliable verification
- Performance Benchmarks: Tests include timing validation for large datasets
- Edge Case Coverage: Comprehensive testing of boundary conditions and error scenarios
- Master Test Runner: Orchestrated execution of all test suites with detailed reporting
- Component Isolation: Both comprehensive and focused component-specific test suites
Compilation and Runtime
Current Compilation Pipeline
- Source (.cure) → Tokens (
cure_lexer.erl) - Tokens → AST (
cure_parser.erl) - AST → Typed AST (
cure_typechecker.erl) - Type Optimization (
cure_type_optimizer.erl)- Monomorphization
- Function specialization
- Inlining analysis
- Dead code elimination
- BEAM Bytecode (
cure_codegen.erl,cure_beam_compiler.erl)
BEAM Integration Features
- Native Processes: FSMs compile to BEAM processes with supervision
- gen_statem Integration: FSMs use OTP gen_statem behavior
- Pattern Matching: Leverages BEAM's efficient pattern matching
- Tail Call Optimization: Preserves BEAM's tail recursion optimization
- Hot Code Loading: Supports BEAM's live code upgrade
- Distributed Computing: Transparent distribution across BEAM nodes
- OTP Compatibility: Seamless integration with Erlang/Elixir ecosystems
Performance and Optimization
Type-Directed Optimizations
Cure's type system enables aggressive optimizations:
# Before optimization (polymorphic)
def map(f: T -> U, xs: List(T)): List(U) = ...
# After monomorphization (specialized for Int -> String)
def map_Int_String(f: Int -> String, xs: List(Int)): List(String) =
# Optimized implementation for specific types
specialized_map_impl(f, xs)Performance Characteristics
- Function calls: ~10ns overhead (optimized)
- FSM events: ~1μs including message passing
- Type checking: Zero runtime overhead (compile-time only)
- Pattern matching: BEAM-native performance
- Memory usage: Comparable to equivalent Erlang code
- Optimizations: 25-60% performance improvement over unoptimized code
Compiler Performance
- Small files (<100 lines): <1 second compilation
- Medium projects (1K-10K lines): 5-30 seconds
- Large projects (100K+ lines): 30-300 seconds with incremental compilation
- Type checking scales O(n²) due to dependent types
- SMT constraint solving typically sub-second for realistic programs
Implementation Status
✅ Fully Implemented
- Core syntax and semantics
- Dependent type system with SMT solving
- FSM compilation and runtime
- Type-directed optimizations
- BEAM code generation
- Standard library with runtime support
- Advanced CLI with wrapper script automation
- Automatic standard library import management
- Comprehensive test suite with performance benchmarks
- CLI wrapper functionality with missing module detection
- Partial compilation failure handling and recovery
🚧 Advanced Features
- Complex type class hierarchies
- Advanced dependent type features (proof obligations)
- Linear types for resource management
- Distributed FSM coordination
This reference covers all currently implemented language features and provides insight into Cure's unique combination of dependent types, native FSM support, and BEAM integration.