@harmoniclabs/pebble 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IR/IRNodes/IRConst.js +14 -3
- package/dist/IR/IRNodes/IRNative/index.js +5 -1
- package/dist/IR/toUPLC/CompilerOptions.d.ts +22 -7
- package/dist/IR/toUPLC/CompilerOptions.js +5 -1
- package/dist/IR/tree_utils/bytesToHex.d.ts +8 -0
- package/dist/IR/tree_utils/bytesToHex.js +69 -0
- package/dist/ast/nodes/expr/functions/FuncExpr.d.ts +16 -2
- package/dist/ast/nodes/expr/functions/FuncExpr.js +17 -0
- package/dist/ast/nodes/expr/litteral/LitteralExpr.d.ts +2 -1
- package/dist/ast/nodes/expr/litteral/LitteralExpr.js +2 -0
- package/dist/ast/nodes/expr/litteral/TemplateStrExpr.d.ts +30 -0
- package/dist/ast/nodes/expr/litteral/TemplateStrExpr.js +35 -0
- package/dist/ast/nodes/statements/ExportStmt.d.ts +3 -3
- package/dist/ast/nodes/statements/PebbleStmt.d.ts +4 -3
- package/dist/ast/nodes/statements/PebbleStmt.js +6 -2
- package/dist/ast/nodes/statements/TestParam.d.ts +18 -0
- package/dist/ast/nodes/statements/TestParam.js +18 -0
- package/dist/ast/nodes/statements/TestStmt.d.ts +5 -3
- package/dist/ast/nodes/statements/TestStmt.js +3 -1
- package/dist/ast/nodes/statements/UsingStmt.d.ts +32 -2
- package/dist/ast/nodes/statements/UsingStmt.js +39 -3
- package/dist/ast/nodes/statements/declarations/NamespaceDecl.d.ts +21 -0
- package/dist/ast/nodes/statements/declarations/NamespaceDecl.js +31 -0
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +26 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +203 -3
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +14 -4
- package/dist/compiler/AstCompiler/internal/exprs/_compileCallExpr.js +97 -6
- package/dist/compiler/AstCompiler/internal/exprs/_compileFuncExpr.js +12 -5
- package/dist/compiler/AstCompiler/internal/exprs/_compileLitteralExpr.js +59 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.d.ts +2 -3
- package/dist/compiler/AstCompiler/internal/exprs/_compilePropAccessExpr.js +28 -0
- package/dist/compiler/AstCompiler/internal/exprs/_compileVarAccessExpr.js +2 -0
- package/dist/compiler/AstCompiler/internal/statements/_compileStatement.js +4 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileTestStmt.d.ts +15 -1
- package/dist/compiler/AstCompiler/internal/statements/_compileTestStmt.js +70 -30
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingAliasStmt.d.ts +11 -0
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingAliasStmt.js +26 -0
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingStmt.d.ts +9 -4
- package/dist/compiler/AstCompiler/internal/statements/_compileUsingStmt.js +51 -10
- package/dist/compiler/AstCompiler/internal/types/_compileDataEncodedConcreteType.js +21 -2
- package/dist/compiler/AstCompiler/internal/types/_compileSopEncodedConcreteType.js +17 -2
- package/dist/compiler/AstCompiler/scope/AstScope.d.ts +70 -1
- package/dist/compiler/AstCompiler/scope/AstScope.js +91 -0
- package/dist/compiler/AstCompiler/utils/getPropAccessReturnType.js +25 -1
- package/dist/compiler/AstCompiler/utils/monomorphizeGeneric.d.ts +36 -0
- package/dist/compiler/AstCompiler/utils/monomorphizeGeneric.js +123 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespaceChain.d.ts +28 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespaceChain.js +95 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespacePath.d.ts +37 -0
- package/dist/compiler/AstCompiler/utils/resolveNamespacePath.js +93 -0
- package/dist/compiler/Compiler.d.ts +9 -1
- package/dist/compiler/Compiler.js +204 -9
- package/dist/compiler/TirCompiler/expressify/expressifyVars.js +26 -7
- package/dist/compiler/test/TestResult.d.ts +38 -0
- package/dist/compiler/test/TestResult.js +6 -0
- package/dist/compiler/test/fuzz/PRNG.d.ts +26 -0
- package/dist/compiler/test/fuzz/PRNG.js +59 -0
- package/dist/compiler/tir/expressions/TirExpr.d.ts +2 -1
- package/dist/compiler/tir/expressions/TirExpr.js +2 -0
- package/dist/compiler/tir/expressions/TirNativeFunc.d.ts +17 -0
- package/dist/compiler/tir/expressions/TirNativeFunc.js +53 -106
- package/dist/compiler/tir/expressions/TirShowExpr.d.ts +52 -0
- package/dist/compiler/tir/expressions/TirShowExpr.js +199 -0
- package/dist/compiler/tir/expressions/TirTraceExpr.js +11 -7
- package/dist/compiler/tir/program/TypedProgram.d.ts +101 -0
- package/dist/compiler/tir/program/TypedProgram.js +43 -0
- package/dist/compiler/tir/program/stdScope/populateBuiltinInterfaces.d.ts +17 -0
- package/dist/compiler/tir/program/stdScope/populateBuiltinInterfaces.js +70 -0
- package/dist/compiler/tir/program/stdScope/populateStdNamespace.d.ts +22 -0
- package/dist/compiler/tir/program/stdScope/populateStdNamespace.js +574 -0
- package/dist/compiler/tir/program/stdScope/stdScope.d.ts +1 -0
- package/dist/compiler/tir/program/stdScope/stdScope.js +1 -1
- package/dist/compiler/tir/statements/TirStmt.js +0 -1
- package/dist/compiler/tir/statements/TirTestStmt.d.ts +46 -0
- package/dist/compiler/tir/statements/TirTestStmt.js +35 -0
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.d.ts +50 -1
- package/dist/compiler/tir/types/TirNativeType/TirNativeType.js +53 -1
- package/dist/compiler/tir/types/TirType.js +3 -1
- package/dist/compiler/tir/types/utils/canAssignTo.js +8 -1
- package/dist/compiler/tir/types/utils/inferTypeArgs.d.ts +19 -0
- package/dist/compiler/tir/types/utils/inferTypeArgs.js +79 -0
- package/dist/compiler/tir/types/utils/substituteTypeParams.d.ts +9 -0
- package/dist/compiler/tir/types/utils/substituteTypeParams.js +62 -0
- package/dist/diagnostics/diagnosticMessages.generated.d.ts +5 -0
- package/dist/diagnostics/diagnosticMessages.generated.js +10 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/parser/Parser.d.ts +73 -3
- package/dist/parser/Parser.js +333 -33
- package/dist/tokenizer/Token.d.ts +105 -102
- package/dist/tokenizer/Token.js +110 -109
- package/dist/tokenizer/utils/tokenFromKeyword.js +9 -6
- package/dist/utils/semverSatisfies.d.ts +1 -0
- package/dist/utils/semverSatisfies.js +161 -0
- package/dist/version.generated.d.ts +1 -0
- package/dist/version.generated.js +2 -0
- package/package.json +4 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { VarStmt } from "../VarStmt.js";
|
|
2
|
+
import { FuncDecl } from "./FuncDecl.js";
|
|
3
|
+
import { InterfaceDecl } from "./InterfaceDecl.js";
|
|
4
|
+
import { isPebbleTypeDecl } from "./PebbleTypeDecl.js";
|
|
5
|
+
export function isNamespaceMemberStmt(thing) {
|
|
6
|
+
return (thing instanceof VarStmt
|
|
7
|
+
|| thing instanceof FuncDecl
|
|
8
|
+
|| isPebbleTypeDecl(thing)
|
|
9
|
+
|| thing instanceof InterfaceDecl
|
|
10
|
+
|| thing instanceof NamespaceDecl);
|
|
11
|
+
}
|
|
12
|
+
export class NamespaceMember {
|
|
13
|
+
isPrivate;
|
|
14
|
+
stmt;
|
|
15
|
+
range;
|
|
16
|
+
constructor(isPrivate, stmt, range) {
|
|
17
|
+
this.isPrivate = isPrivate;
|
|
18
|
+
this.stmt = stmt;
|
|
19
|
+
this.range = range;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class NamespaceDecl {
|
|
23
|
+
name;
|
|
24
|
+
members;
|
|
25
|
+
range;
|
|
26
|
+
constructor(name, members, range) {
|
|
27
|
+
this.name = name;
|
|
28
|
+
this.members = members;
|
|
29
|
+
this.range = range;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -86,6 +86,32 @@ export declare class AstCompiler extends DiagnosticEmitter {
|
|
|
86
86
|
private _collectInterfaceImplSigs;
|
|
87
87
|
private _collectTopLevelConst;
|
|
88
88
|
private _collectTopLevelFuncDeclSig;
|
|
89
|
+
/**
|
|
90
|
+
* Register a generic function template. Compile only the signature in a
|
|
91
|
+
* scope where each type parameter is bound to a `TirTypeParam`; the body
|
|
92
|
+
* is deferred until `monomorphizeGeneric` is invoked at a call site.
|
|
93
|
+
*/
|
|
94
|
+
private _registerGenericTemplate;
|
|
95
|
+
/**
|
|
96
|
+
* Resolve a `<T implements I>` constraint clause to a `TypeParamConstraint`.
|
|
97
|
+
*
|
|
98
|
+
* - `decl.constraint` must be a bare `AstNamedTypeExpr` (no type args).
|
|
99
|
+
* - The named interface must be registered in `scope.interfaces`
|
|
100
|
+
* (walking up the parent chain via `resolveInterface`).
|
|
101
|
+
*
|
|
102
|
+
* The returned object captures the AST method signatures verbatim so the
|
|
103
|
+
* monomorphizer doesn't have to re-resolve the interface each time.
|
|
104
|
+
*/
|
|
105
|
+
private _resolveTypeParamConstraint;
|
|
106
|
+
/**
|
|
107
|
+
* walks `stmts` for `NamespaceDecl` (optionally wrapped in `ExportStmt`),
|
|
108
|
+
* compiles each one into a `NamespaceSymbol`, and registers it on
|
|
109
|
+
* `enclosingScope` (and `enclosingExports` when exported).
|
|
110
|
+
*
|
|
111
|
+
* removes processed `NamespaceDecl` statements from `stmts`.
|
|
112
|
+
*/
|
|
113
|
+
private _collectNamespaceDeclarations;
|
|
114
|
+
private _compileNamespaceDecl;
|
|
89
115
|
private _collectInterfaceDeclarations;
|
|
90
116
|
registerInternalTypeDecl(decl: StructDecl | TypeAliasDecl): void;
|
|
91
117
|
private _collectTypeDeclarations;
|
|
@@ -29,14 +29,18 @@ import { CommonFlags } from "../../common.js";
|
|
|
29
29
|
import { SimpleVarDecl } from "../../ast/nodes/statements/declarations/VarDecl/SimpleVarDecl.js";
|
|
30
30
|
import { Identifier } from "../../ast/nodes/common/Identifier.js";
|
|
31
31
|
import { ArrowKind } from "../../ast/nodes/expr/functions/ArrowKind.js";
|
|
32
|
-
import { _compileFuncExpr } from "./internal/exprs/_compileFuncExpr.js";
|
|
32
|
+
import { _compileFuncExpr, getDataFuncSignature } from "./internal/exprs/_compileFuncExpr.js";
|
|
33
|
+
import { TirTypeParam } from "../tir/types/TirTypeParam.js";
|
|
33
34
|
import { ContractDecl } from "../../ast/nodes/statements/declarations/ContractDecl.js";
|
|
34
35
|
import { _deriveContractBody } from "./internal/_deriveContractBody/_deriveContractBody.js";
|
|
35
36
|
import { DiagnosticCategory } from "../../diagnostics/DiagnosticCategory.js";
|
|
36
37
|
import { VarStmt } from "../../ast/nodes/statements/VarStmt.js";
|
|
37
38
|
import { _compileSimpleVarDecl } from "./internal/statements/_compileVarStmt.js";
|
|
39
|
+
import { _compileTestStmt } from "./internal/statements/_compileTestStmt.js";
|
|
38
40
|
import { SourceTypeMap } from "../SourceTypeMap.js";
|
|
39
41
|
import { isIdentifier } from "../../utils/text.js";
|
|
42
|
+
import { TestStmt } from "../../ast/nodes/statements/TestStmt.js";
|
|
43
|
+
import { NamespaceDecl } from "../../ast/nodes/statements/declarations/NamespaceDecl.js";
|
|
40
44
|
/*
|
|
41
45
|
Handling type expressions that depend on other types
|
|
42
46
|
(such as generics, function return types, and inferred types from complex expressions)
|
|
@@ -273,6 +277,9 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
273
277
|
this._consumeImportsAddSymsInScope(stmts, src.absoluteProjPath, importsScope);
|
|
274
278
|
const topLevelScope = importsScope.newChildScope({ isFunctionDeclScope: false });
|
|
275
279
|
const srcExports = this.preludeScope.newChildScope({ isFunctionDeclScope: false });
|
|
280
|
+
// collect namespace declarations (recursively) so that types/interfaces/signatures
|
|
281
|
+
// can refer to symbols defined inside namespaces.
|
|
282
|
+
this._collectNamespaceDeclarations(stmts, src.uid, topLevelScope, srcExports);
|
|
276
283
|
// collect top level **type** (struct and aliases) declarations
|
|
277
284
|
this._collectTypeDeclarations(stmts, src.uid, topLevelScope, srcExports);
|
|
278
285
|
// collect top level **interface** declarations (NOT implementations)
|
|
@@ -300,6 +307,17 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
300
307
|
exportRange = stmt.range;
|
|
301
308
|
stmt = stmt.stmt;
|
|
302
309
|
}
|
|
310
|
+
if (stmt instanceof TestStmt) {
|
|
311
|
+
if (isEntryFile) {
|
|
312
|
+
const declContext = AstCompilationCtx.fromScope(this.program, topLevelScope);
|
|
313
|
+
_compileTestStmt(declContext, stmt, srcUid, this.cfg.entry);
|
|
314
|
+
}
|
|
315
|
+
// tests from non-entry files are dropped on the floor:
|
|
316
|
+
// they will be collected when their own file is the entry.
|
|
317
|
+
void stmts.splice(i, 1);
|
|
318
|
+
i--;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
303
321
|
if (!(stmt instanceof FuncDecl
|
|
304
322
|
|| stmt instanceof TypeImplementsStmt
|
|
305
323
|
|| stmt instanceof ContractDecl
|
|
@@ -428,6 +446,14 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
428
446
|
if (this._isExporting && astFuncName === this.program.contractTirFuncName) {
|
|
429
447
|
this.program.contractTirFuncName = tirFuncName;
|
|
430
448
|
}
|
|
449
|
+
// Generic function declaration path: do NOT compile the body. Instead,
|
|
450
|
+
// compile the signature in a scope where each type parameter resolves
|
|
451
|
+
// to a fresh `TirTypeParam`, then register a `GenericTemplate` on the
|
|
452
|
+
// program. Call sites instantiate it via `monomorphizeGeneric`.
|
|
453
|
+
if (astFuncExpr.typeParams.length > 0) {
|
|
454
|
+
this._registerGenericTemplate(astFuncExpr, astFuncName, tirFuncName, topLevelScope, srcExports, exportRange);
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
431
457
|
const declContext = AstCompilationCtx.fromScope(this.program, topLevelScope);
|
|
432
458
|
const funcExpr = _compileFuncExpr(declContext, astFuncExpr, undefined, // sig
|
|
433
459
|
false // isMethod
|
|
@@ -456,6 +482,160 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
456
482
|
&& this.program.contractTirFuncName === "")
|
|
457
483
|
this.program.contractTirFuncName = tirFuncName;
|
|
458
484
|
}
|
|
485
|
+
/**
|
|
486
|
+
* Register a generic function template. Compile only the signature in a
|
|
487
|
+
* scope where each type parameter is bound to a `TirTypeParam`; the body
|
|
488
|
+
* is deferred until `monomorphizeGeneric` is invoked at a call site.
|
|
489
|
+
*/
|
|
490
|
+
_registerGenericTemplate(astFuncExpr, astFuncName, tirFuncName, topLevelScope, srcExports, exportRange) {
|
|
491
|
+
if (topLevelScope.functions.has(astFuncName))
|
|
492
|
+
return this.error(DiagnosticCode._0_is_already_defined, astFuncExpr.name.range, astFuncName);
|
|
493
|
+
// Detect duplicate type-param names on the template
|
|
494
|
+
const seenParamNames = new Set();
|
|
495
|
+
const tirTypeParams = [];
|
|
496
|
+
for (const decl of astFuncExpr.typeParams) {
|
|
497
|
+
if (seenParamNames.has(decl.name.text)) {
|
|
498
|
+
return this.error(DiagnosticCode._0_is_already_defined, decl.name.range, decl.name.text);
|
|
499
|
+
}
|
|
500
|
+
seenParamNames.add(decl.name.text);
|
|
501
|
+
tirTypeParams.push(new TirTypeParam(decl.name.text));
|
|
502
|
+
}
|
|
503
|
+
// Build a child scope where each type-param name resolves to its
|
|
504
|
+
// TirTypeParam (via `_compileDataEncodedConcreteType`'s new lookup).
|
|
505
|
+
const templateScope = topLevelScope.newChildScope({
|
|
506
|
+
...topLevelScope.infos,
|
|
507
|
+
isFunctionDeclScope: false,
|
|
508
|
+
isMethodScope: false
|
|
509
|
+
});
|
|
510
|
+
for (let i = 0; i < astFuncExpr.typeParams.length; i++) {
|
|
511
|
+
templateScope.defineTypeParam(astFuncExpr.typeParams[i].name.text, tirTypeParams[i]);
|
|
512
|
+
}
|
|
513
|
+
// Resolve constraints on each type param (the `implements I` clause).
|
|
514
|
+
// For each constrained param, record the constraint on the template
|
|
515
|
+
// so monomorphizeGeneric can inject the matching dictionary at call
|
|
516
|
+
// sites, and on the template scope so `getPropAccessReturnType` can
|
|
517
|
+
// resolve method calls on `T`-typed values inside the body.
|
|
518
|
+
const constraints = new Array(astFuncExpr.typeParams.length).fill(undefined);
|
|
519
|
+
for (let i = 0; i < astFuncExpr.typeParams.length; i++) {
|
|
520
|
+
const decl = astFuncExpr.typeParams[i];
|
|
521
|
+
if (!decl.constraint)
|
|
522
|
+
continue;
|
|
523
|
+
const con = this._resolveTypeParamConstraint(templateScope, decl);
|
|
524
|
+
if (!con)
|
|
525
|
+
return undefined;
|
|
526
|
+
constraints[i] = con;
|
|
527
|
+
templateScope.defineTypeParamConstraint(decl.name.text, con);
|
|
528
|
+
}
|
|
529
|
+
// Compile only the signature: yields a TirFuncT that may contain
|
|
530
|
+
// TirTypeParams in arg/return positions.
|
|
531
|
+
const templateCtx = AstCompilationCtx.fromScope(this.program, templateScope);
|
|
532
|
+
const placeholderFuncType = getDataFuncSignature(templateCtx, astFuncExpr.signature);
|
|
533
|
+
if (!placeholderFuncType)
|
|
534
|
+
return undefined;
|
|
535
|
+
// Register the template on the program
|
|
536
|
+
this.program.genericTemplates.set(astFuncName, {
|
|
537
|
+
kind: "user",
|
|
538
|
+
astFuncName,
|
|
539
|
+
astFuncExpr,
|
|
540
|
+
typeParams: tirTypeParams,
|
|
541
|
+
definingScope: topLevelScope,
|
|
542
|
+
canonicalTirName: tirFuncName,
|
|
543
|
+
placeholderFuncType,
|
|
544
|
+
constraints,
|
|
545
|
+
});
|
|
546
|
+
// Register the generic placeholder value in the top-level scope so
|
|
547
|
+
// identifier lookup at call sites finds it. The `genericTemplateName`
|
|
548
|
+
// field signals to `_compileCallExpr` that this is a template.
|
|
549
|
+
topLevelScope.functions.set(astFuncName, tirFuncName);
|
|
550
|
+
topLevelScope.defineValue({
|
|
551
|
+
name: astFuncName,
|
|
552
|
+
type: placeholderFuncType,
|
|
553
|
+
isConstant: true,
|
|
554
|
+
genericTemplateName: astFuncName,
|
|
555
|
+
});
|
|
556
|
+
if (exportRange && srcExports) {
|
|
557
|
+
if (srcExports.functions.has(astFuncName)
|
|
558
|
+
|| srcExports.variables.has(astFuncName))
|
|
559
|
+
return this.error(DiagnosticCode._0_is_already_exported, exportRange, astFuncName);
|
|
560
|
+
srcExports.functions.set(astFuncName, tirFuncName);
|
|
561
|
+
srcExports.defineValue({
|
|
562
|
+
name: astFuncName,
|
|
563
|
+
type: placeholderFuncType,
|
|
564
|
+
isConstant: true,
|
|
565
|
+
genericTemplateName: astFuncName,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Resolve a `<T implements I>` constraint clause to a `TypeParamConstraint`.
|
|
571
|
+
*
|
|
572
|
+
* - `decl.constraint` must be a bare `AstNamedTypeExpr` (no type args).
|
|
573
|
+
* - The named interface must be registered in `scope.interfaces`
|
|
574
|
+
* (walking up the parent chain via `resolveInterface`).
|
|
575
|
+
*
|
|
576
|
+
* The returned object captures the AST method signatures verbatim so the
|
|
577
|
+
* monomorphizer doesn't have to re-resolve the interface each time.
|
|
578
|
+
*/
|
|
579
|
+
_resolveTypeParamConstraint(scope, decl) {
|
|
580
|
+
const constraint = decl.constraint;
|
|
581
|
+
if (!constraint)
|
|
582
|
+
return undefined;
|
|
583
|
+
if (!(constraint instanceof AstNamedTypeExpr))
|
|
584
|
+
return this.error(DiagnosticCode.Type_expected, constraint.range);
|
|
585
|
+
if (constraint.tyArgs.length > 0)
|
|
586
|
+
return this.error(DiagnosticCode.Not_implemented_0, constraint.range, "generic interface as a type-parameter constraint");
|
|
587
|
+
const interfaceName = constraint.name.text;
|
|
588
|
+
const methods = scope.resolveInterface(interfaceName);
|
|
589
|
+
if (!methods)
|
|
590
|
+
return this.error(DiagnosticCode._0_is_not_defined, constraint.name.range, interfaceName);
|
|
591
|
+
return { interfaceName, methods };
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* walks `stmts` for `NamespaceDecl` (optionally wrapped in `ExportStmt`),
|
|
595
|
+
* compiles each one into a `NamespaceSymbol`, and registers it on
|
|
596
|
+
* `enclosingScope` (and `enclosingExports` when exported).
|
|
597
|
+
*
|
|
598
|
+
* removes processed `NamespaceDecl` statements from `stmts`.
|
|
599
|
+
*/
|
|
600
|
+
_collectNamespaceDeclarations(stmts, srcUid, enclosingScope, enclosingExports) {
|
|
601
|
+
for (let i = 0; i < stmts.length; i++) {
|
|
602
|
+
let stmt = stmts[i];
|
|
603
|
+
let exported = false;
|
|
604
|
+
if (stmt instanceof ExportStmt) {
|
|
605
|
+
exported = true;
|
|
606
|
+
stmt = stmt.stmt;
|
|
607
|
+
}
|
|
608
|
+
if (!(stmt instanceof NamespaceDecl))
|
|
609
|
+
continue;
|
|
610
|
+
this._compileNamespaceDecl(stmt, srcUid, enclosingScope, enclosingExports, exported);
|
|
611
|
+
void stmts.splice(i, 1);
|
|
612
|
+
i--;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
_compileNamespaceDecl(decl, srcUid, enclosingScope, enclosingExports, isExported) {
|
|
616
|
+
const nsName = decl.name.text;
|
|
617
|
+
if (enclosingScope.namespaces.has(nsName))
|
|
618
|
+
return this.error(DiagnosticCode._0_is_already_defined, decl.name.range, nsName);
|
|
619
|
+
const compilationScope = enclosingScope.newChildScope({ isFunctionDeclScope: false });
|
|
620
|
+
const publicScope = enclosingScope.newChildScope({ isFunctionDeclScope: false });
|
|
621
|
+
const nsSrcUid = `${srcUid}::${nsName}`;
|
|
622
|
+
// build a synthetic top-level statement list from the namespace's members:
|
|
623
|
+
// wrap public members in ExportStmt so the existing passes route them
|
|
624
|
+
// to `publicScope` automatically; leave private members bare so they only
|
|
625
|
+
// live in `compilationScope`.
|
|
626
|
+
const fakeStmts = decl.members.map((m) => m.isPrivate
|
|
627
|
+
? m.stmt
|
|
628
|
+
: new ExportStmt(m.stmt, m.range));
|
|
629
|
+
// recurse into nested namespaces first so subsequent passes can
|
|
630
|
+
// resolve `Inner.Member` references.
|
|
631
|
+
this._collectNamespaceDeclarations(fakeStmts, nsSrcUid, compilationScope, publicScope);
|
|
632
|
+
this._collectTypeDeclarations(fakeStmts, nsSrcUid, compilationScope, publicScope);
|
|
633
|
+
this._collectInterfaceDeclarations(fakeStmts, compilationScope, publicScope);
|
|
634
|
+
this._collectAllTopLevelSignatures(fakeStmts, nsSrcUid, compilationScope, publicScope, false);
|
|
635
|
+
enclosingScope.defineNamespace({ name: nsName, publicScope });
|
|
636
|
+
if (isExported)
|
|
637
|
+
enclosingExports.defineNamespace({ name: nsName, publicScope });
|
|
638
|
+
}
|
|
459
639
|
_collectInterfaceDeclarations(stmts, topLevelScope, srcExports) {
|
|
460
640
|
for (let i = 0; i < stmts.length; i++) {
|
|
461
641
|
let stmt = stmts[i];
|
|
@@ -603,7 +783,23 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
603
783
|
for (let i = 0; i < stmts.length; i++) {
|
|
604
784
|
const stmt = stmts[i];
|
|
605
785
|
if (stmt instanceof ImportStarStmt) {
|
|
606
|
-
|
|
786
|
+
const importAbsPath = getAbsolutePath(stmt.fromPath.string, srcAbsPath) ?? "";
|
|
787
|
+
const importedSymbols = this.program.getExportedSymbols(importAbsPath);
|
|
788
|
+
if (!importedSymbols) {
|
|
789
|
+
this.error(DiagnosticCode.File_0_not_found, stmt.fromPath.range, importAbsPath);
|
|
790
|
+
void stmts.splice(i, 1);
|
|
791
|
+
i--;
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
const aliasName = stmt.anIdentifier.text;
|
|
795
|
+
const ok = srcImportsScope.defineNamespace({
|
|
796
|
+
name: aliasName,
|
|
797
|
+
publicScope: importedSymbols
|
|
798
|
+
});
|
|
799
|
+
if (!ok)
|
|
800
|
+
this.error(DiagnosticCode._0_is_already_defined, stmt.anIdentifier.range, aliasName);
|
|
801
|
+
void stmts.splice(i, 1);
|
|
802
|
+
i--;
|
|
607
803
|
continue;
|
|
608
804
|
}
|
|
609
805
|
if (!(stmt instanceof ImportStmt))
|
|
@@ -620,10 +816,12 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
620
816
|
const isType = importedSymbols.types.has(declName);
|
|
621
817
|
const isFunction = importedSymbols.functions.has(declName);
|
|
622
818
|
const isInterface = importedSymbols.interfaces.has(declName);
|
|
819
|
+
const isNamespace = importedSymbols.namespaces.has(declName);
|
|
623
820
|
if (!(isValue
|
|
624
821
|
|| isType
|
|
625
822
|
|| isFunction
|
|
626
|
-
|| isInterface
|
|
823
|
+
|| isInterface
|
|
824
|
+
|| isNamespace)) {
|
|
627
825
|
this.error(DiagnosticCode.Module_0_has_no_exported_member_1, importDecl.identifier.range, stmt.fromPath.string, declName);
|
|
628
826
|
continue;
|
|
629
827
|
}
|
|
@@ -647,6 +845,8 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
647
845
|
srcImportsScope.types.set(declName, importedSymbols.types.get(declName));
|
|
648
846
|
if (isInterface)
|
|
649
847
|
srcImportsScope.interfaces.set(declName, importedSymbols.interfaces.get(declName));
|
|
848
|
+
if (isNamespace)
|
|
849
|
+
srcImportsScope.defineNamespace(importedSymbols.namespaces.get(declName));
|
|
650
850
|
}
|
|
651
851
|
// remove from array so we don't process it again
|
|
652
852
|
void stmts.splice(i, 1);
|
|
@@ -14,6 +14,7 @@ import { LitIntExpr } from "../../../../ast/nodes/expr/litteral/LitIntExpr.js";
|
|
|
14
14
|
import { LitNamedObjExpr } from "../../../../ast/nodes/expr/litteral/LitNamedObjExpr.js";
|
|
15
15
|
import { LitObjExpr } from "../../../../ast/nodes/expr/litteral/LitObjExpr.js";
|
|
16
16
|
import { LitStrExpr } from "../../../../ast/nodes/expr/litteral/LitStrExpr.js";
|
|
17
|
+
import { TemplateStrExpr } from "../../../../ast/nodes/expr/litteral/TemplateStrExpr.js";
|
|
17
18
|
import { LitThisExpr } from "../../../../ast/nodes/expr/litteral/LitThisExpr.js";
|
|
18
19
|
import { LitTrueExpr } from "../../../../ast/nodes/expr/litteral/LitTrueExpr.js";
|
|
19
20
|
import { LitUndefExpr } from "../../../../ast/nodes/expr/litteral/LitUndefExpr.js";
|
|
@@ -44,7 +45,7 @@ import { IfStmt } from "../../../../ast/nodes/statements/IfStmt.js";
|
|
|
44
45
|
import { MatchStmtCase, MatchStmt, MatchStmtElseCase } from "../../../../ast/nodes/statements/MatchStmt.js";
|
|
45
46
|
import { ReturnStmt } from "../../../../ast/nodes/statements/ReturnStmt.js";
|
|
46
47
|
import { TraceStmt } from "../../../../ast/nodes/statements/TraceStmt.js";
|
|
47
|
-
import { UsingStmt } from "../../../../ast/nodes/statements/UsingStmt.js";
|
|
48
|
+
import { UsingAliasStmt, UsingStmt } from "../../../../ast/nodes/statements/UsingStmt.js";
|
|
48
49
|
import { VarStmt } from "../../../../ast/nodes/statements/VarStmt.js";
|
|
49
50
|
import { WhileStmt } from "../../../../ast/nodes/statements/WhileStmt.js";
|
|
50
51
|
import { SourceRange } from "../../../../ast/Source/SourceRange.js";
|
|
@@ -457,7 +458,8 @@ function _getMatchedRedeemerBlockStatements(compiler, stmts, paramsInternalNames
|
|
|
457
458
|
if (stmt instanceof BreakStmt
|
|
458
459
|
|| stmt instanceof ContinueStmt
|
|
459
460
|
|| stmt instanceof EmptyStmt
|
|
460
|
-
|| stmt instanceof UsingStmt
|
|
461
|
+
|| stmt instanceof UsingStmt
|
|
462
|
+
|| stmt instanceof UsingAliasStmt)
|
|
461
463
|
continue;
|
|
462
464
|
if (isImplicitAssignmentStmt(stmt))
|
|
463
465
|
continue;
|
|
@@ -766,6 +768,15 @@ function _exprReplaceParamsAndAssertNoLitContext(compiler, expr, paramsInternalN
|
|
|
766
768
|
expr.body = new BlockStmt(nextBodyStmts, expr.body.range);
|
|
767
769
|
return expr;
|
|
768
770
|
}
|
|
771
|
+
if (expr instanceof TemplateStrExpr) {
|
|
772
|
+
for (let i = 0; i < expr.exprs.length; i++) {
|
|
773
|
+
const newSub = _exprReplaceParamsAndAssertNoLitContext(compiler, expr.exprs[i], paramsInternalNamesMap, renamedVariables);
|
|
774
|
+
if (!newSub)
|
|
775
|
+
return undefined;
|
|
776
|
+
expr.exprs[i] = newSub;
|
|
777
|
+
}
|
|
778
|
+
return expr;
|
|
779
|
+
}
|
|
769
780
|
const tsEnsureExhaustiveCheck = expr;
|
|
770
781
|
console.error(expr);
|
|
771
782
|
throw new Error("unreachable::_exprReplaceParamsAndAssertNoLitContext");
|
|
@@ -774,8 +785,7 @@ function _deriveContractDatumTypeDef(contractName, stateDecls, contractRange) {
|
|
|
774
785
|
let defFlags = StructDeclAstFlags.onlyDataEncoding;
|
|
775
786
|
if (stateDecls.length <= 1)
|
|
776
787
|
defFlags |= StructDeclAstFlags.untaggedSingleConstructor;
|
|
777
|
-
|
|
778
|
-
return new StructDecl(new Identifier(uniqueName, SourceRange.mock), [], // typeParams
|
|
788
|
+
return new StructDecl(new Identifier(contractName, contractRange), [], // typeParams
|
|
779
789
|
stateDecls.map(s => new StructConstrDecl(new Identifier(s.name.text, s.name.range), s.fields, s.range)), defFlags, contractRange);
|
|
780
790
|
}
|
|
781
791
|
function _buildSpendCaseBlock(compiler, contractDecl, paramsInternalNamesMap, baseContextVars, contractRange) {
|
|
@@ -2,12 +2,13 @@ import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.gener
|
|
|
2
2
|
import { TirCallExpr } from "../../../tir/expressions/TirCallExpr.js";
|
|
3
3
|
import { TirFuncT } from "../../../tir/types/TirNativeType/native/function.js";
|
|
4
4
|
import { canAssignTo } from "../../../tir/types/utils/canAssignTo.js";
|
|
5
|
+
import { inferTypeArgs } from "../../../tir/types/utils/inferTypeArgs.js";
|
|
6
|
+
import { substituteTypeParams } from "../../../tir/types/utils/substituteTypeParams.js";
|
|
7
|
+
import { TirVariableAccessExpr } from "../../../tir/expressions/TirVariableAccessExpr.js";
|
|
8
|
+
import { monomorphizeGeneric } from "../../utils/monomorphizeGeneric.js";
|
|
9
|
+
import { _compileDataEncodedConcreteType } from "../types/_compileDataEncodedConcreteType.js";
|
|
5
10
|
import { _compileExpr } from "./_compileExpr.js";
|
|
6
11
|
export function _compileCallExpr(ctx, expr, typeHint) {
|
|
7
|
-
// TODO: expr.genericTypeArgs
|
|
8
|
-
// expr.funcExpr;
|
|
9
|
-
// expr.args;
|
|
10
|
-
// expr.range;
|
|
11
12
|
if (!(typeHint instanceof TirFuncT))
|
|
12
13
|
typeHint = undefined;
|
|
13
14
|
const funcExpr = _compileExpr(ctx, expr.funcExpr, typeHint);
|
|
@@ -15,7 +16,97 @@ export function _compileCallExpr(ctx, expr, typeHint) {
|
|
|
15
16
|
return undefined;
|
|
16
17
|
if (!(funcExpr.type instanceof TirFuncT))
|
|
17
18
|
return ctx.error(DiagnosticCode.Expression_is_not_callable, expr.funcExpr.range);
|
|
18
|
-
|
|
19
|
+
// ---- Generic-callee handling --------------------------------------
|
|
20
|
+
// If the callee resolved to a generic placeholder, the funcExpr is a
|
|
21
|
+
// `TirVariableAccessExpr` whose `variableInfos.genericTemplateName` names
|
|
22
|
+
// a template registered on `program.genericTemplates`. We instantiate it
|
|
23
|
+
// here with explicit or inferred type arguments and replace `funcExpr`
|
|
24
|
+
// with a synthetic access pointing at the concrete monomorphized instance.
|
|
25
|
+
let callee = funcExpr;
|
|
26
|
+
let funcType = funcExpr.type;
|
|
27
|
+
if (funcExpr instanceof TirVariableAccessExpr) {
|
|
28
|
+
const templateName = funcExpr.resolvedValue.variableInfos.genericTemplateName;
|
|
29
|
+
if (typeof templateName === "string") {
|
|
30
|
+
const template = ctx.program.genericTemplates.get(templateName);
|
|
31
|
+
if (!template)
|
|
32
|
+
return ctx.error(DiagnosticCode._0_is_not_defined, expr.funcExpr.range, templateName);
|
|
33
|
+
const nParams = template.typeParams.length;
|
|
34
|
+
// 1) Collect explicit type-args, if any
|
|
35
|
+
const explicitArgs = (Array.isArray(expr.genericTypeArgs)
|
|
36
|
+
? new Array()
|
|
37
|
+
: undefined);
|
|
38
|
+
if (explicitArgs && expr.genericTypeArgs) {
|
|
39
|
+
for (const tArgExpr of expr.genericTypeArgs) {
|
|
40
|
+
const t = _compileDataEncodedConcreteType(ctx, tArgExpr, true);
|
|
41
|
+
if (!t)
|
|
42
|
+
return undefined;
|
|
43
|
+
explicitArgs.push(t);
|
|
44
|
+
}
|
|
45
|
+
if (explicitArgs.length !== nParams) {
|
|
46
|
+
return ctx.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, expr.funcExpr.range, String(nParams), String(explicitArgs.length));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 2) Compile arguments. We need them anyway, and they're used for
|
|
50
|
+
// inference when no explicit args were given.
|
|
51
|
+
const tirArgs = expr.args.map((arg, i) => {
|
|
52
|
+
const expected = explicitArgs
|
|
53
|
+
? substituteTypeParams(funcType.argTypes[i], new Map(template.typeParams.map((tp, idx) => [tp.symbol, explicitArgs[idx]])))
|
|
54
|
+
: undefined;
|
|
55
|
+
return _compileExpr(ctx, arg, expected);
|
|
56
|
+
});
|
|
57
|
+
for (const a of tirArgs)
|
|
58
|
+
if (!a)
|
|
59
|
+
return undefined;
|
|
60
|
+
// 3) Determine final type arguments
|
|
61
|
+
let resolvedArgs;
|
|
62
|
+
if (explicitArgs) {
|
|
63
|
+
resolvedArgs = explicitArgs;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const env = new Map();
|
|
67
|
+
const usable = Math.min(tirArgs.length, funcType.argTypes.length);
|
|
68
|
+
for (let i = 0; i < usable; i++) {
|
|
69
|
+
if (!inferTypeArgs(funcType.argTypes[i], tirArgs[i].type, env)) {
|
|
70
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, tirArgs[i].type.toString(), funcType.argTypes[i].toString());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
resolvedArgs = new Array(nParams);
|
|
74
|
+
for (let i = 0; i < nParams; i++) {
|
|
75
|
+
const bound = env.get(template.typeParams[i].symbol);
|
|
76
|
+
if (!bound) {
|
|
77
|
+
return ctx.error(DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly, expr.funcExpr.range, template.typeParams[i].name);
|
|
78
|
+
}
|
|
79
|
+
resolvedArgs[i] = bound;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// 4) Monomorphize
|
|
83
|
+
const mono = monomorphizeGeneric(ctx, template, resolvedArgs, expr.range);
|
|
84
|
+
if (!mono)
|
|
85
|
+
return undefined;
|
|
86
|
+
funcType = mono.concreteFuncType;
|
|
87
|
+
// 5) Synthesize a TirVariableAccessExpr for the concrete instance.
|
|
88
|
+
// The IR layer looks up by name on `program.functions`, so it
|
|
89
|
+
// matches the entry registered by `monomorphizeGeneric`.
|
|
90
|
+
callee = new TirVariableAccessExpr({
|
|
91
|
+
variableInfos: {
|
|
92
|
+
name: mono.tirFuncName,
|
|
93
|
+
type: funcType,
|
|
94
|
+
isConstant: true,
|
|
95
|
+
},
|
|
96
|
+
isDefinedOutsideFuncScope: true,
|
|
97
|
+
}, expr.funcExpr.range);
|
|
98
|
+
// 6) Re-validate argument assignability against concrete signature
|
|
99
|
+
const finalCallExprType = funcType.argTypes.length === tirArgs.length
|
|
100
|
+
? funcType.returnType
|
|
101
|
+
: new TirFuncT(funcType.argTypes.slice(tirArgs.length), funcType.returnType);
|
|
102
|
+
for (let i = 0; i < tirArgs.length && i < funcType.argTypes.length; i++) {
|
|
103
|
+
if (!canAssignTo(tirArgs[i].type, funcType.argTypes[i]))
|
|
104
|
+
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, tirArgs[i].type.toString(), funcType.argTypes[i].toString());
|
|
105
|
+
}
|
|
106
|
+
return new TirCallExpr(callee, tirArgs, finalCallExprType, expr.range);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// ---- End generic-callee handling ----------------------------------
|
|
19
110
|
for (let i = funcType.argTypes.length; i < expr.args.length; i++) {
|
|
20
111
|
ctx.warning(DiagnosticCode.Unexpected_argument, expr.args[i].range); // not a big deal
|
|
21
112
|
}
|
|
@@ -32,5 +123,5 @@ export function _compileCallExpr(ctx, expr, typeHint) {
|
|
|
32
123
|
if (!canAssignTo(arg.type, funcType.argTypes[i]))
|
|
33
124
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, expr.args[i].range, arg.type.toString(), funcType.argTypes[i].toString());
|
|
34
125
|
}
|
|
35
|
-
return new TirCallExpr(
|
|
126
|
+
return new TirCallExpr(callee, args, finalCallExprType, expr.range);
|
|
36
127
|
}
|
|
@@ -9,7 +9,6 @@ import { TirReturnStmt } from "../../../tir/statements/TirReturnStmt.js";
|
|
|
9
9
|
import { TirSimpleVarDecl } from "../../../tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
10
10
|
import { TirFuncT } from "../../../tir/types/TirNativeType/native/function.js";
|
|
11
11
|
import { void_t } from "../../../tir/program/stdScope/stdScope.js";
|
|
12
|
-
import { TirTypeParam } from "../../../tir/types/TirTypeParam.js";
|
|
13
12
|
import { getUnaliased } from "../../../tir/types/utils/getUnaliased.js";
|
|
14
13
|
import { _compileBlockStmt } from "../statements/_compileBlockStmt.js";
|
|
15
14
|
import { _compileVarDecl } from "../statements/_compileVarStmt.js";
|
|
@@ -91,8 +90,13 @@ export function _compileFuncExpr(ctx, expr, expectedFuncType, isMethod = false)
|
|
|
91
90
|
isConstant: true,
|
|
92
91
|
});
|
|
93
92
|
// if( _hasDuplicateTypeParams( ctx, expr.typeParams ) ) return undefined;
|
|
93
|
+
// Generic functions are compiled per-instantiation by `monomorphizeGeneric`.
|
|
94
|
+
// The cloned `FuncExpr` it produces has `typeParams = []`, so we only need
|
|
95
|
+
// to refuse the (rare) case where someone directly calls `_compileFuncExpr`
|
|
96
|
+
// on a still-generic AST node (e.g. an anonymous lambda annotated with type
|
|
97
|
+
// params, which is not supported yet).
|
|
94
98
|
if (expr.typeParams.length > 0)
|
|
95
|
-
return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic functions");
|
|
99
|
+
return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic lambda expressions (top-level generic functions are supported)");
|
|
96
100
|
const destructuredParamsResult = _getDestructuredParamsAsVarDecls(funcCtx, expr, expectedFuncType);
|
|
97
101
|
if (!destructuredParamsResult)
|
|
98
102
|
return undefined;
|
|
@@ -140,8 +144,10 @@ function _compileFuncExprInferReturnType(ctx, expr, isMethod) {
|
|
|
140
144
|
type: tempFuncType,
|
|
141
145
|
isConstant: true,
|
|
142
146
|
});
|
|
147
|
+
// Inferred-return-type variant: generics are not supported here because
|
|
148
|
+
// signature inference depends on knowing the type-param substitution.
|
|
143
149
|
if (expr.typeParams.length > 0)
|
|
144
|
-
return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic functions");
|
|
150
|
+
return ctx.error(DiagnosticCode.Not_implemented_0, expr.typeParams[0].range, "generic functions with inferred return type — annotate the return type");
|
|
145
151
|
const destructuredParamsResult = _getDestructuredParamsAsVarDecls(funcCtx, expr, tempFuncType);
|
|
146
152
|
if (!destructuredParamsResult)
|
|
147
153
|
return undefined;
|
|
@@ -234,8 +240,9 @@ export function getDataFuncSignature(ctx, signature) {
|
|
|
234
240
|
const returnType = signature.returnType instanceof AstFuncType ?
|
|
235
241
|
getDataFuncSignature(ctx, signature.returnType) :
|
|
236
242
|
_compileSopEncodedConcreteType(ctx, signature.returnType);
|
|
237
|
-
if (!returnType
|
|
238
|
-
|| returnType instanceof TirTypeParam)
|
|
243
|
+
if (!returnType)
|
|
239
244
|
return undefined;
|
|
245
|
+
// NOTE: a bare `TirTypeParam` return type is valid here — it marks the
|
|
246
|
+
// template position. `monomorphizeGeneric` substitutes it at call sites.
|
|
240
247
|
return new TirFuncT(paramTypes, returnType);
|
|
241
248
|
}
|
|
@@ -7,6 +7,7 @@ import { LitIntExpr } from "../../../../ast/nodes/expr/litteral/LitIntExpr.js";
|
|
|
7
7
|
import { LitNamedObjExpr } from "../../../../ast/nodes/expr/litteral/LitNamedObjExpr.js";
|
|
8
8
|
import { LitObjExpr } from "../../../../ast/nodes/expr/litteral/LitObjExpr.js";
|
|
9
9
|
import { LitStrExpr } from "../../../../ast/nodes/expr/litteral/LitStrExpr.js";
|
|
10
|
+
import { TemplateStrExpr } from "../../../../ast/nodes/expr/litteral/TemplateStrExpr.js";
|
|
10
11
|
import { LitThisExpr } from "../../../../ast/nodes/expr/litteral/LitThisExpr.js";
|
|
11
12
|
import { LitTrueExpr } from "../../../../ast/nodes/expr/litteral/LitTrueExpr.js";
|
|
12
13
|
import { LitUndefExpr } from "../../../../ast/nodes/expr/litteral/LitUndefExpr.js";
|
|
@@ -66,6 +67,8 @@ export function _compileLitteralExpr(ctx, expr, typeHint) {
|
|
|
66
67
|
return _compileLitteralNamedObjExpr(ctx, expr, typeHint);
|
|
67
68
|
if (expr instanceof LitFailExpr)
|
|
68
69
|
return new TirLitFailExpr(expr.range);
|
|
70
|
+
if (expr instanceof TemplateStrExpr)
|
|
71
|
+
return _compileTemplateStrExpr(ctx, expr);
|
|
69
72
|
if (expr instanceof LitContextExpr)
|
|
70
73
|
throw new Error("Litteral `context` should have been handled while desugaring.");
|
|
71
74
|
const tsEnsureExhautstiveCheck = expr;
|
|
@@ -226,3 +229,59 @@ export function _compileLitteralArrayExpr(ctx, expr, typeHint) {
|
|
|
226
229
|
return undefined;
|
|
227
230
|
return new TirLitArrExpr([fstCompiledExpr, ...compiledRestElems], listType, expr.range);
|
|
228
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Compile a template string `` `text ${e1} more ${e2} ...` `` into a chain
|
|
234
|
+
* of `appendByteString` calls.
|
|
235
|
+
*
|
|
236
|
+
* Each text fragment becomes a `TirLitHexBytesExpr` containing its UTF-8
|
|
237
|
+
* encoding. Each interpolation is compiled and, if its type is not already
|
|
238
|
+
* `bytes`, wrapped in a `TirShowExpr` so it lowers via the built-in `Show`
|
|
239
|
+
* interface (or the user's `type X implements Show { ... }` override).
|
|
240
|
+
*
|
|
241
|
+
* Empty fragments collapse out — we don't emit `appendByteString("", x)`.
|
|
242
|
+
*/
|
|
243
|
+
function _compileTemplateStrExpr(ctx, expr) {
|
|
244
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
245
|
+
const { fromUtf8 } = require("@harmoniclabs/uint8array-utils");
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
247
|
+
const { TirShowExpr } = require("../../../tir/expressions/TirShowExpr.js");
|
|
248
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
249
|
+
const { TirCallExpr } = require("../../../tir/expressions/TirCallExpr.js");
|
|
250
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
251
|
+
const { TirNativeFunc } = require("../../../tir/expressions/TirNativeFunc.js");
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
253
|
+
const { TirBytesT } = require("../../../tir/types/TirNativeType/native/bytes.js");
|
|
254
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
255
|
+
const { bytes_t } = require("../../../tir/program/stdScope/stdScope.js");
|
|
256
|
+
const pieces = [];
|
|
257
|
+
for (let i = 0; i < expr.parts.length; i++) {
|
|
258
|
+
const text = expr.parts[i];
|
|
259
|
+
if (text.length > 0) {
|
|
260
|
+
pieces.push(new TirLitHexBytesExpr(fromUtf8(text), expr.range));
|
|
261
|
+
}
|
|
262
|
+
if (i < expr.exprs.length) {
|
|
263
|
+
const sub = _compileExpr(ctx, expr.exprs[i], undefined);
|
|
264
|
+
if (!sub)
|
|
265
|
+
return undefined;
|
|
266
|
+
const subType = getUnaliased(sub.type);
|
|
267
|
+
if (subType instanceof TirBytesT) {
|
|
268
|
+
// Already valid UTF-8 by convention — pass through.
|
|
269
|
+
pieces.push(sub);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
// Auto-show via the built-in Show interface dispatch.
|
|
273
|
+
pieces.push(new TirShowExpr(sub, expr.exprs[i].range));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (pieces.length === 0) {
|
|
278
|
+
// Empty template — emit empty bytes.
|
|
279
|
+
return new TirLitHexBytesExpr(new Uint8Array(0), expr.range);
|
|
280
|
+
}
|
|
281
|
+
// Left-fold appendByteString.
|
|
282
|
+
let acc = pieces[0];
|
|
283
|
+
for (let i = 1; i < pieces.length; i++) {
|
|
284
|
+
acc = new TirCallExpr(TirNativeFunc.appendByteString, [acc, pieces[i]], bytes_t, expr.range);
|
|
285
|
+
}
|
|
286
|
+
return acc;
|
|
287
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { PropAccessExpr, OptionalPropAccessExpr, NonNullPropAccessExpr, DotPropAccessExpr } from "../../../../ast/nodes/expr/PropAccessExpr.js";
|
|
2
2
|
import { TirExpr } from "../../../tir/expressions/TirExpr.js";
|
|
3
|
-
import { TirPropAccessExpr } from "../../../tir/expressions/TirPropAccessExpr.js";
|
|
4
3
|
import { TirType } from "../../../tir/types/TirType.js";
|
|
5
4
|
import { AstCompilationCtx } from "../../AstCompilationCtx.js";
|
|
6
5
|
export declare function _compilePropAccessExpr(ctx: AstCompilationCtx, expr: PropAccessExpr, typeHint: TirType | undefined): TirExpr | undefined;
|
|
7
6
|
export declare function _compileOptionalPropAccessExpr(ctx: AstCompilationCtx, expr: OptionalPropAccessExpr, _typeHint: TirType | undefined): TirExpr | undefined;
|
|
8
|
-
export declare function _compileNonNullPropAccessExpr(ctx: AstCompilationCtx, expr: NonNullPropAccessExpr, _typeHint: TirType | undefined):
|
|
9
|
-
export declare function _compileDotPropAccessExpr(ctx: AstCompilationCtx, expr: DotPropAccessExpr, _typeHint: TirType | undefined):
|
|
7
|
+
export declare function _compileNonNullPropAccessExpr(ctx: AstCompilationCtx, expr: NonNullPropAccessExpr, _typeHint: TirType | undefined): TirExpr | undefined;
|
|
8
|
+
export declare function _compileDotPropAccessExpr(ctx: AstCompilationCtx, expr: DotPropAccessExpr, _typeHint: TirType | undefined): TirExpr | undefined;
|