@okcontract/lambdascript 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,24 +18,31 @@ reactive programs.
18
18
  Another notable property is the default use of `Rationals` for both integers
19
19
  and floats of arbitrary length throughout the standard library.
20
20
 
21
+ ## Installation
22
+
23
+ ```sh
24
+ npm install @okcontract/lambdascript @okcontract/cells
25
+ ```
26
+
21
27
  ## Walkthrough
22
28
 
23
29
  ```ts
30
+ import { type AnyCell, Sheet } from "@okcontract/cells";
24
31
  import { Environment, Rational } from "@okcontract/lambdascript";
25
- // create a new cell (see cells repo on how to create a proxy)
32
+
33
+ const proxy = new Sheet().newProxy();
26
34
  const foo = proxy.new(new Rational(1));
27
- // create a λs Environment (and a standard library)
28
35
  const env = new Environment(proxy, {
29
36
  values: {
30
37
  foo,
31
38
  },
32
39
  });
33
- // expr the built reactive expression that will react to `foo` updates
34
- const expr = (await env.evaluateString("foo + 1")) as AnyCell<Rational>; // λs types are not known to TypeScript
40
+
41
+ // The expression is recomputed whenever `foo` changes.
42
+ const expr = (await env.evaluateString("foo + 1")) as AnyCell<Rational>;
35
43
  expect((await expr.get()).toString()).toBe("2");
36
- // we update foo
44
+
37
45
  foo.set(new Rational(2));
38
- // expr is automatically re-computed
39
46
  expect((await expr.get()).toString()).toBe("3");
40
47
  ```
41
48
 
@@ -53,6 +60,26 @@ const env1 = new Environment(proxy1, { lib });
53
60
  const env2 = new Environment(proxy2, { lib });
54
61
  ```
55
62
 
63
+ ## Development
64
+
65
+ Building and testing `lambdascript` requires a system installation of
66
+ [`bun`](https://bun.com). Bun is deliberately not included in the project's
67
+ dependencies.
68
+
69
+ ```sh
70
+ bun install --frozen-lockfile
71
+ bun run grammar
72
+ bun run test
73
+ bun run build
74
+ bun run definitions
75
+ ```
76
+
77
+ [`biome`](https://biomejs.dev) is also deliberately not included as a project
78
+ dependency. Install it as a system binary if you want to run `bun run format`
79
+ or `bun run check`. The standard `bun run build` script formats the source
80
+ before bundling, so it also expects `biome` to be available on `PATH`; direct
81
+ use of `bun build` does not require Biome.
82
+
56
83
  # Design & Philosophy
57
84
 
58
85
  We aim for ease of use, correction and security, so chasing down any bug is
package/dist/ast.d.ts CHANGED
@@ -1,5 +1,9 @@
1
- import { Rational } from "./rational";
1
+ import { Rational } from "./rational.js";
2
2
  export type NodeType = ASTNode["type"];
3
+ export type SourceRange = {
4
+ from: number;
5
+ to: number;
6
+ };
3
7
  export declare const NameApplication = "app";
4
8
  export declare const NameConstant = "const";
5
9
  export declare const NameVariable = "var";
@@ -14,31 +18,39 @@ export type ASTNode = ApplicationNode | ConstantNode<unknown> | VariableNode | L
14
18
  type: "named";
15
19
  key: string;
16
20
  value: ASTNode;
21
+ range?: SourceRange;
17
22
  };
18
23
  export type ApplicationNode = {
19
24
  type: typeof NameApplication;
20
25
  function: ASTNode;
21
26
  params: ASTNode[];
27
+ range?: SourceRange;
22
28
  };
29
+ export declare const apply: (fn: ASTNode, params: ASTNode[]) => ApplicationNode;
30
+ export declare const applyName: (fn: string, params: ASTNode[]) => ApplicationNode;
23
31
  export type RawConstant = string | boolean | Rational;
24
32
  export interface ConstantNode<Extensions> {
25
33
  type: typeof NameConstant;
26
34
  value: RawConstant | Extensions;
35
+ range?: SourceRange;
27
36
  }
28
37
  export declare const newNumber: (n: string | number | bigint | Rational) => ConstantNode<unknown>;
29
38
  export declare const newConstant: (value: string | boolean | number | bigint) => ConstantNode<unknown>;
30
39
  export interface VariableNode {
31
40
  type: typeof NameVariable;
32
41
  name: string;
42
+ range?: SourceRange;
33
43
  }
34
44
  export declare const newVariable: (name: string) => VariableNode;
35
45
  export interface ListNode {
36
46
  type: typeof NameList;
37
47
  elements: ASTNode[];
48
+ range?: SourceRange;
38
49
  }
39
50
  export interface TupleNode {
40
51
  type: typeof NameTuple;
41
52
  elements: ASTNode[];
53
+ range?: SourceRange;
42
54
  }
43
55
  export declare const newList: (elements: ASTNode[]) => ListNode;
44
56
  export declare const newTuple: (elements: ASTNode[]) => TupleNode;
@@ -47,6 +59,7 @@ export interface ObjectNode {
47
59
  values: {
48
60
  [key: string]: ASTNode;
49
61
  };
62
+ range?: SourceRange;
50
63
  }
51
64
  export declare const newObject: (values: {
52
65
  [key: string]: ASTNode;
@@ -55,6 +68,7 @@ export declare const newFromJS: (value: unknown) => ASTNode;
55
68
  export type FieldNode = {
56
69
  type: typeof NameField;
57
70
  expr: ASTNode;
71
+ range?: SourceRange;
58
72
  } & ({
59
73
  field: string;
60
74
  } | {
@@ -64,10 +78,12 @@ export interface LambdaNode {
64
78
  type: typeof NameLambda;
65
79
  parameter: string;
66
80
  body: ASTNode;
81
+ range?: SourceRange;
67
82
  }
68
83
  export declare const newLambda: (parameter: string, body: ASTNode) => LambdaNode;
69
84
  export declare const newLambdaMulti: (parameters: string[], body: ASTNode) => LambdaNode;
70
85
  export interface ErrorNode {
71
86
  type: typeof NameError;
72
87
  value: string;
88
+ range?: SourceRange;
73
89
  }
package/dist/deps.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ASTNode } from "./ast";
1
+ import { type ASTNode } from "./ast.js";
2
2
  /**
3
3
  * exprDependencies computes the free variables in a given expression.
4
4
  * @param expr
package/dist/env.d.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  import { type AnyCell, type SheetProxy } from "@okcontract/cells";
2
- import type { ASTNode } from "./ast";
3
- import { type Value } from "./eval";
4
- import type { ParserExtension } from "./highLevel";
5
- import { type ParseOptions } from "./parse";
6
- import { type LibraryElement, type StandardLibrary } from "./stdlib";
7
- import type { TypeScheme } from "./typeScheme";
2
+ import type { ASTNode } from "./ast.js";
3
+ import { type Value } from "./eval.js";
4
+ import type { ParserExtension } from "./highLevel.js";
5
+ import { type ParseOptions } from "./parse.js";
6
+ import { type LibraryElement, type StandardLibrary } from "./stdlib.js";
7
+ import type { TypeScheme } from "./typeScheme.js";
8
8
  export declare let envCounter: number;
9
9
  export type ValueMap = {
10
10
  [key: string]: Value<unknown>;
11
11
  };
12
+ export type TypeMap = {
13
+ [key: string]: TypeScheme;
14
+ };
12
15
  export type ValueDefinition = [string, Value<unknown>, TypeScheme];
13
16
  /**
14
17
  * Options for the Environment constructor.
@@ -17,9 +20,7 @@ export type EnvironmentOptions = {
17
20
  id?: string;
18
21
  lib?: StandardLibrary;
19
22
  values?: ValueMap;
20
- types?: {
21
- [key: string]: TypeScheme;
22
- };
23
+ types?: TypeMap;
23
24
  cases?: {
24
25
  [key: string]: string;
25
26
  };
@@ -39,17 +40,16 @@ export declare class Environment {
39
40
  * However, `inferType` for `NameLambda` uses an Environment updated
40
41
  * with the type of the bound variable in the lambda.
41
42
  **/
42
- _values: ValueMap;
43
+ private _values;
43
44
  /** type expressions (for values) */
44
45
  private _types;
45
46
  /** original cases for values and types */
46
47
  private _originalCases;
47
48
  readonly proxy: SheetProxy;
48
49
  initialValues: {};
49
- initialTypes: {
50
- [key: string]: TypeScheme;
51
- };
50
+ initialTypes: TypeMap;
52
51
  options: EnvironmentOptions;
52
+ get values(): ValueMap;
53
53
  constructor(proxy: SheetProxy, options?: EnvironmentOptions);
54
54
  _updateLib(lib: StandardLibrary): void;
55
55
  library: (name: string) => LibraryElement | undefined;
@@ -76,6 +76,7 @@ export declare class Environment {
76
76
  */
77
77
  addExpression: (name: string, expr: ASTNode) => Promise<boolean>;
78
78
  addValueType: (name: string, value: Value<unknown>, type: TypeScheme) => boolean;
79
+ removeKey: (key: string) => void;
79
80
  /**
80
81
  * evaluateString evaluates an expression as string.
81
82
  * @param expr
package/dist/equal.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const allDiff: (a: unknown, b: unknown) => any[];
1
+ export declare const allDiff: (a: unknown, b: unknown) => string[];
2
2
  export declare function firstDiff(a: unknown, b: unknown): string | null;
3
3
  export declare function isEqual(a: unknown, b: unknown): boolean;
package/dist/eval.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { AnyCell } from "@okcontract/cells";
2
- import { type ASTNode } from "./ast";
3
- import type { Environment } from "./env";
2
+ import { type ASTNode } from "./ast.js";
3
+ import type { Environment } from "./env.js";
4
4
  export type PrimValue<V> = V | Value<V>[] | {
5
5
  [key: number | string]: Value<unknown>;
6
6
  };
package/dist/find.d.ts CHANGED
@@ -1,14 +1,5 @@
1
- import { type AnyCell, type CellArray, type MapCell, type SheetProxy } from "@okcontract/cells";
2
- /**
3
- * mapArrayCell is a variant of `mapArray` with a function taking
4
- * element cells as arguments.
5
- * @param proxy
6
- * @param arr
7
- * @param fn
8
- * @returns mapped array cell
9
- */
10
- export declare const mapArrayCell: <T, U, NF extends boolean = false>(proxy: SheetProxy, arr: CellArray<T>, fn: AnyCell<(v: AnyCell<T>, idx?: number) => AnyCell<U>>, name?: string, nf?: NF) => MapCell<MapCell<U, NF>[], NF>;
1
+ import { type AnyCell, type CellArray, type SheetProxy } from "@okcontract/cells";
11
2
  export declare const findCell: <T, NF extends boolean = false>(proxy: SheetProxy, arr: CellArray<T>, predicate: AnyCell<(v: AnyCell<T>) => AnyCell<boolean>>, findFunction?: {
12
3
  <S extends any>(predicate: (value: any, index: number, obj: any[]) => value is S, thisArg?: any): S;
13
4
  (predicate: (value: any, index: number, obj: any[]) => unknown, thisArg?: any): any;
14
- }, name?: string, nf?: NF) => MapCell<T, NF>;
5
+ }, name?: string, nf?: NF) => import("@okcontract/cells").MapCell<any, NF>;
@@ -0,0 +1,16 @@
1
+ export declare const Separator: {
2
+ readonly Space: " ";
3
+ };
4
+ export type Separator = (typeof Separator)[keyof typeof Separator];
5
+ export type FormatSettings = {
6
+ separator: Separator;
7
+ spaces: number;
8
+ trailingCommas: boolean;
9
+ width: number;
10
+ };
11
+ export declare const defaultFormatSettings: FormatSettings;
12
+ type FormatOptions = Partial<FormatSettings>;
13
+ export declare const formatSource: (source: string, options?: FormatOptions) => string;
14
+ export declare const formatExpression: (source: string, options?: FormatOptions) => string;
15
+ export declare const formatProgram: (source: string, options?: FormatOptions) => string;
16
+ export {};
@@ -1,6 +1,6 @@
1
- import { type ASTNode } from "./ast";
2
- import type { LowLevelAST } from "./lowLevel";
3
- import type { TypeConst } from "./types";
1
+ import { type ASTNode } from "./ast.js";
2
+ import type { LowLevelAST } from "./lowLevel.js";
3
+ import type { TypeConst } from "./types.js";
4
4
  export type ParserExtension<Result, Name extends string> = {
5
5
  elt: Name;
6
6
  pat: (value: unknown) => boolean;
package/dist/index.d.ts CHANGED
@@ -1,14 +1,17 @@
1
- export { length, plural } from "./utils";
2
- export { NameApplication, NameConstant, NameError, NameField, NameLambda, NameList, NameObject, NameTuple, NameVariable, Names, newConstant, newFromJS, newLambda, newLambdaMulti, newList, newNumber, newObject, newVariable, type ASTNode, type ApplicationNode, type ConstantNode, type FieldNode, type LambdaNode, type ListNode, type ObjectNode, type VariableNode } from "./ast";
3
- export { newTypeScheme, type TypeScheme } from "./typeScheme";
4
- export { newTypeConst, newTypeObject, newTypeTuple, newTypeVar, typeAny, typeFunction, typeList, type MonoType, type TypeAny, type TypeConst } from "./types";
5
- export { allDiff, firstDiff, isEqual } from "./equal";
6
- export { toHighLevelAST, type ParserExtension } from "./highLevel";
7
- export { toLowLevelAST } from "./lowLevel";
8
- export { parseExpression, reservedKeywords } from "./parse";
9
- export { parser } from "./parser/λs";
10
- export { prettyPrint, prettyPrintType } from "./print";
11
- export { Environment, type ValueDefinition } from "./env";
12
- export { EvalOption, Program } from "./program";
13
- export { Rational, isRationalString, rationalNumberRegex, zero } from "./rational";
14
- export { defaultLibrary, rationalNumber, typeBoolean, typeBytes, typeFromJSValue, typeNumber, typeString, type FirstClassValue, type LibraryElement, type StandardLibrary } from "./stdlib";
1
+ export { type ApplicationNode, type ASTNode, apply, applyName, type ConstantNode, type FieldNode, type LambdaNode, type ListNode, NameApplication, NameConstant, NameError, NameField, NameLambda, NameList, NameObject, Names, NameTuple, NameVariable, newConstant, newFromJS, newLambda, newLambdaMulti, newList, newNumber, newObject, newTuple, newVariable, type ObjectNode, type SourceRange, type TupleNode, type VariableNode } from "./ast.js";
2
+ export { Environment, type EnvironmentOptions, type TypeMap, type ValueDefinition, type ValueMap } from "./env.js";
3
+ export { allDiff, firstDiff, isEqual } from "./equal.js";
4
+ export type { Value } from "./eval.js";
5
+ export { defaultFormatSettings, type FormatSettings, formatExpression, formatProgram, formatSource, Separator } from "./format.js";
6
+ export { type ParserExtension, toHighLevelAST } from "./highLevel.js";
7
+ export { toLowLevelAST } from "./lowLevel.js";
8
+ export { type ParsedProgram, type ProgramBinding, type ProgramComponent, parseExpression, parseProgram, reservedKeywords } from "./parse.js";
9
+ export { parser } from "./parser/λs.js";
10
+ export { prettyPrint, prettyPrintType } from "./print.js";
11
+ export { type Binding, EvalOption, Program } from "./program.js";
12
+ export { isRational, isRationalString, Rational, rationalNumberRegex, zero } from "./rational.js";
13
+ export { evaluateASTSingle } from "./singleEval.js";
14
+ export { defaultLibrary, type FirstClassValue, type LibraryElement, rationalNumber, type StandardLibrary, typeBoolean, typeBytes, typeFromJSValue, typeNumber, typeString } from "./stdlib.js";
15
+ export { newTypeScheme, type TypeScheme } from "./typeScheme.js";
16
+ export { type MonoType, newTypeConst, newTypeObject, newTypeTuple, newTypeVar, type TypeAny, type TypeConst, typeAny, typeFunction, typeList } from "./types.js";
17
+ export { length, plural } from "./utils.js";
package/dist/infer.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { type ASTNode } from "./ast";
2
- import type { Environment } from "./env";
3
- import type { ParserExtension } from "./highLevel";
4
- import { Rational } from "./rational";
5
- import { type TypeScheme } from "./typeScheme";
1
+ import { type ASTNode } from "./ast.js";
2
+ import type { Environment } from "./env.js";
3
+ import type { ParserExtension } from "./highLevel.js";
4
+ import { Rational } from "./rational.js";
5
+ import { type TypeScheme } from "./typeScheme.js";
6
6
  export declare const detectConstantType: (v: boolean | string | Rational, extensions?: ParserExtension<unknown, string>[]) => "boolean" | "string" | "number" | (typeof extensions)[number]["elt"];
7
7
  export declare const inferType: (env: Environment) => (node: ASTNode) => Promise<TypeScheme>;
package/dist/json.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type ASTNode } from "./ast";
2
- import type { ParserExtension } from "./highLevel";
1
+ import { type ASTNode } from "./ast.js";
2
+ import type { ParserExtension } from "./highLevel.js";
3
3
  export declare function parseNode(node: ASTNode, ext?: ParserExtension<unknown, string>[]): ASTNode;
4
4
  export declare function parseAst(json: string, ext: ParserExtension<unknown, string>[]): ASTNode;