Skip to content

Language Features Roadmap

This document tracks the implementation status of F# language features in Endo as defined in the language specification.

Legend: [x] Implemented | [~] Partial | [ ] Not yet implemented


Expressions

  • Immutable bindings: let x = 42
  • Mutable bindings: let mut x = 0
  • Export bindings: let export X = expr -- binds value and exports as environment variable
  • Mutation operator: x <- x + 1
  • Lambda expressions: fun x -> x * 2
  • Lambda expression sugar: _ + 1, _.field etc.
  • Let-in expressions: let x = 5 in x + 1
  • If-then-else expressions: if cond then a else b
  • Match expressions: match x with | pattern -> result
  • List expressions: [1; 2; 3]
  • List ranges: [1..10], [1..2..10], [10..-1..7]
  • List comprehensions: [for x in items -> expr], [for x in items when cond -> expr]
  • Record expressions: { name = "Alice"; age = 30 }
  • Record update: { alice with age = 31 }
  • Tuple expressions: (1, "hello") (2 and 3 elements)
  • Tuple destructuring in let: let (x, y) = tuple
  • Record destructuring in let: let { name; age } = person
  • Block scopes: { let inner = 20; inner + outer }

Types

Primitive Types

  • int -- 64-bit signed integer
  • float -- 64-bit floating point
  • str -- UTF-8 string
  • bool -- Boolean
  • unit -- No value (void)

Compound Types

  • Lists: list<int> (cons-cell linked list)
  • Tuples: (int, str) (2 and 3 elements)
  • Options: option<T> with Some and None
  • Results: result<T, E> with Ok and Error
  • Records: type Person = { name: str; age: int }
  • Discriminated Unions: type Shape = | Circle of float | Rectangle of float * float
  • Generic types

Type Annotations

  • Variable annotations: let count: int = 42
  • Function parameter annotations: let add (x: int) (y: int): int = x + y
  • Lambda annotations: fun (x: int) -> x + 1

Type Inference

  • Hindley-Milner type inference (Algorithm W) as separate pre-pass
  • Primitive type inference: int, float, bool, str, unit inferred from usage
  • Operator-driven inference: x + y infers int, x +. y infers float
  • Recursive function inference
  • Let-polymorphism: let id x = x can be used at multiple types
  • [~] Complex type inference: list, option, result, function types inferred but not yet applied to compilation

Functions

  • Single-parameter functions: let double x = x * 2
  • Multi-parameter (curried) functions: let add x y = x + y
  • Partial application: let add5 = add 5
  • Lambda expressions: fun x -> x * 2
  • Multi-parameter lambdas: fun x y -> x + y
  • Closures (capturing outer scope variables)
  • Recursive functions: let rec gcd a b = ...
  • Mutual recursion: let rec isEven n = ... and isOdd n = ...
  • Tail-call optimization
  • Function composition: >> and << operators
  • Type-annotated functions
  • Higher-order functions: passing functions as arguments
  • Variadic parameters: let f ...args = ...
  • Splat expression: ...args in shell commands
  • Shell aliases via let bindings: let ll ...args = & exa -l ...args

Lists and Collections

  • List literal construction: [1; 2; 3]
  • List ranges: [1..10], [1..2..10], [10..-1..7]
  • Character ranges: ['a'..'z'], ['A'..'Z'], ['0'..'9']
  • Cons operator: :: (right-associative)
  • List concatenation: @
  • List comprehensions with optional when filter
  • Standard operations: map, filter, fold, reduce, reverse
  • Indexed access: nth, last (return option<T>)
  • Construction: replicate
  • Utility operations: find, exists, forall, take, drop, zip, flatten
  • Compile-time type checking for heterogeneous list literals

Pattern Matching

Basic Patterns

  • Literal patterns: | 0 -> "zero", | "hello" -> ...
  • Variable binding: | n -> n + 1
  • Wildcard: | _ -> "default"
  • Boolean patterns: | true -> ... | false -> ...

Compound Patterns

  • Tuple patterns: | (a, b) -> a + b
  • List patterns: | [] -> ... | [x] -> ... | head :: tail -> ...
  • Record patterns: | { name; age } -> ...
  • Constructor patterns (Option): | Some x -> ... | None -> ...
  • Constructor patterns (Result): | Ok v -> ... | Error e -> ...

Advanced Patterns

  • Or-patterns: | 1 | 2 | 3 -> "small"
  • As-patterns: | n as val -> ...
  • Guards (when clauses): | x when x > 0 -> "positive"
  • Nested record patterns
  • Nested list patterns

Operators

Arithmetic

  • +, -, *, /, %, **
  • Unary negation: -x

Comparison

  • ==, !=, <, <=, >, >=
  • Dynamic comparison for values from pattern matching

Logical

  • && (AND, short-circuit), || (OR, short-circuit), ! (NOT)

String

  • Concatenation: "hello" + " world"
  • Mixed type concatenation: "count: " + 42
  • Interpolated strings: $"Hello, {name}"
  • Repetition: "ha" * 3

Pipe Operators

  • Forward pipe: |> (value to function)
  • Shell pipe: | (process stdout to stdin)
  • Structured pipeline: shell command |> F# pipeline with output recognition

Composition

  • Forward: >>, Backward: <<

List

  • Cons: :: (right-associative), Concatenation: @

Special

  • Error propagation: ?
  • Optional chaining: ?.
  • Option default: ?|

Error Handling

  • Result type: Ok value, Error msg
  • Option type: Some value, None
  • Error propagation with auto-wrapping: expr?
  • Try-with expression: try expr with | Error e -> handler
  • Try-finally: try ... finally cleanup
  • Option combinators: Option.map, Option.bind, Option.defaultValue
  • Compile-time error for unwrapped Option/Result in binary operations

Control Flow

  • If-then-elif-else expressions (F# style, returns value)
  • Match expressions
  • While loops
  • For-in loops
  • Break and continue
  • For loops with destructuring: for (name, value) in entries do ... done

Standard Library Builtins

  • print, println -- output with/without newline
  • string_length, int_of_string, string_of_int, not
  • env -- returns option<str> for environment variables
  • head, tail, length, isEmpty -- list operations
  • map, filter, fold, reduce -- higher-order list functions
  • find, exists, forall, take, drop, zip, flatten
  • sort, reverse, distinct, sortBy, groupBy
  • nth, last, replicate
  • split, join, trim, contains, startsWith, endsWith, toLower, toUpper, replace
  • fetch -- HTTP GET returning result<str, str>
  • Json.parse, Json.stringify -- JSON serialization
  • File.read, File.write, File.list -- file operations
  • Path.join, Path.extension, Path.basename -- path operations

Shell Integration

  • Shell command expressions: & git status
  • Command substitution: $(cmd), `cmd`
  • Variable substitution: $VAR, ${VAR}
  • String interpolation in double-quoted strings
  • Process substitution: <(cmd), >(cmd)
  • Redirections: >, >>, <, 2>&1, <<<
  • Job management: &, jobs, fg, bg
  • Context-aware shell commands: capture mode in expression context, normal I/O at statement level

REPL

  • Persist function definitions across prompts
  • Persist recursive and mutual-recursive functions
  • Persist simple value bindings
  • Persist closure captures from previous prompts

Implementation Phases

Phase 1 -- Foundation Completions (Complete)

  • Unit type ()
  • Tuple destructuring in let
  • Function composition >> and <<
  • String repetition "ha" * 3
  • Block scopes { let x = 1; x + 2 }

Phase 2 -- List Runtime (Complete)

  • Cons-cell linked list representation
  • IR generation for list literals, cons, concat, ranges, and comprehensions
  • Pattern matching for lists
  • List printing via recursive formatting

Phase 3 -- List Standard Library (Complete)

  • Basic: head, tail, length, isEmpty
  • Higher-order: map, filter, fold, reduce
  • Transformations: sort, reverse, distinct
  • Utility: zip, flatten, take, drop, find, exists, forall
  • Key-based: sortBy, groupBy
  • Indexed: nth, last
  • Character ranges: ['a'..'z']

Phase 4 -- Records (Complete)

  • Type definitions, record literals, field access, record update, pattern matching

Phase 5 -- Discriminated Unions (Complete)

  • Union type definitions, constructors, pattern matching, multi-slot payloads

Phase 6 -- Remaining Operators and Features

  • Optional chaining ?., Option default ?|, Option combinators
  • For loop destructuring
  • Numeric literal suffixes (byte sizes, durations)

Phase 6.3a -- Output Recognition Files (Complete)

  • YAML definition format, output definition registry
  • JSON and fields parsers
  • Pipeline integration
  • Bundled definitions for docker ps, docker images, git log, git status

Phase 6.4 -- Bare Expression Evaluation and Table Display (Complete)

  • Bare expression evaluation at shell prompt
  • display_result builtin for runtime value display
  • Table rendering for lists of records
  • toText builtin for plain text conversion

Phase 7 -- String and File Standard Library

  • String: split, join, trim, contains, startsWith, endsWith, toLower, toUpper, replace
  • File: File.read, File.write, File.list
  • Path: Path.join, Path.extension, Path.basename

Phase 8 -- Module System

  • import statements and module loading
  • Module-qualified access: List.map, String.split

Phase 9 -- Generic Types

  • Type variable introduction ('a syntax)
  • Generic type definitions
  • Monomorphization or type erasure at codegen

Lexer and Parser

  • Context-sensitive tokenization (F# mode vs shell mode)
  • Syntax highlighting with statement-level mode tracking
  • F# operator tokens, nested parentheses, comma tokenization
  • Numeric literals: decimal, hex (0xFF), octal (0o755), binary (0b1010), scientific (1e10), float (3.14)
  • Comments: #, //, (* ... *)
  • true/false as native boolean token literals
  • Numeric literal suffixes: 1kb, 1mb, 1gb, 1tb, 1ms, 1s, 1min, 1h

Completion System

  • Shared completion infrastructure in endo-language
  • Context analyzer, candidate generators, orchestrator
  • Shell completion adapter with fuzzy scoring
  • LSP textDocument/completion support
  • Record-aware dot-access completion
  • Variable-specific record field completion

Modules and Imports

  • import / from ... import statements
  • Module-qualified access
  • Module creation and exports