Standard Library Reference¶
ll-lang ships two layers of stdlib:
- Prelude — ~50 builtin functions always in scope. No
importneeded. - Self-hosted modules — modules written in ll-lang under
stdlib/src. Import withimport Std.X.
Module groups (frozen for v2)¶
The self-hosted modules fall into two distinct, non-overlapping groups:
Group 1 — Reusable foundation stdlib (Std.*)¶
These are general-purpose library modules. Import them in any ll-lang program.
| Module | Import | Purpose |
|---|---|---|
Std.List |
import Std.List |
list operations |
Std.Maybe |
import Std.Maybe |
optional values |
Std.Result |
import Std.Result |
error-or-value |
Std.Monad |
import Std.Monad |
monad trait + adapters |
Std.Map |
import Std.Map |
Okasaki RB-tree map |
Std.Str |
import Std.Str |
string utilities |
Std.State |
import Std.State |
stateful computation |
Std.Parsec |
import Std.Parsec |
parser combinators |
Std.Lazy |
import Std.Lazy |
explicit laziness |
Std.Json |
import Std.Json |
JSON codec |
Std.McpProtocol |
import Std.McpProtocol |
JSON-RPC/MCP envelope helpers |
Std.Reverse |
import Std.Reverse |
self-host reverse foundation |
Std.Toml |
import Std.Toml |
TOML subset parser |
Std.Test |
import Std.Test |
unit test harness |
Group 2 — Compiler implementation (Compiler.*)¶
These modules implement the self-hosted compiler. They live under stdlib/src/ today but are
not general-purpose stdlib. Their canonical namespace is Compiler.* (see
14-v2-canonical-compiler-boundaries.md).
| Current file | Canonical v2 module | Role |
|---|---|---|
stdlib/src/Lexer.lll |
Compiler.Syntax.Lexer |
tokenizer |
stdlib/src/Parser.lll |
Compiler.Syntax.Parser |
recursive-descent parser |
stdlib/src/Elaborator.lll |
Compiler.Frontend.Elaborator |
name resolution + declared-type checks |
stdlib/src/Codegen.lll |
Compiler.Backend.FSharp |
F# emitter |
stdlib/src/CodegenTS.lll |
Compiler.Backend.TypeScript |
TypeScript emitter |
stdlib/src/CodegenPy.lll |
Compiler.Backend.Python |
Python emitter |
stdlib/src/CodegenJava.lll |
Compiler.Backend.Java |
Java emitter |
stdlib/src/CodegenLLVM.lll |
Compiler.Backend.LLVM |
LLVM IR emitter (experimental) |
stdlib/src/CodegenCSharp.lll |
Compiler.Backend.CSharp |
C# emitter |
stdlib/src/Compiler.lll |
Compiler.Main |
pipeline entrypoint |
stdlib/src/Render.lll |
Compiler.Render |
diagnostic/output rendering |
Do not import compiler implementation modules from user programs. They are internal to the
compiler toolchain.
Prelude (always in scope)¶
Output¶
| Function | Type | Description |
|---|---|---|
printfn |
Str -> Unit |
Print string with newline |
print |
Str -> Unit |
Print string without newline |
main() =
_ = printfn "line one"
_ = print "no newline"
0
List operations¶
| Function | Type | Description |
|---|---|---|
listMap |
(A -> B) -> List[A] -> List[B] |
Transform each element |
listFold |
(B -> A -> B) -> B -> List[A] -> B |
Reduce left-to-right |
listFilter |
(A -> Bool) -> List[A] -> List[A] |
Keep matching elements |
listLen |
List[A] -> Int |
Number of elements |
listAppend |
List[A] -> List[A] -> List[A] |
Concatenate two lists |
listAt |
List[A] -> Int -> Maybe[A] |
Element at index (0-based) |
listHead |
List[A] -> Maybe[A] |
First element |
listTail |
List[A] -> Maybe[List[A]] |
All but first element |
listReverse |
List[A] -> List[A] |
Reverse a list |
listConcat |
List[List[A]] -> List[A] |
Flatten one level |
listRange |
Int -> Int -> List[Int] |
listRange 1 5 → [1 2 3 4 5] |
listSum |
List[Int] -> Int |
Sum of integer list |
listJoin |
Str -> List[Str] -> Str |
Join strings with separator |
-- double all even numbers
evensDoubled(xs List[Int]) =
xs -> listFilter (\x. x == (x / 2 * 2)) -> listMap (\x. x * 2)
-- sum with fold
total = listFold (\acc x. acc + x) 0 [1 2 3 4 5]
String operations¶
| Function | Type | Description |
|---|---|---|
strConcat |
Str -> Str -> Str |
Concatenate two strings |
strLen |
Str -> Int |
Length in characters |
strSplit |
Str -> Str -> List[Str] |
Split on separator |
strTrim |
Str -> Str |
Strip leading/trailing whitespace |
strContains |
Str -> Str -> Bool |
Substring test |
strStartsWith |
Str -> Str -> Bool |
Prefix test |
strEndsWith |
Str -> Str -> Bool |
Suffix test |
strSlice |
Str -> Int -> Int -> Str |
Extract substring |
strReplace |
Str -> Str -> Str -> Str |
Replace all occurrences |
strToUpper |
Str -> Str |
Uppercase |
strToLower |
Str -> Str |
Lowercase |
strToChars |
Str -> List[Char] |
Explode to character list |
charsToStr |
List[Char] -> Str |
Assemble from characters |
strToInt |
Str -> Maybe[Int] |
Parse integer |
strToFloat |
Str -> Maybe[Float] |
Parse float |
words = strSplit " " "hello world foo" -- ["hello" "world" "foo"]
upper = strToUpper "hello" -- "HELLO"
joined = listJoin ", " ["a" "b" "c"] -- "a, b, c"
Numeric conversions¶
| Function | Type | Description |
|---|---|---|
intToStr |
Int -> Str |
Integer to string |
floatToStr |
Float -> Str |
Float to string |
intToFloat |
Int -> Float |
Widen integer |
floatToInt |
Float -> Int |
Truncate to integer |
abs |
Int -> Int |
Absolute value |
absFloat |
Float -> Float |
Absolute value (float) |
min |
Int -> Int -> Int |
Minimum |
max |
Int -> Int -> Int |
Maximum |
Character operations¶
| Function | Type | Description |
|---|---|---|
charToInt |
Char -> Int |
Character code point |
intToChar |
Int -> Char |
Code point to character |
charIsDigit |
Char -> Bool |
'0'–'9' |
charIsAlpha |
Char -> Bool |
a–z, A–Z |
charIsSpace |
Char -> Bool |
Whitespace |
charIsUpper |
Char -> Bool |
Uppercase letter |
charIsLower |
Char -> Bool |
Lowercase letter |
Maybe and Result¶
| Function | Type | Description |
|---|---|---|
maybeMap |
(A -> B) -> Maybe[A] -> Maybe[B] |
Transform the value if present |
maybeWithDefault |
A -> Maybe[A] -> A |
Unwrap with a fallback |
maybeDefault |
A -> Maybe[A] -> A |
Alias for maybeWithDefault |
maybeBind |
(A -> Maybe[B]) -> Maybe[A] -> Maybe[B] |
Chain Maybe operations |
maybeToList |
Maybe[A] -> List[A] |
None → [], Some x → [x] |
resultMap |
(A -> B) -> Result[A][E] -> Result[B][E] |
Transform Ok value |
resultBind |
(A -> Result[B][E]) -> Result[A][E] -> Result[B][E] |
Chain Result operations |
resultMapErr |
(E -> F) -> Result[A][E] -> Result[A][F] |
Transform Err value |
resultToMaybe |
Result[A][E] -> Maybe[A] |
Discard error |
isOk |
Result[A][E] -> Bool |
Test for Ok |
isErr |
Result[A][E] -> Bool |
Test for Err |
-- chain operations that might fail
parseAndDouble(s Str) =
s -> strToInt -> maybeMap (\n. n * 2)
-- unwrap with default
value = maybeWithDefault 0 (strToInt "42") -- 42
missing = maybeWithDefault 0 (strToInt "x") -- 0
File I/O¶
| Function | Type | Description |
|---|---|---|
readFile |
Str -> Str |
Read entire file as string |
writeFile |
Str -> Str -> Unit |
Write string to file |
fileExists |
Str -> Bool |
Test path existence |
Process¶
| Function | Type | Description |
|---|---|---|
getArgs |
List[Str] |
Command-line arguments |
exit |
Int -> Unit |
Exit with code |
Category: Core Types¶
Std.Maybe — Optional values¶
Import: import Std.Maybe
Self-tests: 6/6 (isSome/isNone/pattern-match tests; maybeMap/maybeBind tested via F# backend target only — C# prelude type-inference limitation)
Description: Canonical optional type with predicate helpers. Core maybeMap/maybeBind/maybeWithDefault are also available as prelude builtins without an import.
Type:
Maybe A = Some A | None
Functions:
| Function | Type | Description |
|---|---|---|
isSome |
Maybe[A] -> Bool |
True if Some |
isNone |
Maybe[A] -> Bool |
True if None |
Std.Result — Error-or-value¶
Import: import Std.Result
Self-tests: 20/20
Description: Canonical Result type for recoverable errors. Never throw; propagate with resultBind. Integrates with Std.Maybe via resultFromMaybe/resultToMaybe.
Type:
Result A E = Ok A | Err E
Functions:
| Function | Type | Description |
|---|---|---|
resultWithDefault |
A -> Result[A][E] -> A |
Unwrap Ok or return default |
resultMap |
(A -> B) -> Result[A][E] -> Result[B][E] |
Transform Ok value |
resultMapErr |
(E -> F) -> Result[A][E] -> Result[A][F] |
Transform Err value |
resultBind |
Result[A][E] -> (A -> Result[B][E]) -> Result[B][E] |
Chain fallible computations |
resultFold |
(A -> C) -> (E -> C) -> Result[A][E] -> C |
Fold over both branches |
resultOrElse |
(E -> Result[A][E]) -> Result[A][E] -> Result[A][E] |
Recover from Err |
resultIsOk |
Result[A][E] -> Bool |
Test for Ok |
resultIsErr |
Result[A][E] -> Bool |
Test for Err |
resultFromMaybe |
E -> Maybe[A] -> Result[A][E] |
Lift Maybe; use errValue on None |
resultToMaybe |
Result[A][E] -> Maybe[A] |
Discard error |
resultSequence |
List[Result[A][E]] -> Result[List[A]][E] |
Collect Ok or short-circuit |
resultTraverse |
(A -> Result[B][E]) -> List[A] -> Result[List[B]][E] |
Map+sequence |
Usage:
import Std.Result
failIfZero(n Int) =
if n == 0
Err "zero"
else Ok n
pipeline(s Str) =
resultBind (resultFromMaybe "not a number" (strToInt s)) failIfZero
Std.Monad — compact monadic adapters¶
Import: import Std.Monad
Self-tests: covered via host smoke (StdlibStateParsecTests)
Description: Canonical compact monadic surface for Maybe, Result, and State. Keeps parser/compiler-heavy code short without adding new language features.
Functions:
| Function | Type | Description |
|---|---|---|
maybePure |
A -> Maybe[A] |
Maybe constructor via trait |
maybeBindM |
Maybe[A] -> (A -> Maybe[B]) -> Maybe[B] |
Maybe bind adapter |
maybeMapM |
Maybe[A] -> (A -> B) -> Maybe[B] |
Maybe map adapter |
maybeJoinM |
Maybe[Maybe[A]] -> Maybe[A] |
Flatten nested Maybe |
maybeThenM |
Maybe[A] -> Maybe[B] -> Maybe[B] |
Sequence and keep RHS |
resultPure |
A -> Result[A][E] |
Result constructor adapter |
resultBindM |
Result[A][E] -> (A -> Result[B][E]) -> Result[B][E] |
Result bind adapter |
resultMapM |
Result[A][E] -> (A -> B) -> Result[B][E] |
Result map adapter |
resultJoinM |
Result[Result[A][E]][E] -> Result[A][E] |
Flatten nested Result |
resultThenM |
Result[A][E] -> Result[B][E] -> Result[B][E] |
Sequence and keep RHS |
statePureM |
A -> State[S][A] |
State constructor adapter |
stateBindM |
State[S][A] -> (A -> State[S][B]) -> State[S][B] |
State bind adapter |
stateMapM |
State[S][A] -> (A -> B) -> State[S][B] |
State map adapter |
stateJoinM |
State[S][State[S][A]] -> State[S][A] |
Flatten nested State |
stateThenM |
State[S][A] -> State[S][B] -> State[S][B] |
Sequence and keep RHS |
Note:
Std.Monad is intentionally adapter-first for current self-hosted typing/runtime stability. Trait-based generic pure/bind dispatch remains tracked in TODO(selfhost:typing) and can be layered back without API break in call sites using these adapters.
Std.List — Extended list operations¶
Import: import Std.List
Self-tests: 16/16
Description: Extended list operations beyond the prelude. Import adds listTake, listDrop, listFlatMap, listAny, listAll, listFind, listFindIndex, and listPartition.
Functions:
| Function | Type | Description |
|---|---|---|
listTake |
Int -> List[A] -> List[A] |
First N elements |
listDrop |
Int -> List[A] -> List[A] |
Skip first N elements |
listFlatMap |
(A -> List[B]) -> List[A] -> List[B] |
Map then flatten |
listAny |
(A -> Bool) -> List[A] -> Bool |
Any element satisfies predicate |
listAll |
(A -> Bool) -> List[A] -> Bool |
All elements satisfy predicate |
listFind |
(A -> Bool) -> List[A] -> Maybe[A] |
First matching element |
listFindIndex |
(A -> Bool) -> List[A] -> Maybe[Int] |
Index of first match |
listPartition |
(A -> Bool) -> List[A] -> (List[A], List[A]) |
Split into passing/failing |
Std.Str — Extended string operations¶
Import: import Std.Str
Self-tests: 14/14
Description: String utility functions beyond the prelude. Adds isEmpty, startsWith/endsWith, take/drop, repeat, padLeft/padRight.
Functions:
| Function | Type | Description |
|---|---|---|
strIsEmpty |
Str -> Bool |
True if length is 0 |
strStartsWith |
Str -> Str -> Bool |
Prefix test |
strEndsWith |
Str -> Str -> Bool |
Suffix test |
strTake |
Int -> Str -> Str |
First N characters |
strDrop |
Int -> Str -> Str |
Skip first N characters |
strRepeat |
Int -> Str -> Str |
Repeat string N times |
strPadLeft |
Int -> Str -> Str -> Str |
Left-pad to width with fill |
strPadRight |
Int -> Str -> Str -> Str |
Right-pad to width with fill |
Std.Lazy — Explicit laziness¶
Import: import Std.Lazy
Self-tests: 6/6
Description: Controlled deferred evaluation for strict language semantics. Models thunks as Int -> A to avoid a dedicated Unit type.
Type:
Lazy A = Delayed (Int -> A) | Ready A
Functions:
| Function | Type | Description |
|---|---|---|
lazyDelay |
(Int -> A) -> Lazy[A] |
Create deferred value |
lazyReady |
A -> Lazy[A] |
Already-evaluated value |
lazyForce |
Lazy[A] -> (A, Lazy[A]) |
Force + memoize |
lazyValue |
Lazy[A] -> A |
Force and extract value |
lazyMap |
(A -> B) -> Lazy[A] -> Lazy[B] |
Map through deferred value |
lazyBind |
Lazy[A] -> (A -> Lazy[B]) -> Lazy[B] |
Compose deferred computations |
Category: Data Structures¶
Std.Map — Ordered map (red-black tree)¶
Import: import Std.Map
LOC: 223
Description: Functional ordered map using Okasaki's red-black tree. O(log n) insert, lookup, and delete. Keys are compared via an explicit comparator function, making it usable with any ordered type.
Key functions:
| Function | Type | Description |
|---|---|---|
mapEmpty |
RBMap[K][V] |
Empty map value |
mapInsert |
(K -> K -> Int) -> K -> V -> RBMap[K][V] -> RBMap[K][V] |
Insert key-value pair |
mapLookup |
(K -> K -> Int) -> K -> RBMap[K][V] -> Maybe[V] |
Lookup by key |
mapDelete |
(K -> K -> Int) -> K -> RBMap[K][V] -> RBMap[K][V] |
Remove key |
mapSize |
RBMap[K][V] -> Int |
Number of entries |
mapFold |
(B -> K -> V -> B) -> B -> RBMap[K][V] -> B |
In-order fold |
mapKeys |
RBMap[K][V] -> List[K] |
All keys in sorted order |
mapValues |
RBMap[K][V] -> List[V] |
All values in key order |
mapToList |
RBMap[K][V] -> List[(K, V)] |
All pairs in sorted order |
Usage:
module MyApp.Example
import Std.Map
-- String comparator (lexicographic)
strCmp(a Str)(b Str) =
if a < b
-1
else if a > b
1
else 0
-- Build a map
scores =
mapEmpty
-> mapInsert strCmp "alice" 95
-> mapInsert strCmp "bob" 87
-> mapInsert strCmp "carol" 92
-- Lookup
aliceScore = mapLookup strCmp "alice" scores -- Some 95
missing = mapLookup strCmp "dave" scores -- None
-- Iterate
total = mapFold (\acc _k v. acc + v) 0 scores -- 274
Category: Parsing and Config¶
Std.Toml — TOML config parser¶
Import: import Std.Toml
Self-tests: 5/5
Description: Minimal TOML parser for project manifests. Parses [table] headers, key = "value" string pairs, and key = ["a", "b"] string arrays. Pure functional, no mutable state.
Types:
Manifest = MkManifest Str Str Str (List[Str]) (List[Str])
-- name version entry deps platform
Key functions:
| Function | Type | Description |
|---|---|---|
parseManifest |
Str -> Maybe[Manifest] |
Parse TOML string to manifest |
manifestName |
Manifest -> Str |
Project name |
manifestVersion |
Manifest -> Str |
Project version |
manifestDeps |
Manifest -> List[Str] |
Dependency keys (flat list) |
manifestPlatform |
Manifest -> List[Str] |
Platform target names |
Usage:
module MyApp.Config
import Std.Toml
loadConfig(path Str) =
content = readFile path
match parseManifest content
| None -> printfn "invalid config"
| Some m -> printfn (manifestName m)
Std.Json — JSON parser and serializer¶
Import: import Std.Json
Self-tests: 12/12
Description: JSON parser and serializer built on Std.Parsec combinators. Supports strict number shape validation, string escapes (\uXXXX + surrogate pairs), deterministic serializer, and structural equality helpers.
Key functions:
| Function | Type | Description |
|---|---|---|
parseJson |
Str -> ParseResult[JsonValue] |
Parse JSON text into AST |
stringify |
JsonValue -> Str |
Serialize AST back to JSON text |
equalJson |
JsonValue -> JsonValue -> Bool |
Structural AST equality |
Backward-compatible aliases are also provided:
- parse (alias of parseJson)
- renderJson (alias-compatible implementation for stringify)
- eqJsonValue (alias-compatible implementation for equalJson)
Usage:
module MyApp.JsonUse
import Std.Json
validateAndRoundtrip(src Str) =
match parseJson src
| ParseErr e -> strConcat "ERR: " e
| ParseOk v _ ->
out = stringify v
match parseJson out
| ParseErr e2 -> strConcat "ERR2: " e2
| ParseOk v2 _ ->
if equalJson v v2
"OK"
else "MISMATCH"
Std.McpProtocol — JSON-RPC / MCP envelope helpers¶
Import: import Std.McpProtocol
Self-tests: covered via host smoke (StdlibStateParsecTests)
Description: Pure ll-lang encode/decode helpers for MCP/JSON-RPC request, notification, success-response, and error-response envelopes. Built on Std.Json.
Key types:
McpId = McpIdStr Str | McpIdInt Int | McpIdNull
McpRequest = MkMcpRequest Str McpId JsonValue
McpNotification = MkMcpNotification Str JsonValue
McpSuccessResponse = MkMcpSuccessResponse McpId JsonValue
McpErrorObject = MkMcpErrorObject Int Str Maybe[JsonValue]
McpErrorResponse = MkMcpErrorResponse McpId McpErrorObject
Key functions:
| Function | Type | Description |
|---|---|---|
parseRequestJson |
Str -> Result[McpRequest][Str] |
Parse+decode request envelope |
parseNotificationJson |
Str -> Result[McpNotification][Str] |
Parse+decode notification envelope |
encodeRequest |
McpRequest -> Str |
Serialize request envelope |
encodeNotification |
McpNotification -> Str |
Serialize notification envelope |
encodeSuccess |
McpSuccessResponse -> Str |
Serialize success response |
encodeError |
McpErrorResponse -> Str |
Serialize error response |
Std.McpProtocol is intentionally transport-agnostic; stdio process lifecycle and tool dispatch remain in host tooling.
Std.Reverse — self-host reverse foundation¶
Import: import Std.Reverse
Self-tests: covered via host smoke (StdlibStateParsecTests)
Description: Minimal reverse-transpiling substrate implemented in ll-lang. Current stable slice recovers module/let declarations from F# output; other targets return explicit upgrade marker.
Key functions:
| Function | Type | Description |
|---|---|---|
reverseToLll |
Str -> Str -> Str |
Reverse source for target alias (fs, fsharp, f#) |
Behavior:
- For
fs/fsharp/f#: extractsmodule ...and simplelet/let recdeclarations. - For non-F# targets: returns a deterministic placeholder with
TODO(selfhost:backend)marker.
This module is intentionally foundation-only in this pass; broader target parity remains tracked under selfhost:backend.
Std.State — stateful computation primitives¶
Import: import Std.State
Self-tests: 7/7
Description: Concrete state monad foundation for self-hosted compiler passes and imperative-style pipelines via stateBind.
Key types:
StateUnit = StateUnit
StatePair A S = MkStatePair A S
State S A = MkState (S -> StatePair[A][S])
Key functions:
| Function | Type | Description |
|---|---|---|
stateRun |
State[S][A] -> S -> StatePair[A][S] |
Run stateful computation |
stateEval |
State[S][A] -> S -> A |
Extract result value |
stateExec |
State[S][A] -> S -> S |
Extract final state |
statePure |
A -> State[S][A] |
Lift pure value |
stateMap |
(A -> B) -> State[S][A] -> State[S][B] |
Map over result |
stateBind |
State[S][A] -> (A -> State[S][B]) -> State[S][B] |
Sequence computations |
stateGet |
S -> State[S][S] |
Read state (seed argument pins S in current compiler) |
statePut |
S -> State[S][StateUnit] |
Replace state |
stateModify |
(S -> S) -> State[S][StateUnit] |
Transform state |
stateGet is temporarily argument-based due current top-level polymorphic value inference limits; once zero-arg polymorphic values are stabilized it can be reduced to a plain State[S][S] value.
Std.Test — unit test harness¶
Import: import Std.Test
Self-tests: 8 (4 pass + 4 intentional fails exercising the harness itself)
Description: Lightweight test harness for ll-lang modules. Collects TestResult values, prints OK/FAIL lines, and returns a failure count. Intended for module self-tests reachable via lllc run.
Type:
TestResult = Pass Str | Fail Str
Functions:
| Function | Type | Description |
|---|---|---|
assertTrue |
Str -> Bool -> TestResult |
Pass iff condition is true |
assertEqInt |
Str -> Int -> Int -> TestResult |
Pass iff ints match |
assertEqStr |
Str -> Str -> Str -> TestResult |
Pass iff strings match |
assertEqBool |
Str -> Bool -> Bool -> TestResult |
Pass iff bools match |
renderResult |
TestResult -> Str |
Format OK/FAIL line |
run |
List[TestResult] -> Int |
Print all results; return fail count |
Usage:
module MyModule
import Std.Test
main =
failCount = run
[ assertEqInt "add" 5 (2 + 3)
; assertEqStr "hello" "hello" "hello"
; assertTrue "positive" (3 > 0)
]
printfn (strConcat "Done failCount=" (intToStr failCount))
Std.Parsec — parser combinator toolkit¶
Import: import Std.Parsec
Self-tests: 12/12
Description: Reusable parser-combinator substrate for self-hosted parsing tasks. Works over source text with explicit position tracking and backtracking control.
Key types:
ParsePos = MkParsePos Int Int Int
ParseState = MkParseState Str List[Char] ParsePos
ParseError = MkParseError Str ParsePos
Parser A = MkParser (ParseState -> ParseStep[A])
Core functions:
| Function | Description |
|---|---|
runParser |
Run parser on Str and return Result |
parsePure / parseMap / parseBind |
Core combinators |
parseOrElse / parseTry |
Choice + controlled rollback |
parseLabel / parseFail |
Diagnostics helpers |
parseSatisfy / parseChar / parseString |
Primitive token parsers |
parseOneOf / parseNoneOf / parsePeekChar / parseAnyChar / parseEof |
Character/EOF parsers |
parseMany / parseMany1 / parseOptional / parseSepBy / parseSepBy1 / parseBetween |
Structural combinators |
parseWhitespace / parseSpaces / parseDigit / parseInt / parseQuotedString |
Common building blocks |
Std.Json uses Std.Parsec as its parser backend.
Combinator pipelines can use either parenthesized lambdas or trailing lambda sugar:
parseBind parseInt \n.
parsePure (n + 1)
Std.Lazy — explicit laziness on top of strict evaluation¶
Import: import Std.Lazy
Description: Controlled delayed evaluation for expensive or recursive computations without changing strict language semantics.
Key types:
Lazy[A] = Delayed (Int -> A) | Ready A
Core functions:
| Function | Type | Description |
|---|---|---|
lazyDelay |
(Int -> A) -> Lazy[A] |
Create delayed value |
lazyReady |
A -> Lazy[A] |
Create already-forced value |
lazyForce |
Lazy[A] -> (A, Lazy[A]) |
Force and return memoized node |
lazyValue |
Lazy[A] -> A |
Force and return value only |
lazyMap |
(A -> B) -> Lazy[A] -> Lazy[B] |
Map through delayed value |
lazyBind |
Lazy[A] -> (A -> Lazy[B]) -> Lazy[B] |
Compose delayed computations |
Std.Lexer — ll-lang tokenizer¶
Import: import Std.Lexer
LOC: 473
Description: Standalone ll-lang lexer written in ll-lang. Tokenizes ll-lang source to a flat List[Token]. Recognizes all language keywords, identifiers (by case), literals, and operators.
Token type (selected constructors):
Token =
| KwIf | KwElse | KwMatch | KwTrait | KwImpl
| KwImport | KwExport | KwModule | KwTag | KwUnit
| Ident Str -- lowercase identifier
| TypeId Str -- uppercase identifier / constructor
| IntLit Int | FloatLit Str | StrLit Str | CharLit Char
| Arrow | Eq | Bar | LBrack | RBrack | LParen | RParen
| Plus | Minus | Star | Slash
| Newline | Indent | Dedent | Eof
Key functions:
| Function | Type | Description |
|---|---|---|
tokenize |
Str -> List[Token] |
Lex a source string to token list |
tokenToStr |
Token -> Str |
Debug representation of a token |
isKeyword |
Token -> Bool |
Test for keyword token |
Usage:
module MyApp.Analyze
import Std.Lexer
countIdents(src Str) =
tokens = tokenize src
listLen (listFilter (\t. match t | Ident _ -> true | _ -> false) tokens)
Std.Parser — ll-lang recursive-descent parser¶
Import: import Std.Parser
LOC: 802
Description: Recursive-descent parser consuming a List[Token] from Std.Lexer and producing an AST. Return convention: every parse function returns (result, remainingTokens).
Key types:
Expr =
| EInt Int | EStr Str | EBool Bool | EVar Str | ECon Str
| EApp Expr Expr | ELam Str Expr | EIf Expr Expr Expr
| EMatch Expr (List[Pattern]) (List[Expr])
| ELet Str Expr Expr | EBinOp Str Expr Expr
Decl =
| DFn Str (List[(Str, TypeExpr)]) (Maybe[TypeExpr]) Expr
| DType Str (List[Str]) (List[(Str, List[TypeExpr])])
| DTag Str | DImport Str | DExport Decl
Key functions:
| Function | Type | Description |
|---|---|---|
parseModule |
List[Token] -> Maybe[LLModule] |
Parse full module from tokens |
parseExpr |
List[Token] -> Maybe[(Expr, List[Token])] |
Parse a single expression |
parseDecl |
List[Token] -> Maybe[(Decl, List[Token])] |
Parse a single declaration |
Usage:
module MyApp.Parse
import Std.Lexer
import Std.Parser
parseSource(src Str) =
tokens = tokenize src
match parseModule tokens
| None -> printfn "parse error"
| Some m -> printfn "ok"
Category: Code Generation¶
Std.Elaborator — name resolver / type checker¶
Import: import Std.Elaborator
LOC: 344
Description: Simplified elaborator pass operating on the AST from Std.Parser. Performs name resolution: detects unbound variables, unbound constructors, and duplicate declarations. Produces an enriched AST or a list of error messages.
Key types:
ElabError =
| UnboundVar Str
| UnboundCon Str
| DuplicateDecl Str
ElabResult A = ElabOk A | ElabErr (List[ElabError])
Key functions:
| Function | Type | Description |
|---|---|---|
elaborate |
LLModule -> ElabResult[LLModule] |
Check a module for binding errors |
collectDecls |
LLModule -> Env |
Build environment from module decls |
checkExpr |
Env -> Expr -> List[ElabError] |
Check an expression |
Std.Codegen — F# code emitter¶
Import: import Std.Codegen
LOC: 569
Description: F# source emitter written in ll-lang. Takes the AST from Std.Parser and emits idiomatic F# source. This is the self-hosted reference implementation of the F# backend.
Key functions:
| Function | Type | Description |
|---|---|---|
emitModule |
LLModule -> Str |
Emit entire module as F# source |
emitDecl |
Decl -> Str |
Emit one declaration |
emitExpr |
Expr -> Int -> Str |
Emit expression (indent level) |
emitType |
TypeExpr -> Str |
Emit type annotation |
Usage:
module MyApp.Transpile
import Std.Lexer
import Std.Parser
import Std.Codegen
transpileToFSharp(src Str) =
tokens = tokenize src
match parseModule tokens
| None -> Err "parse error"
| Some m -> Ok (emitModule m)
Std.CodegenTS — TypeScript emitter¶
Import: import Std.CodegenTS
LOC: 492
Description: TypeScript source emitter written in ll-lang. Emits TypeScript sealed interfaces for ADTs, readonly records, and typed functions.
Key functions:
| Function | Type | Description |
|---|---|---|
emitModule |
LLModule -> Str |
Emit module as TypeScript source |
emitDecl |
Decl -> Str |
Emit one declaration |
emitType |
TypeExpr -> Str |
Emit TypeScript type annotation |
Std.CodegenPy — Python emitter¶
Import: import Std.CodegenPy
LOC: 501
Description: Python source emitter. Emits @dataclass classes, Union types from typing, and module-level functions.
Key functions:
| Function | Type | Description |
|---|---|---|
emitModule |
LLModule -> Str |
Emit module as Python source |
emitDecl |
Decl -> Str |
Emit one declaration |
emitType |
TypeExpr -> Str |
Emit Python type annotation |
Std.CodegenJava — Java 21 emitter¶
Import: import Std.CodegenJava
LOC: 633
Description: Java 21 source emitter. Emits sealed interface + record hierarchies for ADTs, static methods for functions.
Key functions:
| Function | Type | Description |
|---|---|---|
emitModule |
LLModule -> Str |
Emit module as Java source |
emitDecl |
Decl -> Str |
Emit one declaration |
emitType |
TypeExpr -> Str |
Emit Java type annotation |
Std.CodegenCSharp — C# emitter¶
Import: import Std.CodegenCSharp
LOC: 548
Description: C# source emitter. Emits sealed record/interface hierarchies for ADTs, static methods for functions, wrapped IIFE style for let-bindings.
Key functions:
| Function | Type | Description |
|---|---|---|
emitModule |
LLModule -> Str |
Emit module as C# source |
emitDecl |
Decl -> Str |
Emit one declaration |
emitType |
TypeExpr -> Str |
Emit C# type annotation |
Std.CompilerTypes — HM type representations¶
Import: import Std.CompilerTypes
LOC: 336
Description: Hindley-Milner type representations for the v2 self-hosted compiler. Provides Scheme, substitution helpers (RBMap[Str][TypeExpr]), free-type-variable utilities, fresh variable generation, unification (unify), and generalize/instantiate. Canonical home for all type-level machinery shared across compiler passes.
Key types:
-- Flex (unification) vars: TyName "$0", TyName "$1", ...
-- Rigid type vars: TyName "a", TyName "b", ...
-- Type names: TyName "Int", TyName "Maybe", ...
Scheme = MkScheme (List[Str]) TypeExpr
InferResult A = InferOk A | InferErr Str
Fresh = MkFresh Int
Key functions:
| Function | Type | Description |
|---|---|---|
isFlex |
Str -> Bool |
True if name starts with $ |
freshVarName |
Int -> Str |
"$N" |
freshNext |
Fresh -> (TypeExpr, Fresh) |
Allocate next flex var |
generalize |
RBMap[Str][Scheme] -> TypeExpr -> Scheme |
Generalize over free flex vars |
instantiate |
Fresh -> Scheme -> (TypeExpr, Fresh) |
Replace quantified vars with fresh flex vars |
unify |
TypeExpr -> TypeExpr -> InferResult[RBMap[Str][TypeExpr]] |
Algorithm W unification with occurs check |
applyType |
RBMap[Str][TypeExpr] -> TypeExpr -> TypeExpr |
Apply substitution to a type |
substCompose |
Subst -> Subst -> Subst |
Compose substitutions (s1 after s2) |
renderType |
TypeExpr -> Str |
Pretty-print a type for error messages |
ftvTypeList |
TypeExpr -> List[Str] |
Free flex vars in a type |
Std.CompilerTyped — typed IR shapes¶
Import: import Std.CompilerTyped
LOC: 206
Description: Typed intermediate representation (IR) for the v2 self-hosted compiler. Defines TypedExpr, TypedPattern, TypedFnSig, TypedDecl, and TypedModule. These are the output shapes produced by Std.CompilerInfer and consumed by lowering and backend passes. Flat sum-type design avoids mutual-recursion constraints.
Key types:
-- Pattern with resolved type
TypedPattern = MkTypedPat Pattern TypeExpr
-- Expression nodes (last arg is always the expression's TypeExpr)
TypedExpr =
| TEInt Int TypeExpr
| TEStr Str TypeExpr
| TEBool Bool TypeExpr
| TEVar Str TypeExpr
| TECon Str TypeExpr
| TEApp TypedExpr TypedExpr TypeExpr
| TELam Str TypeExpr TypedExpr TypeExpr
| TeLet Str TypedExpr TypedExpr TypeExpr
| TEIf TypedExpr TypedExpr TypedExpr TypeExpr
| TEMatch TypedExpr (List[TypedPattern]) (List[TypedExpr]) TypeExpr
| TEBinOp Str TypedExpr TypedExpr TypeExpr
| ...
TypedDecl =
| TDFn TypedFnSig Scheme TypedExpr
| TDLet Str Scheme TypedExpr
| TDType Str (List[Str]) (List[Constructor])
| ...
TypedModule = MkTypedModule (List[Str]) (List[TypedDecl]) (RBMap[Str][Scheme])
Key functions:
| Function | Type | Description |
|---|---|---|
typedExprType |
TypedExpr -> TypeExpr |
Extract type from any node |
typedPatType |
TypedPattern -> TypeExpr |
Extract type from pattern |
typedFnName |
TypedFnSig -> Str |
Function name |
typedModDecls |
TypedModule -> List[TypedDecl] |
Module declarations |
renderTypedExprTag |
TypedExpr -> Str |
Tag name for debugging |
Std.CompilerInfer — HM Algorithm W inference¶
Import: import Std.CompilerInfer
LOC: 471
Description: Hindley-Milner Algorithm W type inference for the v2 self-hosted compiler. Builds on Std.CompilerTypes. Provides InferState threading, a prelude base environment, and inferExpr / inferDecl / inferModule for inferring types over the Expr/Decl AST from Std.Parser.
Key types:
-- (env, fresh counter, error list, accumulated substitution)
InferState = MkInferState
(RBMap[Str][Scheme]) -- type environment
Fresh -- fresh variable counter
(List[Str]) -- accumulated errors
(RBMap[Str][TypeExpr]) -- accumulated substitution
Key functions:
| Function | Type | Description |
|---|---|---|
inferExpr |
InferState -> Expr -> (TypeExpr, InferState) |
Infer type of an expression |
inferDecl |
InferState -> Decl -> InferState |
Elaborate one declaration into the env |
inferModule |
List[Decl] -> List[Str] |
Infer a whole module; return errors |
baseEnv |
() -> RBMap[Str][Scheme] |
Prelude: arithmetic, comparison, printfn, etc. |
inferUnify |
InferState -> TypeExpr -> TypeExpr -> Str -> InferState |
Unify two types, compose substitution |
inferFreshVar |
InferState -> (TypeExpr, InferState) |
Allocate a fresh flex var |
inferInstantiate |
InferState -> Scheme -> (TypeExpr, InferState) |
Instantiate a scheme |
Usage:
module MyApp.Check
import Std.Parser
import Std.CompilerInfer
checkSource(src Str) =
tokens = tokenize src
match parseModule tokens
| None -> ["parse error"]
| Some m ->
inferModule m.decls
Std.CompilerLower — backend-neutral lowering pass¶
Import: import Std.CompilerLower
LOC: 296
Description: Lowering pass for the v2 self-hosted compiler. Takes a TypedModule (from Std.CompilerTyped) and produces a LowModule — a backend-neutral lowered IR. Primary active transformation: TEBinOp desugaring into curried LApp chains. Match/lambda lowering is architecture-complete but semantically stubbed (issue #48).
Key types:
LowExpr =
| LInt Int TypeExpr
| LStr Str TypeExpr
| LVar Str TypeExpr
| LApp LowExpr LowExpr TypeExpr
| LLam Str TypeExpr LowExpr TypeExpr
| LLet Str LowExpr LowExpr TypeExpr
| LIf LowExpr LowExpr LowExpr TypeExpr
| LMatch LowExpr (List[TypedPattern]) (List[LowExpr]) TypeExpr
| ...
LowDecl =
| LDFn Str (List[Param]) TypeExpr Scheme LowExpr
| LDLet Str Scheme LowExpr
| ...
LowModule = MkLowModule (List[Str]) (List[LowDecl]) (RBMap[Str][Scheme])
Key functions:
| Function | Type | Description |
|---|---|---|
lowerModule |
TypedModule -> LowModule |
Lower entire typed module |
lowerExpr |
LowState -> TypedExpr -> (LowExpr, LowState) |
Lower one typed expression |
lowerDecl |
LowState -> TypedDecl -> (LowDecl, LowState) |
Lower one typed declaration |
lowExprType |
LowExpr -> TypeExpr |
Extract type from a lowered expression |
Std.Compiler — full pipeline (source → F#)¶
Import: import Std.Compiler
LOC: 1516
Description: End-to-end compiler pipeline in ll-lang: Lexer → Parser → Elaborator → Codegen. Self-contained — all types defined inline. This is the bootstrap compiler that produced compiler₁.fs == compiler₂.fs.
Key functions:
| Function | Type | Description |
|---|---|---|
compile |
Str -> Result[Str][List[Str]] |
Compile source string to F# |
compileFile |
Str -> Result[Str][List[Str]] |
Read file, compile, return F# |
pipeline |
Str -> Maybe[LLModule] |
Lex + parse only |
Usage:
module MyApp.Build
import Std.Compiler
buildFile(path Str) =
src = readFile path
match compile src
| Err errs -> listFold (\_ e. printfn e) () errs
| Ok fsharp -> writeFile (strConcat path ".fs") fsharp
Module index by category¶
| Category | Module | Purpose |
|---|---|---|
| Core types | Std.Maybe |
Maybe helpers and tests |
| Core types | Std.Monad |
Compact monadic adapters (Maybe/Result/State) |
| Data structures | Std.Map |
Ordered map, O(log n) |
| Config | Std.Toml |
TOML manifest parser |
| Parsing | Std.Json |
JSON parse + stringify + roundtrip helpers |
| Parsing | Std.McpProtocol |
JSON-RPC/MCP envelope encode/decode helpers |
| Parsing | Std.Reverse |
Self-host reverse foundation (fs stable slice) |
| Parsing | Std.Parsec |
Parser combinator substrate |
| Runtime | Std.Lazy |
Explicit delayed evaluation |
| Parsing | Std.Lexer |
ll-lang tokenizer |
| Parsing | Std.Parser |
Recursive-descent parser |
| Type checking | Std.Elaborator |
Name resolution, binding checks |
| Code generation | Std.Codegen |
F# emitter |
| Code generation | Std.CodegenTS |
TypeScript emitter |
| Code generation | Std.CodegenPy |
Python emitter |
| Code generation | Std.CodegenJava |
Java emitter |
| Code generation | Std.CodegenLLVM |
LLVM emitter |
| Code generation | Std.CodegenCSharp |
C# emitter |
| Rendering | Std.Render |
Shared rendering helpers |
| Testing | Std.Test |
Test assertions/utilities |
| Type inference | Std.CompilerTypes |
HM substitutions, unification, schemes |
| Type inference | Std.CompilerTyped |
Typed IR shapes (TypedExpr, TypedDecl, TypedModule) |
| Type inference | Std.CompilerInfer |
Algorithm W for Expr/Decl |
| Lowering | Std.CompilerLower |
BinOp desugaring; TypedModule → LowModule |
| Project system | Std.CompilerManifest |
lll.toml parsing, DepSource, LLManifest, validation |
| Project system | Std.CompilerLoader |
Dependency graph, cycle detection, Kahn's topo sort |
| Full pipeline | Std.Compiler |
Source pipeline helpers |
Compiler implementation modules vs reusable stdlib¶
The modules below are currently importable like ordinary stdlib modules, but they should be read as the self-hosted compiler slice rather than as general application-library APIs:
Std.LexerStd.ParserStd.ElaboratorStd.CompilerTypesStd.CompilerTypedStd.CompilerInferStd.CompilerLowerStd.CompilerManifestStd.CompilerLoaderStd.CodegenStd.CodegenTSStd.CodegenPyStd.CodegenJavaStd.CodegenLLVMStd.Compiler
These modules are important because they show that ll-lang can already express substantial compiler logic. They should not be treated as proof that the full canonical compiler boundary has already migrated away from stage0. That boundary is tracked in v2 canonical compiler boundaries.
Notes on self-hosted modules¶
The stdlib modules are written in ll-lang and compiled via the bootstrap compiler. Library modules are no longer expected to be independently runnable via main(); smoke/demo entrypoints should live in dedicated executable modules.
When using multiple modules together in a project, import them in dependency order: Std.Lexer before Std.Parser before Std.Elaborator before Std.Codegen.
Naming convention (frozen for v2)¶
All public stdlib names use a verbOnType prefix style — no namespacing inside modules, no operator overloading. The type prefix is lowercase and comes first.
| Type | Prefix | Example |
|---|---|---|
List |
list |
listMap, listFilter, listFold |
Maybe |
maybe |
maybeMap, maybeBind, maybeWithDefault |
Result |
result |
resultMap, resultBind, resultIsOk |
Map |
map |
mapInsert, mapLookup, mapDelete |
Str |
str |
strConcat, strSplit, strTrim |
State |
state |
stateRun, stateBind, stateGet |
Parsec |
parse |
parsePure, parseBind, parseMany |
Lazy |
lazy |
lazyDelay, lazyForce, lazyValue |
Json |
json |
jsonParse, jsonStringify |
Toml |
toml |
tomlParse |
Rules:
1. The type-name prefix is always lowercase and always first in the name.
2. No two functions in different modules may share an unambiguous short name (e.g., map is not a valid export — use mapInsert).
3. Prelude function names are owned by the prelude; imported modules must not re-export conflicting names.
4. Legacy names or aliases are removed aggressively; backwards-compatibility shims are not kept.
Prelude boundary rule (frozen for v2)¶
A function belongs in the Prelude if and only if:
- It is needed by almost every ll-lang program (≥ 90% of programs would import it otherwise)
- It operates on a type that is built into the language (List, Maybe, Str, Int, Bool, Char)
- Its definition is 1–3 lines and has no non-trivial dependencies
A function does NOT belong in the Prelude if: - It is useful only in specific domains (parsing, state threading, config loading) - It requires importing another stdlib module to typecheck - It could be replaced by a 2–3 line inline in the call site
Current Prelude surface is frozen. Adding to it requires removing something of equal or greater cognitive weight. The prelude must stay small enough that a developer can memorize it in one sitting.
Compiler-facing proof-of-use (M3.H)¶
The following sketch shows the foundation modules supporting a real compiler-shaped task: a single-pass diagnostic accumulator that resolves imports, collects errors, and formats them.
This uses Std.State for pass state, Std.Maybe for optional lookups, Std.Map for the
module registry, and Std.Result for error propagation.
module Compiler.ImportResolver
import Std.State
import Std.Maybe
import Std.Map
import Std.Result
-- Pass state: seen module names + accumulated diagnostics
ResolverState = MkResolverState
(RBMap[Str][Bool]) -- seen modules
(List[Str]) -- diagnostics
emptyResolverState() =
MkResolverState (mapEmpty()) []
addDiag(diag Str)(s ResolverState) =
match s
| MkResolverState seen diags ->
MkResolverState seen (diag :: diags)
markSeen(modName Str)(s ResolverState) =
match s
| MkResolverState seen diags ->
MkResolverState (mapInsert strCmp modName true seen) diags
isSeen(modName Str)(s ResolverState) =
match s
| MkResolverState seen _ -> isSome (mapLookup strCmp modName seen)
-- Resolve one import: emit diagnostic if unknown, mark as seen
resolveImport(known RBMap[Str][Bool])(modName Str) =
stateBind (stateGet (emptyResolverState())) \s.
if isSeen modName s
statePure ()
else
match mapLookup strCmp modName known
| None ->
stateModify (addDiag (strConcat "E002 unknown module: " modName))
| Some _ ->
stateModify (markSeen modName)
-- Run resolver over a list of imports
resolveAll(known RBMap[Str][Bool])(imports List[Str]) =
listFold
(\acc imp. stateBind acc (\_ . resolveImport known imp))
(statePure ())
imports
-- Entry: returns accumulated diagnostics
checkImports(known RBMap[Str][Bool])(imports List[Str]) =
s = stateExec (resolveAll known imports) (emptyResolverState())
match s
| MkResolverState _ diags -> diags
This sketch validates that Std.State + Std.Map + Std.Maybe compose correctly for
compiler-style pass work without fighting the language or requiring ad hoc helpers.