Java Target¶
ll-lang compiles to Java 21+. The output uses sealed interfaces, records, and switch expressions — modern Java features that map cleanly to ll-lang's algebraic types.
Usage¶
lllc build --target java file.lll # emits file.java
lllc build --target jvm file.lll # same (alias)
Type Mapping¶
| ll-lang | Java |
|---|---|
Int |
long |
Float |
double |
Str |
String |
Bool |
boolean |
Char |
char |
Unit |
void |
List[A] |
List<A> (java.util.List) |
Maybe[A] |
Maybe<A> (when declared in module) or Optional<A> (java.util.Optional) |
In generic positions (type parameters), primitive types are boxed automatically (Long, Double, Boolean, Character).
Sum Types¶
Sum types become sealed interfaces with inner record classes:
Shape = Circle Float | Rect Float Float | Empty
Emits:
sealed interface Shape permits Shape.Circle, Shape.Rect, Shape.Empty {
record Circle(double _0) implements Shape {}
record Rect(double _0, double _1) implements Shape {}
record Empty() implements Shape {}
}
Parametric sum types use Java generics:
Maybe A = Some A | None
Emits:
sealed interface Maybe<A> permits Maybe.Some, Maybe.None {
record Some<A>(A _0) implements Maybe<A> {}
record None<A>() implements Maybe<A> {}
}
Functions¶
Single-parameter functions become static methods:
double(x Int) = x * 2
Emits:
public static long double_(long x) {
return x * 2;
}
Curried (multi-parameter-group) functions return nested Function:
add(a Int)(b Int) = a + b
Emits:
public static Function<Long, Long> add(long a) {
return b -> a + b;
}
The backend emits Java imports for commonly used JDK types (List, Optional, Function, ArrayList, Collectors, Stream, etc.), so generated signatures stay concise and idiomatic.
Pattern Matching¶
Match expressions become ternary if/instanceof chains:
area(s Shape) =
| Circle r -> r * r * 3.14
| Rect w h -> w * h
| Empty -> 0.0
Emits:
public static double area(Shape s) {
return (s instanceof Shape.Circle _c0 ? _c0._0() * _c0._0() * 3.14
: (s instanceof Shape.Rect _c1 ? _c1._0() * _c1._1()
: 0.0));
}
Module → Class¶
Each ll-lang module compiles to a Java class. The class name is derived from the last component of the module path:
module Examples.Hello
main() = printfn "Hello!"
Emits a class Hello wrapping all declarations as public static members, with a public static void main(String[] args) entry point.
Stdlib¶
The Java backend emits a // --- ll-lang stdlib (Java) --- helper block on demand (only when stdlib helpers are referenced). Helpers are lowered to private static methods, and call-sites are mapped to Java-safe helper names where needed (abs -> abs_, min -> min_, max -> max_, print -> print_, exit -> exit_).
Key functions:
| ll-lang | Java |
|---|---|
printfn s |
System.out.println(s) |
strLen s |
s.length() |
strConcat a b |
a + b |
listMap f xs |
xs.stream().map(f).collect(...) |
listFold f acc xs |
loop |
intToStr n |
Long.toString(n) |
Running the Output¶
lllc build --target java hello.lll
## lllc also prints SDK suggestions:
## suggested compile: javac /.../Hello.java
## suggested run: javac /.../Hello.java && java Hello
javac Hello.java
java Hello
Requires Java 21 or later.
When source filename and module-tail class name differ (for example hello.lll -> class Hello), lllc keeps the primary output (hello.java) and also writes a class-aligned mirror (Hello.java) for javac.
Validation Status¶
Java output is covered by automated javac checks in the platform parity matrix for:
- arithmetic / conditionals
- ADT and tuple/string match
- trait impl dispatch (
impl_method) - constrained dispatch (
constrained_dispatch)
This coverage runs in CI tests via PlatformParityMatrixTests when javac is available.
Reserved Words¶
Java reserved words that conflict with ll-lang identifiers get a _ suffix: class_, void_, long_, interface_, record_, for_, while_, etc.