tjs-lang 0.8.2 → 0.8.4
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/CLAUDE.md +5 -2
- package/demo/autocomplete.test.ts +37 -0
- package/demo/docs.json +701 -11
- package/demo/src/autocomplete.ts +40 -2
- package/demo/src/introspection-bridge.ts +140 -0
- package/demo/src/introspection-doc.test.ts +63 -0
- package/demo/src/playground-shared.ts +53 -0
- package/demo/src/tjs-playground.ts +21 -0
- package/dist/experiments/predicates/css.predicates.d.ts +13 -0
- package/dist/experiments/predicates/verify.d.ts +39 -0
- package/dist/index.js +101 -97
- package/dist/index.js.map +4 -4
- package/dist/src/lang/index.d.ts +2 -0
- package/dist/src/lang/predicate-schema.d.ts +39 -0
- package/dist/src/lang/predicate.d.ts +103 -0
- package/dist/src/lang/transpiler.d.ts +2 -0
- package/dist/src/vm/runtime.d.ts +22 -0
- package/dist/tjs-eval.js +29 -29
- package/dist/tjs-eval.js.map +3 -3
- package/dist/tjs-from-ts.js +1 -1
- package/dist/tjs-from-ts.js.map +2 -2
- package/dist/tjs-lang.js +86 -82
- package/dist/tjs-lang.js.map +4 -4
- package/dist/tjs-vm.js +45 -45
- package/dist/tjs-vm.js.map +3 -3
- package/editors/codemirror/ajs-language.ts +130 -44
- package/editors/codemirror/completion-source.test.ts +114 -0
- package/editors/introspect-value.test.ts +61 -0
- package/editors/introspect-value.ts +86 -0
- package/editors/scope-symbols.test.ts +113 -0
- package/editors/scope-symbols.ts +173 -0
- package/package.json +2 -1
- package/src/lang/index.ts +22 -0
- package/src/lang/predicate-schema.test.ts +97 -0
- package/src/lang/predicate-schema.ts +168 -0
- package/src/lang/predicate.test.ts +184 -0
- package/src/lang/predicate.ts +550 -0
- package/src/lang/runtime.test.ts +46 -0
- package/src/lang/suggest.test.ts +84 -0
- package/src/lang/transpiler.ts +26 -0
- package/src/runtime.test.ts +6 -6
- package/src/vm/atom-effects.test.ts +72 -0
- package/src/vm/atoms/batteries.ts +12 -0
- package/src/vm/equality.test.ts +59 -0
- package/src/vm/runtime.ts +77 -59
package/dist/src/lang/index.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ import type { TranspileOptions, TranspileResult, FunctionSignature } from './typ
|
|
|
25
25
|
export * from './types';
|
|
26
26
|
export { parse, preprocess, extractTDoc, validateSingleFunction, extractFunctions, } from './parser';
|
|
27
27
|
export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
|
|
28
|
+
export { verifyPredicate, compilePredicate, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type Suggestion, type SuggestOptions, } from './predicate';
|
|
29
|
+
export { compilePredicateSchema, validatePredicateSchema, type PredicateSchema, type SchemaError, type SchemaValidationResult, type PredicateSchemaOptions, } from './predicate-schema';
|
|
28
30
|
export { transformFunction } from './emitters/ast';
|
|
29
31
|
export { transpileToJS, stripModuleSyntax, stripTjsPreamble, type TJSTranspileOptions, type TJSTranspileResult, type TJSTypeInfo, } from './emitters/js';
|
|
30
32
|
export { generateDTS, typeDescriptorToTS, type GenerateDTSOptions, } from './emitters/dts';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { CompilePredicateOptions } from './predicate';
|
|
2
|
+
/** A JSON-Schema node, optionally carrying a `$predicate` (predicate source). */
|
|
3
|
+
export interface PredicateSchema {
|
|
4
|
+
type?: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
|
|
5
|
+
properties?: Record<string, PredicateSchema>;
|
|
6
|
+
required?: string[];
|
|
7
|
+
items?: PredicateSchema;
|
|
8
|
+
/**
|
|
9
|
+
* Predicate cluster source. The LAST top-level function is the entry; it
|
|
10
|
+
* receives the value at this node and returns a boolean. Ignored by naive
|
|
11
|
+
* validators (it's a custom keyword); run by predicate-aware ones.
|
|
12
|
+
*/
|
|
13
|
+
$predicate?: string;
|
|
14
|
+
[k: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface SchemaError {
|
|
17
|
+
/** JSON-pointer-ish path to the offending value, e.g. `/style/color`. */
|
|
18
|
+
path: string;
|
|
19
|
+
message: string;
|
|
20
|
+
}
|
|
21
|
+
export interface SchemaValidationResult {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
errors: SchemaError[];
|
|
24
|
+
}
|
|
25
|
+
export interface PredicateSchemaOptions extends CompilePredicateOptions {
|
|
26
|
+
/**
|
|
27
|
+
* Validate structure only — skip every `$predicate` (i.e. behave like a naive
|
|
28
|
+
* JSON-Schema validator). Useful for demonstrating progressive enhancement.
|
|
29
|
+
*/
|
|
30
|
+
ignorePredicates?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compile a predicate-aware JSON-Schema into a reusable validator. Every
|
|
34
|
+
* `$predicate` cluster is verified + compiled once (fuel-bounded, IO-rejected);
|
|
35
|
+
* an invalid/unsafe predicate throws here, at compile time.
|
|
36
|
+
*/
|
|
37
|
+
export declare function compilePredicateSchema(schema: PredicateSchema, opts?: PredicateSchemaOptions): (value: unknown) => SchemaValidationResult;
|
|
38
|
+
/** One-shot convenience: compile + validate. */
|
|
39
|
+
export declare function validatePredicateSchema(schema: PredicateSchema, value: unknown, opts?: PredicateSchemaOptions): SchemaValidationResult;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export interface PredicateDiagnostic {
|
|
2
|
+
/** Name of the predicate the problem is in. */
|
|
3
|
+
predicate: string;
|
|
4
|
+
message: string;
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PredicateVerifyResult {
|
|
9
|
+
safe: boolean;
|
|
10
|
+
/** Names of the top-level functions found (the predicate cluster). */
|
|
11
|
+
predicates: string[];
|
|
12
|
+
diagnostics: PredicateDiagnostic[];
|
|
13
|
+
}
|
|
14
|
+
export interface VerifyPredicateOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Names that are effectful and must not be called — IO atoms + JS IO globals.
|
|
17
|
+
* Compose from the atom registry with `effectfulFromAtoms`. The built-in JS IO
|
|
18
|
+
* globals are always included.
|
|
19
|
+
*/
|
|
20
|
+
effectful?: Set<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Externally-verified predicate names this source may compose with (a shared
|
|
23
|
+
* registry), in addition to the functions declared in `source`.
|
|
24
|
+
*/
|
|
25
|
+
knownPredicates?: Set<string>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the effectful-name set from a VM atom registry: every atom tagged
|
|
29
|
+
* `effects: 'io'`, plus the built-in JS IO globals. This is how the verifier
|
|
30
|
+
* consumes the atom-effects classification (the keystone).
|
|
31
|
+
*/
|
|
32
|
+
export declare function effectfulFromAtoms(atoms: Record<string, {
|
|
33
|
+
op?: string;
|
|
34
|
+
effects?: 'pure' | 'io';
|
|
35
|
+
}>): Set<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Verify every top-level function declaration in `source` is predicate-safe.
|
|
38
|
+
* Returns all diagnostics; `safe` is true iff there are none (closure property).
|
|
39
|
+
*/
|
|
40
|
+
export declare function verifyPredicate(source: string, opts?: VerifyPredicateOptions): PredicateVerifyResult;
|
|
41
|
+
/** Format diagnostics for a thrown error / log. */
|
|
42
|
+
export declare function formatPredicateDiagnostics(d: PredicateDiagnostic[]): string;
|
|
43
|
+
export interface Suggestion {
|
|
44
|
+
value: string;
|
|
45
|
+
/**
|
|
46
|
+
* `'value'` — a concrete candidate (a keyword/literal the predicate accepts);
|
|
47
|
+
* `'stub'` — a partial completion to keep typing (e.g. `var(--`, `calc(`),
|
|
48
|
+
* mined from a `startsWith(...)` guard. TS's `string` fallback
|
|
49
|
+
* offers neither; a finite TS union offers only `'value'`.
|
|
50
|
+
*/
|
|
51
|
+
kind: 'value' | 'stub';
|
|
52
|
+
}
|
|
53
|
+
export interface SuggestOptions extends CompilePredicateOptions {
|
|
54
|
+
/** Only return candidates relevant to the text typed so far. */
|
|
55
|
+
prefix?: string;
|
|
56
|
+
/** Cap the number of suggestions (default 50). */
|
|
57
|
+
limit?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Run each mined *value* through the compiled entry predicate and keep only
|
|
60
|
+
* those that actually pass — so completions are guaranteed valid, not merely
|
|
61
|
+
* enumerated. Default true when the cluster is predicate-safe; stubs are never
|
|
62
|
+
* validated (they're partial by construction).
|
|
63
|
+
*/
|
|
64
|
+
validate?: boolean;
|
|
65
|
+
/** Entry predicate to validate against (default: last top-level function). */
|
|
66
|
+
entry?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Mine a predicate cluster's source for autocomplete candidates. Two sources:
|
|
70
|
+
* - **values** — string literals compared with `==`/`===` and members of
|
|
71
|
+
* array literals (the keyword sets a predicate checks membership against).
|
|
72
|
+
* - **stubs** — the argument of a `.startsWith(...)` guard, surfaced as a
|
|
73
|
+
* partial completion (`var(--`, `calc(`) the user keeps typing.
|
|
74
|
+
*
|
|
75
|
+
* Pure syntactic mining over the parsed source — no execution. By default the
|
|
76
|
+
* mined *values* are then run through the compiled entry predicate, so the
|
|
77
|
+
* returned set is exactly what the predicate accepts (a literal that only ever
|
|
78
|
+
* appears in a `!=` / negative context is dropped). This is the autocomplete
|
|
79
|
+
* win over a TS `string` fallback (which suggests nothing) and over a finite TS
|
|
80
|
+
* union (which can't offer the open-ended `var(--`/`calc(` stubs).
|
|
81
|
+
*/
|
|
82
|
+
export declare function suggest(source: string, opts?: SuggestOptions): Suggestion[];
|
|
83
|
+
/** Thrown when a predicate exceeds its fuel budget (likely a pathological input). */
|
|
84
|
+
export declare class PredicateFuelExhausted extends Error {
|
|
85
|
+
constructor(budget: number);
|
|
86
|
+
}
|
|
87
|
+
export interface CompilePredicateOptions extends VerifyPredicateOptions {
|
|
88
|
+
/** Max fuel per top-level predicate call (default 1,000,000). */
|
|
89
|
+
fuel?: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Verify, then compile the cluster to native synchronous JS functions —
|
|
93
|
+
* **fuel-bounded and global-shadowed**. Throws (with located diagnostics) at
|
|
94
|
+
* definition time if not predicate-safe.
|
|
95
|
+
*
|
|
96
|
+
* Each compiled predicate runs with a fresh fuel budget; a runaway input throws
|
|
97
|
+
* `PredicateFuelExhausted` rather than hanging. The effectful globals are
|
|
98
|
+
* shadowed to `undefined` as defense-in-depth beneath the static verifier.
|
|
99
|
+
*
|
|
100
|
+
* NOTE: preserves JS semantics (no structural-`==` rewrite yet — a future
|
|
101
|
+
* opt-in). Emission is offset-spliced source, not a full AJS-AST→JS codegen.
|
|
102
|
+
*/
|
|
103
|
+
export declare function compilePredicate(source: string, exportNames: string[], opts?: CompilePredicateOptions): Record<string, (...args: any[]) => any>;
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
export { transpile, ajs, tjs, createAgent, getToolDefinitions } from './core';
|
|
13
13
|
export { parse, preprocess, extractTDoc } from './parser';
|
|
14
14
|
export { dialectForFilename, sourceKindForFilename, type Dialect, type SourceKind, } from './dialect';
|
|
15
|
+
export { verifyPredicate, compilePredicate, suggest, effectfulFromAtoms, formatPredicateDiagnostics, PredicateFuelExhausted, type PredicateDiagnostic, type PredicateVerifyResult, type VerifyPredicateOptions, type CompilePredicateOptions, type Suggestion, type SuggestOptions, } from './predicate';
|
|
16
|
+
export { compilePredicateSchema, validatePredicateSchema, type PredicateSchema, type SchemaError, type SchemaValidationResult, type PredicateSchemaOptions, } from './predicate-schema';
|
|
15
17
|
export { transformFunction } from './emitters/ast';
|
|
16
18
|
export { transpileToJS } from './emitters/js';
|
|
17
19
|
export type { TJSTranspileOptions, TJSTranspileResult, TJSTypeInfo, } from './emitters/js';
|
package/dist/src/vm/runtime.d.ts
CHANGED
|
@@ -89,6 +89,17 @@ export interface RuntimeContext {
|
|
|
89
89
|
callDepth?: number;
|
|
90
90
|
}
|
|
91
91
|
export type AtomExec = (step: any, ctx: RuntimeContext) => Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Effect classification of an atom.
|
|
94
|
+
* - `'pure'`: deterministic, no IO, no capability access, no observable side
|
|
95
|
+
* effects — safe inside a synchronous predicate (see the predicate verifier).
|
|
96
|
+
* - `'io'`: touches `ctx.capabilities` (fetch/store/llm/agent/code), or is
|
|
97
|
+
* nondeterministic (random/uuid), or has side effects (console). Not allowed
|
|
98
|
+
* in a predicate.
|
|
99
|
+
* Defaults to `'pure'`; effectful atoms must opt into `'io'`. The invariant
|
|
100
|
+
* "anything touching ctx.capabilities is tagged 'io'" is guarded by a test.
|
|
101
|
+
*/
|
|
102
|
+
export type AtomEffects = 'pure' | 'io';
|
|
92
103
|
export interface AtomDef {
|
|
93
104
|
op: OpCode;
|
|
94
105
|
inputSchema: any;
|
|
@@ -97,6 +108,7 @@ export interface AtomDef {
|
|
|
97
108
|
docs?: string;
|
|
98
109
|
timeoutMs?: number;
|
|
99
110
|
cost?: number | ((input: any, ctx: RuntimeContext) => number);
|
|
111
|
+
effects?: AtomEffects;
|
|
100
112
|
}
|
|
101
113
|
export interface Atom<I, O> extends AtomDef {
|
|
102
114
|
create(input: I): I & {
|
|
@@ -107,6 +119,8 @@ export interface AtomOptions {
|
|
|
107
119
|
docs?: string;
|
|
108
120
|
timeoutMs?: number;
|
|
109
121
|
cost?: number | ((input: any, ctx: RuntimeContext) => number);
|
|
122
|
+
/** Effect class — defaults to `'pure'`; effectful atoms set `'io'`. */
|
|
123
|
+
effects?: AtomEffects;
|
|
110
124
|
}
|
|
111
125
|
export interface RunResult {
|
|
112
126
|
result: any;
|
|
@@ -349,3 +363,11 @@ export declare const coreAtoms: {
|
|
|
349
363
|
releaseProcedure: Atom<Record<string, any>, boolean>;
|
|
350
364
|
clearExpiredProcedures: Atom<Record<string, any>, number>;
|
|
351
365
|
};
|
|
366
|
+
/**
|
|
367
|
+
* Effectful core atoms — anything that touches `ctx.capabilities`
|
|
368
|
+
* (fetch/store/llm/agent/code), is nondeterministic (random/uuid), or has
|
|
369
|
+
* observable side effects (console). Tagged centrally so the list reads as one
|
|
370
|
+
* audit surface; a test asserts every capability-touching atom is in here.
|
|
371
|
+
* Everything else defaults to `effects: 'pure'`.
|
|
372
|
+
*/
|
|
373
|
+
export declare const EFFECTFUL_CORE_OPS: readonly ["httpFetch", "storeGet", "storeSet", "storeQuery", "storeVectorSearch", "llmPredict", "agentRun", "transpileCode", "runCode", "random", "uuid", "consoleLog", "consoleWarn", "consoleError", "storeProcedure", "releaseProcedure", "clearExpiredProcedures", "cache", "memoize"];
|