@manifesto-ai/compiler 1.6.2 → 1.8.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 +67 -18
- package/dist/chunk-BH25NHMN.js +74 -0
- package/dist/chunk-BH25NHMN.js.map +1 -0
- package/dist/chunk-D62NIFP4.js +33 -0
- package/dist/chunk-D62NIFP4.js.map +1 -0
- package/dist/chunk-MKLDAZ2Z.js +6920 -0
- package/dist/chunk-MKLDAZ2Z.js.map +1 -0
- package/dist/esbuild.d.ts +8 -0
- package/dist/esbuild.js +14 -0
- package/dist/esbuild.js.map +1 -0
- package/dist/index.d.ts +2810 -11
- package/dist/index.js +2425 -43
- package/dist/index.js.map +1 -1
- package/dist/node-loader.d.ts +18 -0
- package/dist/node-loader.js +47 -0
- package/dist/node-loader.js.map +1 -0
- package/dist/rollup.d.ts +8 -0
- package/dist/rollup.js +14 -0
- package/dist/rollup.js.map +1 -0
- package/dist/rspack.d.ts +7 -0
- package/dist/rspack.js +14 -0
- package/dist/rspack.js.map +1 -0
- package/dist/unplugin-6wnvFiEo.d.ts +17 -0
- package/dist/vite.d.ts +8 -17
- package/dist/vite.js +13 -33
- package/dist/vite.js.map +1 -1
- package/dist/webpack.d.ts +8 -0
- package/dist/webpack.js +14 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +40 -22
- package/dist/analyzer/index.d.ts +0 -6
- package/dist/analyzer/index.d.ts.map +0 -1
- package/dist/analyzer/index.js +0 -6
- package/dist/analyzer/index.js.map +0 -1
- package/dist/analyzer/scope.d.ts +0 -77
- package/dist/analyzer/scope.d.ts.map +0 -1
- package/dist/analyzer/scope.js +0 -296
- package/dist/analyzer/scope.js.map +0 -1
- package/dist/analyzer/validator.d.ts +0 -60
- package/dist/analyzer/validator.d.ts.map +0 -1
- package/dist/analyzer/validator.js +0 -439
- package/dist/analyzer/validator.js.map +0 -1
- package/dist/api/compile-mel-patch-collector.d.ts +0 -32
- package/dist/api/compile-mel-patch-collector.d.ts.map +0 -1
- package/dist/api/compile-mel-patch-collector.js +0 -425
- package/dist/api/compile-mel-patch-collector.js.map +0 -1
- package/dist/api/compile-mel-patch-expr.d.ts +0 -9
- package/dist/api/compile-mel-patch-expr.d.ts.map +0 -1
- package/dist/api/compile-mel-patch-expr.js +0 -179
- package/dist/api/compile-mel-patch-expr.js.map +0 -1
- package/dist/api/compile-mel-patch-location.d.ts +0 -10
- package/dist/api/compile-mel-patch-location.d.ts.map +0 -1
- package/dist/api/compile-mel-patch-location.js +0 -48
- package/dist/api/compile-mel-patch-location.js.map +0 -1
- package/dist/api/compile-mel-patch.d.ts +0 -6
- package/dist/api/compile-mel-patch.d.ts.map +0 -1
- package/dist/api/compile-mel-patch.js +0 -244
- package/dist/api/compile-mel-patch.js.map +0 -1
- package/dist/api/compile-mel.d.ts +0 -126
- package/dist/api/compile-mel.d.ts.map +0 -1
- package/dist/api/compile-mel.js +0 -114
- package/dist/api/compile-mel.js.map +0 -1
- package/dist/api/index.d.ts +0 -10
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -9
- package/dist/api/index.js.map +0 -1
- package/dist/diagnostics/codes.d.ts +0 -25
- package/dist/diagnostics/codes.d.ts.map +0 -1
- package/dist/diagnostics/codes.js +0 -154
- package/dist/diagnostics/codes.js.map +0 -1
- package/dist/diagnostics/index.d.ts +0 -6
- package/dist/diagnostics/index.d.ts.map +0 -1
- package/dist/diagnostics/index.js +0 -6
- package/dist/diagnostics/index.js.map +0 -1
- package/dist/diagnostics/types.d.ts +0 -67
- package/dist/diagnostics/types.d.ts.map +0 -1
- package/dist/diagnostics/types.js +0 -58
- package/dist/diagnostics/types.js.map +0 -1
- package/dist/evaluation/context.d.ts +0 -91
- package/dist/evaluation/context.d.ts.map +0 -1
- package/dist/evaluation/context.js +0 -53
- package/dist/evaluation/context.js.map +0 -1
- package/dist/evaluation/evaluate-expr.d.ts +0 -24
- package/dist/evaluation/evaluate-expr.d.ts.map +0 -1
- package/dist/evaluation/evaluate-expr.js +0 -577
- package/dist/evaluation/evaluate-expr.js.map +0 -1
- package/dist/evaluation/evaluate-patch.d.ts +0 -123
- package/dist/evaluation/evaluate-patch.d.ts.map +0 -1
- package/dist/evaluation/evaluate-patch.js +0 -202
- package/dist/evaluation/evaluate-patch.js.map +0 -1
- package/dist/evaluation/evaluate-runtime-patch.d.ts +0 -86
- package/dist/evaluation/evaluate-runtime-patch.d.ts.map +0 -1
- package/dist/evaluation/evaluate-runtime-patch.js +0 -185
- package/dist/evaluation/evaluate-runtime-patch.js.map +0 -1
- package/dist/evaluation/index.d.ts +0 -15
- package/dist/evaluation/index.d.ts.map +0 -1
- package/dist/evaluation/index.js +0 -13
- package/dist/evaluation/index.js.map +0 -1
- package/dist/generator/index.d.ts +0 -7
- package/dist/generator/index.d.ts.map +0 -1
- package/dist/generator/index.js +0 -7
- package/dist/generator/index.js.map +0 -1
- package/dist/generator/ir.d.ts +0 -348
- package/dist/generator/ir.d.ts.map +0 -1
- package/dist/generator/ir.js +0 -715
- package/dist/generator/ir.js.map +0 -1
- package/dist/generator/lowering.d.ts +0 -11
- package/dist/generator/lowering.d.ts.map +0 -1
- package/dist/generator/lowering.js +0 -369
- package/dist/generator/lowering.js.map +0 -1
- package/dist/generator/normalizer.d.ts +0 -16
- package/dist/generator/normalizer.d.ts.map +0 -1
- package/dist/generator/normalizer.js +0 -181
- package/dist/generator/normalizer.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lexer/index.d.ts +0 -7
- package/dist/lexer/index.d.ts.map +0 -1
- package/dist/lexer/index.js +0 -7
- package/dist/lexer/index.js.map +0 -1
- package/dist/lexer/lexer.d.ts +0 -59
- package/dist/lexer/lexer.d.ts.map +0 -1
- package/dist/lexer/lexer.js +0 -433
- package/dist/lexer/lexer.js.map +0 -1
- package/dist/lexer/source-location.d.ts +0 -41
- package/dist/lexer/source-location.d.ts.map +0 -1
- package/dist/lexer/source-location.js +0 -33
- package/dist/lexer/source-location.js.map +0 -1
- package/dist/lexer/tokens.d.ts +0 -47
- package/dist/lexer/tokens.d.ts.map +0 -1
- package/dist/lexer/tokens.js +0 -73
- package/dist/lexer/tokens.js.map +0 -1
- package/dist/loader.d.ts +0 -23
- package/dist/loader.d.ts.map +0 -1
- package/dist/loader.js +0 -62
- package/dist/loader.js.map +0 -1
- package/dist/lowering/context.d.ts +0 -96
- package/dist/lowering/context.d.ts.map +0 -1
- package/dist/lowering/context.js +0 -42
- package/dist/lowering/context.js.map +0 -1
- package/dist/lowering/errors.d.ts +0 -84
- package/dist/lowering/errors.d.ts.map +0 -1
- package/dist/lowering/errors.js +0 -81
- package/dist/lowering/errors.js.map +0 -1
- package/dist/lowering/index.d.ts +0 -20
- package/dist/lowering/index.d.ts.map +0 -1
- package/dist/lowering/index.js +0 -13
- package/dist/lowering/index.js.map +0 -1
- package/dist/lowering/lower-expr.d.ts +0 -76
- package/dist/lowering/lower-expr.d.ts.map +0 -1
- package/dist/lowering/lower-expr.js +0 -366
- package/dist/lowering/lower-expr.js.map +0 -1
- package/dist/lowering/lower-patch.d.ts +0 -231
- package/dist/lowering/lower-patch.d.ts.map +0 -1
- package/dist/lowering/lower-patch.js +0 -146
- package/dist/lowering/lower-patch.js.map +0 -1
- package/dist/lowering/lower-runtime-patch.d.ts +0 -100
- package/dist/lowering/lower-runtime-patch.d.ts.map +0 -1
- package/dist/lowering/lower-runtime-patch.js +0 -49
- package/dist/lowering/lower-runtime-patch.js.map +0 -1
- package/dist/mel-module.d.ts +0 -13
- package/dist/mel-module.d.ts.map +0 -1
- package/dist/mel-module.js +0 -33
- package/dist/mel-module.js.map +0 -1
- package/dist/parser/ast.d.ts +0 -344
- package/dist/parser/ast.d.ts.map +0 -1
- package/dist/parser/ast.js +0 -24
- package/dist/parser/ast.js.map +0 -1
- package/dist/parser/index.d.ts +0 -7
- package/dist/parser/index.d.ts.map +0 -1
- package/dist/parser/index.js +0 -7
- package/dist/parser/index.js.map +0 -1
- package/dist/parser/parser.d.ts +0 -92
- package/dist/parser/parser.d.ts.map +0 -1
- package/dist/parser/parser.js +0 -892
- package/dist/parser/parser.js.map +0 -1
- package/dist/parser/precedence.d.ts +0 -44
- package/dist/parser/precedence.d.ts.map +0 -1
- package/dist/parser/precedence.js +0 -69
- package/dist/parser/precedence.js.map +0 -1
- package/dist/renderer/expr-node.d.ts +0 -172
- package/dist/renderer/expr-node.d.ts.map +0 -1
- package/dist/renderer/expr-node.js +0 -218
- package/dist/renderer/expr-node.js.map +0 -1
- package/dist/renderer/fragment.d.ts +0 -84
- package/dist/renderer/fragment.d.ts.map +0 -1
- package/dist/renderer/fragment.js +0 -172
- package/dist/renderer/fragment.js.map +0 -1
- package/dist/renderer/index.d.ts +0 -23
- package/dist/renderer/index.d.ts.map +0 -1
- package/dist/renderer/index.js +0 -27
- package/dist/renderer/index.js.map +0 -1
- package/dist/renderer/patch-op.d.ts +0 -82
- package/dist/renderer/patch-op.d.ts.map +0 -1
- package/dist/renderer/patch-op.js +0 -204
- package/dist/renderer/patch-op.js.map +0 -1
- package/dist/renderer/type-expr.d.ts +0 -61
- package/dist/renderer/type-expr.d.ts.map +0 -1
- package/dist/renderer/type-expr.js +0 -131
- package/dist/renderer/type-expr.js.map +0 -1
- package/dist/vite.d.ts.map +0 -1
- package/loader.cjs +0 -22
package/dist/generator/ir.js
DELETED
|
@@ -1,715 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IR Generator - Transforms MEL AST to Core DomainSchema
|
|
3
|
-
* Based on MEL SPEC v0.3.3 Section 5
|
|
4
|
-
*/
|
|
5
|
-
import { normalizeExpr, normalizeFunctionCall } from "./normalizer.js";
|
|
6
|
-
import { hashSchemaSync, sha256Sync } from "@manifesto-ai/core";
|
|
7
|
-
function createContext(domainName) {
|
|
8
|
-
return {
|
|
9
|
-
domainName,
|
|
10
|
-
stateFields: new Set(),
|
|
11
|
-
computedFields: new Set(),
|
|
12
|
-
actionParams: new Map(),
|
|
13
|
-
onceIntentCounters: new Map(),
|
|
14
|
-
currentAction: null,
|
|
15
|
-
diagnostics: [],
|
|
16
|
-
typeDefs: new Map(),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
// ============ Main Generator ============
|
|
20
|
-
/**
|
|
21
|
-
* Generate Core DomainSchema from MEL AST
|
|
22
|
-
*/
|
|
23
|
-
export function generate(program) {
|
|
24
|
-
const ctx = createContext(program.domain.name);
|
|
25
|
-
// First pass: collect state and computed field names
|
|
26
|
-
collectFieldNames(program.domain, ctx);
|
|
27
|
-
// v0.3.3: Generate types first
|
|
28
|
-
const types = generateTypes(program.domain, ctx);
|
|
29
|
-
// Generate schema parts
|
|
30
|
-
const state = generateState(program.domain, ctx);
|
|
31
|
-
const computed = generateComputed(program.domain, ctx);
|
|
32
|
-
const actions = generateActions(program.domain, ctx);
|
|
33
|
-
if (ctx.diagnostics.some(d => d.severity === "error")) {
|
|
34
|
-
return {
|
|
35
|
-
schema: null,
|
|
36
|
-
diagnostics: ctx.diagnostics,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
// Create schema
|
|
40
|
-
const schemaWithoutHash = {
|
|
41
|
-
id: `mel:${program.domain.name.toLowerCase()}`,
|
|
42
|
-
version: "1.0.0",
|
|
43
|
-
types,
|
|
44
|
-
state,
|
|
45
|
-
computed,
|
|
46
|
-
actions,
|
|
47
|
-
meta: {
|
|
48
|
-
name: program.domain.name,
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
// Compute hash
|
|
52
|
-
const hash = computeHash(schemaWithoutHash);
|
|
53
|
-
const schema = {
|
|
54
|
-
...schemaWithoutHash,
|
|
55
|
-
hash,
|
|
56
|
-
};
|
|
57
|
-
return {
|
|
58
|
-
schema,
|
|
59
|
-
diagnostics: ctx.diagnostics,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// ============ Field Collection ============
|
|
63
|
-
function collectFieldNames(domain, ctx) {
|
|
64
|
-
// Collect type declarations first
|
|
65
|
-
for (const typeDecl of domain.types) {
|
|
66
|
-
ctx.typeDefs.set(typeDecl.name, typeDecl);
|
|
67
|
-
}
|
|
68
|
-
for (const member of domain.members) {
|
|
69
|
-
if (member.kind === "state") {
|
|
70
|
-
for (const field of member.fields) {
|
|
71
|
-
ctx.stateFields.add(field.name);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
else if (member.kind === "computed") {
|
|
75
|
-
ctx.computedFields.add(member.name);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// ============ Type Generation (v0.3.3) ============
|
|
80
|
-
function generateTypes(domain, _ctx) {
|
|
81
|
-
const types = {};
|
|
82
|
-
for (const typeDecl of domain.types) {
|
|
83
|
-
types[typeDecl.name] = {
|
|
84
|
-
name: typeDecl.name,
|
|
85
|
-
definition: typeExprToDefinition(typeDecl.typeExpr),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
return types;
|
|
89
|
-
}
|
|
90
|
-
function typeExprToDefinition(typeExpr) {
|
|
91
|
-
switch (typeExpr.kind) {
|
|
92
|
-
case "simpleType":
|
|
93
|
-
// Primitive types vs type references
|
|
94
|
-
if (["string", "number", "boolean", "null"].includes(typeExpr.name)) {
|
|
95
|
-
return { kind: "primitive", type: typeExpr.name };
|
|
96
|
-
}
|
|
97
|
-
// User-defined type reference
|
|
98
|
-
return { kind: "ref", name: typeExpr.name };
|
|
99
|
-
case "arrayType":
|
|
100
|
-
return {
|
|
101
|
-
kind: "array",
|
|
102
|
-
element: typeExprToDefinition(typeExpr.elementType),
|
|
103
|
-
};
|
|
104
|
-
case "recordType":
|
|
105
|
-
return {
|
|
106
|
-
kind: "record",
|
|
107
|
-
key: typeExprToDefinition(typeExpr.keyType),
|
|
108
|
-
value: typeExprToDefinition(typeExpr.valueType),
|
|
109
|
-
};
|
|
110
|
-
case "objectType":
|
|
111
|
-
const fields = {};
|
|
112
|
-
for (const field of typeExpr.fields) {
|
|
113
|
-
fields[field.name] = {
|
|
114
|
-
type: typeExprToDefinition(field.typeExpr),
|
|
115
|
-
optional: field.optional,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
return { kind: "object", fields };
|
|
119
|
-
case "unionType":
|
|
120
|
-
return {
|
|
121
|
-
kind: "union",
|
|
122
|
-
types: typeExpr.types.map(typeExprToDefinition),
|
|
123
|
-
};
|
|
124
|
-
case "literalType":
|
|
125
|
-
return { kind: "literal", value: typeExpr.value };
|
|
126
|
-
default:
|
|
127
|
-
// Exhaustive check
|
|
128
|
-
const _exhaustive = typeExpr;
|
|
129
|
-
throw new Error(`Unknown type expression kind: ${typeExpr.kind}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
// ============ State Generation ============
|
|
133
|
-
function generateState(domain, ctx) {
|
|
134
|
-
const fields = {};
|
|
135
|
-
for (const member of domain.members) {
|
|
136
|
-
if (member.kind === "state") {
|
|
137
|
-
for (const field of member.fields) {
|
|
138
|
-
fields[field.name] = generateFieldSpec(field, ctx);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return { fields };
|
|
143
|
-
}
|
|
144
|
-
function generateFieldSpec(field, ctx) {
|
|
145
|
-
const spec = typeExprToFieldSpec(field.typeExpr, ctx);
|
|
146
|
-
const defaultValue = field.initializer
|
|
147
|
-
? evaluateInitializer(field.initializer, ctx)
|
|
148
|
-
: undefined;
|
|
149
|
-
return {
|
|
150
|
-
...spec,
|
|
151
|
-
required: true,
|
|
152
|
-
default: defaultValue,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Convert TypeExprNode to complete FieldSpec (including nested fields)
|
|
157
|
-
* This is the full conversion that includes `fields` for object types
|
|
158
|
-
*/
|
|
159
|
-
function typeExprToFieldSpec(typeExpr, ctx) {
|
|
160
|
-
switch (typeExpr.kind) {
|
|
161
|
-
case "simpleType":
|
|
162
|
-
switch (typeExpr.name) {
|
|
163
|
-
case "string": return { type: "string", required: true };
|
|
164
|
-
case "number": return { type: "number", required: true };
|
|
165
|
-
case "boolean": return { type: "boolean", required: true };
|
|
166
|
-
case "null": return { type: "null", required: true };
|
|
167
|
-
default: {
|
|
168
|
-
// User-defined type - look up and expand
|
|
169
|
-
const typeDef = ctx.typeDefs.get(typeExpr.name);
|
|
170
|
-
if (typeDef) {
|
|
171
|
-
return typeExprToFieldSpec(typeDef.typeExpr, ctx);
|
|
172
|
-
}
|
|
173
|
-
// Unknown type - treat as opaque object
|
|
174
|
-
return { type: "object", required: true };
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
case "unionType": {
|
|
178
|
-
// Check if it's a literal union (enum)
|
|
179
|
-
const literals = [];
|
|
180
|
-
let isLiteralUnion = true;
|
|
181
|
-
let hasNull = false;
|
|
182
|
-
for (const t of typeExpr.types) {
|
|
183
|
-
if (t.kind === "literalType") {
|
|
184
|
-
if (t.value === null) {
|
|
185
|
-
hasNull = true;
|
|
186
|
-
}
|
|
187
|
-
literals.push(t.value);
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
if (t.kind === "simpleType" && t.name === "null") {
|
|
191
|
-
hasNull = true;
|
|
192
|
-
literals.push(null);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
isLiteralUnion = false;
|
|
196
|
-
}
|
|
197
|
-
if (isLiteralUnion && literals.length > 0) {
|
|
198
|
-
return { type: { enum: literals }, required: !hasNull };
|
|
199
|
-
}
|
|
200
|
-
// Nullable type: T | null -> get spec of T
|
|
201
|
-
if (hasNull) {
|
|
202
|
-
for (const t of typeExpr.types) {
|
|
203
|
-
if (t.kind !== "simpleType" || t.name !== "null") {
|
|
204
|
-
const innerSpec = typeExprToFieldSpec(t, ctx);
|
|
205
|
-
return { ...innerSpec, required: false };
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
// Mixed union - default to first non-null type
|
|
210
|
-
for (const t of typeExpr.types) {
|
|
211
|
-
if (t.kind !== "simpleType" || t.name !== "null") {
|
|
212
|
-
return typeExprToFieldSpec(t, ctx);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return { type: "null", required: true };
|
|
216
|
-
}
|
|
217
|
-
case "arrayType": {
|
|
218
|
-
const itemSpec = typeExprToFieldSpec(typeExpr.elementType, ctx);
|
|
219
|
-
return {
|
|
220
|
-
type: "array",
|
|
221
|
-
required: true,
|
|
222
|
-
items: itemSpec,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
case "recordType":
|
|
226
|
-
return { type: "object", required: true };
|
|
227
|
-
case "literalType":
|
|
228
|
-
// Single literal type - use its base type
|
|
229
|
-
if (typeof typeExpr.value === "string")
|
|
230
|
-
return { type: "string", required: true };
|
|
231
|
-
if (typeof typeExpr.value === "number")
|
|
232
|
-
return { type: "number", required: true };
|
|
233
|
-
if (typeof typeExpr.value === "boolean")
|
|
234
|
-
return { type: "boolean", required: true };
|
|
235
|
-
return { type: "null", required: true };
|
|
236
|
-
case "objectType": {
|
|
237
|
-
// v0.3.3: Inline object type - expand to fields
|
|
238
|
-
const objectFields = {};
|
|
239
|
-
for (const field of typeExpr.fields) {
|
|
240
|
-
const fieldSpec = typeExprToFieldSpec(field.typeExpr, ctx);
|
|
241
|
-
objectFields[field.name] = {
|
|
242
|
-
...fieldSpec,
|
|
243
|
-
required: !field.optional,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
return {
|
|
247
|
-
type: "object",
|
|
248
|
-
required: true,
|
|
249
|
-
fields: objectFields,
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Simple type extraction (for backward compat with action input specs)
|
|
256
|
-
*/
|
|
257
|
-
function typeExprToFieldType(typeExpr, ctx) {
|
|
258
|
-
const spec = typeExprToFieldSpec(typeExpr, ctx);
|
|
259
|
-
return spec.type;
|
|
260
|
-
}
|
|
261
|
-
function evaluateInitializer(expr, ctx) {
|
|
262
|
-
// Only evaluate literals and simple expressions for default values
|
|
263
|
-
switch (expr.kind) {
|
|
264
|
-
case "literal":
|
|
265
|
-
return expr.value;
|
|
266
|
-
case "arrayLiteral":
|
|
267
|
-
return expr.elements.map(e => evaluateInitializer(e, ctx));
|
|
268
|
-
case "objectLiteral": {
|
|
269
|
-
const obj = {};
|
|
270
|
-
for (const prop of expr.properties) {
|
|
271
|
-
obj[prop.key] = evaluateInitializer(prop.value, ctx);
|
|
272
|
-
}
|
|
273
|
-
return obj;
|
|
274
|
-
}
|
|
275
|
-
default:
|
|
276
|
-
// Complex expressions can't be evaluated statically
|
|
277
|
-
return undefined;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
// ============ Computed Generation ============
|
|
281
|
-
function generateComputed(domain, ctx) {
|
|
282
|
-
const fields = {};
|
|
283
|
-
for (const member of domain.members) {
|
|
284
|
-
if (member.kind === "computed") {
|
|
285
|
-
const expr = generateExpr(member.expression, ctx);
|
|
286
|
-
const deps = extractDeps(expr);
|
|
287
|
-
fields[`computed.${member.name}`] = {
|
|
288
|
-
deps,
|
|
289
|
-
expr,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return { fields };
|
|
294
|
-
}
|
|
295
|
-
function extractDeps(expr) {
|
|
296
|
-
const deps = new Set();
|
|
297
|
-
function visit(node) {
|
|
298
|
-
if (node.kind === "get") {
|
|
299
|
-
deps.add(node.path);
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
// Visit all nested expressions
|
|
303
|
-
for (const value of Object.values(node)) {
|
|
304
|
-
if (typeof value === "object" && value !== null) {
|
|
305
|
-
if (Array.isArray(value)) {
|
|
306
|
-
for (const item of value) {
|
|
307
|
-
if (typeof item === "object" && item !== null && "kind" in item) {
|
|
308
|
-
visit(item);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
else if ("kind" in value) {
|
|
313
|
-
visit(value);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
visit(expr);
|
|
320
|
-
return Array.from(deps);
|
|
321
|
-
}
|
|
322
|
-
// ============ Action Generation ============
|
|
323
|
-
function generateActions(domain, ctx) {
|
|
324
|
-
const actions = {};
|
|
325
|
-
for (const member of domain.members) {
|
|
326
|
-
if (member.kind === "action") {
|
|
327
|
-
ctx.currentAction = member.name;
|
|
328
|
-
ctx.onceIntentCounters.set(member.name, 0);
|
|
329
|
-
// Collect params
|
|
330
|
-
const params = new Set();
|
|
331
|
-
for (const param of member.params) {
|
|
332
|
-
params.add(param.name);
|
|
333
|
-
}
|
|
334
|
-
ctx.actionParams.set(member.name, params);
|
|
335
|
-
const flow = generateFlow(member.body, ctx);
|
|
336
|
-
// Generate input spec if there are params
|
|
337
|
-
let input;
|
|
338
|
-
if (member.params.length > 0) {
|
|
339
|
-
const inputFields = {};
|
|
340
|
-
for (const param of member.params) {
|
|
341
|
-
const fieldSpec = typeExprToFieldSpec(param.typeExpr, ctx);
|
|
342
|
-
const inputField = {
|
|
343
|
-
type: fieldSpec.type,
|
|
344
|
-
required: fieldSpec.required ?? true,
|
|
345
|
-
};
|
|
346
|
-
if (fieldSpec.type === "object" && fieldSpec.fields) {
|
|
347
|
-
inputField.fields = fieldSpec.fields;
|
|
348
|
-
}
|
|
349
|
-
if (fieldSpec.type === "array" && fieldSpec.items) {
|
|
350
|
-
inputField.items = fieldSpec.items;
|
|
351
|
-
}
|
|
352
|
-
inputFields[param.name] = inputField;
|
|
353
|
-
}
|
|
354
|
-
input = {
|
|
355
|
-
type: "object",
|
|
356
|
-
required: true,
|
|
357
|
-
fields: inputFields,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
// v0.3.2: Generate available condition if present
|
|
361
|
-
let available;
|
|
362
|
-
if (member.available) {
|
|
363
|
-
available = generateExpr(member.available, ctx);
|
|
364
|
-
}
|
|
365
|
-
actions[member.name] = {
|
|
366
|
-
flow,
|
|
367
|
-
input,
|
|
368
|
-
available,
|
|
369
|
-
};
|
|
370
|
-
ctx.currentAction = null;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
return actions;
|
|
374
|
-
}
|
|
375
|
-
function generateFlow(stmts, ctx) {
|
|
376
|
-
if (stmts.length === 0) {
|
|
377
|
-
return { kind: "seq", steps: [] };
|
|
378
|
-
}
|
|
379
|
-
if (stmts.length === 1) {
|
|
380
|
-
return generateStmt(stmts[0], ctx);
|
|
381
|
-
}
|
|
382
|
-
return {
|
|
383
|
-
kind: "seq",
|
|
384
|
-
steps: stmts.map(s => generateStmt(s, ctx)),
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
function generateStmt(stmt, ctx) {
|
|
388
|
-
switch (stmt.kind) {
|
|
389
|
-
case "when":
|
|
390
|
-
return generateWhen(stmt, ctx);
|
|
391
|
-
case "once":
|
|
392
|
-
return generateOnce(stmt, ctx);
|
|
393
|
-
case "onceIntent":
|
|
394
|
-
return generateOnceIntent(stmt, ctx);
|
|
395
|
-
case "patch":
|
|
396
|
-
return generatePatch(stmt, ctx);
|
|
397
|
-
case "effect":
|
|
398
|
-
return generateEffect(stmt, ctx);
|
|
399
|
-
case "fail":
|
|
400
|
-
return generateFail(stmt, ctx);
|
|
401
|
-
case "stop":
|
|
402
|
-
return generateStop(stmt, ctx);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
function generateWhen(stmt, ctx) {
|
|
406
|
-
const cond = generateExpr(stmt.condition, ctx);
|
|
407
|
-
const thenFlow = generateFlow(stmt.body, ctx);
|
|
408
|
-
return {
|
|
409
|
-
kind: "if",
|
|
410
|
-
cond,
|
|
411
|
-
then: thenFlow,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
function generateOnce(stmt, ctx) {
|
|
415
|
-
// Desugar once(marker) { ... } to:
|
|
416
|
-
// when neq(marker, $meta.intentId) { patch marker = $meta.intentId; ... }
|
|
417
|
-
// Note: Core accesses $meta intent values via meta.*
|
|
418
|
-
const markerPath = generatePath(stmt.marker, ctx);
|
|
419
|
-
const intentIdExpr = { kind: "get", path: "meta.intentId" };
|
|
420
|
-
// Condition: marker != $meta.intentId
|
|
421
|
-
let cond = {
|
|
422
|
-
kind: "neq",
|
|
423
|
-
left: { kind: "get", path: markerPath },
|
|
424
|
-
right: intentIdExpr,
|
|
425
|
-
};
|
|
426
|
-
// Add extra condition if present
|
|
427
|
-
if (stmt.condition) {
|
|
428
|
-
const extraCond = generateExpr(stmt.condition, ctx);
|
|
429
|
-
cond = {
|
|
430
|
-
kind: "and",
|
|
431
|
-
args: [cond, extraCond],
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
// Body: patch marker = $meta.intentId, then rest
|
|
435
|
-
const markerPatch = {
|
|
436
|
-
kind: "patch",
|
|
437
|
-
op: "set",
|
|
438
|
-
path: markerPath,
|
|
439
|
-
value: intentIdExpr,
|
|
440
|
-
};
|
|
441
|
-
const bodySteps = stmt.body.map(s => generateStmt(s, ctx));
|
|
442
|
-
return {
|
|
443
|
-
kind: "if",
|
|
444
|
-
cond,
|
|
445
|
-
then: {
|
|
446
|
-
kind: "seq",
|
|
447
|
-
steps: [markerPatch, ...bodySteps],
|
|
448
|
-
},
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
function generateOnceIntent(stmt, ctx) {
|
|
452
|
-
const actionName = ctx.currentAction ?? "unknown";
|
|
453
|
-
const nextIndex = ctx.onceIntentCounters.get(actionName) ?? 0;
|
|
454
|
-
ctx.onceIntentCounters.set(actionName, nextIndex + 1);
|
|
455
|
-
const guardId = sha256Sync(`${actionName}:${nextIndex}:intent`);
|
|
456
|
-
const guardPath = `$mel.guards.intent.${guardId}`;
|
|
457
|
-
const intentIdExpr = { kind: "get", path: "meta.intentId" };
|
|
458
|
-
let cond = {
|
|
459
|
-
kind: "neq",
|
|
460
|
-
left: { kind: "get", path: guardPath },
|
|
461
|
-
right: intentIdExpr,
|
|
462
|
-
};
|
|
463
|
-
if (stmt.condition) {
|
|
464
|
-
const extraCond = generateExpr(stmt.condition, ctx);
|
|
465
|
-
cond = {
|
|
466
|
-
kind: "and",
|
|
467
|
-
args: [cond, extraCond],
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
// Guard write: semantic target is guardPath, lowered as map-level merge.
|
|
471
|
-
const markerPatch = {
|
|
472
|
-
kind: "patch",
|
|
473
|
-
op: "merge",
|
|
474
|
-
path: "$mel.guards.intent",
|
|
475
|
-
value: {
|
|
476
|
-
kind: "object",
|
|
477
|
-
fields: { [guardId]: intentIdExpr },
|
|
478
|
-
},
|
|
479
|
-
};
|
|
480
|
-
const bodySteps = stmt.body.map(s => generateStmt(s, ctx));
|
|
481
|
-
return {
|
|
482
|
-
kind: "if",
|
|
483
|
-
cond,
|
|
484
|
-
then: {
|
|
485
|
-
kind: "seq",
|
|
486
|
-
steps: [markerPatch, ...bodySteps],
|
|
487
|
-
},
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
function generatePatch(stmt, ctx) {
|
|
491
|
-
const path = generatePath(stmt.path, ctx);
|
|
492
|
-
const result = {
|
|
493
|
-
kind: "patch",
|
|
494
|
-
op: stmt.op,
|
|
495
|
-
path,
|
|
496
|
-
};
|
|
497
|
-
if (stmt.value) {
|
|
498
|
-
result.value = generateExpr(stmt.value, ctx);
|
|
499
|
-
}
|
|
500
|
-
return result;
|
|
501
|
-
}
|
|
502
|
-
function generateEffect(stmt, ctx) {
|
|
503
|
-
const params = {};
|
|
504
|
-
for (const arg of stmt.args) {
|
|
505
|
-
if (arg.isPath) {
|
|
506
|
-
// Path arguments like into:, pass:, fail:
|
|
507
|
-
params[arg.name] = { kind: "lit", value: generatePath(arg.value, ctx) };
|
|
508
|
-
}
|
|
509
|
-
else {
|
|
510
|
-
params[arg.name] = generateExpr(arg.value, ctx);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
return {
|
|
514
|
-
kind: "effect",
|
|
515
|
-
type: stmt.effectType,
|
|
516
|
-
params,
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* v0.3.2: Generate fail statement
|
|
521
|
-
* fail "CODE" with expr → { kind: "fail", code, message? }
|
|
522
|
-
*/
|
|
523
|
-
function generateFail(stmt, ctx) {
|
|
524
|
-
const result = {
|
|
525
|
-
kind: "fail",
|
|
526
|
-
code: stmt.code,
|
|
527
|
-
};
|
|
528
|
-
if (stmt.message) {
|
|
529
|
-
result.message = generateExpr(stmt.message, ctx);
|
|
530
|
-
}
|
|
531
|
-
return result;
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* v0.3.2: Generate stop statement
|
|
535
|
-
* stop "reason" → { kind: "halt", reason }
|
|
536
|
-
*/
|
|
537
|
-
function generateStop(stmt, ctx) {
|
|
538
|
-
return {
|
|
539
|
-
kind: "halt",
|
|
540
|
-
reason: stmt.reason,
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
// ============ Path Generation ============
|
|
544
|
-
function escapePathSegment(segment) {
|
|
545
|
-
return segment.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
|
|
546
|
-
}
|
|
547
|
-
function joinPathPreserveEmptySegments(...segments) {
|
|
548
|
-
return segments.map(escapePathSegment).join(".");
|
|
549
|
-
}
|
|
550
|
-
function generatePath(path, ctx) {
|
|
551
|
-
const segments = [];
|
|
552
|
-
for (const segment of path.segments) {
|
|
553
|
-
if (segment.kind === "propertySegment") {
|
|
554
|
-
segments.push(segment.name);
|
|
555
|
-
}
|
|
556
|
-
else {
|
|
557
|
-
// Index segment - for now, stringify the index
|
|
558
|
-
// In reality, this would need runtime evaluation
|
|
559
|
-
const indexExpr = generateExpr(segment.index, ctx);
|
|
560
|
-
if (indexExpr.kind === "lit") {
|
|
561
|
-
segments.push(String(indexExpr.value));
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
// Dynamic index - use placeholder
|
|
565
|
-
segments.push("*");
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
// Determine prefix based on first segment
|
|
570
|
-
const first = segments[0];
|
|
571
|
-
if (ctx.stateFields.has(first)) {
|
|
572
|
-
// Core expects state paths without prefix (e.g., "count" not "data.count")
|
|
573
|
-
return joinPathPreserveEmptySegments(...segments);
|
|
574
|
-
}
|
|
575
|
-
if (ctx.computedFields.has(first)) {
|
|
576
|
-
return `computed.${joinPathPreserveEmptySegments(...segments)}`;
|
|
577
|
-
}
|
|
578
|
-
if (ctx.currentAction && ctx.actionParams.get(ctx.currentAction)?.has(first)) {
|
|
579
|
-
return `input.${joinPathPreserveEmptySegments(...segments)}`;
|
|
580
|
-
}
|
|
581
|
-
// Default to plain path (state-like)
|
|
582
|
-
return joinPathPreserveEmptySegments(...segments);
|
|
583
|
-
}
|
|
584
|
-
// ============ Expression Generation ============
|
|
585
|
-
function generateExpr(expr, ctx) {
|
|
586
|
-
switch (expr.kind) {
|
|
587
|
-
case "literal":
|
|
588
|
-
return { kind: "lit", value: expr.value };
|
|
589
|
-
case "identifier":
|
|
590
|
-
return generateIdentifier(expr.name, ctx);
|
|
591
|
-
case "systemIdent":
|
|
592
|
-
return generateSystemIdent(expr.path, ctx);
|
|
593
|
-
case "iterationVar":
|
|
594
|
-
// v0.3.2: $item only (reduce pattern deprecated, $acc removed)
|
|
595
|
-
// $item is used in filter/map expressions
|
|
596
|
-
return { kind: "get", path: `$${expr.name}` };
|
|
597
|
-
case "propertyAccess":
|
|
598
|
-
return generatePropertyAccess(expr, ctx);
|
|
599
|
-
case "indexAccess":
|
|
600
|
-
return {
|
|
601
|
-
kind: "at",
|
|
602
|
-
array: generateExpr(expr.object, ctx),
|
|
603
|
-
index: generateExpr(expr.index, ctx),
|
|
604
|
-
};
|
|
605
|
-
case "functionCall":
|
|
606
|
-
return normalizeFunctionCall(expr.name, expr.args.map(a => generateExpr(a, ctx)));
|
|
607
|
-
case "binary":
|
|
608
|
-
return normalizeExpr(expr.operator, generateExpr(expr.left, ctx), generateExpr(expr.right, ctx));
|
|
609
|
-
case "unary":
|
|
610
|
-
if (expr.operator === "!") {
|
|
611
|
-
return { kind: "not", arg: generateExpr(expr.operand, ctx) };
|
|
612
|
-
}
|
|
613
|
-
else {
|
|
614
|
-
return { kind: "neg", arg: generateExpr(expr.operand, ctx) };
|
|
615
|
-
}
|
|
616
|
-
case "ternary":
|
|
617
|
-
return {
|
|
618
|
-
kind: "if",
|
|
619
|
-
cond: generateExpr(expr.condition, ctx),
|
|
620
|
-
then: generateExpr(expr.consequent, ctx),
|
|
621
|
-
else: generateExpr(expr.alternate, ctx),
|
|
622
|
-
};
|
|
623
|
-
case "objectLiteral": {
|
|
624
|
-
const fields = {};
|
|
625
|
-
for (const prop of expr.properties) {
|
|
626
|
-
fields[prop.key] = generateExpr(prop.value, ctx);
|
|
627
|
-
}
|
|
628
|
-
return { kind: "object", fields };
|
|
629
|
-
}
|
|
630
|
-
case "arrayLiteral":
|
|
631
|
-
// For array literals, we build using append
|
|
632
|
-
if (expr.elements.length === 0) {
|
|
633
|
-
return { kind: "lit", value: [] };
|
|
634
|
-
}
|
|
635
|
-
// Check if all elements are literals
|
|
636
|
-
const allLiterals = expr.elements.every(e => e.kind === "literal");
|
|
637
|
-
if (allLiterals) {
|
|
638
|
-
return { kind: "lit", value: expr.elements.map(e => e.value) };
|
|
639
|
-
}
|
|
640
|
-
// Otherwise use append
|
|
641
|
-
return {
|
|
642
|
-
kind: "append",
|
|
643
|
-
array: { kind: "lit", value: [] },
|
|
644
|
-
items: expr.elements.map(e => generateExpr(e, ctx)),
|
|
645
|
-
};
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
function generateIdentifier(name, ctx) {
|
|
649
|
-
// Resolve identifier to path
|
|
650
|
-
if (ctx.stateFields.has(name)) {
|
|
651
|
-
// Core expects state paths without prefix (e.g., "count" not "data.count")
|
|
652
|
-
return { kind: "get", path: name };
|
|
653
|
-
}
|
|
654
|
-
if (ctx.computedFields.has(name)) {
|
|
655
|
-
return { kind: "get", path: `computed.${name}` };
|
|
656
|
-
}
|
|
657
|
-
if (ctx.currentAction && ctx.actionParams.get(ctx.currentAction)?.has(name)) {
|
|
658
|
-
return { kind: "get", path: `input.${name}` };
|
|
659
|
-
}
|
|
660
|
-
// Unknown identifier - report error and default to plain path
|
|
661
|
-
ctx.diagnostics.push({
|
|
662
|
-
severity: "error",
|
|
663
|
-
code: "E_UNKNOWN_IDENT",
|
|
664
|
-
message: `Unknown identifier '${name}'`,
|
|
665
|
-
location: { start: { line: 0, column: 0, offset: 0 }, end: { line: 0, column: 0, offset: 0 } },
|
|
666
|
-
});
|
|
667
|
-
return { kind: "get", path: name };
|
|
668
|
-
}
|
|
669
|
-
function generateSystemIdent(path, ctx) {
|
|
670
|
-
// $system.uuid -> will be lowered later
|
|
671
|
-
// $meta.intentId -> meta.intentId
|
|
672
|
-
// $input.* -> input.*
|
|
673
|
-
const [namespace, ...rest] = path;
|
|
674
|
-
switch (namespace) {
|
|
675
|
-
case "system":
|
|
676
|
-
// $system values are placeholders - will be lowered in the lowering pass
|
|
677
|
-
return { kind: "get", path: `$system.${rest.join(".")}` };
|
|
678
|
-
case "meta":
|
|
679
|
-
return { kind: "get", path: `meta.${rest.join(".")}` };
|
|
680
|
-
case "input":
|
|
681
|
-
return { kind: "get", path: `input.${rest.join(".")}` };
|
|
682
|
-
default:
|
|
683
|
-
ctx.diagnostics.push({
|
|
684
|
-
severity: "error",
|
|
685
|
-
code: "E_INVALID_SYSTEM",
|
|
686
|
-
message: `Invalid system identifier namespace '$${namespace}'`,
|
|
687
|
-
location: { start: { line: 0, column: 0, offset: 0 }, end: { line: 0, column: 0, offset: 0 } },
|
|
688
|
-
});
|
|
689
|
-
return { kind: "lit", value: null };
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
function generatePropertyAccess(expr, ctx) {
|
|
693
|
-
// Handle chained property access
|
|
694
|
-
const objectExpr = generateExpr(expr.object, ctx);
|
|
695
|
-
// If the object is a get expression, we can extend the path
|
|
696
|
-
if (objectExpr.kind === "get") {
|
|
697
|
-
return { kind: "get", path: `${objectExpr.path}.${expr.property}` };
|
|
698
|
-
}
|
|
699
|
-
// Static member access: use field() to access a known property on a computed object.
|
|
700
|
-
// This is semantically distinct from at() (array indexing) and get() (snapshot path lookup).
|
|
701
|
-
return {
|
|
702
|
-
kind: "field",
|
|
703
|
-
object: objectExpr,
|
|
704
|
-
property: expr.property,
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
// ============ Hash Computation ============
|
|
708
|
-
/**
|
|
709
|
-
* Compute schema hash using browser-compatible SHA-256.
|
|
710
|
-
* Uses @manifesto-ai/core's sha256Sync for universal compatibility.
|
|
711
|
-
*/
|
|
712
|
-
function computeHash(schema) {
|
|
713
|
-
return hashSchemaSync(schema);
|
|
714
|
-
}
|
|
715
|
-
//# sourceMappingURL=ir.js.map
|