@platforma-sdk/tengo-builder 2.5.30 → 3.0.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/dist/compiler/compiler.cjs +46 -1
- package/dist/compiler/compiler.cjs.map +1 -1
- package/dist/compiler/compiler.js +46 -1
- package/dist/compiler/compiler.js.map +1 -1
- package/dist/compiler/main.cjs +132 -6
- package/dist/compiler/main.cjs.map +1 -1
- package/dist/compiler/main.js +132 -6
- package/dist/compiler/main.js.map +1 -1
- package/dist/compiler/pack_limits.cjs +49 -0
- package/dist/compiler/pack_limits.cjs.map +1 -0
- package/dist/compiler/pack_limits.js +47 -0
- package/dist/compiler/pack_limits.js.map +1 -0
- package/dist/compiler/package.cjs.map +1 -1
- package/dist/compiler/package.js.map +1 -1
- package/dist/compiler/source.cjs +6 -2
- package/dist/compiler/source.cjs.map +1 -1
- package/dist/compiler/source.js +6 -2
- package/dist/compiler/source.js.map +1 -1
- package/dist/shared/basecmd.cjs +2 -1
- package/dist/shared/basecmd.cjs.map +1 -1
- package/dist/shared/basecmd.js +2 -1
- package/dist/shared/basecmd.js.map +1 -1
- package/dist/shared/dump.cjs +4 -0
- package/dist/shared/dump.cjs.map +1 -1
- package/dist/shared/dump.js +4 -0
- package/dist/shared/dump.js.map +1 -1
- package/package.json +6 -6
- package/src/compiler/compiler.test.ts +91 -0
- package/src/compiler/compiler.ts +75 -1
- package/src/compiler/main.ts +217 -11
- package/src/compiler/pack_limits.test.ts +173 -0
- package/src/compiler/pack_limits.ts +103 -0
- package/src/compiler/package.ts +1 -1
- package/src/compiler/source.test.ts +30 -0
- package/src/compiler/source.ts +4 -0
- package/src/shared/basecmd.ts +1 -1
- package/src/shared/dump.ts +9 -0
|
@@ -4,10 +4,18 @@ const require_template = require("./template.cjs");
|
|
|
4
4
|
const require_artifactset = require("./artifactset.cjs");
|
|
5
5
|
const require_compileroptions = require("./compileroptions.cjs");
|
|
6
6
|
//#region src/compiler/compiler.ts
|
|
7
|
+
/** Add a capability token to a template's `requiredCapabilities` list,
|
|
8
|
+
* skipping duplicates. Initializes the array lazily so the field stays
|
|
9
|
+
* absent for templates that need nothing. */
|
|
10
|
+
function addRequiredCapability(template, capability) {
|
|
11
|
+
template.requiredCapabilities = template.requiredCapabilities ?? [];
|
|
12
|
+
if (!template.requiredCapabilities.includes(capability)) template.requiredCapabilities.push(capability);
|
|
13
|
+
}
|
|
7
14
|
var TengoTemplateCompiler = class {
|
|
8
15
|
libs = new require_artifactset.ArtifactStore((src) => src.fullName);
|
|
9
16
|
software = new require_artifactset.ArtifactStore((src) => src.fullName);
|
|
10
17
|
assets = new require_artifactset.ArtifactStore((src) => src.fullName);
|
|
18
|
+
wasm = new require_artifactset.ArtifactStore((src) => src.fullName);
|
|
11
19
|
templates = new require_artifactset.ArtifactStore((tpl) => tpl.fullName);
|
|
12
20
|
constructor(compileMode) {
|
|
13
21
|
this.compileMode = compileMode;
|
|
@@ -50,12 +58,24 @@ var TengoTemplateCompiler = class {
|
|
|
50
58
|
data.hashToSource[asset.sourceHash] = asset.src;
|
|
51
59
|
break;
|
|
52
60
|
}
|
|
61
|
+
case "wasm": {
|
|
62
|
+
const wasm = this.getWasmOrError(dep);
|
|
63
|
+
data.template.wasm = data.template.wasm ?? {};
|
|
64
|
+
data.template.wasm[require_package.artifactNameToString(dep)] = {
|
|
65
|
+
...require_package.formatArtefactNameAndVersion(wasm.fullName),
|
|
66
|
+
sourceHash: wasm.sourceHash
|
|
67
|
+
};
|
|
68
|
+
data.hashToSource[wasm.sourceHash] = wasm.src;
|
|
69
|
+
addRequiredCapability(data.template, "wasm:v1");
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
53
72
|
case "template": {
|
|
54
73
|
if (require_package.typedArtifactNamesEquals(fullName, dep)) continue;
|
|
55
74
|
const tpl = this.getTemplateOrError(dep);
|
|
56
75
|
data.template.templates[require_package.artifactNameToString(dep)] = tpl.data.template;
|
|
57
76
|
data.hashToSource[tpl.data.template.sourceHash] = tpl.source;
|
|
58
77
|
for (const [hash, src] of Object.entries(tpl.data.hashToSource)) data.hashToSource[hash] = src;
|
|
78
|
+
for (const cap of tpl.data.template.requiredCapabilities ?? []) addRequiredCapability(data.template, cap);
|
|
59
79
|
break;
|
|
60
80
|
}
|
|
61
81
|
case "test": throw new Error(`dependencies tree error: tests should never be part of template: ${require_package.typedArtifactNameToString(dep)} is dependency of ${require_package.artifactNameToString(fullName)}`);
|
|
@@ -137,6 +157,22 @@ var TengoTemplateCompiler = class {
|
|
|
137
157
|
if (!asset) throw new Error(`asset info not found: ${require_package.artifactNameToString(name)}`);
|
|
138
158
|
return asset;
|
|
139
159
|
}
|
|
160
|
+
addWasm(wasm) {
|
|
161
|
+
const wasmFromMap = this.wasm.add(wasm.compileMode, wasm, false);
|
|
162
|
+
if (wasmFromMap && !require_package.fullNameEquals(wasm.fullName, wasmFromMap.fullName)) throw new Error(`compiler already contain info for wasm: adding = ${require_package.fullNameToString(wasm.fullName)}, contains = ${require_package.fullNameToString(wasmFromMap.fullName)}`);
|
|
163
|
+
}
|
|
164
|
+
allWasm() {
|
|
165
|
+
return this.wasm.array(this.compileMode);
|
|
166
|
+
}
|
|
167
|
+
getWasm(name) {
|
|
168
|
+
if (name.type !== "wasm") throw new Error(`illegal artifact type: got ${name.type} instead of 'wasm'`);
|
|
169
|
+
return this.wasm.get(this.compileMode, name);
|
|
170
|
+
}
|
|
171
|
+
getWasmOrError(name) {
|
|
172
|
+
const wasm = this.getWasm(name);
|
|
173
|
+
if (!wasm) throw new Error(`wasm info not found: ${require_package.artifactNameToString(name)}`);
|
|
174
|
+
return wasm;
|
|
175
|
+
}
|
|
140
176
|
addTemplate(tpl) {
|
|
141
177
|
const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);
|
|
142
178
|
if (tplFromMap && !require_package.fullNameEquals(tpl.fullName, tplFromMap.fullName)) throw new Error(`compiler already contain such template: adding = ${require_package.fullNameToString(tpl.fullName)}, contains = ${require_package.fullNameToString(tplFromMap.fullName)}`);
|
|
@@ -159,6 +195,7 @@ var TengoTemplateCompiler = class {
|
|
|
159
195
|
case "library": return this.getLib(name);
|
|
160
196
|
case "software": return this.getSoftware(name);
|
|
161
197
|
case "asset": return this.getAsset(name);
|
|
198
|
+
case "wasm": return this.getWasm(name);
|
|
162
199
|
case "test": return;
|
|
163
200
|
default: require_util.assertNever(name.type);
|
|
164
201
|
}
|
|
@@ -168,7 +205,8 @@ var TengoTemplateCompiler = class {
|
|
|
168
205
|
templates: [],
|
|
169
206
|
libs: [],
|
|
170
207
|
software: [],
|
|
171
|
-
assets: []
|
|
208
|
+
assets: [],
|
|
209
|
+
wasm: []
|
|
172
210
|
};
|
|
173
211
|
let current = [];
|
|
174
212
|
for (const src of sources) if (src.fullName.type === "library") {
|
|
@@ -180,6 +218,9 @@ var TengoTemplateCompiler = class {
|
|
|
180
218
|
} else if (src.fullName.type === "asset") {
|
|
181
219
|
this.addAsset(src);
|
|
182
220
|
result.assets.push(src);
|
|
221
|
+
} else if (src.fullName.type === "wasm") {
|
|
222
|
+
this.addWasm(src);
|
|
223
|
+
result.wasm.push(src);
|
|
183
224
|
} else current.push(src);
|
|
184
225
|
while (current.length > 0) {
|
|
185
226
|
const unprocessed = [];
|
|
@@ -207,6 +248,10 @@ var TengoTemplateCompiler = class {
|
|
|
207
248
|
this.addAsset(src);
|
|
208
249
|
result.assets.push(src);
|
|
209
250
|
break;
|
|
251
|
+
case "wasm":
|
|
252
|
+
this.addWasm(src);
|
|
253
|
+
result.wasm.push(src);
|
|
254
|
+
break;
|
|
210
255
|
case "template":
|
|
211
256
|
try {
|
|
212
257
|
const tpl = this.compileAndAddTemplate(src);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.cjs","names":["ArtifactStore","artifactNameToString","formatArtefactNameAndVersion","typedArtifactNamesEquals","typedArtifactNameToString","fullNameEquals","fullNameToString","newTemplateWithSource"],"sources":["../../src/compiler/compiler.ts"],"sourcesContent":["import type { ArtifactSource } from \"./source\";\nimport type { TemplateWithSource } from \"./template\";\nimport { newTemplateWithSource } from \"./template\";\nimport type { TypedArtifactName, FullArtifactName, CompileMode } from \"./package\";\nimport {\n fullNameToString,\n typedArtifactNameToString,\n artifactNameToString,\n formatArtefactNameAndVersion,\n typedArtifactNamesEquals,\n fullNameEquals,\n} from \"./package\";\nimport { ArtifactStore } from \"./artifactset\";\nimport { assertNever } from \"./util\";\nimport { applyLibraryCompilerOptions, applyTemplateCompilerOptions } from \"./compileroptions\";\nimport type { CompiledTemplateV3 } from \"@milaboratories/pl-model-backend\";\n\n/** A compilation result. */\nexport interface TemplatesAndLibs {\n templates: TemplateWithSource[];\n libs: ArtifactSource[];\n software: ArtifactSource[];\n assets: ArtifactSource[];\n}\n\nexport class TengoTemplateCompiler {\n private readonly libs = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly software = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly assets = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly templates = new ArtifactStore<TemplateWithSource>((tpl) => tpl.fullName);\n\n constructor(private readonly compileMode: CompileMode) {}\n\n /** Recursively add dependencies to the template. */\n private populateTemplateDataFromDependencies(\n fullName: FullArtifactName,\n data: CompiledTemplateV3,\n deps: TypedArtifactName[],\n trace: string[],\n ) {\n for (const dep of deps) {\n switch (dep.type) {\n case \"library\": {\n const lib = this.getLibOrError(dep);\n\n const recursionStart = trace.indexOf(artifactNameToString(dep));\n if (recursionStart >= 0) {\n const errorMessage =\n `library import recursion detected: ` +\n `${trace.slice(recursionStart).join(\" -> \")} -> ${artifactNameToString(dep)}`;\n throw new Error(errorMessage);\n }\n\n const tplLib = {\n ...formatArtefactNameAndVersion(lib.fullName),\n sourceHash: lib.sourceHash,\n };\n\n applyLibraryCompilerOptions(lib.compilerOptions, tplLib);\n data.template.libs[artifactNameToString(dep)] = tplLib;\n data.hashToSource[tplLib.sourceHash] = lib.src;\n\n // populate with transient library dependencies\n this.populateTemplateDataFromDependencies(fullName, data, lib.dependencies, [\n ...trace,\n artifactNameToString(dep),\n ]);\n\n break;\n }\n case \"software\": {\n const software = this.getSoftwareOrError(dep);\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(software.fullName),\n sourceHash: software.sourceHash,\n };\n data.hashToSource[software.sourceHash] = software.src;\n\n break;\n }\n case \"asset\": {\n const asset = this.getAssetOrError(dep);\n // Yes, we temporarily put assets into 'software' section of template, so controller can\n // handle it the right way without updates\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(asset.fullName),\n sourceHash: asset.sourceHash,\n };\n data.hashToSource[asset.sourceHash] = asset.src;\n break;\n }\n case \"template\": {\n if (typedArtifactNamesEquals(fullName, dep))\n // skipping self reference\n continue;\n\n const tpl = this.getTemplateOrError(dep);\n data.template.templates[artifactNameToString(dep)] = tpl.data.template;\n data.hashToSource[tpl.data.template.sourceHash] = tpl.source;\n\n // add all the sources of transitivedependencies to the resulted hashToSource\n for (const [hash, src] of Object.entries(tpl.data.hashToSource)) {\n data.hashToSource[hash] = src;\n }\n\n break;\n }\n case \"test\":\n throw new Error(\n `dependencies tree error: tests should never be part of template: ` +\n `${typedArtifactNameToString(dep)} is dependency of ${artifactNameToString(fullName)}`,\n );\n default:\n assertNever(dep.type);\n }\n }\n }\n\n /** This method assumes that all dependencies are already added to the compiler's context */\n private compileAndAddTemplate(tplSrc: ArtifactSource): CompiledTemplateV3 {\n if (tplSrc.fullName.type !== \"template\") throw new Error(\"unexpected source type\");\n\n // creating template with unpopulated dependencies\n const tplData: CompiledTemplateV3 = {\n type: \"pl.tengo-template.v3\",\n hashToSource: {\n [tplSrc.sourceHash]: tplSrc.src,\n },\n template: {\n ...formatArtefactNameAndVersion(tplSrc.fullName),\n templates: {},\n libs: {},\n software: {},\n assets: {},\n sourceHash: tplSrc.sourceHash,\n },\n };\n\n applyTemplateCompilerOptions(tplSrc.compilerOptions, tplData.template);\n\n // collecting dependencies in output format\n this.populateTemplateDataFromDependencies(tplSrc.fullName, tplData, tplSrc.dependencies, []);\n\n return tplData;\n }\n\n addLib(lib: ArtifactSource) {\n const libFromMap = this.libs.add(lib.compileMode, lib, false);\n if (libFromMap && !fullNameEquals(lib.fullName, libFromMap.fullName))\n throw new Error(\n `compiler already contain such library: adding = ${fullNameToString(lib.fullName)}, contains = ${fullNameToString(libFromMap.fullName)}`,\n );\n }\n\n allLibs(): ArtifactSource[] {\n return this.libs.array(this.compileMode);\n }\n\n getLib(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"library\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'library`);\n return this.libs.get(this.compileMode, name);\n }\n\n getLibOrError(name: TypedArtifactName): ArtifactSource {\n const lib = this.getLib(name);\n if (!lib) throw new Error(`library not found: ${artifactNameToString(name)}`);\n return lib;\n }\n\n checkLibs() {\n this.libs.forEach(this.compileMode, (lib) => {\n for (const dep of lib.dependencies) {\n if (dep.type === \"test\")\n throw new Error(\n `test should never be dependency of production code: ${typedArtifactNameToString(dep)} test is dependency of ${fullNameToString(lib.fullName)}`,\n );\n\n if (!this.getArtefact(dep))\n throw new Error(\n `unresolved dependency ${typedArtifactNameToString(dep)} for ${fullNameToString(lib.fullName)}`,\n );\n }\n });\n }\n\n addSoftware(software: ArtifactSource) {\n const swFromMap = this.software.add(software.compileMode, software, false);\n if (swFromMap && !fullNameEquals(software.fullName, swFromMap.fullName))\n throw new Error(\n `compiler already contain info for software: adding = ${fullNameToString(software.fullName)}, contains = ${fullNameToString(swFromMap.fullName)}`,\n );\n }\n\n allSoftware(): ArtifactSource[] {\n return this.software.array(this.compileMode);\n }\n\n getSoftware(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"software\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'software`);\n\n return this.software.get(this.compileMode, name);\n }\n\n getSoftwareOrError(name: TypedArtifactName): ArtifactSource {\n const software = this.getSoftware(name);\n if (!software) throw new Error(`software info not found: ${artifactNameToString(name)}`);\n return software;\n }\n\n addAsset(asset: ArtifactSource) {\n const assetFromMap = this.assets.add(asset.compileMode, asset, false);\n if (assetFromMap && !fullNameEquals(asset.fullName, assetFromMap.fullName))\n throw new Error(\n `compiler already contain info for asset: adding = ${fullNameToString(asset.fullName)}, contains = ${fullNameToString(assetFromMap.fullName)}`,\n );\n }\n\n allAssets(): ArtifactSource[] {\n return this.assets.array(this.compileMode);\n }\n\n getAsset(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"asset\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'asset`);\n\n return this.assets.get(this.compileMode, name);\n }\n\n getAssetOrError(name: TypedArtifactName): ArtifactSource {\n const asset = this.getAsset(name);\n if (!asset) throw new Error(`asset info not found: ${artifactNameToString(name)}`);\n return asset;\n }\n\n addTemplate(tpl: TemplateWithSource) {\n const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);\n if (tplFromMap && !fullNameEquals(tpl.fullName, tplFromMap.fullName))\n throw new Error(\n `compiler already contain such template: adding = ${fullNameToString(tpl.fullName)}, contains = ${fullNameToString(tplFromMap.fullName)}`,\n );\n }\n\n allTemplates(): TemplateWithSource[] {\n return this.templates.array(this.compileMode);\n }\n\n getTemplate(name: TypedArtifactName): TemplateWithSource | undefined {\n if (name.type !== \"template\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'template`);\n return this.templates.get(this.compileMode, name);\n }\n\n getTemplateOrError(name: TypedArtifactName): TemplateWithSource {\n const tpl = this.getTemplate(name);\n if (!tpl) throw new Error(`template not found: ${artifactNameToString(name)}`);\n return tpl;\n }\n\n getArtefact(name: TypedArtifactName): ArtifactSource | TemplateWithSource | undefined {\n switch (name.type) {\n case \"template\":\n return this.getTemplate(name);\n case \"library\":\n return this.getLib(name);\n case \"software\":\n return this.getSoftware(name);\n case \"asset\":\n return this.getAsset(name);\n case \"test\":\n // Tests are ignored by the complier. They should never be compiled into templates or libs and\n // should never be a dependency.\n return undefined;\n default:\n assertNever(name.type);\n }\n }\n\n compileAndAdd(sources: ArtifactSource[]): TemplatesAndLibs {\n const result: TemplatesAndLibs = {\n templates: [],\n libs: [],\n software: [],\n assets: [],\n };\n\n let current: ArtifactSource[] = [];\n\n for (const src of sources) {\n if (src.fullName.type === \"library\") {\n // add libraries 'as-is' to be able to resolve them as dependencies\n this.addLib(src);\n result.libs.push(src);\n } else if (src.fullName.type === \"software\") {\n // add software 'as-is' to be able to resolve them as dependencies\n this.addSoftware(src);\n result.software.push(src);\n } else if (src.fullName.type === \"asset\") {\n // add assets 'as-is' to be able to resolve them as dependencies\n this.addAsset(src);\n result.assets.push(src);\n } else {\n current.push(src);\n }\n }\n\n while (current.length > 0) {\n const unprocessed: { src: ArtifactSource; err: Error }[] = [];\n\n for (const src of current) {\n //\n // If one of the dependencies can't be resolved with current compiler context,\n // we put aside the source until next iteration, in hope that the dependency\n // will be satisfied then.\n //\n // This is equivalent to topological sorting of input sources.\n //\n const unsatisfied = src.dependencies.filter(\n (dep) =>\n !this.getArtefact(dep) &&\n // allow self reference for templates\n !(src.fullName.type === \"template\" && typedArtifactNamesEquals(src.fullName, dep)),\n );\n if (unsatisfied.length > 0) {\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n for (const dep of unsatisfied) {\n errorMessage += ` - ${typedArtifactNameToString(dep)}\\n`;\n }\n unprocessed.push({ src, err: new Error(errorMessage) });\n\n continue;\n }\n\n // type specific processing\n switch (src.fullName.type) {\n case \"library\":\n // libraries are added as is\n this.addLib(src);\n result.libs.push(src);\n break;\n case \"software\":\n // software dependencies are added as is\n this.addSoftware(src);\n result.software.push(src);\n break;\n case \"asset\":\n // software dependencies are added as is\n this.addAsset(src);\n result.assets.push(src);\n break;\n case \"template\":\n // templates are compiled and then added\n try {\n const tpl = this.compileAndAddTemplate(src);\n const tplWithSrc = newTemplateWithSource(src.compileMode, src.fullName, tpl, src.src);\n this.addTemplate(tplWithSrc);\n result.templates.push(tplWithSrc);\n } catch (error: unknown) {\n const err = error as Error;\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n errorMessage += ` - ${err.message}\\n`;\n\n unprocessed.push({ src, err: Error(errorMessage) }); // one or more dependencies are not resolvable yet\n }\n break;\n case \"test\":\n // Ignore tests: they never should be part of compiled code or be a dependency.\n break;\n default:\n assertNever(src.fullName.type);\n }\n }\n\n // checking that we successfully added at least one source,\n // if not all the source files in unprocessed array have unmet dependencies\n if (current.length === unprocessed.length) {\n let errorMessage = \"\";\n\n for (const u of unprocessed) {\n errorMessage += `\\n${u.err.message}`;\n }\n throw new Error(errorMessage);\n }\n\n current = unprocessed.map(({ src: ArtifactSource }) => ArtifactSource);\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compiler.cjs","names":["ArtifactStore","artifactNameToString","formatArtefactNameAndVersion","typedArtifactNamesEquals","typedArtifactNameToString","fullNameEquals","fullNameToString","newTemplateWithSource"],"sources":["../../src/compiler/compiler.ts"],"sourcesContent":["import type { ArtifactSource } from \"./source\";\nimport type { TemplateWithSource } from \"./template\";\nimport { newTemplateWithSource } from \"./template\";\nimport type { TypedArtifactName, FullArtifactName, CompileMode } from \"./package\";\nimport {\n fullNameToString,\n typedArtifactNameToString,\n artifactNameToString,\n formatArtefactNameAndVersion,\n typedArtifactNamesEquals,\n fullNameEquals,\n} from \"./package\";\nimport { ArtifactStore } from \"./artifactset\";\nimport { assertNever } from \"./util\";\nimport { applyLibraryCompilerOptions, applyTemplateCompilerOptions } from \"./compileroptions\";\nimport type {\n BackendCapability,\n CompiledTemplateV3,\n TemplateDataV3,\n} from \"@milaboratories/pl-model-backend\";\n\n/** Add a capability token to a template's `requiredCapabilities` list,\n * skipping duplicates. Initializes the array lazily so the field stays\n * absent for templates that need nothing. */\nfunction addRequiredCapability(template: TemplateDataV3, capability: BackendCapability): void {\n template.requiredCapabilities = template.requiredCapabilities ?? [];\n if (!template.requiredCapabilities.includes(capability)) {\n template.requiredCapabilities.push(capability);\n }\n}\n\n/** A compilation result. */\nexport interface TemplatesAndLibs {\n templates: TemplateWithSource[];\n libs: ArtifactSource[];\n software: ArtifactSource[];\n assets: ArtifactSource[];\n wasm: ArtifactSource[];\n}\n\nexport class TengoTemplateCompiler {\n private readonly libs = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly software = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly assets = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly wasm = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly templates = new ArtifactStore<TemplateWithSource>((tpl) => tpl.fullName);\n\n constructor(private readonly compileMode: CompileMode) {}\n\n /** Recursively add dependencies to the template. */\n private populateTemplateDataFromDependencies(\n fullName: FullArtifactName,\n data: CompiledTemplateV3,\n deps: TypedArtifactName[],\n trace: string[],\n ) {\n for (const dep of deps) {\n switch (dep.type) {\n case \"library\": {\n const lib = this.getLibOrError(dep);\n\n const recursionStart = trace.indexOf(artifactNameToString(dep));\n if (recursionStart >= 0) {\n const errorMessage =\n `library import recursion detected: ` +\n `${trace.slice(recursionStart).join(\" -> \")} -> ${artifactNameToString(dep)}`;\n throw new Error(errorMessage);\n }\n\n const tplLib = {\n ...formatArtefactNameAndVersion(lib.fullName),\n sourceHash: lib.sourceHash,\n };\n\n applyLibraryCompilerOptions(lib.compilerOptions, tplLib);\n data.template.libs[artifactNameToString(dep)] = tplLib;\n data.hashToSource[tplLib.sourceHash] = lib.src;\n\n // populate with transient library dependencies\n this.populateTemplateDataFromDependencies(fullName, data, lib.dependencies, [\n ...trace,\n artifactNameToString(dep),\n ]);\n\n break;\n }\n case \"software\": {\n const software = this.getSoftwareOrError(dep);\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(software.fullName),\n sourceHash: software.sourceHash,\n };\n data.hashToSource[software.sourceHash] = software.src;\n\n break;\n }\n case \"asset\": {\n const asset = this.getAssetOrError(dep);\n // Yes, we temporarily put assets into 'software' section of template, so controller can\n // handle it the right way without updates\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(asset.fullName),\n sourceHash: asset.sourceHash,\n };\n data.hashToSource[asset.sourceHash] = asset.src;\n break;\n }\n case \"wasm\": {\n const wasm = this.getWasmOrError(dep);\n data.template.wasm = data.template.wasm ?? {};\n data.template.wasm[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(wasm.fullName),\n sourceHash: wasm.sourceHash,\n };\n data.hashToSource[wasm.sourceHash] = wasm.src;\n // Embedding a wasm artifact means this template requires the\n // backend's wasm runtime to run. The token is propagated upward\n // when this template is in turn embedded as a sub-template.\n addRequiredCapability(data.template, \"wasm:v1\");\n break;\n }\n case \"template\": {\n if (typedArtifactNamesEquals(fullName, dep))\n // skipping self reference\n continue;\n\n const tpl = this.getTemplateOrError(dep);\n data.template.templates[artifactNameToString(dep)] = tpl.data.template;\n data.hashToSource[tpl.data.template.sourceHash] = tpl.source;\n\n // add all the sources of transitivedependencies to the resulted hashToSource\n for (const [hash, src] of Object.entries(tpl.data.hashToSource)) {\n data.hashToSource[hash] = src;\n }\n\n // Union the sub-template's compile-time-computed capability\n // requirements into ours, so the top template carries the full\n // transitive set without consumers having to walk the tree.\n for (const cap of tpl.data.template.requiredCapabilities ?? []) {\n addRequiredCapability(data.template, cap);\n }\n\n break;\n }\n case \"test\":\n throw new Error(\n `dependencies tree error: tests should never be part of template: ` +\n `${typedArtifactNameToString(dep)} is dependency of ${artifactNameToString(fullName)}`,\n );\n default:\n assertNever(dep.type);\n }\n }\n }\n\n /** This method assumes that all dependencies are already added to the compiler's context */\n private compileAndAddTemplate(tplSrc: ArtifactSource): CompiledTemplateV3 {\n if (tplSrc.fullName.type !== \"template\") throw new Error(\"unexpected source type\");\n\n // creating template with unpopulated dependencies\n const tplData: CompiledTemplateV3 = {\n type: \"pl.tengo-template.v3\",\n hashToSource: {\n [tplSrc.sourceHash]: tplSrc.src,\n },\n template: {\n ...formatArtefactNameAndVersion(tplSrc.fullName),\n templates: {},\n libs: {},\n software: {},\n assets: {},\n sourceHash: tplSrc.sourceHash,\n },\n };\n\n applyTemplateCompilerOptions(tplSrc.compilerOptions, tplData.template);\n\n // collecting dependencies in output format\n this.populateTemplateDataFromDependencies(tplSrc.fullName, tplData, tplSrc.dependencies, []);\n\n return tplData;\n }\n\n addLib(lib: ArtifactSource) {\n const libFromMap = this.libs.add(lib.compileMode, lib, false);\n if (libFromMap && !fullNameEquals(lib.fullName, libFromMap.fullName))\n throw new Error(\n `compiler already contain such library: adding = ${fullNameToString(lib.fullName)}, contains = ${fullNameToString(libFromMap.fullName)}`,\n );\n }\n\n allLibs(): ArtifactSource[] {\n return this.libs.array(this.compileMode);\n }\n\n getLib(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"library\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'library`);\n return this.libs.get(this.compileMode, name);\n }\n\n getLibOrError(name: TypedArtifactName): ArtifactSource {\n const lib = this.getLib(name);\n if (!lib) throw new Error(`library not found: ${artifactNameToString(name)}`);\n return lib;\n }\n\n checkLibs() {\n this.libs.forEach(this.compileMode, (lib) => {\n for (const dep of lib.dependencies) {\n if (dep.type === \"test\")\n throw new Error(\n `test should never be dependency of production code: ${typedArtifactNameToString(dep)} test is dependency of ${fullNameToString(lib.fullName)}`,\n );\n\n if (!this.getArtefact(dep))\n throw new Error(\n `unresolved dependency ${typedArtifactNameToString(dep)} for ${fullNameToString(lib.fullName)}`,\n );\n }\n });\n }\n\n addSoftware(software: ArtifactSource) {\n const swFromMap = this.software.add(software.compileMode, software, false);\n if (swFromMap && !fullNameEquals(software.fullName, swFromMap.fullName))\n throw new Error(\n `compiler already contain info for software: adding = ${fullNameToString(software.fullName)}, contains = ${fullNameToString(swFromMap.fullName)}`,\n );\n }\n\n allSoftware(): ArtifactSource[] {\n return this.software.array(this.compileMode);\n }\n\n getSoftware(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"software\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'software`);\n\n return this.software.get(this.compileMode, name);\n }\n\n getSoftwareOrError(name: TypedArtifactName): ArtifactSource {\n const software = this.getSoftware(name);\n if (!software) throw new Error(`software info not found: ${artifactNameToString(name)}`);\n return software;\n }\n\n addAsset(asset: ArtifactSource) {\n const assetFromMap = this.assets.add(asset.compileMode, asset, false);\n if (assetFromMap && !fullNameEquals(asset.fullName, assetFromMap.fullName))\n throw new Error(\n `compiler already contain info for asset: adding = ${fullNameToString(asset.fullName)}, contains = ${fullNameToString(assetFromMap.fullName)}`,\n );\n }\n\n allAssets(): ArtifactSource[] {\n return this.assets.array(this.compileMode);\n }\n\n getAsset(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"asset\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'asset`);\n\n return this.assets.get(this.compileMode, name);\n }\n\n getAssetOrError(name: TypedArtifactName): ArtifactSource {\n const asset = this.getAsset(name);\n if (!asset) throw new Error(`asset info not found: ${artifactNameToString(name)}`);\n return asset;\n }\n\n addWasm(wasm: ArtifactSource) {\n const wasmFromMap = this.wasm.add(wasm.compileMode, wasm, false);\n if (wasmFromMap && !fullNameEquals(wasm.fullName, wasmFromMap.fullName))\n throw new Error(\n `compiler already contain info for wasm: adding = ${fullNameToString(wasm.fullName)}, contains = ${fullNameToString(wasmFromMap.fullName)}`,\n );\n }\n\n allWasm(): ArtifactSource[] {\n return this.wasm.array(this.compileMode);\n }\n\n getWasm(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"wasm\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'wasm'`);\n\n return this.wasm.get(this.compileMode, name);\n }\n\n getWasmOrError(name: TypedArtifactName): ArtifactSource {\n const wasm = this.getWasm(name);\n if (!wasm) throw new Error(`wasm info not found: ${artifactNameToString(name)}`);\n return wasm;\n }\n\n addTemplate(tpl: TemplateWithSource) {\n const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);\n if (tplFromMap && !fullNameEquals(tpl.fullName, tplFromMap.fullName))\n throw new Error(\n `compiler already contain such template: adding = ${fullNameToString(tpl.fullName)}, contains = ${fullNameToString(tplFromMap.fullName)}`,\n );\n }\n\n allTemplates(): TemplateWithSource[] {\n return this.templates.array(this.compileMode);\n }\n\n getTemplate(name: TypedArtifactName): TemplateWithSource | undefined {\n if (name.type !== \"template\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'template`);\n return this.templates.get(this.compileMode, name);\n }\n\n getTemplateOrError(name: TypedArtifactName): TemplateWithSource {\n const tpl = this.getTemplate(name);\n if (!tpl) throw new Error(`template not found: ${artifactNameToString(name)}`);\n return tpl;\n }\n\n getArtefact(name: TypedArtifactName): ArtifactSource | TemplateWithSource | undefined {\n switch (name.type) {\n case \"template\":\n return this.getTemplate(name);\n case \"library\":\n return this.getLib(name);\n case \"software\":\n return this.getSoftware(name);\n case \"asset\":\n return this.getAsset(name);\n case \"wasm\":\n return this.getWasm(name);\n case \"test\":\n // Tests are ignored by the complier. They should never be compiled into templates or libs and\n // should never be a dependency.\n return undefined;\n default:\n assertNever(name.type);\n }\n }\n\n compileAndAdd(sources: ArtifactSource[]): TemplatesAndLibs {\n const result: TemplatesAndLibs = {\n templates: [],\n libs: [],\n software: [],\n assets: [],\n wasm: [],\n };\n\n let current: ArtifactSource[] = [];\n\n for (const src of sources) {\n if (src.fullName.type === \"library\") {\n // add libraries 'as-is' to be able to resolve them as dependencies\n this.addLib(src);\n result.libs.push(src);\n } else if (src.fullName.type === \"software\") {\n // add software 'as-is' to be able to resolve them as dependencies\n this.addSoftware(src);\n result.software.push(src);\n } else if (src.fullName.type === \"asset\") {\n // add assets 'as-is' to be able to resolve them as dependencies\n this.addAsset(src);\n result.assets.push(src);\n } else if (src.fullName.type === \"wasm\") {\n // add wasm 'as-is' to be able to resolve them as dependencies\n this.addWasm(src);\n result.wasm.push(src);\n } else {\n current.push(src);\n }\n }\n\n while (current.length > 0) {\n const unprocessed: { src: ArtifactSource; err: Error }[] = [];\n\n for (const src of current) {\n //\n // If one of the dependencies can't be resolved with current compiler context,\n // we put aside the source until next iteration, in hope that the dependency\n // will be satisfied then.\n //\n // This is equivalent to topological sorting of input sources.\n //\n const unsatisfied = src.dependencies.filter(\n (dep) =>\n !this.getArtefact(dep) &&\n // allow self reference for templates\n !(src.fullName.type === \"template\" && typedArtifactNamesEquals(src.fullName, dep)),\n );\n if (unsatisfied.length > 0) {\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n for (const dep of unsatisfied) {\n errorMessage += ` - ${typedArtifactNameToString(dep)}\\n`;\n }\n unprocessed.push({ src, err: new Error(errorMessage) });\n\n continue;\n }\n\n // type specific processing\n switch (src.fullName.type) {\n case \"library\":\n // libraries are added as is\n this.addLib(src);\n result.libs.push(src);\n break;\n case \"software\":\n // software dependencies are added as is\n this.addSoftware(src);\n result.software.push(src);\n break;\n case \"asset\":\n // software dependencies are added as is\n this.addAsset(src);\n result.assets.push(src);\n break;\n case \"wasm\":\n // wasm dependencies are added as is\n this.addWasm(src);\n result.wasm.push(src);\n break;\n case \"template\":\n // templates are compiled and then added\n try {\n const tpl = this.compileAndAddTemplate(src);\n const tplWithSrc = newTemplateWithSource(src.compileMode, src.fullName, tpl, src.src);\n this.addTemplate(tplWithSrc);\n result.templates.push(tplWithSrc);\n } catch (error: unknown) {\n const err = error as Error;\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n errorMessage += ` - ${err.message}\\n`;\n\n unprocessed.push({ src, err: Error(errorMessage) }); // one or more dependencies are not resolvable yet\n }\n break;\n case \"test\":\n // Ignore tests: they never should be part of compiled code or be a dependency.\n break;\n default:\n assertNever(src.fullName.type);\n }\n }\n\n // checking that we successfully added at least one source,\n // if not all the source files in unprocessed array have unmet dependencies\n if (current.length === unprocessed.length) {\n let errorMessage = \"\";\n\n for (const u of unprocessed) {\n errorMessage += `\\n${u.err.message}`;\n }\n throw new Error(errorMessage);\n }\n\n current = unprocessed.map(({ src: ArtifactSource }) => ArtifactSource);\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
|
@@ -4,10 +4,18 @@ import { newTemplateWithSource } from "./template.js";
|
|
|
4
4
|
import { ArtifactStore } from "./artifactset.js";
|
|
5
5
|
import { applyLibraryCompilerOptions, applyTemplateCompilerOptions } from "./compileroptions.js";
|
|
6
6
|
//#region src/compiler/compiler.ts
|
|
7
|
+
/** Add a capability token to a template's `requiredCapabilities` list,
|
|
8
|
+
* skipping duplicates. Initializes the array lazily so the field stays
|
|
9
|
+
* absent for templates that need nothing. */
|
|
10
|
+
function addRequiredCapability(template, capability) {
|
|
11
|
+
template.requiredCapabilities = template.requiredCapabilities ?? [];
|
|
12
|
+
if (!template.requiredCapabilities.includes(capability)) template.requiredCapabilities.push(capability);
|
|
13
|
+
}
|
|
7
14
|
var TengoTemplateCompiler = class {
|
|
8
15
|
libs = new ArtifactStore((src) => src.fullName);
|
|
9
16
|
software = new ArtifactStore((src) => src.fullName);
|
|
10
17
|
assets = new ArtifactStore((src) => src.fullName);
|
|
18
|
+
wasm = new ArtifactStore((src) => src.fullName);
|
|
11
19
|
templates = new ArtifactStore((tpl) => tpl.fullName);
|
|
12
20
|
constructor(compileMode) {
|
|
13
21
|
this.compileMode = compileMode;
|
|
@@ -50,12 +58,24 @@ var TengoTemplateCompiler = class {
|
|
|
50
58
|
data.hashToSource[asset.sourceHash] = asset.src;
|
|
51
59
|
break;
|
|
52
60
|
}
|
|
61
|
+
case "wasm": {
|
|
62
|
+
const wasm = this.getWasmOrError(dep);
|
|
63
|
+
data.template.wasm = data.template.wasm ?? {};
|
|
64
|
+
data.template.wasm[artifactNameToString(dep)] = {
|
|
65
|
+
...formatArtefactNameAndVersion(wasm.fullName),
|
|
66
|
+
sourceHash: wasm.sourceHash
|
|
67
|
+
};
|
|
68
|
+
data.hashToSource[wasm.sourceHash] = wasm.src;
|
|
69
|
+
addRequiredCapability(data.template, "wasm:v1");
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
53
72
|
case "template": {
|
|
54
73
|
if (typedArtifactNamesEquals(fullName, dep)) continue;
|
|
55
74
|
const tpl = this.getTemplateOrError(dep);
|
|
56
75
|
data.template.templates[artifactNameToString(dep)] = tpl.data.template;
|
|
57
76
|
data.hashToSource[tpl.data.template.sourceHash] = tpl.source;
|
|
58
77
|
for (const [hash, src] of Object.entries(tpl.data.hashToSource)) data.hashToSource[hash] = src;
|
|
78
|
+
for (const cap of tpl.data.template.requiredCapabilities ?? []) addRequiredCapability(data.template, cap);
|
|
59
79
|
break;
|
|
60
80
|
}
|
|
61
81
|
case "test": throw new Error(`dependencies tree error: tests should never be part of template: ${typedArtifactNameToString(dep)} is dependency of ${artifactNameToString(fullName)}`);
|
|
@@ -137,6 +157,22 @@ var TengoTemplateCompiler = class {
|
|
|
137
157
|
if (!asset) throw new Error(`asset info not found: ${artifactNameToString(name)}`);
|
|
138
158
|
return asset;
|
|
139
159
|
}
|
|
160
|
+
addWasm(wasm) {
|
|
161
|
+
const wasmFromMap = this.wasm.add(wasm.compileMode, wasm, false);
|
|
162
|
+
if (wasmFromMap && !fullNameEquals(wasm.fullName, wasmFromMap.fullName)) throw new Error(`compiler already contain info for wasm: adding = ${fullNameToString(wasm.fullName)}, contains = ${fullNameToString(wasmFromMap.fullName)}`);
|
|
163
|
+
}
|
|
164
|
+
allWasm() {
|
|
165
|
+
return this.wasm.array(this.compileMode);
|
|
166
|
+
}
|
|
167
|
+
getWasm(name) {
|
|
168
|
+
if (name.type !== "wasm") throw new Error(`illegal artifact type: got ${name.type} instead of 'wasm'`);
|
|
169
|
+
return this.wasm.get(this.compileMode, name);
|
|
170
|
+
}
|
|
171
|
+
getWasmOrError(name) {
|
|
172
|
+
const wasm = this.getWasm(name);
|
|
173
|
+
if (!wasm) throw new Error(`wasm info not found: ${artifactNameToString(name)}`);
|
|
174
|
+
return wasm;
|
|
175
|
+
}
|
|
140
176
|
addTemplate(tpl) {
|
|
141
177
|
const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);
|
|
142
178
|
if (tplFromMap && !fullNameEquals(tpl.fullName, tplFromMap.fullName)) throw new Error(`compiler already contain such template: adding = ${fullNameToString(tpl.fullName)}, contains = ${fullNameToString(tplFromMap.fullName)}`);
|
|
@@ -159,6 +195,7 @@ var TengoTemplateCompiler = class {
|
|
|
159
195
|
case "library": return this.getLib(name);
|
|
160
196
|
case "software": return this.getSoftware(name);
|
|
161
197
|
case "asset": return this.getAsset(name);
|
|
198
|
+
case "wasm": return this.getWasm(name);
|
|
162
199
|
case "test": return;
|
|
163
200
|
default: assertNever(name.type);
|
|
164
201
|
}
|
|
@@ -168,7 +205,8 @@ var TengoTemplateCompiler = class {
|
|
|
168
205
|
templates: [],
|
|
169
206
|
libs: [],
|
|
170
207
|
software: [],
|
|
171
|
-
assets: []
|
|
208
|
+
assets: [],
|
|
209
|
+
wasm: []
|
|
172
210
|
};
|
|
173
211
|
let current = [];
|
|
174
212
|
for (const src of sources) if (src.fullName.type === "library") {
|
|
@@ -180,6 +218,9 @@ var TengoTemplateCompiler = class {
|
|
|
180
218
|
} else if (src.fullName.type === "asset") {
|
|
181
219
|
this.addAsset(src);
|
|
182
220
|
result.assets.push(src);
|
|
221
|
+
} else if (src.fullName.type === "wasm") {
|
|
222
|
+
this.addWasm(src);
|
|
223
|
+
result.wasm.push(src);
|
|
183
224
|
} else current.push(src);
|
|
184
225
|
while (current.length > 0) {
|
|
185
226
|
const unprocessed = [];
|
|
@@ -207,6 +248,10 @@ var TengoTemplateCompiler = class {
|
|
|
207
248
|
this.addAsset(src);
|
|
208
249
|
result.assets.push(src);
|
|
209
250
|
break;
|
|
251
|
+
case "wasm":
|
|
252
|
+
this.addWasm(src);
|
|
253
|
+
result.wasm.push(src);
|
|
254
|
+
break;
|
|
210
255
|
case "template":
|
|
211
256
|
try {
|
|
212
257
|
const tpl = this.compileAndAddTemplate(src);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.js","names":[],"sources":["../../src/compiler/compiler.ts"],"sourcesContent":["import type { ArtifactSource } from \"./source\";\nimport type { TemplateWithSource } from \"./template\";\nimport { newTemplateWithSource } from \"./template\";\nimport type { TypedArtifactName, FullArtifactName, CompileMode } from \"./package\";\nimport {\n fullNameToString,\n typedArtifactNameToString,\n artifactNameToString,\n formatArtefactNameAndVersion,\n typedArtifactNamesEquals,\n fullNameEquals,\n} from \"./package\";\nimport { ArtifactStore } from \"./artifactset\";\nimport { assertNever } from \"./util\";\nimport { applyLibraryCompilerOptions, applyTemplateCompilerOptions } from \"./compileroptions\";\nimport type { CompiledTemplateV3 } from \"@milaboratories/pl-model-backend\";\n\n/** A compilation result. */\nexport interface TemplatesAndLibs {\n templates: TemplateWithSource[];\n libs: ArtifactSource[];\n software: ArtifactSource[];\n assets: ArtifactSource[];\n}\n\nexport class TengoTemplateCompiler {\n private readonly libs = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly software = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly assets = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly templates = new ArtifactStore<TemplateWithSource>((tpl) => tpl.fullName);\n\n constructor(private readonly compileMode: CompileMode) {}\n\n /** Recursively add dependencies to the template. */\n private populateTemplateDataFromDependencies(\n fullName: FullArtifactName,\n data: CompiledTemplateV3,\n deps: TypedArtifactName[],\n trace: string[],\n ) {\n for (const dep of deps) {\n switch (dep.type) {\n case \"library\": {\n const lib = this.getLibOrError(dep);\n\n const recursionStart = trace.indexOf(artifactNameToString(dep));\n if (recursionStart >= 0) {\n const errorMessage =\n `library import recursion detected: ` +\n `${trace.slice(recursionStart).join(\" -> \")} -> ${artifactNameToString(dep)}`;\n throw new Error(errorMessage);\n }\n\n const tplLib = {\n ...formatArtefactNameAndVersion(lib.fullName),\n sourceHash: lib.sourceHash,\n };\n\n applyLibraryCompilerOptions(lib.compilerOptions, tplLib);\n data.template.libs[artifactNameToString(dep)] = tplLib;\n data.hashToSource[tplLib.sourceHash] = lib.src;\n\n // populate with transient library dependencies\n this.populateTemplateDataFromDependencies(fullName, data, lib.dependencies, [\n ...trace,\n artifactNameToString(dep),\n ]);\n\n break;\n }\n case \"software\": {\n const software = this.getSoftwareOrError(dep);\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(software.fullName),\n sourceHash: software.sourceHash,\n };\n data.hashToSource[software.sourceHash] = software.src;\n\n break;\n }\n case \"asset\": {\n const asset = this.getAssetOrError(dep);\n // Yes, we temporarily put assets into 'software' section of template, so controller can\n // handle it the right way without updates\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(asset.fullName),\n sourceHash: asset.sourceHash,\n };\n data.hashToSource[asset.sourceHash] = asset.src;\n break;\n }\n case \"template\": {\n if (typedArtifactNamesEquals(fullName, dep))\n // skipping self reference\n continue;\n\n const tpl = this.getTemplateOrError(dep);\n data.template.templates[artifactNameToString(dep)] = tpl.data.template;\n data.hashToSource[tpl.data.template.sourceHash] = tpl.source;\n\n // add all the sources of transitivedependencies to the resulted hashToSource\n for (const [hash, src] of Object.entries(tpl.data.hashToSource)) {\n data.hashToSource[hash] = src;\n }\n\n break;\n }\n case \"test\":\n throw new Error(\n `dependencies tree error: tests should never be part of template: ` +\n `${typedArtifactNameToString(dep)} is dependency of ${artifactNameToString(fullName)}`,\n );\n default:\n assertNever(dep.type);\n }\n }\n }\n\n /** This method assumes that all dependencies are already added to the compiler's context */\n private compileAndAddTemplate(tplSrc: ArtifactSource): CompiledTemplateV3 {\n if (tplSrc.fullName.type !== \"template\") throw new Error(\"unexpected source type\");\n\n // creating template with unpopulated dependencies\n const tplData: CompiledTemplateV3 = {\n type: \"pl.tengo-template.v3\",\n hashToSource: {\n [tplSrc.sourceHash]: tplSrc.src,\n },\n template: {\n ...formatArtefactNameAndVersion(tplSrc.fullName),\n templates: {},\n libs: {},\n software: {},\n assets: {},\n sourceHash: tplSrc.sourceHash,\n },\n };\n\n applyTemplateCompilerOptions(tplSrc.compilerOptions, tplData.template);\n\n // collecting dependencies in output format\n this.populateTemplateDataFromDependencies(tplSrc.fullName, tplData, tplSrc.dependencies, []);\n\n return tplData;\n }\n\n addLib(lib: ArtifactSource) {\n const libFromMap = this.libs.add(lib.compileMode, lib, false);\n if (libFromMap && !fullNameEquals(lib.fullName, libFromMap.fullName))\n throw new Error(\n `compiler already contain such library: adding = ${fullNameToString(lib.fullName)}, contains = ${fullNameToString(libFromMap.fullName)}`,\n );\n }\n\n allLibs(): ArtifactSource[] {\n return this.libs.array(this.compileMode);\n }\n\n getLib(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"library\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'library`);\n return this.libs.get(this.compileMode, name);\n }\n\n getLibOrError(name: TypedArtifactName): ArtifactSource {\n const lib = this.getLib(name);\n if (!lib) throw new Error(`library not found: ${artifactNameToString(name)}`);\n return lib;\n }\n\n checkLibs() {\n this.libs.forEach(this.compileMode, (lib) => {\n for (const dep of lib.dependencies) {\n if (dep.type === \"test\")\n throw new Error(\n `test should never be dependency of production code: ${typedArtifactNameToString(dep)} test is dependency of ${fullNameToString(lib.fullName)}`,\n );\n\n if (!this.getArtefact(dep))\n throw new Error(\n `unresolved dependency ${typedArtifactNameToString(dep)} for ${fullNameToString(lib.fullName)}`,\n );\n }\n });\n }\n\n addSoftware(software: ArtifactSource) {\n const swFromMap = this.software.add(software.compileMode, software, false);\n if (swFromMap && !fullNameEquals(software.fullName, swFromMap.fullName))\n throw new Error(\n `compiler already contain info for software: adding = ${fullNameToString(software.fullName)}, contains = ${fullNameToString(swFromMap.fullName)}`,\n );\n }\n\n allSoftware(): ArtifactSource[] {\n return this.software.array(this.compileMode);\n }\n\n getSoftware(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"software\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'software`);\n\n return this.software.get(this.compileMode, name);\n }\n\n getSoftwareOrError(name: TypedArtifactName): ArtifactSource {\n const software = this.getSoftware(name);\n if (!software) throw new Error(`software info not found: ${artifactNameToString(name)}`);\n return software;\n }\n\n addAsset(asset: ArtifactSource) {\n const assetFromMap = this.assets.add(asset.compileMode, asset, false);\n if (assetFromMap && !fullNameEquals(asset.fullName, assetFromMap.fullName))\n throw new Error(\n `compiler already contain info for asset: adding = ${fullNameToString(asset.fullName)}, contains = ${fullNameToString(assetFromMap.fullName)}`,\n );\n }\n\n allAssets(): ArtifactSource[] {\n return this.assets.array(this.compileMode);\n }\n\n getAsset(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"asset\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'asset`);\n\n return this.assets.get(this.compileMode, name);\n }\n\n getAssetOrError(name: TypedArtifactName): ArtifactSource {\n const asset = this.getAsset(name);\n if (!asset) throw new Error(`asset info not found: ${artifactNameToString(name)}`);\n return asset;\n }\n\n addTemplate(tpl: TemplateWithSource) {\n const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);\n if (tplFromMap && !fullNameEquals(tpl.fullName, tplFromMap.fullName))\n throw new Error(\n `compiler already contain such template: adding = ${fullNameToString(tpl.fullName)}, contains = ${fullNameToString(tplFromMap.fullName)}`,\n );\n }\n\n allTemplates(): TemplateWithSource[] {\n return this.templates.array(this.compileMode);\n }\n\n getTemplate(name: TypedArtifactName): TemplateWithSource | undefined {\n if (name.type !== \"template\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'template`);\n return this.templates.get(this.compileMode, name);\n }\n\n getTemplateOrError(name: TypedArtifactName): TemplateWithSource {\n const tpl = this.getTemplate(name);\n if (!tpl) throw new Error(`template not found: ${artifactNameToString(name)}`);\n return tpl;\n }\n\n getArtefact(name: TypedArtifactName): ArtifactSource | TemplateWithSource | undefined {\n switch (name.type) {\n case \"template\":\n return this.getTemplate(name);\n case \"library\":\n return this.getLib(name);\n case \"software\":\n return this.getSoftware(name);\n case \"asset\":\n return this.getAsset(name);\n case \"test\":\n // Tests are ignored by the complier. They should never be compiled into templates or libs and\n // should never be a dependency.\n return undefined;\n default:\n assertNever(name.type);\n }\n }\n\n compileAndAdd(sources: ArtifactSource[]): TemplatesAndLibs {\n const result: TemplatesAndLibs = {\n templates: [],\n libs: [],\n software: [],\n assets: [],\n };\n\n let current: ArtifactSource[] = [];\n\n for (const src of sources) {\n if (src.fullName.type === \"library\") {\n // add libraries 'as-is' to be able to resolve them as dependencies\n this.addLib(src);\n result.libs.push(src);\n } else if (src.fullName.type === \"software\") {\n // add software 'as-is' to be able to resolve them as dependencies\n this.addSoftware(src);\n result.software.push(src);\n } else if (src.fullName.type === \"asset\") {\n // add assets 'as-is' to be able to resolve them as dependencies\n this.addAsset(src);\n result.assets.push(src);\n } else {\n current.push(src);\n }\n }\n\n while (current.length > 0) {\n const unprocessed: { src: ArtifactSource; err: Error }[] = [];\n\n for (const src of current) {\n //\n // If one of the dependencies can't be resolved with current compiler context,\n // we put aside the source until next iteration, in hope that the dependency\n // will be satisfied then.\n //\n // This is equivalent to topological sorting of input sources.\n //\n const unsatisfied = src.dependencies.filter(\n (dep) =>\n !this.getArtefact(dep) &&\n // allow self reference for templates\n !(src.fullName.type === \"template\" && typedArtifactNamesEquals(src.fullName, dep)),\n );\n if (unsatisfied.length > 0) {\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n for (const dep of unsatisfied) {\n errorMessage += ` - ${typedArtifactNameToString(dep)}\\n`;\n }\n unprocessed.push({ src, err: new Error(errorMessage) });\n\n continue;\n }\n\n // type specific processing\n switch (src.fullName.type) {\n case \"library\":\n // libraries are added as is\n this.addLib(src);\n result.libs.push(src);\n break;\n case \"software\":\n // software dependencies are added as is\n this.addSoftware(src);\n result.software.push(src);\n break;\n case \"asset\":\n // software dependencies are added as is\n this.addAsset(src);\n result.assets.push(src);\n break;\n case \"template\":\n // templates are compiled and then added\n try {\n const tpl = this.compileAndAddTemplate(src);\n const tplWithSrc = newTemplateWithSource(src.compileMode, src.fullName, tpl, src.src);\n this.addTemplate(tplWithSrc);\n result.templates.push(tplWithSrc);\n } catch (error: unknown) {\n const err = error as Error;\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n errorMessage += ` - ${err.message}\\n`;\n\n unprocessed.push({ src, err: Error(errorMessage) }); // one or more dependencies are not resolvable yet\n }\n break;\n case \"test\":\n // Ignore tests: they never should be part of compiled code or be a dependency.\n break;\n default:\n assertNever(src.fullName.type);\n }\n }\n\n // checking that we successfully added at least one source,\n // if not all the source files in unprocessed array have unmet dependencies\n if (current.length === unprocessed.length) {\n let errorMessage = \"\";\n\n for (const u of unprocessed) {\n errorMessage += `\\n${u.err.message}`;\n }\n throw new Error(errorMessage);\n }\n\n current = unprocessed.map(({ src: ArtifactSource }) => ArtifactSource);\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compiler.js","names":[],"sources":["../../src/compiler/compiler.ts"],"sourcesContent":["import type { ArtifactSource } from \"./source\";\nimport type { TemplateWithSource } from \"./template\";\nimport { newTemplateWithSource } from \"./template\";\nimport type { TypedArtifactName, FullArtifactName, CompileMode } from \"./package\";\nimport {\n fullNameToString,\n typedArtifactNameToString,\n artifactNameToString,\n formatArtefactNameAndVersion,\n typedArtifactNamesEquals,\n fullNameEquals,\n} from \"./package\";\nimport { ArtifactStore } from \"./artifactset\";\nimport { assertNever } from \"./util\";\nimport { applyLibraryCompilerOptions, applyTemplateCompilerOptions } from \"./compileroptions\";\nimport type {\n BackendCapability,\n CompiledTemplateV3,\n TemplateDataV3,\n} from \"@milaboratories/pl-model-backend\";\n\n/** Add a capability token to a template's `requiredCapabilities` list,\n * skipping duplicates. Initializes the array lazily so the field stays\n * absent for templates that need nothing. */\nfunction addRequiredCapability(template: TemplateDataV3, capability: BackendCapability): void {\n template.requiredCapabilities = template.requiredCapabilities ?? [];\n if (!template.requiredCapabilities.includes(capability)) {\n template.requiredCapabilities.push(capability);\n }\n}\n\n/** A compilation result. */\nexport interface TemplatesAndLibs {\n templates: TemplateWithSource[];\n libs: ArtifactSource[];\n software: ArtifactSource[];\n assets: ArtifactSource[];\n wasm: ArtifactSource[];\n}\n\nexport class TengoTemplateCompiler {\n private readonly libs = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly software = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly assets = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly wasm = new ArtifactStore<ArtifactSource>((src) => src.fullName);\n private readonly templates = new ArtifactStore<TemplateWithSource>((tpl) => tpl.fullName);\n\n constructor(private readonly compileMode: CompileMode) {}\n\n /** Recursively add dependencies to the template. */\n private populateTemplateDataFromDependencies(\n fullName: FullArtifactName,\n data: CompiledTemplateV3,\n deps: TypedArtifactName[],\n trace: string[],\n ) {\n for (const dep of deps) {\n switch (dep.type) {\n case \"library\": {\n const lib = this.getLibOrError(dep);\n\n const recursionStart = trace.indexOf(artifactNameToString(dep));\n if (recursionStart >= 0) {\n const errorMessage =\n `library import recursion detected: ` +\n `${trace.slice(recursionStart).join(\" -> \")} -> ${artifactNameToString(dep)}`;\n throw new Error(errorMessage);\n }\n\n const tplLib = {\n ...formatArtefactNameAndVersion(lib.fullName),\n sourceHash: lib.sourceHash,\n };\n\n applyLibraryCompilerOptions(lib.compilerOptions, tplLib);\n data.template.libs[artifactNameToString(dep)] = tplLib;\n data.hashToSource[tplLib.sourceHash] = lib.src;\n\n // populate with transient library dependencies\n this.populateTemplateDataFromDependencies(fullName, data, lib.dependencies, [\n ...trace,\n artifactNameToString(dep),\n ]);\n\n break;\n }\n case \"software\": {\n const software = this.getSoftwareOrError(dep);\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(software.fullName),\n sourceHash: software.sourceHash,\n };\n data.hashToSource[software.sourceHash] = software.src;\n\n break;\n }\n case \"asset\": {\n const asset = this.getAssetOrError(dep);\n // Yes, we temporarily put assets into 'software' section of template, so controller can\n // handle it the right way without updates\n data.template.software[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(asset.fullName),\n sourceHash: asset.sourceHash,\n };\n data.hashToSource[asset.sourceHash] = asset.src;\n break;\n }\n case \"wasm\": {\n const wasm = this.getWasmOrError(dep);\n data.template.wasm = data.template.wasm ?? {};\n data.template.wasm[artifactNameToString(dep)] = {\n ...formatArtefactNameAndVersion(wasm.fullName),\n sourceHash: wasm.sourceHash,\n };\n data.hashToSource[wasm.sourceHash] = wasm.src;\n // Embedding a wasm artifact means this template requires the\n // backend's wasm runtime to run. The token is propagated upward\n // when this template is in turn embedded as a sub-template.\n addRequiredCapability(data.template, \"wasm:v1\");\n break;\n }\n case \"template\": {\n if (typedArtifactNamesEquals(fullName, dep))\n // skipping self reference\n continue;\n\n const tpl = this.getTemplateOrError(dep);\n data.template.templates[artifactNameToString(dep)] = tpl.data.template;\n data.hashToSource[tpl.data.template.sourceHash] = tpl.source;\n\n // add all the sources of transitivedependencies to the resulted hashToSource\n for (const [hash, src] of Object.entries(tpl.data.hashToSource)) {\n data.hashToSource[hash] = src;\n }\n\n // Union the sub-template's compile-time-computed capability\n // requirements into ours, so the top template carries the full\n // transitive set without consumers having to walk the tree.\n for (const cap of tpl.data.template.requiredCapabilities ?? []) {\n addRequiredCapability(data.template, cap);\n }\n\n break;\n }\n case \"test\":\n throw new Error(\n `dependencies tree error: tests should never be part of template: ` +\n `${typedArtifactNameToString(dep)} is dependency of ${artifactNameToString(fullName)}`,\n );\n default:\n assertNever(dep.type);\n }\n }\n }\n\n /** This method assumes that all dependencies are already added to the compiler's context */\n private compileAndAddTemplate(tplSrc: ArtifactSource): CompiledTemplateV3 {\n if (tplSrc.fullName.type !== \"template\") throw new Error(\"unexpected source type\");\n\n // creating template with unpopulated dependencies\n const tplData: CompiledTemplateV3 = {\n type: \"pl.tengo-template.v3\",\n hashToSource: {\n [tplSrc.sourceHash]: tplSrc.src,\n },\n template: {\n ...formatArtefactNameAndVersion(tplSrc.fullName),\n templates: {},\n libs: {},\n software: {},\n assets: {},\n sourceHash: tplSrc.sourceHash,\n },\n };\n\n applyTemplateCompilerOptions(tplSrc.compilerOptions, tplData.template);\n\n // collecting dependencies in output format\n this.populateTemplateDataFromDependencies(tplSrc.fullName, tplData, tplSrc.dependencies, []);\n\n return tplData;\n }\n\n addLib(lib: ArtifactSource) {\n const libFromMap = this.libs.add(lib.compileMode, lib, false);\n if (libFromMap && !fullNameEquals(lib.fullName, libFromMap.fullName))\n throw new Error(\n `compiler already contain such library: adding = ${fullNameToString(lib.fullName)}, contains = ${fullNameToString(libFromMap.fullName)}`,\n );\n }\n\n allLibs(): ArtifactSource[] {\n return this.libs.array(this.compileMode);\n }\n\n getLib(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"library\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'library`);\n return this.libs.get(this.compileMode, name);\n }\n\n getLibOrError(name: TypedArtifactName): ArtifactSource {\n const lib = this.getLib(name);\n if (!lib) throw new Error(`library not found: ${artifactNameToString(name)}`);\n return lib;\n }\n\n checkLibs() {\n this.libs.forEach(this.compileMode, (lib) => {\n for (const dep of lib.dependencies) {\n if (dep.type === \"test\")\n throw new Error(\n `test should never be dependency of production code: ${typedArtifactNameToString(dep)} test is dependency of ${fullNameToString(lib.fullName)}`,\n );\n\n if (!this.getArtefact(dep))\n throw new Error(\n `unresolved dependency ${typedArtifactNameToString(dep)} for ${fullNameToString(lib.fullName)}`,\n );\n }\n });\n }\n\n addSoftware(software: ArtifactSource) {\n const swFromMap = this.software.add(software.compileMode, software, false);\n if (swFromMap && !fullNameEquals(software.fullName, swFromMap.fullName))\n throw new Error(\n `compiler already contain info for software: adding = ${fullNameToString(software.fullName)}, contains = ${fullNameToString(swFromMap.fullName)}`,\n );\n }\n\n allSoftware(): ArtifactSource[] {\n return this.software.array(this.compileMode);\n }\n\n getSoftware(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"software\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'software`);\n\n return this.software.get(this.compileMode, name);\n }\n\n getSoftwareOrError(name: TypedArtifactName): ArtifactSource {\n const software = this.getSoftware(name);\n if (!software) throw new Error(`software info not found: ${artifactNameToString(name)}`);\n return software;\n }\n\n addAsset(asset: ArtifactSource) {\n const assetFromMap = this.assets.add(asset.compileMode, asset, false);\n if (assetFromMap && !fullNameEquals(asset.fullName, assetFromMap.fullName))\n throw new Error(\n `compiler already contain info for asset: adding = ${fullNameToString(asset.fullName)}, contains = ${fullNameToString(assetFromMap.fullName)}`,\n );\n }\n\n allAssets(): ArtifactSource[] {\n return this.assets.array(this.compileMode);\n }\n\n getAsset(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"asset\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'asset`);\n\n return this.assets.get(this.compileMode, name);\n }\n\n getAssetOrError(name: TypedArtifactName): ArtifactSource {\n const asset = this.getAsset(name);\n if (!asset) throw new Error(`asset info not found: ${artifactNameToString(name)}`);\n return asset;\n }\n\n addWasm(wasm: ArtifactSource) {\n const wasmFromMap = this.wasm.add(wasm.compileMode, wasm, false);\n if (wasmFromMap && !fullNameEquals(wasm.fullName, wasmFromMap.fullName))\n throw new Error(\n `compiler already contain info for wasm: adding = ${fullNameToString(wasm.fullName)}, contains = ${fullNameToString(wasmFromMap.fullName)}`,\n );\n }\n\n allWasm(): ArtifactSource[] {\n return this.wasm.array(this.compileMode);\n }\n\n getWasm(name: TypedArtifactName): ArtifactSource | undefined {\n if (name.type !== \"wasm\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'wasm'`);\n\n return this.wasm.get(this.compileMode, name);\n }\n\n getWasmOrError(name: TypedArtifactName): ArtifactSource {\n const wasm = this.getWasm(name);\n if (!wasm) throw new Error(`wasm info not found: ${artifactNameToString(name)}`);\n return wasm;\n }\n\n addTemplate(tpl: TemplateWithSource) {\n const tplFromMap = this.templates.add(tpl.compileMode, tpl, false);\n if (tplFromMap && !fullNameEquals(tpl.fullName, tplFromMap.fullName))\n throw new Error(\n `compiler already contain such template: adding = ${fullNameToString(tpl.fullName)}, contains = ${fullNameToString(tplFromMap.fullName)}`,\n );\n }\n\n allTemplates(): TemplateWithSource[] {\n return this.templates.array(this.compileMode);\n }\n\n getTemplate(name: TypedArtifactName): TemplateWithSource | undefined {\n if (name.type !== \"template\")\n throw new Error(`illegal artifact type: got ${name.type} instead of 'template`);\n return this.templates.get(this.compileMode, name);\n }\n\n getTemplateOrError(name: TypedArtifactName): TemplateWithSource {\n const tpl = this.getTemplate(name);\n if (!tpl) throw new Error(`template not found: ${artifactNameToString(name)}`);\n return tpl;\n }\n\n getArtefact(name: TypedArtifactName): ArtifactSource | TemplateWithSource | undefined {\n switch (name.type) {\n case \"template\":\n return this.getTemplate(name);\n case \"library\":\n return this.getLib(name);\n case \"software\":\n return this.getSoftware(name);\n case \"asset\":\n return this.getAsset(name);\n case \"wasm\":\n return this.getWasm(name);\n case \"test\":\n // Tests are ignored by the complier. They should never be compiled into templates or libs and\n // should never be a dependency.\n return undefined;\n default:\n assertNever(name.type);\n }\n }\n\n compileAndAdd(sources: ArtifactSource[]): TemplatesAndLibs {\n const result: TemplatesAndLibs = {\n templates: [],\n libs: [],\n software: [],\n assets: [],\n wasm: [],\n };\n\n let current: ArtifactSource[] = [];\n\n for (const src of sources) {\n if (src.fullName.type === \"library\") {\n // add libraries 'as-is' to be able to resolve them as dependencies\n this.addLib(src);\n result.libs.push(src);\n } else if (src.fullName.type === \"software\") {\n // add software 'as-is' to be able to resolve them as dependencies\n this.addSoftware(src);\n result.software.push(src);\n } else if (src.fullName.type === \"asset\") {\n // add assets 'as-is' to be able to resolve them as dependencies\n this.addAsset(src);\n result.assets.push(src);\n } else if (src.fullName.type === \"wasm\") {\n // add wasm 'as-is' to be able to resolve them as dependencies\n this.addWasm(src);\n result.wasm.push(src);\n } else {\n current.push(src);\n }\n }\n\n while (current.length > 0) {\n const unprocessed: { src: ArtifactSource; err: Error }[] = [];\n\n for (const src of current) {\n //\n // If one of the dependencies can't be resolved with current compiler context,\n // we put aside the source until next iteration, in hope that the dependency\n // will be satisfied then.\n //\n // This is equivalent to topological sorting of input sources.\n //\n const unsatisfied = src.dependencies.filter(\n (dep) =>\n !this.getArtefact(dep) &&\n // allow self reference for templates\n !(src.fullName.type === \"template\" && typedArtifactNamesEquals(src.fullName, dep)),\n );\n if (unsatisfied.length > 0) {\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n for (const dep of unsatisfied) {\n errorMessage += ` - ${typedArtifactNameToString(dep)}\\n`;\n }\n unprocessed.push({ src, err: new Error(errorMessage) });\n\n continue;\n }\n\n // type specific processing\n switch (src.fullName.type) {\n case \"library\":\n // libraries are added as is\n this.addLib(src);\n result.libs.push(src);\n break;\n case \"software\":\n // software dependencies are added as is\n this.addSoftware(src);\n result.software.push(src);\n break;\n case \"asset\":\n // software dependencies are added as is\n this.addAsset(src);\n result.assets.push(src);\n break;\n case \"wasm\":\n // wasm dependencies are added as is\n this.addWasm(src);\n result.wasm.push(src);\n break;\n case \"template\":\n // templates are compiled and then added\n try {\n const tpl = this.compileAndAddTemplate(src);\n const tplWithSrc = newTemplateWithSource(src.compileMode, src.fullName, tpl, src.src);\n this.addTemplate(tplWithSrc);\n result.templates.push(tplWithSrc);\n } catch (error: unknown) {\n const err = error as Error;\n let errorMessage = `Unsatisfied dependencies in ${fullNameToString(src.fullName)}:\\n`;\n errorMessage += ` - ${err.message}\\n`;\n\n unprocessed.push({ src, err: Error(errorMessage) }); // one or more dependencies are not resolvable yet\n }\n break;\n case \"test\":\n // Ignore tests: they never should be part of compiled code or be a dependency.\n break;\n default:\n assertNever(src.fullName.type);\n }\n }\n\n // checking that we successfully added at least one source,\n // if not all the source files in unprocessed array have unmet dependencies\n if (current.length === unprocessed.length) {\n let errorMessage = \"\";\n\n for (const u of unprocessed) {\n errorMessage += `\\n${u.err.message}`;\n }\n throw new Error(errorMessage);\n }\n\n current = unprocessed.map(({ src: ArtifactSource }) => ArtifactSource);\n }\n\n return result;\n }\n}\n"],"mappings":"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"}
|
package/dist/compiler/main.cjs
CHANGED
|
@@ -4,6 +4,7 @@ const require_package = require("./package.cjs");
|
|
|
4
4
|
const require_template = require("./template.cjs");
|
|
5
5
|
const require_compiler = require("./compiler.cjs");
|
|
6
6
|
const require_source = require("./source.cjs");
|
|
7
|
+
const require_pack_limits = require("./pack_limits.cjs");
|
|
7
8
|
let node_path = require("node:path");
|
|
8
9
|
node_path = require_runtime.__toESM(node_path);
|
|
9
10
|
let node_fs = require("node:fs");
|
|
@@ -11,10 +12,13 @@ node_fs = require_runtime.__toESM(node_fs);
|
|
|
11
12
|
let _milaboratories_pl_model_backend = require("@milaboratories/pl-model-backend");
|
|
12
13
|
let _milaboratories_resolve_helper = require("@milaboratories/resolve-helper");
|
|
13
14
|
//#region src/compiler/main.ts
|
|
15
|
+
const wasmExportCondition = "wasm";
|
|
16
|
+
const defaultWasmExportId = "main";
|
|
14
17
|
const compiledTplSuffix = ".plj.gz";
|
|
15
18
|
const compiledLibSuffix = ".lib.tengo";
|
|
16
19
|
const compiledSoftwareSuffix = ".sw.json";
|
|
17
20
|
const compiledAssetSuffix = ".as.json";
|
|
21
|
+
const compiledWasmSuffix = ".wasm";
|
|
18
22
|
const srcTestSuffix = ".test.tengo";
|
|
19
23
|
const srcTplSuffix = ".tpl.tengo";
|
|
20
24
|
const srcLibSuffix = ".lib.tengo";
|
|
@@ -42,11 +46,20 @@ function resolvePackageJsonPackage(root, depPackageName) {
|
|
|
42
46
|
} while (depth < 7 && node_path.basename(resolved) !== "node_modules");
|
|
43
47
|
}
|
|
44
48
|
const resolved2 = (0, _milaboratories_resolve_helper.tryResolveOrError)(root, `${depPackageName}/package.json`);
|
|
45
|
-
if (resolved2.result
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
if (resolved2.result !== void 0) return resolved2.result;
|
|
50
|
+
if (resolved2.err === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
|
|
51
|
+
const fromNodeModules = findInNodeModules(root, depPackageName);
|
|
52
|
+
if (fromNodeModules !== void 0) return fromNodeModules;
|
|
53
|
+
return;
|
|
48
54
|
}
|
|
49
|
-
|
|
55
|
+
throw new Error(`Can't resolve package.json for package ${depPackageName ?? "."} relative to ${root}`);
|
|
56
|
+
}
|
|
57
|
+
function findInNodeModules(root, depPackageName) {
|
|
58
|
+
const candidate = node_path.join(root, "node_modules", depPackageName, "package.json");
|
|
59
|
+
if (require_util.pathType(candidate) === "file") return candidate;
|
|
60
|
+
const parent = node_path.dirname(root);
|
|
61
|
+
if (parent === root) return void 0;
|
|
62
|
+
return findInNodeModules(parent, depPackageName);
|
|
50
63
|
}
|
|
51
64
|
function resolvePackageJsonRoot(root) {
|
|
52
65
|
if (!node_path.isAbsolute(root)) throw new Error(`Root path must be absolute: ${root}`);
|
|
@@ -97,6 +110,9 @@ function resolveSoftwareDst(mode, root) {
|
|
|
97
110
|
function resolveAssetsDst(mode, root) {
|
|
98
111
|
return node_path.resolve(root, mode, "tengo", "asset");
|
|
99
112
|
}
|
|
113
|
+
function resolveWasmDst(mode, root) {
|
|
114
|
+
return node_path.resolve(root, mode, "tengo", "wasm");
|
|
115
|
+
}
|
|
100
116
|
function loadDependencies(logger, compiler, packageInfo) {
|
|
101
117
|
for (const dep of packageInfo.dependencies) loadDependencies(logger, compiler, dep);
|
|
102
118
|
if (packageInfo.context === "root") return;
|
|
@@ -104,11 +120,14 @@ function loadDependencies(logger, compiler, packageInfo) {
|
|
|
104
120
|
const tplDistFolder = resolveTemplatesDst("dist", packageInfo.root);
|
|
105
121
|
const softwareDistFolder = resolveSoftwareDst("dist", packageInfo.root);
|
|
106
122
|
const assetDistFolder = resolveAssetsDst("dist", packageInfo.root);
|
|
123
|
+
const wasmDistFolder = resolveWasmDst("dist", packageInfo.root);
|
|
107
124
|
const libDistExists = require_util.pathType(libDistFolder) === "dir";
|
|
108
125
|
const tplDistExists = require_util.pathType(tplDistFolder) === "dir";
|
|
109
126
|
const softwareDistExists = require_util.pathType(softwareDistFolder) === "dir";
|
|
110
127
|
const assetDistExists = require_util.pathType(assetDistFolder) === "dir";
|
|
111
|
-
|
|
128
|
+
const wasmDistExists = require_util.pathType(wasmDistFolder) === "dir";
|
|
129
|
+
const wasmExports = collectWasmExportPaths(packageInfo.root);
|
|
130
|
+
if (!libDistExists && !tplDistExists && !softwareDistExists && !assetDistExists && !wasmDistExists && wasmExports.length === 0) return;
|
|
112
131
|
const packageId = {
|
|
113
132
|
name: packageInfo.name,
|
|
114
133
|
version: packageInfo.version
|
|
@@ -117,6 +136,8 @@ function loadDependencies(logger, compiler, packageInfo) {
|
|
|
117
136
|
if (tplDistExists) loadTemplatesFromDir(logger, packageId, "dist", tplDistFolder, compiler);
|
|
118
137
|
if (softwareDistExists) loadSoftwareFromDir(logger, packageId, "dist", softwareDistFolder, compiler);
|
|
119
138
|
if (assetDistExists) loadAssetsFromDir(logger, packageId, "dist", assetDistFolder, compiler);
|
|
139
|
+
if (wasmDistExists) loadWasmFromDir(logger, packageId, "dist", wasmDistFolder, compiler);
|
|
140
|
+
for (const wasmExport of wasmExports) loadWasmFromExport(logger, packageId, "dist", packageInfo.root, wasmExport, compiler);
|
|
120
141
|
}
|
|
121
142
|
function loadLibsFromDir(logger, packageId, mode, folder, compiler) {
|
|
122
143
|
for (const f of node_fs.readdirSync(folder)) {
|
|
@@ -184,6 +205,100 @@ function loadAssetsFromDir(logger, packageId, mode, folder, compiler) {
|
|
|
184
205
|
compiler.addAsset(asset);
|
|
185
206
|
}
|
|
186
207
|
}
|
|
208
|
+
function loadWasmFromDir(logger, packageId, mode, folder, compiler) {
|
|
209
|
+
for (const f of node_fs.readdirSync(folder)) {
|
|
210
|
+
const file = node_path.resolve(folder, f);
|
|
211
|
+
if (!f.endsWith(compiledWasmSuffix)) throw new Error(`unexpected file in 'wasm' folder: ${file}`);
|
|
212
|
+
addWasmFile(logger, mode, file, {
|
|
213
|
+
type: "wasm",
|
|
214
|
+
pkg: packageId.name,
|
|
215
|
+
id: f.slice(0, f.length - 5),
|
|
216
|
+
version: packageId.version
|
|
217
|
+
}, compiler);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function loadWasmFromExport(logger, packageId, mode, packageRoot, wasmExport, compiler) {
|
|
221
|
+
const file = node_path.resolve(packageRoot, wasmExport.relPath);
|
|
222
|
+
if (require_util.pathType(file) !== "file") throw new Error(`wasm export "${wasmExport.id}" points to missing file: ${file} (package ${packageId.name})`);
|
|
223
|
+
addWasmFile(logger, mode, file, {
|
|
224
|
+
type: "wasm",
|
|
225
|
+
pkg: packageId.name,
|
|
226
|
+
id: wasmExport.id,
|
|
227
|
+
version: packageId.version
|
|
228
|
+
}, compiler);
|
|
229
|
+
}
|
|
230
|
+
function addWasmFile(logger, mode, file, fullName, compiler) {
|
|
231
|
+
const bytes = node_fs.readFileSync(file);
|
|
232
|
+
require_pack_limits.assertWasmFileSize(file, bytes.length, fullName);
|
|
233
|
+
const source = bytes.toString("base64");
|
|
234
|
+
const wasm = new require_source.ArtifactSource(mode, fullName, require_source.getSha256(source), source, file, [], []);
|
|
235
|
+
logger.debug(`Adding dependency ${require_package.fullNameToString(fullName)} from ${file}`);
|
|
236
|
+
compiler.addWasm(wasm);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Discover wasm artifacts declared by a package's `package.json` via the
|
|
240
|
+
* node `exports` conditional-exports map.
|
|
241
|
+
*
|
|
242
|
+
* Convention: a package that wants to ship one or more wasm components to
|
|
243
|
+
* tengo-builder publishes them under a `"wasm"` condition keyed by an
|
|
244
|
+
* `exports` subpath. The subpath becomes the wasm artifact id (`.` →
|
|
245
|
+
* `main`, `./foo` → `foo`). Example shape we look for:
|
|
246
|
+
*
|
|
247
|
+
* {
|
|
248
|
+
* "exports": {
|
|
249
|
+
* ".": {
|
|
250
|
+
* "wasm": "./dist/pframes_rs_wasip2.wasm", // ← discovered
|
|
251
|
+
* "wit": "./wit/world.wit"
|
|
252
|
+
* },
|
|
253
|
+
* "./extra": {
|
|
254
|
+
* "wasm": "./dist/extra.wasm" // ← discovered as id "extra"
|
|
255
|
+
* }
|
|
256
|
+
* }
|
|
257
|
+
* }
|
|
258
|
+
*
|
|
259
|
+
* Why raw traversal instead of Zod / a typed schema:
|
|
260
|
+
* 1. `package.json#exports` is a community convention with no fixed shape
|
|
261
|
+
* — any combination of strings, objects, arrays, and conditions is
|
|
262
|
+
* legal node syntax. A strict schema would either reject valid
|
|
263
|
+
* packages or have to admit `unknown` for half of it anyway.
|
|
264
|
+
* 2. We care about exactly one condition (`wasm`) on subpath entries,
|
|
265
|
+
* not the rest of the exports tree. A targeted walk reads more
|
|
266
|
+
* directly than a schema that re-describes the conditional-exports
|
|
267
|
+
* grammar.
|
|
268
|
+
* 3. Errors here should always mean "this package contributes no wasm";
|
|
269
|
+
* never crash the build. Every check returns `[]` or `continue`s.
|
|
270
|
+
*
|
|
271
|
+
* Returns the discovered wasm exports; empty when the file is missing,
|
|
272
|
+
* malformed, has no `exports`, or has no subpath with a `"wasm"`
|
|
273
|
+
* condition pointing at a string path.
|
|
274
|
+
*/
|
|
275
|
+
function collectWasmExportPaths(packageRoot) {
|
|
276
|
+
const packageJsonPath = node_path.join(packageRoot, "package.json");
|
|
277
|
+
if (require_util.pathType(packageJsonPath) !== "file") return [];
|
|
278
|
+
let raw;
|
|
279
|
+
try {
|
|
280
|
+
raw = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
|
|
281
|
+
} catch {
|
|
282
|
+
return [];
|
|
283
|
+
}
|
|
284
|
+
if (typeof raw !== "object" || raw === null) return [];
|
|
285
|
+
const exportsField = raw.exports;
|
|
286
|
+
if (typeof exportsField !== "object" || exportsField === null) return [];
|
|
287
|
+
const result = [];
|
|
288
|
+
for (const [subpath, value] of Object.entries(exportsField)) {
|
|
289
|
+
if (!subpath.startsWith(".")) continue;
|
|
290
|
+
if (typeof value !== "object" || value === null) continue;
|
|
291
|
+
const wasmPath = value[wasmExportCondition];
|
|
292
|
+
if (typeof wasmPath !== "string") continue;
|
|
293
|
+
const id = subpath === "." ? defaultWasmExportId : subpath.replace(/^\.\/?/, "");
|
|
294
|
+
if (!id) continue;
|
|
295
|
+
result.push({
|
|
296
|
+
id,
|
|
297
|
+
relPath: wasmPath
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
187
302
|
function parseSources(logger, packageId, mode, root, subdir) {
|
|
188
303
|
const sources = [];
|
|
189
304
|
for (const f of node_fs.readdirSync(node_path.join(root, subdir))) {
|
|
@@ -276,8 +391,10 @@ function savePacks(logger, compiled, mode) {
|
|
|
276
391
|
node_fs.mkdirSync(tplOutput, { recursive: true });
|
|
277
392
|
for (const tpl of compiled.templates) {
|
|
278
393
|
const file = node_path.resolve(tplOutput, tpl.fullName.id + compiledTplSuffix);
|
|
394
|
+
const packed = (0, _milaboratories_pl_model_backend.serializeTemplate)(tpl.data);
|
|
395
|
+
require_pack_limits.assertTemplatePackSize(require_package.fullNameToString(tpl.fullName), packed.byteLength, require_pack_limits.collectWasmContributions(tpl.data));
|
|
279
396
|
logger.info(` - writing ${file}`);
|
|
280
|
-
node_fs.writeFileSync(file,
|
|
397
|
+
node_fs.writeFileSync(file, packed);
|
|
281
398
|
}
|
|
282
399
|
}
|
|
283
400
|
if (compiled.software.length > 0) {
|
|
@@ -298,6 +415,15 @@ function savePacks(logger, compiled, mode) {
|
|
|
298
415
|
node_fs.writeFileSync(file, sw.src);
|
|
299
416
|
}
|
|
300
417
|
}
|
|
418
|
+
if (compiled.wasm.length > 0) {
|
|
419
|
+
const wasmOutput = resolveWasmDst(mode, ".");
|
|
420
|
+
node_fs.mkdirSync(wasmOutput, { recursive: true });
|
|
421
|
+
for (const wasm of compiled.wasm) {
|
|
422
|
+
const file = node_path.resolve(wasmOutput, wasm.fullName.id + compiledWasmSuffix);
|
|
423
|
+
logger.info(` - writing ${file}`);
|
|
424
|
+
node_fs.writeFileSync(file, Buffer.from(wasm.src, "base64"));
|
|
425
|
+
}
|
|
426
|
+
}
|
|
301
427
|
}
|
|
302
428
|
//#endregion
|
|
303
429
|
exports.compile = compile;
|