| name | east |
| description | East programming language - a statically typed, expression-based language embedded in TypeScript. Use when writing East programs with @elaraai/east. Triggers for: (1) Writing East functions with East.function() or East.asyncFunction(), (2) Defining types (IntegerType, StringType, ArrayType, StructType, VariantType, etc.), (3) Using platform functions with East.platform() or East.asyncPlatform(), (4) Compiling East programs with East.compile(), (5) Working with East expressions (arithmetic, collections, control flow), (6) Serializing East IR with .toIR() and EastIR.fromJSON(), (7) Standard library operations (formatting, rounding, generation). |
East Language
A statically typed, expression-based programming language embedded in TypeScript. Write programs using a fluent API, compile to portable IR.
Quick Start
import { East, IntegerType, StringType, ArrayType, NullType } from "@elaraai/east";
const log = East.platform("log", [StringType], NullType);
const platform = [log.implement(console.log)];
const sumArray = East.function([ArrayType(IntegerType)], IntegerType, ($, arr) => {
const total = $.let(arr.sum());
$(log(East.str`Sum: ${total}`));
$.return(total);
});
const compiled = East.compile(sumArray, platform);
compiled([1n, 2n, 3n]);
Decision Tree: What Do You Need?
Task → What do you need?
│
├─ Create East Expressions (East.*)
│ ├─ From TypeScript value → East.value(tsValue) or East.value(tsValue, Type)
│ ├─ String interpolation → East.str`Hello ${name}!`
│ └─ Inside function body → $.let(value), $.const(value)
│
├─ Define a Type (import from package, NOT East.*)
│ ├─ Primitive → IntegerType, FloatType, StringType, BooleanType, DateTimeType, BlobType, NullType
│ ├─ Collection → ArrayType(T), SetType(K), DictType(K, V), RefType(T)
│ ├─ Numeric → VectorType(T), MatrixType(T) where T is FloatType, IntegerType, or BooleanType
│ ├─ Compound → StructType({...}), VariantType({...}), RecursiveType(...)
│ ├─ Function → FunctionType<I, O>, AsyncFunctionType<I, O>
│ └─ Patch → PatchType(T) (compute patch type for any East type)
│
├─ Create TypeScript Values for East Types
│ ├─ NullType → null
│ ├─ BooleanType → true, false
│ ├─ IntegerType → 42n (bigint literal)
│ ├─ FloatType → 3.14 (number literal)
│ ├─ StringType → "hello"
│ ├─ DateTimeType → new Date("2025-01-01T00:00:00Z")
│ ├─ BlobType → new Uint8Array([...])
│ ├─ ArrayType(T) → [1n, 2n, 3n]
│ ├─ SetType(K) → new Set([1n, 2n, 3n])
│ ├─ DictType(K, V) → new Map([["a", 1n], ["b", 2n]])
│ ├─ StructType({...}) → { field1: value1, field2: value2 }
│ ├─ VariantType({...}) (use helpers from package)
│ │ ├─ Option type → some(value), none ← preferred for Option/Maybe
│ │ └─ Other variants → variant("caseName", value)
│ ├─ VectorType(FloatType) → new Float64Array([1.0, 2.0, 3.0])
│ ├─ VectorType(IntegerType) → new BigInt64Array([1n, 2n, 3n])
│ ├─ VectorType(BooleanType) → new Uint8ClampedArray([1, 0, 1])
│ ├─ MatrixType(FloatType) → matrix(Float64Array.from([1.0, 2.0, 3.0, 4.0]), 2, 2)
│ ├─ MatrixType(IntegerType) → matrix(BigInt64Array.from([1n, 2n, 3n, 4n]), 2, 2)
│ ├─ MatrixType(BooleanType) → matrix(Uint8ClampedArray.from([1, 0, 0, 1]), 2, 2)
│ └─ RefType(T) (use helper from package) → ref(value)
│
├─ Write a Function (East.*)
│ ├─ Synchronous → East.function([inputs], output, ($, ...args) => { ... })
│ └─ Asynchronous → East.asyncFunction([inputs], output, ($, ...args) => { ... })
│
├─ Compile and Execute (East.*)
│ ├─ Sync function → East.compile(fn, platform)
│ └─ Async function → East.compileAsync(fn, platform)
│
├─ Use Platform Effects (East.*)
│ ├─ Sync effect → East.platform("name", [inputs], output).implement(fn)
│ └─ Async effect → East.asyncPlatform("name", [inputs], output).implement(fn)
│
├─ Block Operations ($)
│ ├─ Variables → $.let(value), $.const(value), $.assign(var, value)
│ ├─ Execute → $(expr), $.return(value), $.error(message)
│ ├─ Control Flow → $.if(...), $.while(...), $.for(...), $.match(...), $.matchTag(...)
│ └─ Error Handling → $.try(...).catch(...).finally(...)
│
├─ Expression Operations
│ ├─ Boolean
│ │ ├─ Logic → .and($=>), .or($=>), .not(), .ifElse($=>,$=>)
│ │ ├─ Bitwise → .bitAnd(), .bitOr(), .bitXor()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ ├─ Integer
│ │ ├─ Math → .add()/.plus(), .subtract()/.sub()/.minus(), .multiply()/.mul()/.times(), .divide()/.div(), .remainder()/.mod()/.rem()/.modulo(), .pow(), .abs(), .sign(), .negate(), .log()
│ │ ├─ Convert → .toFloat()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne(), .lessThan()/.less()/.lt(), .greaterThan()/.greater()/.gt(), .lessThanOrEqual()/.lessEqual()/.lte()/.le(), .greaterThanOrEqual()/.greaterEqual()/.gte()/.ge()
│ ├─ Float
│ │ ├─ Math → .add()/.plus(), .subtract()/.sub()/.minus(), .multiply()/.mul()/.times(), .divide()/.div(), .remainder()/.mod()/.rem()/.modulo(), .pow(), .abs(), .sign(), .negate()
│ │ ├─ Advanced → .sqrt(), .exp(), .log(), .sin(), .cos(), .tan()
│ │ ├─ Convert → .toInteger()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne(), .lessThan()/.less()/.lt(), .greaterThan()/.greater()/.gt(), .lessThanOrEqual()/.lessEqual()/.lte()/.le(), .greaterThanOrEqual()/.greaterEqual()/.gte()/.ge()
│ ├─ String
│ │ ├─ Transform → .concat(), .repeat(), .substring(), .upperCase(), .lowerCase(), .trim(), .trimStart(), .trimEnd()
│ │ ├─ Replace → .replace(), .replaceAll(), .split()
│ │ ├─ Query → .length(), .startsWith(), .endsWith(), .contains(), .indexOf(), .charAt()
│ │ ├─ Parse → .parse(), .parseJson()
│ │ ├─ Encode → .encodeUtf8(), .encodeUtf16()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne(), .lessThan()/.less()/.lt(), .greaterThan()/.greater()/.gt(), .lessThanOrEqual()/.lessEqual()/.lte()/.le(), .greaterThanOrEqual()/.greaterEqual()/.gte()/.ge()
│ ├─ DateTime
│ │ ├─ Components → .getYear(), .getMonth(), .getDayOfMonth(), .getDayOfWeek(), .getHour(), .getMinute(), .getSecond(), .getMillisecond()
│ │ ├─ Arithmetic → .addDays(), .subtractDays(), .addHours(), .subtractHours(), .addMinutes(), .addSeconds(), .addMilliseconds(), .addWeeks()
│ │ ├─ Duration → .durationDays(), .durationHours(), .durationMinutes(), .durationSeconds(), .durationMilliseconds(), .durationWeeks()
│ │ ├─ Convert → .toEpochMilliseconds(), .printFormatted()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne(), .lessThan()/.less()/.lt(), .greaterThan()/.greater()/.gt(), .lessThanOrEqual()/.lessEqual()/.lte()/.le(), .greaterThanOrEqual()/.greaterEqual()/.gte()/.ge()
│ ├─ Blob
│ │ ├─ Read → .size(), .getUint8()
│ │ ├─ Decode → .decodeUtf8(), .decodeUtf16(), .decodeBeast(), .decodeCsv()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ ├─ Array
│ │ ├─ Read → .size(), .length(), .has(), .get(), .at(), .tryGet(), .getKeys()
│ │ ├─ Mutate → .update(), .pushLast(), .popLast(), .pushFirst(), .popFirst(), .append(), .prepend(), .clear(), .sortInPlace(), .reverseInPlace()
│ │ ├─ Transform → .copy(), .slice(), .concat(), .sort(), .reverse(), .map(), .filter(), .filterMap(), .flatMap()
│ │ ├─ Search → .findFirst(), .findAll(), .firstMap(), .isSorted()
│ │ ├─ Reduce → .reduce(), .every(), .some(), .sum(), .mean(), .maximum(), .minimum(), .findMaximum(), .findMinimum()
│ │ ├─ Convert → .stringJoin(), .toSet(), .toDict(), .flattenToSet(), .flattenToDict(), .encodeCsv()
│ │ ├─ Group → .groupReduce(), .groupSize(), .groupSum(), .groupMean(), .groupMinimum(), .groupMaximum(), .groupToArrays(), .groupToSets(), .groupToDicts(), .groupEvery(), .groupSome()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ ├─ Set
│ │ ├─ Read → .size(), .has()
│ │ ├─ Mutate → .insert(), .tryInsert(), .delete(), .tryDelete(), .clear(), .unionInPlace()
│ │ ├─ Set Ops → .copy(), .union(), .intersection(), .difference(), .symmetricDifference(), .isSubsetOf(), .isSupersetOf(), .isDisjointFrom()
│ │ ├─ Transform → .filter(), .filterMap(), .map(), .forEach(), .firstMap()
│ │ ├─ Reduce → .reduce(), .every(), .some(), .sum(), .mean()
│ │ ├─ Convert → .toArray(), .toSet(), .toDict(), .flattenToArray(), .flattenToSet(), .flattenToDict()
│ │ ├─ Group → .groupReduce(), .groupSize(), .groupSum(), .groupMean(), .groupToArrays(), .groupToSets(), .groupToDicts(), .groupEvery(), .groupSome()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ ├─ Dict
│ │ ├─ Read → .size(), .has(), .get(), .tryGet(), .keys(), .getKeys()
│ │ ├─ Mutate → .insert(), .insertOrUpdate(), .update(), .merge(), .getOrInsert(), .delete(), .tryDelete(), .pop(), .swap(), .clear(), .unionInPlace()
│ │ ├─ Transform → .copy(), .map(), .filter(), .filterMap(), .forEach(), .firstMap()
│ │ ├─ Reduce → .reduce(), .every(), .some(), .sum(), .mean()
│ │ ├─ Convert → .toArray(), .toSet(), .toDict(), .flattenToArray(), .flattenToSet(), .flattenToDict()
│ │ ├─ Group → .groupReduce(), .groupSize(), .groupSum(), .groupMean(), .groupToArrays(), .groupToSets(), .groupToDicts(), .groupEvery(), .groupSome()
│ │ └─ Compare → .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ ├─ Vector
│ │ ├─ Read → .length(), .get()
│ │ ├─ Mutate → .set()
│ │ ├─ Transform → .slice(), .concat(), .map(), .reduce()
│ │ └─ Convert → .toArray(), .toMatrix()
│ ├─ Matrix
│ │ ├─ Read → .rows(), .cols(), .get(), .getRow(), .getCol()
│ │ ├─ Mutate → .set()
│ │ ├─ Transform → .transpose()
│ │ └─ Convert → .toVector(), .toArray()
│ ├─ Struct → .fieldName (direct property access)
│ ├─ Variant → .match(), .matchTag(), .unwrap(), .hasTag(), .getTag(), .equals()/.equal()/.eq(), .notEquals()/.notEqual()/.ne()
│ └─ Ref → .get(), .update(), .merge()
│
├─ Standard Library (East.*)
│ ├─ Integer → East.Integer.printCommaSeperated(), .roundNearest(), .printOrdinal()
│ ├─ Float → East.Float.roundToDecimals(), .printCurrency(), .printCompact()
│ ├─ DateTime → East.DateTime.fromComponents(), .roundDownDay(), .parseFormatted()
│ ├─ Array → East.Array.range(), .linspace(), .generate()
│ ├─ Set → East.Set.generate()
│ ├─ Dict → East.Dict.generate()
│ ├─ Blob → East.Blob.encodeBeast(), blob.decodeCsv(), array.encodeCsv()
│ ├─ Vector → East.Vector.zeros(), .ones(), .fill(), .fromArray()
│ ├─ Matrix → East.Matrix.zeros(), .ones(), .fill(), .fromArray()
│ └─ String → East.String.printJson(), East.String.printError()
│
├─ Comparisons (East.*)
│ ├─ Equality → East.equal()/.equals()/.eq(), East.notEqual()/.notEquals()/.ne()
│ ├─ Ordering → East.less()/.lessThan()/.lt(), East.greater()/.greaterThan()/.gt()
│ ├─ Bounds → East.lessEqual()/.lte()/.le(), East.greaterEqual()/.gte()/.ge()
│ ├─ Identity → East.is() (reference equality for mutable types)
│ └─ Utilities → East.min(), East.max(), East.clamp()
│
├─ Conversion (East.*)
│ └─ To string → East.print(expr)
│
├─ Patch Operations (East.*)
│ ├─ Compute diff → East.diff(before, after) → returns patch
│ ├─ Apply patch → East.applyPatch(value, patch) → returns patched value
│ ├─ Compose patches → East.composePatch(first, second, type) → returns combined patch
│ └─ Invert patch → East.invertPatch(patch, type) → returns undo patch
│
└─ Serialization
├─ IR → fn.toIR(), ir.toJSON(), EastIR.fromJSON(data).compile(platform)
└─ Data → East.Blob.encodeBeast(value, 'v2'), blob.decodeBeast(type, 'v2')
Reference Documentation
- API Reference - Complete function signatures, types, and arguments
- Examples - Working code examples by use case
Type System Summary
| Type | ValueTypeOf<Type> | Mutability |
|---|
NullType | null | Immutable |
BooleanType | boolean | Immutable |
IntegerType | bigint | Immutable |
FloatType | number | Immutable |
StringType | string | Immutable |
DateTimeType | Date | Immutable |
BlobType | Uint8Array | Immutable |
ArrayType<T> | ValueTypeOf<T>[] | Mutable |
SetType<K> | Set<ValueTypeOf<K>> | Mutable |
DictType<K, V> | Map<ValueTypeOf<K>, ValueTypeOf<V>> | Mutable |
RefType<T> | ref<ValueTypeOf<T>> | Mutable |
VectorType<FloatType> | Float64Array | Mutable |
VectorType<IntegerType> | BigInt64Array | Mutable |
VectorType<BooleanType> | Uint8ClampedArray | Mutable |
MatrixType<T> | matrix<TypedArray> | Mutable |
StructType<Fields> | {...} | Immutable |
VariantType<Cases> | variant | Immutable |
FunctionType<I, O> | Function | Immutable |
PatchType<T> | variant | Immutable |
Key Patterns
TypeScript Values vs East Expressions
TypeScript values and East expressions are different. East methods only work on East expressions.
const THRESHOLD = 100n;
East.function([IntegerType], BooleanType, ($, x) => {
$.return(x.greaterThan(THRESHOLD)); // ERROR: THRESHOLD has no .greaterThan()
});
const THRESHOLD = 100n;
East.function([IntegerType], BooleanType, ($, x) => {
$.return(x.greaterThan(East.value(THRESHOLD))); // OK
});
East.function([IntegerType], BooleanType, ($, x) => {
const threshold = $.const(THRESHOLD); // Creates East expression
$.return(x.greaterThan(threshold)); // OK
});
Rule: Function parameters are already East expressions. External TypeScript values must be wrapped with East.value() or bound with $.const().
Creating Variant Values
import { variant, some, none, ref } from "@elaraai/east";
const hasValue = some(42n);
const noValue = none;
const success = variant("ok", "done");
const failure = variant("error", "failed");
const counter = ref(0n);
String Interpolation
const MY_CONSTANT = 100n;
East.function([IntegerType], StringType, ($, x) => {
// CORRECT - x is already an East expression (function parameter)
const msg1 = $.let(East.str`Value: ${x}`);
// CORRECT - wrap TypeScript constant with East.value()
const msg2 = $.let(East.str`Threshold: ${East.value(MY_CONSTANT)}`);
// CORRECT - use $.const() to create East expression first
const threshold = $.const(MY_CONSTANT);
const msg3 = $.let(East.str`Threshold: ${threshold}`);
// WRONG - cannot interpolate plain TypeScript values
// const msg4 = $.let(East.str`Threshold: ${MY_CONSTANT}`); // ERROR
$.return(msg1);
});
Error Handling
$.try($ => {
$.assign(result, arr.get(index));
}).catch(($, message, stack) => {
$.assign(result, -1n);
}).finally($ => {
});
Platform Function Implementations
const log = East.platform("log", [StringType], NullType);
const timeNs = East.platform("time_ns", [], IntegerType);
const fetchStatus = East.asyncPlatform("fetch_status", [StringType], StringType);
const platform = [
log.implement(console.log),
timeNs.implement(() => process.hrtime.bigint()),
fetchStatus.implement(async (url: string) => {
const response = await fetch(url);
return `${response.status}`;
}),
];
const myFn = East.asyncFunction([StringType], NullType, ($, url) => {
const t1 = $.let(timeNs());
const status = $.let(fetchStatus(url));
const t2 = $.let(timeNs());
$(log(East.str`Fetched in ${t2.subtract(t1)} ns, status: ${status}`));
});
const compiled = East.compileAsync(myFn, platform);
await compiled("https://example.com");