@harmoniclabs/pebble 0.1.10 → 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 +13 -2
- 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 +3 -2
|
@@ -2,7 +2,7 @@ import { TirAliasType } from "../../tir/types/TirAliasType.js";
|
|
|
2
2
|
import { isTirStructType } from "../../tir/types/TirStructType.js";
|
|
3
3
|
import { TirTypeParam } from "../../tir/types/TirTypeParam.js";
|
|
4
4
|
import { int_t, bytes_t, bool_t, string_t } from "../../tir/program/stdScope/stdScope.js";
|
|
5
|
-
import { TirUnConstrDataResultT, TirPairDataT } from "../../tir/types/TirNativeType/index.js";
|
|
5
|
+
import { TirBlsG1T, TirBlsG2T, TirMlResultT, TirUnConstrDataResultT, TirPairDataT } from "../../tir/types/TirNativeType/index.js";
|
|
6
6
|
import { TirBoolT } from "../../tir/types/TirNativeType/native/bool.js";
|
|
7
7
|
import { TirBytesT } from "../../tir/types/TirNativeType/native/bytes.js";
|
|
8
8
|
import { TirDataT } from "../../tir/types/TirNativeType/native/data.js";
|
|
@@ -27,6 +27,24 @@ export function getPropAccessReturnType(ctx, objType, propId) {
|
|
|
27
27
|
objType = objType.aliased;
|
|
28
28
|
}
|
|
29
29
|
// if( objType instanceof TirAliasType ) return findPropInImpls( objType.impls, propName ) ?? getPropAccessReturnType( objType.aliased, propId );
|
|
30
|
+
// Universal `.show()` — every (built-in) type implementing the Show
|
|
31
|
+
// interface has signature `(): bytes`. Struct types fall through to
|
|
32
|
+
// `getStructPropAccessReturnType`, which checks user-declared
|
|
33
|
+
// `type X implements Show { ... }` impls first; if absent, the
|
|
34
|
+
// expressify-time fallback emits a TirShowExpr that auto-derives via
|
|
35
|
+
// `_showIR` (e.g. for data-encoded structs).
|
|
36
|
+
if (propName === "show") {
|
|
37
|
+
if (objType instanceof TirVoidT
|
|
38
|
+
|| objType instanceof TirBoolT
|
|
39
|
+
|| objType instanceof TirIntT
|
|
40
|
+
|| objType instanceof TirBytesT
|
|
41
|
+
|| objType instanceof TirStringT
|
|
42
|
+
|| objType instanceof TirDataT
|
|
43
|
+
|| objType instanceof TirListT
|
|
44
|
+
|| objType instanceof TirLinearMapT
|
|
45
|
+
|| isTirOptType(objType))
|
|
46
|
+
return new TirFuncT([], bytes_t);
|
|
47
|
+
}
|
|
30
48
|
if (isTirStructType(objType))
|
|
31
49
|
return getStructPropAccessReturnType(ctx, objType, propName);
|
|
32
50
|
if (objType instanceof TirVoidT)
|
|
@@ -60,6 +78,12 @@ export function getPropAccessReturnType(ctx, objType, propId) {
|
|
|
60
78
|
return undefined;
|
|
61
79
|
if (objType instanceof TirPairDataT)
|
|
62
80
|
return undefined;
|
|
81
|
+
if (objType instanceof TirBlsG1T)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (objType instanceof TirBlsG2T)
|
|
84
|
+
return undefined;
|
|
85
|
+
if (objType instanceof TirMlResultT)
|
|
86
|
+
return undefined;
|
|
63
87
|
const tsEnsureExhaustiveCheck = objType;
|
|
64
88
|
console.error(objType);
|
|
65
89
|
throw new Error("unreachable::getPropAccessReturnType");
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SourceRange } from "../../../ast/Source/SourceRange.js";
|
|
2
|
+
import { GenericTemplate } from "../../tir/program/TypedProgram.js";
|
|
3
|
+
import { TirFuncT } from "../../tir/types/TirNativeType/native/function.js";
|
|
4
|
+
import { TirType } from "../../tir/types/TirType.js";
|
|
5
|
+
import { AstCompilationCtx } from "../AstCompilationCtx.js";
|
|
6
|
+
export interface MonomorphizationResult {
|
|
7
|
+
/** the canonical TIR function name registered in `program.functions` */
|
|
8
|
+
tirFuncName: string;
|
|
9
|
+
/** the substituted concrete TirFuncT (no remaining type params) */
|
|
10
|
+
concreteFuncType: TirFuncT;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Returns a deterministic instance key for memoization & function-table naming.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildMonomorphizationKey(templateCanonicalName: string, typeArgs: TirType[]): string;
|
|
16
|
+
/**
|
|
17
|
+
* Instantiate a generic function template with the given concrete type
|
|
18
|
+
* arguments, producing (and caching) a fresh concrete TIR function.
|
|
19
|
+
*
|
|
20
|
+
* The strategy is "desugar to a concrete function during AST→TIR":
|
|
21
|
+
*
|
|
22
|
+
* 1. Build a child scope on the template's defining scope where each type
|
|
23
|
+
* parameter name resolves as a type alias for its concrete type. When the
|
|
24
|
+
* cloned FuncExpr is re-compiled, every `AstNamedTypeExpr` mentioning a
|
|
25
|
+
* type parameter resolves to its concrete TIR type.
|
|
26
|
+
* 2. Construct a fresh `FuncExpr` reusing the template's body & signature but
|
|
27
|
+
* with `typeParams = []` (so the "not implemented: generic functions"
|
|
28
|
+
* guard in `_compileFuncExpr` does not trip) and a unique instance name.
|
|
29
|
+
* 3. Compile via `_compileFuncExpr` and register the resulting `TirFuncExpr`
|
|
30
|
+
* in `program.functions` under the instance name.
|
|
31
|
+
*
|
|
32
|
+
* Results are memoized per `(template, type-args)` tuple — repeated calls
|
|
33
|
+
* with the same type arguments return the same instance and do not
|
|
34
|
+
* re-compile.
|
|
35
|
+
*/
|
|
36
|
+
export declare function monomorphizeGeneric(ctx: AstCompilationCtx, template: GenericTemplate, typeArgs: TirType[], callRange: SourceRange): MonomorphizationResult | undefined;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { FuncExpr } from "../../../ast/nodes/expr/functions/FuncExpr.js";
|
|
2
|
+
import { Identifier } from "../../../ast/nodes/common/Identifier.js";
|
|
3
|
+
import { ArrowKind } from "../../../ast/nodes/expr/functions/ArrowKind.js";
|
|
4
|
+
import { DiagnosticCode } from "../../../diagnostics/diagnosticMessages.generated.js";
|
|
5
|
+
import { substituteTypeParams } from "../../tir/types/utils/substituteTypeParams.js";
|
|
6
|
+
import { AstCompilationCtx } from "../AstCompilationCtx.js";
|
|
7
|
+
import { _compileFuncExpr } from "../internal/exprs/_compileFuncExpr.js";
|
|
8
|
+
/**
|
|
9
|
+
* Returns a deterministic instance key for memoization & function-table naming.
|
|
10
|
+
*/
|
|
11
|
+
export function buildMonomorphizationKey(templateCanonicalName, typeArgs) {
|
|
12
|
+
return templateCanonicalName + "$$" + typeArgs.map(t => t.toConcreteTirTypeName()).join("$$");
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Instantiate a generic function template with the given concrete type
|
|
16
|
+
* arguments, producing (and caching) a fresh concrete TIR function.
|
|
17
|
+
*
|
|
18
|
+
* The strategy is "desugar to a concrete function during AST→TIR":
|
|
19
|
+
*
|
|
20
|
+
* 1. Build a child scope on the template's defining scope where each type
|
|
21
|
+
* parameter name resolves as a type alias for its concrete type. When the
|
|
22
|
+
* cloned FuncExpr is re-compiled, every `AstNamedTypeExpr` mentioning a
|
|
23
|
+
* type parameter resolves to its concrete TIR type.
|
|
24
|
+
* 2. Construct a fresh `FuncExpr` reusing the template's body & signature but
|
|
25
|
+
* with `typeParams = []` (so the "not implemented: generic functions"
|
|
26
|
+
* guard in `_compileFuncExpr` does not trip) and a unique instance name.
|
|
27
|
+
* 3. Compile via `_compileFuncExpr` and register the resulting `TirFuncExpr`
|
|
28
|
+
* in `program.functions` under the instance name.
|
|
29
|
+
*
|
|
30
|
+
* Results are memoized per `(template, type-args)` tuple — repeated calls
|
|
31
|
+
* with the same type arguments return the same instance and do not
|
|
32
|
+
* re-compile.
|
|
33
|
+
*/
|
|
34
|
+
export function monomorphizeGeneric(ctx, template, typeArgs, callRange) {
|
|
35
|
+
const program = ctx.program;
|
|
36
|
+
if (typeArgs.length !== template.typeParams.length) {
|
|
37
|
+
ctx.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, callRange, String(template.typeParams.length), String(typeArgs.length));
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
// Build the substitution env for substituteTypeParams
|
|
41
|
+
const subst = new Map();
|
|
42
|
+
for (let i = 0; i < template.typeParams.length; i++) {
|
|
43
|
+
subst.set(template.typeParams[i].symbol, typeArgs[i]);
|
|
44
|
+
}
|
|
45
|
+
// Compute concrete signature up-front (used by callers to type the call expr)
|
|
46
|
+
const concreteFuncType = substituteTypeParams(template.placeholderFuncType, subst);
|
|
47
|
+
// Memo key & cache hit
|
|
48
|
+
const instanceName = buildMonomorphizationKey(template.canonicalTirName, typeArgs);
|
|
49
|
+
const cached = program.monomorphizationCache.get(instanceName);
|
|
50
|
+
if (typeof cached === "string") {
|
|
51
|
+
return { tirFuncName: cached, concreteFuncType };
|
|
52
|
+
}
|
|
53
|
+
// Native template path: skip AST cloning entirely.
|
|
54
|
+
if (template.kind === "native") {
|
|
55
|
+
const tirFunc = template.instantiate(typeArgs);
|
|
56
|
+
program.functions.set(instanceName, tirFunc);
|
|
57
|
+
program.monomorphizationCache.set(instanceName, instanceName);
|
|
58
|
+
return { tirFuncName: instanceName, concreteFuncType };
|
|
59
|
+
}
|
|
60
|
+
// Cycle detection: polymorphic recursion (same template + same type args
|
|
61
|
+
// re-entering before the first compile finished) is impossible because
|
|
62
|
+
// recursion at the same type-args hits the memo cache below. Recursion at
|
|
63
|
+
// *different* type-args is allowed and produces a separate instance.
|
|
64
|
+
if (program.monomorphizationInFlight.has(instanceName)) {
|
|
65
|
+
// intentionally rare path; surface as a Not_implemented diagnostic
|
|
66
|
+
ctx.error(DiagnosticCode.Not_implemented_0, callRange, "mutually-recursive monomorphization for " + instanceName);
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
program.monomorphizationInFlight.add(instanceName);
|
|
70
|
+
// Pre-register memo so recursive same-args call resolves to the same name
|
|
71
|
+
program.monomorphizationCache.set(instanceName, instanceName);
|
|
72
|
+
try {
|
|
73
|
+
// Build child scope where each type-param name aliases its concrete type
|
|
74
|
+
const monoScope = template.definingScope.newChildScope({
|
|
75
|
+
...template.definingScope.infos,
|
|
76
|
+
isFunctionDeclScope: false,
|
|
77
|
+
isMethodScope: false
|
|
78
|
+
});
|
|
79
|
+
for (let i = 0; i < template.typeParams.length; i++) {
|
|
80
|
+
const tparam = template.typeParams[i];
|
|
81
|
+
const concrete = typeArgs[i];
|
|
82
|
+
const concreteKey = concrete.toConcreteTirTypeName();
|
|
83
|
+
if (!program.types.has(concreteKey)) {
|
|
84
|
+
program.types.set(concreteKey, concrete);
|
|
85
|
+
}
|
|
86
|
+
monoScope.defineUnambigousType(tparam.name, concreteKey, concrete.hasDataEncoding(), new Map() // no methods on a bare type alias
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
// Register the instance in the parent (defining) scope under the
|
|
90
|
+
// instance name so the body's own recursive `id(...)` call (which
|
|
91
|
+
// resolves through the parent chain) sees a concrete value of the
|
|
92
|
+
// already-substituted type. Without this, recursive calls would
|
|
93
|
+
// re-trigger the generic placeholder path and infinite-loop the
|
|
94
|
+
// monomorphizer.
|
|
95
|
+
// Use the mono scope (not the defining scope) so the entry is local
|
|
96
|
+
// to this instantiation.
|
|
97
|
+
monoScope.defineValue({
|
|
98
|
+
name: instanceName,
|
|
99
|
+
type: concreteFuncType,
|
|
100
|
+
isConstant: true,
|
|
101
|
+
});
|
|
102
|
+
const cloneExpr = new FuncExpr(new Identifier(instanceName, template.astFuncExpr.name.range), template.astFuncExpr.flags, [], // intentionally empty: this clone is the monomorphized concrete fn
|
|
103
|
+
template.astFuncExpr.signature, template.astFuncExpr.body, template.astFuncExpr.arrowKind ?? ArrowKind.None, template.astFuncExpr.range);
|
|
104
|
+
// Pre-seed program.functions with the concrete signature so
|
|
105
|
+
// `_compileFuncExpr` picks it up via `program.functions.get(...).sig()`.
|
|
106
|
+
// We will replace this with the real TirFuncExpr after compile.
|
|
107
|
+
// (placeholder is not strictly required; _compileFuncExpr falls back to
|
|
108
|
+
// inferring from the signature if not present — leaving this out for
|
|
109
|
+
// simplicity)
|
|
110
|
+
const monoCtx = AstCompilationCtx.fromScope(program, monoScope);
|
|
111
|
+
const tirFuncExpr = _compileFuncExpr(monoCtx, cloneExpr, undefined, false // isMethod
|
|
112
|
+
);
|
|
113
|
+
if (!tirFuncExpr) {
|
|
114
|
+
program.monomorphizationCache.delete(instanceName);
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
program.functions.set(instanceName, tirFuncExpr);
|
|
118
|
+
return { tirFuncName: instanceName, concreteFuncType };
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
program.monomorphizationInFlight.delete(instanceName);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { PebbleExpr } from "../../../ast/nodes/expr/PebbleExpr.js";
|
|
2
|
+
import { TirExpr } from "../../tir/expressions/TirExpr.js";
|
|
3
|
+
import { AstCompilationCtx } from "../AstCompilationCtx.js";
|
|
4
|
+
import { NamespaceSymbol } from "../scope/AstScope.js";
|
|
5
|
+
export type NamespaceChainResolution = {
|
|
6
|
+
kind: "namespace";
|
|
7
|
+
namespace: NamespaceSymbol;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "value";
|
|
10
|
+
expr: TirExpr;
|
|
11
|
+
}
|
|
12
|
+
/** the chain points to a non-value (type / interface / nested ns
|
|
13
|
+
* used in non-expression position). callers should typically error. */
|
|
14
|
+
| {
|
|
15
|
+
kind: "incomplete";
|
|
16
|
+
} | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* if `expr` is `Identifier` or a chain of `DotPropAccessExpr` ending in an
|
|
19
|
+
* `Identifier`, AND the head identifier resolves to a namespace in scope,
|
|
20
|
+
* walks the chain through namespace `publicScope`s and returns the resolved
|
|
21
|
+
* member. otherwise returns `undefined` so the caller can fall back to
|
|
22
|
+
* normal value/property-access compilation.
|
|
23
|
+
*
|
|
24
|
+
* the resolution does NOT emit diagnostics on plain "not a namespace"
|
|
25
|
+
* outcomes — those are silent failures so the caller can choose another
|
|
26
|
+
* resolution strategy.
|
|
27
|
+
*/
|
|
28
|
+
export declare function tryResolveNamespaceChain(ctx: AstCompilationCtx, expr: PebbleExpr): NamespaceChainResolution;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Identifier } from "../../../ast/nodes/common/Identifier.js";
|
|
2
|
+
import { DotPropAccessExpr } from "../../../ast/nodes/expr/PropAccessExpr.js";
|
|
3
|
+
import { DiagnosticCode } from "../../../diagnostics/diagnosticMessages.generated.js";
|
|
4
|
+
import { TirVariableAccessExpr } from "../../tir/expressions/TirVariableAccessExpr.js";
|
|
5
|
+
/**
|
|
6
|
+
* if `expr` is `Identifier` or a chain of `DotPropAccessExpr` ending in an
|
|
7
|
+
* `Identifier`, AND the head identifier resolves to a namespace in scope,
|
|
8
|
+
* walks the chain through namespace `publicScope`s and returns the resolved
|
|
9
|
+
* member. otherwise returns `undefined` so the caller can fall back to
|
|
10
|
+
* normal value/property-access compilation.
|
|
11
|
+
*
|
|
12
|
+
* the resolution does NOT emit diagnostics on plain "not a namespace"
|
|
13
|
+
* outcomes — those are silent failures so the caller can choose another
|
|
14
|
+
* resolution strategy.
|
|
15
|
+
*/
|
|
16
|
+
export function tryResolveNamespaceChain(ctx, expr) {
|
|
17
|
+
const segments = _collectChainSegments(expr);
|
|
18
|
+
if (!segments)
|
|
19
|
+
return undefined;
|
|
20
|
+
const head = ctx.scope.resolveNamespace(segments[0].text);
|
|
21
|
+
if (!head)
|
|
22
|
+
return undefined;
|
|
23
|
+
// head is a namespace; from here on, any failure emits a diagnostic
|
|
24
|
+
let current = head;
|
|
25
|
+
for (let i = 1; i < segments.length; i++) {
|
|
26
|
+
const seg = segments[i];
|
|
27
|
+
const name = seg.text;
|
|
28
|
+
const pub = current.publicScope;
|
|
29
|
+
const nested = pub.namespaces.get(name);
|
|
30
|
+
if (nested) {
|
|
31
|
+
current = nested;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const variable = pub.variables.get(name);
|
|
35
|
+
if (variable) {
|
|
36
|
+
// last segment must end here; if not, the chain is invalid
|
|
37
|
+
if (i !== segments.length - 1) {
|
|
38
|
+
ctx.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, seg.range, segments[i + 1].text, variable.type.toString());
|
|
39
|
+
return { kind: "incomplete" };
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
kind: "value",
|
|
43
|
+
expr: new TirVariableAccessExpr({ variableInfos: variable, isDefinedOutsideFuncScope: true }, seg.range)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const tirFuncName = pub.functions.get(name);
|
|
47
|
+
if (tirFuncName) {
|
|
48
|
+
if (i !== segments.length - 1) {
|
|
49
|
+
// function-typed member can't be further dotted
|
|
50
|
+
ctx.error(DiagnosticCode.Namespace_path_is_incomplete_expected_a_value_type_function_or_interface, seg.range);
|
|
51
|
+
return { kind: "incomplete" };
|
|
52
|
+
}
|
|
53
|
+
const funcExpr = pub.program.functions.get(tirFuncName);
|
|
54
|
+
if (!funcExpr) {
|
|
55
|
+
ctx.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, seg.range, current.name, name);
|
|
56
|
+
return { kind: "incomplete" };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
kind: "value",
|
|
60
|
+
expr: new TirVariableAccessExpr({
|
|
61
|
+
variableInfos: {
|
|
62
|
+
isConstant: true,
|
|
63
|
+
name: tirFuncName,
|
|
64
|
+
type: funcExpr.type,
|
|
65
|
+
},
|
|
66
|
+
isDefinedOutsideFuncScope: true,
|
|
67
|
+
}, seg.range)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// not a namespace, not a value, not a function — likely a type or
|
|
71
|
+
// interface. either way it can't be used as a value here.
|
|
72
|
+
if (pub.types.has(name) || pub.interfaces.has(name)) {
|
|
73
|
+
ctx.error(DiagnosticCode.Namespace_path_is_incomplete_expected_a_value_type_function_or_interface, seg.range);
|
|
74
|
+
return { kind: "incomplete" };
|
|
75
|
+
}
|
|
76
|
+
ctx.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, seg.range, current.name, name);
|
|
77
|
+
return { kind: "incomplete" };
|
|
78
|
+
}
|
|
79
|
+
// chain consumed entirely as namespaces (no leaf member)
|
|
80
|
+
return { kind: "namespace", namespace: current };
|
|
81
|
+
}
|
|
82
|
+
function _collectChainSegments(expr) {
|
|
83
|
+
if (expr instanceof Identifier)
|
|
84
|
+
return [expr];
|
|
85
|
+
if (expr instanceof DotPropAccessExpr) {
|
|
86
|
+
const inner = _collectChainSegments(expr.object);
|
|
87
|
+
if (!inner)
|
|
88
|
+
return undefined;
|
|
89
|
+
inner.push(expr.prop);
|
|
90
|
+
return inner;
|
|
91
|
+
}
|
|
92
|
+
// anything other than a plain dotted-identifier chain disqualifies
|
|
93
|
+
// namespace resolution.
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Identifier } from "../../../ast/nodes/common/Identifier.js";
|
|
2
|
+
import { UsingPath } from "../../../ast/nodes/statements/UsingStmt.js";
|
|
3
|
+
import { AstScope, NamespaceSymbol } from "../scope/AstScope.js";
|
|
4
|
+
import { AstCompilationCtx } from "../AstCompilationCtx.js";
|
|
5
|
+
export interface ResolvedNamespacePath {
|
|
6
|
+
/** the namespace the path resolves to */
|
|
7
|
+
namespace: NamespaceSymbol;
|
|
8
|
+
/** the chain of resolved namespaces (one per segment of the path) */
|
|
9
|
+
chain: NamespaceSymbol[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* walks a dotted namespace path against the given scope.
|
|
13
|
+
*
|
|
14
|
+
* - returns the final `NamespaceSymbol` if every segment resolves to a namespace.
|
|
15
|
+
* - if the first segment is not a namespace, returns `undefined`
|
|
16
|
+
* (no diagnostic emitted; the caller can fall back to a different
|
|
17
|
+
* resolution strategy, e.g. struct lookup).
|
|
18
|
+
* - if a later segment is missing or is not a namespace, emits a
|
|
19
|
+
* diagnostic and returns `undefined`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveNamespacePath(ctx: AstCompilationCtx, path: UsingPath): ResolvedNamespacePath | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* looks up a member name in a namespace's public scope.
|
|
24
|
+
*
|
|
25
|
+
* the member can be any of:
|
|
26
|
+
* - a value (variable)
|
|
27
|
+
* - a function
|
|
28
|
+
* - a type
|
|
29
|
+
* - an interface
|
|
30
|
+
* - a nested namespace
|
|
31
|
+
*
|
|
32
|
+
* binds the resolved member into `target` (under either `originalName`
|
|
33
|
+
* or `aliasName` if provided). emits a diagnostic and returns `false`
|
|
34
|
+
* if no such member is exported, or if a conflicting binding already
|
|
35
|
+
* exists in `target`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function bindNamespaceMember(ctx: AstCompilationCtx, ns: NamespaceSymbol, originalName: Identifier, aliasName: Identifier | undefined, target: AstScope): boolean;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { DiagnosticCode } from "../../../diagnostics/diagnosticMessages.generated.js";
|
|
2
|
+
/**
|
|
3
|
+
* walks a dotted namespace path against the given scope.
|
|
4
|
+
*
|
|
5
|
+
* - returns the final `NamespaceSymbol` if every segment resolves to a namespace.
|
|
6
|
+
* - if the first segment is not a namespace, returns `undefined`
|
|
7
|
+
* (no diagnostic emitted; the caller can fall back to a different
|
|
8
|
+
* resolution strategy, e.g. struct lookup).
|
|
9
|
+
* - if a later segment is missing or is not a namespace, emits a
|
|
10
|
+
* diagnostic and returns `undefined`.
|
|
11
|
+
*/
|
|
12
|
+
export function resolveNamespacePath(ctx, path) {
|
|
13
|
+
const segments = path.segments;
|
|
14
|
+
if (segments.length === 0)
|
|
15
|
+
return undefined;
|
|
16
|
+
const head = segments[0];
|
|
17
|
+
const first = ctx.scope.resolveNamespace(head.text);
|
|
18
|
+
if (!first)
|
|
19
|
+
return undefined;
|
|
20
|
+
const chain = [first];
|
|
21
|
+
let current = first;
|
|
22
|
+
for (let i = 1; i < segments.length; i++) {
|
|
23
|
+
const seg = segments[i];
|
|
24
|
+
const inner = current.publicScope.namespaces.get(seg.text);
|
|
25
|
+
if (!inner) {
|
|
26
|
+
ctx.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, seg.range, current.name, seg.text);
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
chain.push(inner);
|
|
30
|
+
current = inner;
|
|
31
|
+
}
|
|
32
|
+
return { namespace: current, chain };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* looks up a member name in a namespace's public scope.
|
|
36
|
+
*
|
|
37
|
+
* the member can be any of:
|
|
38
|
+
* - a value (variable)
|
|
39
|
+
* - a function
|
|
40
|
+
* - a type
|
|
41
|
+
* - an interface
|
|
42
|
+
* - a nested namespace
|
|
43
|
+
*
|
|
44
|
+
* binds the resolved member into `target` (under either `originalName`
|
|
45
|
+
* or `aliasName` if provided). emits a diagnostic and returns `false`
|
|
46
|
+
* if no such member is exported, or if a conflicting binding already
|
|
47
|
+
* exists in `target`.
|
|
48
|
+
*/
|
|
49
|
+
export function bindNamespaceMember(ctx, ns, originalName, aliasName, target) {
|
|
50
|
+
const pub = ns.publicScope;
|
|
51
|
+
const name = originalName.text;
|
|
52
|
+
const localName = aliasName?.text ?? name;
|
|
53
|
+
const variable = pub.variables.get(name);
|
|
54
|
+
const fn = pub.functions.get(name);
|
|
55
|
+
const tirFunc = fn ? pub.program.functions.get(fn) : undefined;
|
|
56
|
+
const ty = pub.types.get(name);
|
|
57
|
+
const iface = pub.interfaces.get(name);
|
|
58
|
+
const nested = pub.namespaces.get(name);
|
|
59
|
+
if (!variable && !fn && !ty && !iface && !nested) {
|
|
60
|
+
ctx.error(DiagnosticCode.Namespace_0_has_no_exported_member_1, originalName.range, ns.name, name);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
let ok = true;
|
|
64
|
+
if (variable) {
|
|
65
|
+
ok = target.defineValue({ ...variable, name: localName }) && ok;
|
|
66
|
+
}
|
|
67
|
+
if (fn) {
|
|
68
|
+
target.functions.set(localName, fn);
|
|
69
|
+
if (tirFunc) {
|
|
70
|
+
target.defineValue({
|
|
71
|
+
isConstant: true,
|
|
72
|
+
name: localName,
|
|
73
|
+
type: tirFunc.type,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (ty) {
|
|
78
|
+
ok = target.defineType(localName, ty) && ok;
|
|
79
|
+
}
|
|
80
|
+
if (iface) {
|
|
81
|
+
if (target.interfaces.has(localName))
|
|
82
|
+
ok = false;
|
|
83
|
+
else
|
|
84
|
+
target.interfaces.set(localName, iface);
|
|
85
|
+
}
|
|
86
|
+
if (nested) {
|
|
87
|
+
ok = target.defineNamespace({
|
|
88
|
+
name: localName,
|
|
89
|
+
publicScope: nested.publicScope
|
|
90
|
+
}) && ok;
|
|
91
|
+
}
|
|
92
|
+
return ok;
|
|
93
|
+
}
|
|
@@ -3,11 +3,13 @@ import { DiagnosticMessage } from "../diagnostics/DiagnosticMessage.js";
|
|
|
3
3
|
import { CompilerOptions } from "../IR/toUPLC/CompilerOptions.js";
|
|
4
4
|
import { CompilerIoApi } from "./io/CompilerIoApi.js";
|
|
5
5
|
import { CheckResult } from "./SourceTypeMap.js";
|
|
6
|
+
import { TestResult } from "./test/TestResult.js";
|
|
6
7
|
export { CheckResult, SourceTypeMap, TypeEntry, MemberInfo } from "./SourceTypeMap.js";
|
|
8
|
+
export { TestBudget, TestIterationResult, TestResult, TestKind, } from "./test/TestResult.js";
|
|
7
9
|
export declare class Compiler extends DiagnosticEmitter {
|
|
8
10
|
readonly io: CompilerIoApi;
|
|
9
11
|
readonly cfg: CompilerOptions;
|
|
10
|
-
constructor(io
|
|
12
|
+
constructor(io: CompilerIoApi, cfg: CompilerOptions, diagnostics?: DiagnosticMessage[]);
|
|
11
13
|
check(config?: Partial<CompilerOptions>): Promise<CheckResult>;
|
|
12
14
|
compile(config?: Partial<CompilerOptions>): Promise<Uint8Array>;
|
|
13
15
|
export(config: Partial<ExportOptions> & HasFuncitonName): Promise<Uint8Array>;
|
|
@@ -16,6 +18,12 @@ export declare class Compiler extends DiagnosticEmitter {
|
|
|
16
18
|
budgetSpent: import("@harmoniclabs/plutus-machine").ExBudget;
|
|
17
19
|
logs: string[];
|
|
18
20
|
}>;
|
|
21
|
+
test(config?: Partial<CompilerOptions> & {
|
|
22
|
+
nameFilter?: string | RegExp;
|
|
23
|
+
propertyIterations?: number;
|
|
24
|
+
seed?: number;
|
|
25
|
+
}): Promise<TestResult[]>;
|
|
26
|
+
private _runOneTest;
|
|
19
27
|
runRepl(config?: Partial<CompilerOptions>): Promise<{
|
|
20
28
|
result: import("@harmoniclabs/plutus-machine").CEKValueObj;
|
|
21
29
|
budgetSpent: import("@harmoniclabs/plutus-machine").ExBudget;
|