@forthix/forthic 0.4.0 → 0.5.1
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 +8 -2
- package/dist/cjs/forthic/decorators/schemaUtils.d.ts +70 -0
- package/dist/cjs/forthic/decorators/schemaUtils.js +77 -0
- package/dist/cjs/forthic/decorators/schemaUtils.js.map +1 -0
- package/dist/cjs/forthic/decorators/stackEffect.d.ts +63 -0
- package/dist/cjs/forthic/decorators/stackEffect.js +179 -0
- package/dist/cjs/forthic/decorators/stackEffect.js.map +1 -0
- package/dist/cjs/forthic/errors.d.ts +2 -0
- package/dist/cjs/forthic/errors.js +13 -2
- package/dist/cjs/forthic/errors.js.map +1 -1
- package/dist/cjs/forthic/interpreter.d.ts +11 -1
- package/dist/cjs/forthic/interpreter.js +50 -14
- package/dist/cjs/forthic/interpreter.js.map +1 -1
- package/dist/cjs/forthic/literals.d.ts +6 -1
- package/dist/cjs/forthic/literals.js +13 -2
- package/dist/cjs/forthic/literals.js.map +1 -1
- package/dist/cjs/forthic/module.d.ts +23 -1
- package/dist/cjs/forthic/module.js +63 -3
- package/dist/cjs/forthic/module.js.map +1 -1
- package/dist/cjs/forthic/tokenizer.js +28 -3
- package/dist/cjs/forthic/tokenizer.js.map +1 -1
- package/dist/cjs/grpc/client.js +10 -10
- package/dist/cjs/grpc/client.js.map +1 -1
- package/dist/esm/forthic/decorators/schemaUtils.d.ts +70 -0
- package/dist/esm/forthic/decorators/schemaUtils.js +72 -0
- package/dist/esm/forthic/decorators/schemaUtils.js.map +1 -0
- package/dist/esm/forthic/decorators/stackEffect.d.ts +63 -0
- package/dist/esm/forthic/decorators/stackEffect.js +174 -0
- package/dist/esm/forthic/decorators/stackEffect.js.map +1 -0
- package/dist/esm/forthic/errors.d.ts +2 -0
- package/dist/esm/forthic/errors.js +13 -2
- package/dist/esm/forthic/errors.js.map +1 -1
- package/dist/esm/forthic/interpreter.d.ts +11 -1
- package/dist/esm/forthic/interpreter.js +51 -15
- package/dist/esm/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/literals.d.ts +6 -1
- package/dist/esm/forthic/literals.js +13 -2
- package/dist/esm/forthic/literals.js.map +1 -1
- package/dist/esm/forthic/module.d.ts +23 -1
- package/dist/esm/forthic/module.js +62 -3
- package/dist/esm/forthic/module.js.map +1 -1
- package/dist/esm/forthic/tokenizer.js +28 -3
- package/dist/esm/forthic/tokenizer.js.map +1 -1
- package/dist/esm/grpc/client.js +2 -2
- package/dist/esm/grpc/client.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/grpc/server.test.d.ts +0 -1
- package/dist/cjs/grpc/server.test.js +0 -156
- package/dist/cjs/grpc/server.test.js.map +0 -1
- package/dist/cjs/grpc/temporal_utils.d.ts +0 -36
- package/dist/cjs/grpc/temporal_utils.js +0 -80
- package/dist/cjs/grpc/temporal_utils.js.map +0 -1
- package/dist/cjs/websocket/action_cable_client.d.ts +0 -106
- package/dist/cjs/websocket/action_cable_client.js +0 -269
- package/dist/cjs/websocket/action_cable_client.js.map +0 -1
- package/dist/cjs/websocket/client.d.ts +0 -103
- package/dist/cjs/websocket/client.js +0 -266
- package/dist/cjs/websocket/client.js.map +0 -1
- package/dist/cjs/websocket/remote_module.d.ts +0 -68
- package/dist/cjs/websocket/remote_module.js +0 -107
- package/dist/cjs/websocket/remote_module.js.map +0 -1
- package/dist/cjs/websocket/remote_word.d.ts +0 -53
- package/dist/cjs/websocket/remote_word.js +0 -93
- package/dist/cjs/websocket/remote_word.js.map +0 -1
- package/dist/cjs/websocket/runtime_manager.d.ts +0 -69
- package/dist/cjs/websocket/runtime_manager.js +0 -112
- package/dist/cjs/websocket/runtime_manager.js.map +0 -1
- package/dist/esm/grpc/server.test.d.ts +0 -1
- package/dist/esm/grpc/server.test.js +0 -121
- package/dist/esm/grpc/server.test.js.map +0 -1
- package/dist/esm/grpc/temporal_utils.d.ts +0 -36
- package/dist/esm/grpc/temporal_utils.js +0 -72
- package/dist/esm/grpc/temporal_utils.js.map +0 -1
- package/dist/esm/websocket/action_cable_client.d.ts +0 -106
- package/dist/esm/websocket/action_cable_client.js +0 -265
- package/dist/esm/websocket/action_cable_client.js.map +0 -1
- package/dist/esm/websocket/client.d.ts +0 -103
- package/dist/esm/websocket/client.js +0 -262
- package/dist/esm/websocket/client.js.map +0 -1
- package/dist/esm/websocket/remote_module.d.ts +0 -68
- package/dist/esm/websocket/remote_module.js +0 -103
- package/dist/esm/websocket/remote_module.js.map +0 -1
- package/dist/esm/websocket/remote_word.d.ts +0 -53
- package/dist/esm/websocket/remote_word.js +0 -89
- package/dist/esm/websocket/remote_word.js.map +0 -1
- package/dist/esm/websocket/runtime_manager.d.ts +0 -69
- package/dist/esm/websocket/runtime_manager.js +0 -108
- package/dist/esm/websocket/runtime_manager.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Use Forthic to wrap your TypeScript/JavaScript code within composable words, leveraging categorical principles for clean, powerful abstractions.
|
|
6
6
|
|
|
7
|
-
**[
|
|
7
|
+
**[Learn at forthix.com](https://forthix.com)** | **[Forthic Docs](https://github.com/forthix/forthic)** | **[Getting Started](#getting-started)** | **[Examples](examples/)** | **[API Docs](docs/)**
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -16,7 +16,9 @@ Forthic enables **categorical coding** - a way to solve problems by viewing them
|
|
|
16
16
|
2. **Compose transformations** cleanly using stack-based operations
|
|
17
17
|
3. **Build powerful abstractions** from simple primitives
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**[Learn more about Categorical Coding →](https://forthix.com/blog/category-theory-for-the-rest-of-us-coders)**
|
|
20
|
+
|
|
21
|
+
See the [Forthic repository](https://github.com/forthix/forthic) for technical documentation and API references.
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
@@ -200,6 +202,10 @@ import { GrpcClient, RemoteModule, startGrpcServer } from '@forthix/forthic/grpc
|
|
|
200
202
|
|
|
201
203
|
## Documentation
|
|
202
204
|
|
|
205
|
+
### Learning Resources
|
|
206
|
+
- **[forthix.com](https://forthix.com)** - Learn about Forthic and Categorical Coding
|
|
207
|
+
- **[Category Theory for Coders](https://forthix.com/blog/category-theory-for-the-rest-of-us-coders)** - Understand the foundations
|
|
208
|
+
|
|
203
209
|
### This Runtime
|
|
204
210
|
- **[Getting Started](docs/getting-started.md)** - TypeScript-specific setup
|
|
205
211
|
- **[Module API Reference](docs/modules/)** - Standard library documentation
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Registry metadata types for stack objects and class instances.
|
|
4
|
+
*/
|
|
5
|
+
type StackObjectMetadata = {
|
|
6
|
+
objectType: "stackObject";
|
|
7
|
+
stackObjectType: string;
|
|
8
|
+
className?: undefined;
|
|
9
|
+
OriginalClass?: undefined;
|
|
10
|
+
} | {
|
|
11
|
+
objectType: "class";
|
|
12
|
+
OriginalClass: new (...args: any[]) => any;
|
|
13
|
+
className: string;
|
|
14
|
+
stackObjectType?: undefined;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Track metadata for schema comparison in tests and documentation.
|
|
18
|
+
* Only required for schemas that can't be compared out of the box,
|
|
19
|
+
* like custom schemas or instanceof schemas.
|
|
20
|
+
*/
|
|
21
|
+
export declare const stackObjectRegistry: z.core.$ZodRegistry<StackObjectMetadata, z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a Zod schema for stack objects that have a stackObjectType property.
|
|
24
|
+
* This is a helper to reduce boilerplate when creating custom stack object schemas.
|
|
25
|
+
* It also ensures the schema is registered in stackObjectRegistry, which enables
|
|
26
|
+
* proper type string generation in stack effects.
|
|
27
|
+
*
|
|
28
|
+
* Use this instead of z.custom() directly for stack objects.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* interface StackEmail {
|
|
33
|
+
* stackObjectType: "email";
|
|
34
|
+
* to: string;
|
|
35
|
+
* subject: string;
|
|
36
|
+
* body: string;
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* const stackEmailSchema = createStackObjectSchema<StackEmail>("email");
|
|
40
|
+
*
|
|
41
|
+
* // Use in stack effect:
|
|
42
|
+
* @ForthicWord(se`(email:${stackEmailSchema} -- sent:${z.boolean()})`, "Send email")
|
|
43
|
+
* async SEND(email: StackEmail): Promise<boolean> { ... }
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function createStackObjectSchema<T extends {
|
|
47
|
+
stackObjectType: string;
|
|
48
|
+
}>(stackObjectType: string, errorMessage?: string): z.ZodCustom<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a Zod instanceof schema with automatic metadata registration.
|
|
51
|
+
* This ensures the schema is registered in stackObjectRegistry, which enables
|
|
52
|
+
* proper type string generation in stack effects.
|
|
53
|
+
*
|
|
54
|
+
* Use this instead of z.instanceof() directly.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* import { Temporal } from "temporal-polyfill";
|
|
59
|
+
*
|
|
60
|
+
* const plainDateSchema = createInstanceOfSchema(Temporal.PlainDate);
|
|
61
|
+
*
|
|
62
|
+
* // Use in stack effect:
|
|
63
|
+
* @ForthicWord(se`(date:${plainDateSchema} -- formatted:${z.string()})`, "Format date")
|
|
64
|
+
* async FORMAT(date: Temporal.PlainDate): Promise<string> { ... }
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function createInstanceOfSchema<T extends abstract new (...args: any[]) => any>(ClassToSchematize: T,
|
|
68
|
+
/** If not passed, falls back to class.name */
|
|
69
|
+
className?: string): z.ZodType<InstanceType<T>>;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stackObjectRegistry = void 0;
|
|
4
|
+
exports.createStackObjectSchema = createStackObjectSchema;
|
|
5
|
+
exports.createInstanceOfSchema = createInstanceOfSchema;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
/**
|
|
8
|
+
* Track metadata for schema comparison in tests and documentation.
|
|
9
|
+
* Only required for schemas that can't be compared out of the box,
|
|
10
|
+
* like custom schemas or instanceof schemas.
|
|
11
|
+
*/
|
|
12
|
+
exports.stackObjectRegistry = zod_1.z.registry();
|
|
13
|
+
/**
|
|
14
|
+
* Creates a Zod schema for stack objects that have a stackObjectType property.
|
|
15
|
+
* This is a helper to reduce boilerplate when creating custom stack object schemas.
|
|
16
|
+
* It also ensures the schema is registered in stackObjectRegistry, which enables
|
|
17
|
+
* proper type string generation in stack effects.
|
|
18
|
+
*
|
|
19
|
+
* Use this instead of z.custom() directly for stack objects.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* interface StackEmail {
|
|
24
|
+
* stackObjectType: "email";
|
|
25
|
+
* to: string;
|
|
26
|
+
* subject: string;
|
|
27
|
+
* body: string;
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* const stackEmailSchema = createStackObjectSchema<StackEmail>("email");
|
|
31
|
+
*
|
|
32
|
+
* // Use in stack effect:
|
|
33
|
+
* @ForthicWord(se`(email:${stackEmailSchema} -- sent:${z.boolean()})`, "Send email")
|
|
34
|
+
* async SEND(email: StackEmail): Promise<boolean> { ... }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
function createStackObjectSchema(stackObjectType, errorMessage) {
|
|
38
|
+
const schema = zod_1.z.custom((maybeStackObject) => maybeStackObject?.stackObjectType === stackObjectType, errorMessage ?? `expected ${stackObjectType} stackObjectType`);
|
|
39
|
+
// Register schema with metadata
|
|
40
|
+
exports.stackObjectRegistry.add(schema, {
|
|
41
|
+
objectType: "stackObject",
|
|
42
|
+
stackObjectType,
|
|
43
|
+
});
|
|
44
|
+
return schema;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates a Zod instanceof schema with automatic metadata registration.
|
|
48
|
+
* This ensures the schema is registered in stackObjectRegistry, which enables
|
|
49
|
+
* proper type string generation in stack effects.
|
|
50
|
+
*
|
|
51
|
+
* Use this instead of z.instanceof() directly.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { Temporal } from "temporal-polyfill";
|
|
56
|
+
*
|
|
57
|
+
* const plainDateSchema = createInstanceOfSchema(Temporal.PlainDate);
|
|
58
|
+
*
|
|
59
|
+
* // Use in stack effect:
|
|
60
|
+
* @ForthicWord(se`(date:${plainDateSchema} -- formatted:${z.string()})`, "Format date")
|
|
61
|
+
* async FORMAT(date: Temporal.PlainDate): Promise<string> { ... }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
function createInstanceOfSchema(ClassToSchematize,
|
|
65
|
+
/** If not passed, falls back to class.name */
|
|
66
|
+
className) {
|
|
67
|
+
const schema = zod_1.z.instanceof(ClassToSchematize);
|
|
68
|
+
// Register schema with metadata
|
|
69
|
+
const resolvedClassName = className ?? ClassToSchematize.name;
|
|
70
|
+
exports.stackObjectRegistry.add(schema, {
|
|
71
|
+
objectType: "class",
|
|
72
|
+
OriginalClass: ClassToSchematize,
|
|
73
|
+
className: resolvedClassName,
|
|
74
|
+
});
|
|
75
|
+
return schema;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=schemaUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemaUtils.js","sourceRoot":"","sources":["../../../../src/forthic/decorators/schemaUtils.ts"],"names":[],"mappings":";;;AAkDA,0DAgBC;AAoBD,wDAgBC;AAtGD,6BAAwB;AAmBxB;;;;GAIG;AACU,QAAA,mBAAmB,GAAG,OAAC,CAAC,QAAQ,EAAuB,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,uBAAuB,CACrC,eAAuB,EACvB,YAAqB;IAErB,MAAM,MAAM,GAAG,OAAC,CAAC,MAAM,CACrB,CAAC,gBAAgB,EAAE,EAAE,CAAE,gBAAkC,EAAE,eAAe,KAAK,eAAe,EAC9F,YAAY,IAAI,YAAY,eAAe,kBAAkB,CAC9D,CAAC;IAEF,gCAAgC;IAChC,2BAAmB,CAAC,GAAG,CAAC,MAAM,EAAE;QAC9B,UAAU,EAAE,aAAa;QACzB,eAAe;KAChB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,sBAAsB,CACpC,iBAAoB;AACpB,8CAA8C;AAC9C,SAAkB;IAElB,MAAM,MAAM,GAAG,OAAC,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAE/C,gCAAgC;IAChC,MAAM,iBAAiB,GAAG,SAAS,IAAI,iBAAiB,CAAC,IAAI,CAAC;IAC9D,2BAAmB,CAAC,GAAG,CAAC,MAAM,EAAE;QAC9B,UAAU,EAAE,OAAO;QACnB,aAAa,EAAE,iBAAiB;QAChC,SAAS,EAAE,iBAAiB;KAC7B,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { util as zodUtil } from "zod/v4/core";
|
|
3
|
+
/**
|
|
4
|
+
* Map the set of Zod types to the strings we use in Forthic stack effects.
|
|
5
|
+
* Uses Zod's internal def.type for comprehensive type detection.
|
|
6
|
+
*/
|
|
7
|
+
export declare const mapZodToStackEffectType: (zodType: z.ZodTypeAny) => string;
|
|
8
|
+
type InferTupleTypes<T extends zodUtil.TupleItems> = {
|
|
9
|
+
[K in keyof T]: T[K] extends z.ZodTypeAny ? z.infer<T[K]> : never;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Represents a type-safe stack effect with Zod schemas for validation.
|
|
13
|
+
*
|
|
14
|
+
* @template Args - Tuple of Zod schemas for input parameters
|
|
15
|
+
* @template Return - Zod schema for the return type
|
|
16
|
+
*/
|
|
17
|
+
export type TaggedStackEffect<Args extends zodUtil.TupleItems, Return extends z.core.$ZodFunctionOut = z.core.$ZodFunctionOut> = {
|
|
18
|
+
/** The human-readable stack effect string (e.g., "( a:number b:string -- result:string )") */
|
|
19
|
+
stackEffect: string;
|
|
20
|
+
/** Zod schemas for runtime validation */
|
|
21
|
+
schema: {
|
|
22
|
+
inputSchemas: z.ZodTypeAny[];
|
|
23
|
+
outputSchema: z.ZodTypeAny;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Phantom property to convey the expected function signature, constructed from the input + output types.
|
|
27
|
+
* DO NOT USE AT RUNTIME - it's only used for type inference.
|
|
28
|
+
*/
|
|
29
|
+
_implType: (...args: InferTupleTypes<Args>) => Promise<z.infer<Return>>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Tagged template literal for stack effects. Use with the @ForthicWord decorator to
|
|
33
|
+
* create a type-safe stack effect.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* // Type-safe stack effect with Zod validation
|
|
38
|
+
* @ForthicWord(se`(a:${z.number()} b:${z.string()} -- result:${z.string()})`, "Concatenate number and string")
|
|
39
|
+
* async CONCAT(a: number, b: string): Promise<string> {
|
|
40
|
+
* return `${a}${b}`;
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // No parameters, returns string
|
|
47
|
+
* @ForthicWord(se`( -- message:${z.string()})`, "Get greeting")
|
|
48
|
+
* async GREET(): Promise<string> {
|
|
49
|
+
* return "Hello!";
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* // Takes string, no return (void)
|
|
56
|
+
* @ForthicWord(se`(input:${z.string()} -- ${z.void()})`, "Log to console")
|
|
57
|
+
* async LOG(input: string): Promise<void> {
|
|
58
|
+
* console.log(input);
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const se: <Args extends zodUtil.TupleItems, Return extends z.core.$ZodFunctionOut>(template: TemplateStringsArray, ...values: [...Args, Return]) => TaggedStackEffect<Args, Return>;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.se = exports.mapZodToStackEffectType = void 0;
|
|
4
|
+
const schemaUtils_js_1 = require("./schemaUtils.js");
|
|
5
|
+
/**
|
|
6
|
+
* Map the set of Zod types to the strings we use in Forthic stack effects.
|
|
7
|
+
* Uses Zod's internal def.type for comprehensive type detection.
|
|
8
|
+
*/
|
|
9
|
+
const mapZodToStackEffectType = (zodType) => {
|
|
10
|
+
const def = zodType.def;
|
|
11
|
+
switch (def.type) {
|
|
12
|
+
case "string":
|
|
13
|
+
return "string";
|
|
14
|
+
case "int":
|
|
15
|
+
case "bigint":
|
|
16
|
+
return "number";
|
|
17
|
+
case "number":
|
|
18
|
+
return "number";
|
|
19
|
+
case "boolean":
|
|
20
|
+
return "boolean";
|
|
21
|
+
case "null":
|
|
22
|
+
return "null";
|
|
23
|
+
case "undefined":
|
|
24
|
+
case "void":
|
|
25
|
+
return "";
|
|
26
|
+
case "date":
|
|
27
|
+
return "date";
|
|
28
|
+
case "symbol":
|
|
29
|
+
return "symbol";
|
|
30
|
+
case "object": {
|
|
31
|
+
const objectDef = def;
|
|
32
|
+
const objectShape = objectDef.shape;
|
|
33
|
+
// Get all property types
|
|
34
|
+
const properties = Object.entries(objectShape).map(([key, fieldSchema]) => {
|
|
35
|
+
const fieldType = (0, exports.mapZodToStackEffectType)(fieldSchema);
|
|
36
|
+
return `${key}: ${fieldType}`;
|
|
37
|
+
});
|
|
38
|
+
// Return formatted object type
|
|
39
|
+
return properties.length > 0 ? `{ ${properties.join(", ")} }` : "{}";
|
|
40
|
+
}
|
|
41
|
+
case "literal": {
|
|
42
|
+
const literalDef = def;
|
|
43
|
+
const value = literalDef.values[0];
|
|
44
|
+
// Quote string literals
|
|
45
|
+
return typeof value === "string" ? `"${value}"` : String(value);
|
|
46
|
+
}
|
|
47
|
+
case "enum": {
|
|
48
|
+
const enumDef = def;
|
|
49
|
+
const enumEntries = Object.values(enumDef.entries);
|
|
50
|
+
// Return union of quoted values - zod enums are always strings
|
|
51
|
+
return enumEntries.map((entry) => `"${entry}"`).join("|");
|
|
52
|
+
}
|
|
53
|
+
case "optional": {
|
|
54
|
+
const optionalDef = def;
|
|
55
|
+
const innerType = (0, exports.mapZodToStackEffectType)(optionalDef.innerType);
|
|
56
|
+
// Optional is a union with undefined
|
|
57
|
+
return innerType ? `${innerType}|undefined` : "undefined";
|
|
58
|
+
}
|
|
59
|
+
case "nullable": {
|
|
60
|
+
const nullableDef = def;
|
|
61
|
+
const innerType = (0, exports.mapZodToStackEffectType)(nullableDef.innerType);
|
|
62
|
+
// Nullable is a union with null
|
|
63
|
+
return innerType ? `${innerType}|null` : "null";
|
|
64
|
+
}
|
|
65
|
+
case "union": {
|
|
66
|
+
const unionDef = def;
|
|
67
|
+
const unionOptions = unionDef.options;
|
|
68
|
+
// Recursively get types for all union options
|
|
69
|
+
const optionTypes = unionOptions.map((option) => (0, exports.mapZodToStackEffectType)(option));
|
|
70
|
+
// Dedupe
|
|
71
|
+
return [...new Set(optionTypes)].join("|");
|
|
72
|
+
}
|
|
73
|
+
case "tuple": {
|
|
74
|
+
const tupleDef = def;
|
|
75
|
+
const tupleItems = tupleDef.items;
|
|
76
|
+
const elementTypes = tupleItems.map((item) => (0, exports.mapZodToStackEffectType)(item));
|
|
77
|
+
return `[${elementTypes.join(", ")}]`;
|
|
78
|
+
}
|
|
79
|
+
case "array": {
|
|
80
|
+
const arrayDef = def;
|
|
81
|
+
const elementType = (0, exports.mapZodToStackEffectType)(arrayDef.element);
|
|
82
|
+
// If the element is a union (contains "|") but not already an array type (doesn't end with "]"),
|
|
83
|
+
// wrap it in parentheses
|
|
84
|
+
const needsParens = elementType.includes("|") && !elementType.endsWith("]");
|
|
85
|
+
const wrappedType = needsParens ? `(${elementType})` : elementType;
|
|
86
|
+
return `${wrappedType}[]`;
|
|
87
|
+
}
|
|
88
|
+
case "custom": {
|
|
89
|
+
const metadata = schemaUtils_js_1.stackObjectRegistry.get(zodType);
|
|
90
|
+
if (!metadata) {
|
|
91
|
+
throw new Error(`Custom schema found without stack object registry entry. Consider using createStackObjectSchema or createInstanceOfSchema or manually registering the schema.`);
|
|
92
|
+
}
|
|
93
|
+
return metadata.stackObjectType ?? metadata.className ?? "object";
|
|
94
|
+
}
|
|
95
|
+
case "any":
|
|
96
|
+
return "any";
|
|
97
|
+
case "record":
|
|
98
|
+
case "function":
|
|
99
|
+
case "promise":
|
|
100
|
+
case "map":
|
|
101
|
+
case "set":
|
|
102
|
+
case "lazy":
|
|
103
|
+
case "never":
|
|
104
|
+
case "unknown":
|
|
105
|
+
case "file":
|
|
106
|
+
case "nonoptional":
|
|
107
|
+
case "success":
|
|
108
|
+
case "transform":
|
|
109
|
+
case "prefault":
|
|
110
|
+
case "nan":
|
|
111
|
+
case "pipe":
|
|
112
|
+
case "template_literal":
|
|
113
|
+
case "intersection":
|
|
114
|
+
case "catch":
|
|
115
|
+
case "default":
|
|
116
|
+
case "readonly":
|
|
117
|
+
// Unsupported types - throw error to ensure we handle everything
|
|
118
|
+
throw new Error(`Stack effect string generation not supported for type: "${def.type}" - you may either update mapZodToStackEffectType or use a simpler type (e.g. use createStackObjectSchema)`);
|
|
119
|
+
default:
|
|
120
|
+
throw new Error(`Unknown type: "${def.type}". You either need to update mapZodToStackEffectType, or zod is doing something unexpected.`);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
exports.mapZodToStackEffectType = mapZodToStackEffectType;
|
|
124
|
+
/**
|
|
125
|
+
* Tagged template literal for stack effects. Use with the @ForthicWord decorator to
|
|
126
|
+
* create a type-safe stack effect.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* // Type-safe stack effect with Zod validation
|
|
131
|
+
* @ForthicWord(se`(a:${z.number()} b:${z.string()} -- result:${z.string()})`, "Concatenate number and string")
|
|
132
|
+
* async CONCAT(a: number, b: string): Promise<string> {
|
|
133
|
+
* return `${a}${b}`;
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* // No parameters, returns string
|
|
140
|
+
* @ForthicWord(se`( -- message:${z.string()})`, "Get greeting")
|
|
141
|
+
* async GREET(): Promise<string> {
|
|
142
|
+
* return "Hello!";
|
|
143
|
+
* }
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* // Takes string, no return (void)
|
|
149
|
+
* @ForthicWord(se`(input:${z.string()} -- ${z.void()})`, "Log to console")
|
|
150
|
+
* async LOG(input: string): Promise<void> {
|
|
151
|
+
* console.log(input);
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
const se = (template, ...values) => {
|
|
156
|
+
const stackEffectTypes = values.map((value) => (0, exports.mapZodToStackEffectType)(value));
|
|
157
|
+
// Outputs the template string as if it weren't tagged, e.g. "( a:string b:number -- c:number )"
|
|
158
|
+
const parts = [];
|
|
159
|
+
for (let i = 0; i < template.length; i++) {
|
|
160
|
+
parts.push(template[i]);
|
|
161
|
+
if (i < stackEffectTypes.length) {
|
|
162
|
+
parts.push(stackEffectTypes[i]);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const outStr = parts.join("");
|
|
166
|
+
const taggedStackEffect = {
|
|
167
|
+
stackEffect: outStr,
|
|
168
|
+
schema: {
|
|
169
|
+
inputSchemas: values.slice(0, -1),
|
|
170
|
+
outputSchema: values[values.length - 1],
|
|
171
|
+
},
|
|
172
|
+
_implType: async () => {
|
|
173
|
+
throw new Error("This function should not be called at runtime, it's only used for type inference");
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
return taggedStackEffect;
|
|
177
|
+
};
|
|
178
|
+
exports.se = se;
|
|
179
|
+
//# sourceMappingURL=stackEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stackEffect.js","sourceRoot":"","sources":["../../../../src/forthic/decorators/stackEffect.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@ export declare class ForthicError extends Error {
|
|
|
15
15
|
getError(): Error;
|
|
16
16
|
getForthic(): string;
|
|
17
17
|
getNote(): string;
|
|
18
|
+
getMessage(): string;
|
|
18
19
|
}
|
|
19
20
|
export declare class UnknownWordError extends ForthicError {
|
|
20
21
|
private word;
|
|
@@ -26,6 +27,7 @@ export declare class WordExecutionError extends ForthicError {
|
|
|
26
27
|
private definition_location?;
|
|
27
28
|
constructor(message: string, error: Error, call_location?: CodeLocationData, definition_location?: CodeLocationData);
|
|
28
29
|
getError(): Error;
|
|
30
|
+
getRootError(): Error;
|
|
29
31
|
getDefinitionLocation(): CodeLocationData | undefined;
|
|
30
32
|
}
|
|
31
33
|
export declare class MissingSemicolonError extends ForthicError {
|
|
@@ -19,7 +19,7 @@ class ForthicError extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
getDescription() {
|
|
22
|
-
|
|
22
|
+
return this.note;
|
|
23
23
|
}
|
|
24
24
|
getError() {
|
|
25
25
|
return this;
|
|
@@ -30,6 +30,9 @@ class ForthicError extends Error {
|
|
|
30
30
|
getNote() {
|
|
31
31
|
return this.note;
|
|
32
32
|
}
|
|
33
|
+
getMessage() {
|
|
34
|
+
return this.note;
|
|
35
|
+
}
|
|
33
36
|
}
|
|
34
37
|
exports.ForthicError = ForthicError;
|
|
35
38
|
class UnknownWordError extends ForthicError {
|
|
@@ -49,13 +52,21 @@ class WordExecutionError extends ForthicError {
|
|
|
49
52
|
innerError;
|
|
50
53
|
definition_location;
|
|
51
54
|
constructor(message, error, call_location, definition_location) {
|
|
52
|
-
|
|
55
|
+
// Pass the error as cause to maintain compatibility with code that checks .cause
|
|
56
|
+
super("", message, call_location, error);
|
|
53
57
|
this.innerError = error;
|
|
54
58
|
this.definition_location = definition_location;
|
|
55
59
|
}
|
|
56
60
|
getError() {
|
|
57
61
|
return this.innerError;
|
|
58
62
|
}
|
|
63
|
+
getRootError() {
|
|
64
|
+
let current = this.innerError;
|
|
65
|
+
while (current.cause instanceof Error) {
|
|
66
|
+
current = current.cause;
|
|
67
|
+
}
|
|
68
|
+
return current;
|
|
69
|
+
}
|
|
59
70
|
getDefinitionLocation() {
|
|
60
71
|
return this.definition_location;
|
|
61
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/forthic/errors.ts"],"names":[],"mappings":";AAAA,wCAAwC;;;
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/forthic/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -81,6 +81,16 @@ export declare class Interpreter {
|
|
|
81
81
|
execute_with_recovery(numAttempts?: number): Promise<number>;
|
|
82
82
|
continue(): Promise<void>;
|
|
83
83
|
run_with_tokenizer(tokenizer: Tokenizer): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* Execute a sequence of word tokens with deferred word lookup.
|
|
86
|
+
* This resolves words at execution time (not parse time) to support
|
|
87
|
+
* dynamically defined words (e.g., words defined by LOAD).
|
|
88
|
+
*
|
|
89
|
+
* Words are looked up and executed ONE AT A TIME to ensure that
|
|
90
|
+
* words defined during execution (e.g., by LOAD) are available
|
|
91
|
+
* for subsequent words in the same batch.
|
|
92
|
+
*/
|
|
93
|
+
private executeBatchedWordTokens;
|
|
84
94
|
/**
|
|
85
95
|
* Execute a sequence of words with batching optimization
|
|
86
96
|
*/
|
|
@@ -107,7 +117,7 @@ export declare class Interpreter {
|
|
|
107
117
|
private register_standard_literals;
|
|
108
118
|
/**
|
|
109
119
|
* Register a custom literal handler
|
|
110
|
-
*
|
|
120
|
+
* New handlers are added first so they can override existing ones
|
|
111
121
|
*/
|
|
112
122
|
register_literal_handler(handler: LiteralHandler): void;
|
|
113
123
|
/**
|
|
@@ -293,30 +293,30 @@ class Interpreter {
|
|
|
293
293
|
return;
|
|
294
294
|
}
|
|
295
295
|
async run_with_tokenizer(tokenizer) {
|
|
296
|
-
// Collect
|
|
297
|
-
|
|
296
|
+
// Collect word tokens first for batching optimization
|
|
297
|
+
// We store tokens (not resolved Words) to defer word lookup until execution time.
|
|
298
|
+
// This allows dynamically defined words (e.g., from LOAD) to be found.
|
|
299
|
+
const wordTokens = [];
|
|
298
300
|
let token;
|
|
299
301
|
do {
|
|
300
302
|
this.previous_token = token;
|
|
301
303
|
token = tokenizer.next_token();
|
|
302
|
-
// For word tokens, collect
|
|
304
|
+
// For word tokens, collect the token (defer word lookup until execution)
|
|
303
305
|
if (token.type === tokenizer_js_1.TokenType.WORD && !this.is_compiling) {
|
|
304
|
-
|
|
305
|
-
word.set_location(token.location);
|
|
306
|
-
words.push(word);
|
|
306
|
+
wordTokens.push(token);
|
|
307
307
|
}
|
|
308
308
|
else {
|
|
309
309
|
// For non-word tokens, execute any collected words first, then handle the token
|
|
310
|
-
if (
|
|
311
|
-
await this.
|
|
312
|
-
|
|
310
|
+
if (wordTokens.length > 0) {
|
|
311
|
+
await this.executeBatchedWordTokens(wordTokens);
|
|
312
|
+
wordTokens.length = 0; // Clear the array
|
|
313
313
|
}
|
|
314
314
|
await this.handle_token(token);
|
|
315
315
|
}
|
|
316
316
|
if (token.type === tokenizer_js_1.TokenType.EOS) {
|
|
317
317
|
// Execute any remaining words
|
|
318
|
-
if (
|
|
319
|
-
await this.
|
|
318
|
+
if (wordTokens.length > 0) {
|
|
319
|
+
await this.executeBatchedWordTokens(wordTokens);
|
|
320
320
|
}
|
|
321
321
|
break;
|
|
322
322
|
}
|
|
@@ -324,6 +324,25 @@ class Interpreter {
|
|
|
324
324
|
} while (true);
|
|
325
325
|
return true; // Done executing
|
|
326
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Execute a sequence of word tokens with deferred word lookup.
|
|
329
|
+
* This resolves words at execution time (not parse time) to support
|
|
330
|
+
* dynamically defined words (e.g., words defined by LOAD).
|
|
331
|
+
*
|
|
332
|
+
* Words are looked up and executed ONE AT A TIME to ensure that
|
|
333
|
+
* words defined during execution (e.g., by LOAD) are available
|
|
334
|
+
* for subsequent words in the same batch.
|
|
335
|
+
*/
|
|
336
|
+
async executeBatchedWordTokens(tokens) {
|
|
337
|
+
// Look up and execute each word one at a time
|
|
338
|
+
// This ensures words defined during execution are available for later words
|
|
339
|
+
for (const token of tokens) {
|
|
340
|
+
const word = this.find_word(token.string);
|
|
341
|
+
word.set_location(token.location);
|
|
342
|
+
this.count_word(word);
|
|
343
|
+
await word.execute(this);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
327
346
|
/**
|
|
328
347
|
* Execute a sequence of words with batching optimization
|
|
329
348
|
*/
|
|
@@ -346,7 +365,24 @@ class Interpreter {
|
|
|
346
365
|
// Execute local words one by one
|
|
347
366
|
for (const word of batch.words) {
|
|
348
367
|
this.count_word(word);
|
|
349
|
-
|
|
368
|
+
try {
|
|
369
|
+
await word.execute(this);
|
|
370
|
+
}
|
|
371
|
+
catch (e) {
|
|
372
|
+
// Don't wrap IntentionalStopError - it's a control-flow mechanism for debugging
|
|
373
|
+
if (e instanceof errors_js_1.IntentionalStopError) {
|
|
374
|
+
throw e;
|
|
375
|
+
}
|
|
376
|
+
// Don't wrap ForthicError subclasses - they already have location context
|
|
377
|
+
if (e instanceof errors_js_1.ForthicError) {
|
|
378
|
+
throw e;
|
|
379
|
+
}
|
|
380
|
+
// Wrap generic errors in WordExecutionError to add location context
|
|
381
|
+
if (e instanceof Error) {
|
|
382
|
+
throw new errors_js_1.WordExecutionError(e.message, e, this.get_tokenizer()?.get_token_location(), word.get_location() || undefined);
|
|
383
|
+
}
|
|
384
|
+
throw e;
|
|
385
|
+
}
|
|
350
386
|
}
|
|
351
387
|
}
|
|
352
388
|
else {
|
|
@@ -494,10 +530,10 @@ class Interpreter {
|
|
|
494
530
|
}
|
|
495
531
|
/**
|
|
496
532
|
* Register a custom literal handler
|
|
497
|
-
*
|
|
533
|
+
* New handlers are added first so they can override existing ones
|
|
498
534
|
*/
|
|
499
535
|
register_literal_handler(handler) {
|
|
500
|
-
this.literal_handlers.
|
|
536
|
+
this.literal_handlers.unshift(handler);
|
|
501
537
|
}
|
|
502
538
|
/**
|
|
503
539
|
* Unregister a literal handler
|