JVM Interoperability
Elara is a purely functional language targeting the JVM. Every Elara program compiles to JVM bytecode that can run on any standard Java Virtual Machine (Java 8+).Compilation Strategy
Elara uses a multi-stage compilation pipeline:JVM Intermediate Representation
Before emitting bytecode, Elara uses a high-level IR that abstracts JVM details:IR Instructions
The IR provides structured control flow:Assignment
Assignment
Conditional Jumps
Conditional Jumps
Method Calls
Method Calls
Field Access
Field Access
Translation Rules
Modules to Classes
Each Elara module becomes a JVM class:Static by Default: All top-level Elara definitions become static members since Elara modules are not instantiated.
Functions and Currying
Elara functions are automatically curried. Multi-parameter functions become chains of single-parameter functions:Single Parameter
Single Parameter
Multiple Parameters
Multiple Parameters
Func, Func2) for closure representation.Partial Application
Partial Application
x = 5.Closures and Lambda Lifting
Nested functions that capture variables are compiled usinginvokedynamic:
Data Types
Algebraic data types compile to class hierarchies:Sum Types
Sum Types
Product Types (Records)
Product Types (Records)
Pattern Matching
Pattern matching compiles to instanceof checks and field access:Exhaustiveness checking happens at compile-time, so the final
else branch should never execute.Primitive Operations
Elara primitive operations map to JVM instructions or standard library calls:| Elara PrimOp | JVM Implementation |
|---|---|
IntAdd | Prelude.add (handles boxed integers) |
IntSubtract | Prelude.minus |
IntMultiply | Prelude.times |
PrimEquals | Objects.equals + boolean wrapping |
Println | IO.println (wraps System.out.println) |
StringCons | Elara.String.cons method |
ToString | PrimOps.toString (dispatches to .toString()) |
Boolean Representation
Elara booleans are not JVM primitive booleans:IO and Side Effects
TheIO monad is represented as a JVM class:
Main Method
Elara’smain : IO () is wrapped in a standard Java main:
JVM Standard Library
Elara includes a small JVM runtime injvm-stdlib/:
Elara/Func.java- Functional interface for 1-argument functionsElara/Func2.java- For 2-argument functionsElara/IO.java- IO monad implementationElara/Prelude.java- Basic operations (arithmetic, etc.)Elara/Error.java- Error handlingElara/Unit.java- Unit type singleton
Class File Generation
The bytecode emitter atsrc/Elara/JVM/Emit.hs generates standard Java class files:
Method Descriptors
JVM method descriptors specify argument and return types:Object except primitives.
Performance Considerations
Boxed Arithmetic
Boxed Arithmetic
Elara integers use
java.lang.Integer, which has allocation overhead. For performance-critical code, future versions may optimize to primitive int.Closure Allocation
Closure Allocation
Each lambda creates a new closure object. The JVM’s escape analysis can sometimes optimize away short-lived closures.
Tail Call Optimization
Tail Call Optimization
Not yet implemented. Elara currently does not optimize tail-recursive functions, which can cause stack overflows on deep recursion.
Debugging
Elara class files can be debugged with standard JVM tools:Future Directions
- Native Java Interop: Call Java libraries directly from Elara
- Inline Primitives: Generate specialized bytecode for Int/Float operations
- Tail Call Optimization: Transform tail recursion to loops
- Value Types: Use Project Valhalla’s value types for zero-cost abstractions
Further Reading
- Compiler Internals - Full compilation pipeline
- Type Inference - How types guide code generation
- JVM Specification: https://docs.oracle.com/javase/specs/jvms/se8/html/