@harmoniclabs/pebble 0.1.3-dev3 → 0.1.3-dev4
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/ast/nodes/statements/declarations/VarDecl/SimpleVarDecl.d.ts +5 -1
- package/dist/ast/nodes/statements/declarations/VarDecl/SimpleVarDecl.js +5 -1
- package/dist/compiler/AstCompiler/AstCompiler.d.ts +15 -0
- package/dist/compiler/AstCompiler/AstCompiler.js +226 -10
- package/dist/compiler/AstCompiler/internal/_deriveContractBody/_deriveContractBody.js +40 -35
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.d.ts +7 -2
- package/dist/compiler/AstCompiler/internal/statements/_compileVarStmt.js +17 -14
- package/dist/compiler/Compiler.d.ts +8 -1
- package/dist/compiler/Compiler.js +34 -1
- package/dist/compiler/SourceTypeMap.d.ts +43 -0
- package/dist/compiler/SourceTypeMap.js +432 -0
- package/dist/compiler/tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.d.ts +19 -1
- package/dist/compiler/tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js +13 -1
- package/dist/compiler/tir/statements/TirVarDecl/TirSimpleVarDecl.d.ts +9 -1
- package/dist/compiler/tir/statements/TirVarDecl/TirSimpleVarDecl.js +9 -1
- package/dist/compiler/tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.d.ts +15 -1
- package/dist/compiler/tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.js +9 -1
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ export function _compileSimpleVarDecl(ctx, decl, typeHint) {
|
|
|
44
44
|
const typeAndExpr = _getVarDeclTypeAndExpr(ctx, decl, typeHint);
|
|
45
45
|
if (!typeAndExpr)
|
|
46
46
|
return undefined;
|
|
47
|
-
const [finalVarType, initExpr] = typeAndExpr;
|
|
47
|
+
const [finalVarType, initExpr, typeAnnotationRange] = typeAndExpr;
|
|
48
48
|
const success = ctx.scope.defineValue({
|
|
49
49
|
name: decl.name.text,
|
|
50
50
|
type: finalVarType,
|
|
@@ -52,7 +52,7 @@ export function _compileSimpleVarDecl(ctx, decl, typeHint) {
|
|
|
52
52
|
});
|
|
53
53
|
if (!success)
|
|
54
54
|
return ctx.error(DiagnosticCode.Duplicate_identifier_0, decl.name.range, decl.name.text);
|
|
55
|
-
return new TirSimpleVarDecl(decl.name.text, finalVarType, initExpr, decl.isConst(), decl.range);
|
|
55
|
+
return new TirSimpleVarDecl(decl.name.text, finalVarType, initExpr, decl.isConst(), decl.range, typeAnnotationRange, decl.sourceName);
|
|
56
56
|
}
|
|
57
57
|
export function _compileNamedDeconstructVarDecl(ctx, decl, typeHint) {
|
|
58
58
|
// const Spending{ ref, optionalDatum: datum as MyDatum } = purpose
|
|
@@ -71,7 +71,7 @@ export function _compileNamedDeconstructVarDecl(ctx, decl, typeHint) {
|
|
|
71
71
|
const typeAndExpr = _getVarDeclTypeAndExpr(ctx, decl, typeHint);
|
|
72
72
|
if (!typeAndExpr)
|
|
73
73
|
return undefined;
|
|
74
|
-
const [finalVarType, initExpr] = typeAndExpr;
|
|
74
|
+
const [finalVarType, initExpr, typeAnnotationRange] = typeAndExpr;
|
|
75
75
|
const namedDestructableType = getNamedDestructableType(finalVarType);
|
|
76
76
|
if (!namedDestructableType
|
|
77
77
|
|| !namedDestructableType.isConcrete())
|
|
@@ -86,8 +86,8 @@ export function _compileNamedDeconstructVarDecl(ctx, decl, typeHint) {
|
|
|
86
86
|
] : []));
|
|
87
87
|
if (!deconstructedFields)
|
|
88
88
|
return undefined;
|
|
89
|
-
const [fieds, rest] = deconstructedFields;
|
|
90
|
-
return new TirNamedDeconstructVarDecl(decl.name.text, fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range);
|
|
89
|
+
const [fieds, rest, fieldLabelRanges] = deconstructedFields;
|
|
90
|
+
return new TirNamedDeconstructVarDecl(decl.name.text, fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range, decl.name.range, fieldLabelRanges, typeAnnotationRange);
|
|
91
91
|
}
|
|
92
92
|
if (isTirStructType(namedDestructableType)) {
|
|
93
93
|
const finalConstructorDef = namedDestructableType.constructors.find(ctor => ctor.name === decl.name.text);
|
|
@@ -96,15 +96,15 @@ export function _compileNamedDeconstructVarDecl(ctx, decl, typeHint) {
|
|
|
96
96
|
const deconstructedFields = _getDeconstructedFields(ctx, decl, finalConstructorDef);
|
|
97
97
|
if (!deconstructedFields)
|
|
98
98
|
return undefined;
|
|
99
|
-
const [fieds, rest] = deconstructedFields;
|
|
100
|
-
return new TirNamedDeconstructVarDecl(decl.name.text, fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range);
|
|
99
|
+
const [fieds, rest, fieldLabelRanges] = deconstructedFields;
|
|
100
|
+
return new TirNamedDeconstructVarDecl(decl.name.text, fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range, decl.name.range, fieldLabelRanges, typeAnnotationRange);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
export function _compileSingleDeconstructVarDecl(ctx, decl, typeHint) {
|
|
104
104
|
const typeAndExpr = _getVarDeclTypeAndExpr(ctx, decl, typeHint);
|
|
105
105
|
if (!typeAndExpr)
|
|
106
106
|
return undefined;
|
|
107
|
-
const [finalVarType, initExpr] = typeAndExpr;
|
|
107
|
+
const [finalVarType, initExpr, typeAnnotationRange] = typeAndExpr;
|
|
108
108
|
const finalStructType = getStructType(finalVarType);
|
|
109
109
|
if (!finalStructType)
|
|
110
110
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, decl.range, finalVarType.toString(), "Struct");
|
|
@@ -113,14 +113,14 @@ export function _compileSingleDeconstructVarDecl(ctx, decl, typeHint) {
|
|
|
113
113
|
const deconstructedFields = _getDeconstructedFields(ctx, decl, finalStructType.constructors[0]);
|
|
114
114
|
if (!deconstructedFields)
|
|
115
115
|
return undefined;
|
|
116
|
-
const [fieds, rest] = deconstructedFields;
|
|
117
|
-
return new TirSingleDeconstructVarDecl(fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range);
|
|
116
|
+
const [fieds, rest, fieldLabelRanges] = deconstructedFields;
|
|
117
|
+
return new TirSingleDeconstructVarDecl(fieds, rest, finalVarType, initExpr, decl.isConst(), decl.range, fieldLabelRanges, typeAnnotationRange);
|
|
118
118
|
}
|
|
119
119
|
export function _compileArrayLikeDeconstr(ctx, decl, typeHint) {
|
|
120
120
|
const typeAndExpr = _getVarDeclTypeAndExpr(ctx, decl, typeHint);
|
|
121
121
|
if (!typeAndExpr)
|
|
122
122
|
return undefined;
|
|
123
|
-
const [finalVarType, initExpr] = typeAndExpr;
|
|
123
|
+
const [finalVarType, initExpr, _typeAnnotationRange] = typeAndExpr;
|
|
124
124
|
const elemsType = getListTypeArg(finalVarType);
|
|
125
125
|
if (!elemsType)
|
|
126
126
|
return ctx.error(DiagnosticCode.Type_0_is_not_assignable_to_type_1, decl.range, finalVarType.toString(), "List");
|
|
@@ -146,6 +146,7 @@ export function _compileArrayLikeDeconstr(ctx, decl, typeHint) {
|
|
|
146
146
|
}
|
|
147
147
|
export function _getDeconstructedFields(ctx, astDeconstruct, ctorDef) {
|
|
148
148
|
const tirFields = new Map();
|
|
149
|
+
const fieldLabelRanges = new Map();
|
|
149
150
|
const ctorDefFieldNames = ctorDef.fields.map(f => f.name);
|
|
150
151
|
const ctorNamesAlreadySpecified = [];
|
|
151
152
|
for (const [fieldIdentifier, varDecl] of astDeconstruct.fields) {
|
|
@@ -155,8 +156,10 @@ export function _getDeconstructedFields(ctx, astDeconstruct, ctorDef) {
|
|
|
155
156
|
if (ctorNamesAlreadySpecified.includes(fieldName))
|
|
156
157
|
return ctx.error(DiagnosticCode.Duplicate_identifier_0, fieldIdentifier.range, fieldName);
|
|
157
158
|
ctorNamesAlreadySpecified.push(fieldName);
|
|
159
|
+
const ctorFieldType = ctorDef.fields.find(f => f.name === fieldName).type;
|
|
160
|
+
fieldLabelRanges.set(fieldName, { range: fieldIdentifier.range, type: ctorFieldType });
|
|
158
161
|
// adds to scope "simple" var decls
|
|
159
|
-
const tirVarDecl = _compileVarDecl(ctx, varDecl,
|
|
162
|
+
const tirVarDecl = _compileVarDecl(ctx, varDecl, ctorFieldType);
|
|
160
163
|
if (!tirVarDecl)
|
|
161
164
|
return undefined;
|
|
162
165
|
tirFields.set(fieldName, tirVarDecl);
|
|
@@ -164,7 +167,7 @@ export function _getDeconstructedFields(ctx, astDeconstruct, ctorDef) {
|
|
|
164
167
|
if (astDeconstruct.rest && ctorDefFieldNames.length === ctorNamesAlreadySpecified.length)
|
|
165
168
|
return ctx.error(DiagnosticCode.Invalid_rest_parameter_there_are_no_more_fields, astDeconstruct.rest.range);
|
|
166
169
|
let rest = astDeconstruct.rest ? astDeconstruct.rest.text : undefined;
|
|
167
|
-
return [tirFields, rest];
|
|
170
|
+
return [tirFields, rest, fieldLabelRanges];
|
|
168
171
|
}
|
|
169
172
|
export function _getVarDeclTypeAndExpr(ctx, decl, deconstructTypeHint) {
|
|
170
173
|
const declarationType = decl.type ? _compileSopEncodedConcreteType(ctx, decl.type) : undefined;
|
|
@@ -204,5 +207,5 @@ export function _getVarDeclTypeAndExpr(ctx, decl, deconstructTypeHint) {
|
|
|
204
207
|
const finalVarType = typeHint ?? initExpr?.type;
|
|
205
208
|
if (!finalVarType)
|
|
206
209
|
return ctx.error(DiagnosticCode.Cannot_infer_variable_type_Try_to_make_the_type_explicit, decl.range);
|
|
207
|
-
return [finalVarType, initExpr];
|
|
210
|
+
return [finalVarType, initExpr, decl.type?.range];
|
|
208
211
|
}
|
|
@@ -2,10 +2,13 @@ import { DiagnosticEmitter } from "../diagnostics/DiagnosticEmitter.js";
|
|
|
2
2
|
import { DiagnosticMessage } from "../diagnostics/DiagnosticMessage.js";
|
|
3
3
|
import { CompilerOptions } from "../IR/toUPLC/CompilerOptions.js";
|
|
4
4
|
import { CompilerIoApi } from "./io/CompilerIoApi.js";
|
|
5
|
+
import { CheckResult } from "./SourceTypeMap.js";
|
|
6
|
+
export { CheckResult, SourceTypeMap, TypeEntry, MemberInfo } from "./SourceTypeMap.js";
|
|
5
7
|
export declare class Compiler extends DiagnosticEmitter {
|
|
6
8
|
readonly io: CompilerIoApi;
|
|
7
9
|
readonly cfg: CompilerOptions;
|
|
8
10
|
constructor(io?: CompilerIoApi, cfg?: CompilerOptions, diagnostics?: DiagnosticMessage[]);
|
|
11
|
+
check(config?: Partial<CompilerOptions>): Promise<CheckResult>;
|
|
9
12
|
compile(config?: Partial<CompilerOptions>): Promise<Uint8Array>;
|
|
10
13
|
export(config: Partial<ExportOptions> & HasFuncitonName): Promise<Uint8Array>;
|
|
11
14
|
run(config?: Partial<CompilerOptions>): Promise<{
|
|
@@ -13,6 +16,11 @@ export declare class Compiler extends DiagnosticEmitter {
|
|
|
13
16
|
budgetSpent: import("@harmoniclabs/plutus-machine").ExBudget;
|
|
14
17
|
logs: string[];
|
|
15
18
|
}>;
|
|
19
|
+
runRepl(config?: Partial<CompilerOptions>): Promise<{
|
|
20
|
+
result: import("@harmoniclabs/plutus-machine").CEKValueObj;
|
|
21
|
+
budgetSpent: import("@harmoniclabs/plutus-machine").ExBudget;
|
|
22
|
+
logs: string[];
|
|
23
|
+
}>;
|
|
16
24
|
private _compileBackend;
|
|
17
25
|
}
|
|
18
26
|
interface HasFuncitonName {
|
|
@@ -20,4 +28,3 @@ interface HasFuncitonName {
|
|
|
20
28
|
}
|
|
21
29
|
export interface ExportOptions extends CompilerOptions, HasFuncitonName {
|
|
22
30
|
}
|
|
23
|
-
export {};
|
|
@@ -7,6 +7,7 @@ import { createMemoryCompilerIoApi } from "./io/CompilerIoApi.js";
|
|
|
7
7
|
import { compileTypedProgram } from "./TirCompiler/compileTirProgram.js";
|
|
8
8
|
import { __VERY_UNSAFE_FORGET_IRHASH_ONLY_USE_AT_END_OF_UPLC_COMPILATION } from "../IR/IRHash.js";
|
|
9
9
|
import { compileIRToUPLC } from "../IR/toUPLC/compileIRToUPLC.js";
|
|
10
|
+
export { SourceTypeMap } from "./SourceTypeMap.js";
|
|
10
11
|
export class Compiler extends DiagnosticEmitter {
|
|
11
12
|
io;
|
|
12
13
|
cfg;
|
|
@@ -18,6 +19,15 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
18
19
|
this.io.stdout = { write() { } };
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
async check(config) {
|
|
23
|
+
const cfg = {
|
|
24
|
+
...this.cfg,
|
|
25
|
+
...config,
|
|
26
|
+
silent: true,
|
|
27
|
+
};
|
|
28
|
+
const astCompiler = new AstCompiler(cfg, this.io, this.diagnostics);
|
|
29
|
+
return await astCompiler.check();
|
|
30
|
+
}
|
|
21
31
|
async compile(config) {
|
|
22
32
|
const cfg = {
|
|
23
33
|
...this.cfg,
|
|
@@ -30,9 +40,10 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
30
40
|
globalThis.console && console.log(this.diagnostics);
|
|
31
41
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
32
42
|
const nDiags = this.diagnostics.length;
|
|
33
|
-
|
|
43
|
+
for (msg of this.diagnostics) {
|
|
34
44
|
this.io.stdout.write(msg.toString() + "\n");
|
|
35
45
|
}
|
|
46
|
+
// return new Uint8Array();
|
|
36
47
|
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
37
48
|
}
|
|
38
49
|
return this._compileBackend(cfg, program);
|
|
@@ -84,6 +95,28 @@ export class Compiler extends DiagnosticEmitter {
|
|
|
84
95
|
const uplcProgram = parseUPLC(serialized);
|
|
85
96
|
return Machine.eval(uplcProgram.body);
|
|
86
97
|
}
|
|
98
|
+
async runRepl(config) {
|
|
99
|
+
const cfg = {
|
|
100
|
+
...this.cfg,
|
|
101
|
+
...config,
|
|
102
|
+
addMarker: false,
|
|
103
|
+
};
|
|
104
|
+
const astCompiler = new AstCompiler(cfg, this.io, this.diagnostics);
|
|
105
|
+
const program = await astCompiler.runRepl();
|
|
106
|
+
if (this.diagnostics.length > 0) {
|
|
107
|
+
let msg;
|
|
108
|
+
globalThis.console && console.log(this.diagnostics);
|
|
109
|
+
const fstErrorMsg = this.diagnostics[0].toString();
|
|
110
|
+
const nDiags = this.diagnostics.length;
|
|
111
|
+
while (msg = this.diagnostics.shift()) {
|
|
112
|
+
this.io.stdout.write(msg.toString() + "\n");
|
|
113
|
+
}
|
|
114
|
+
throw new Error("compilation failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
115
|
+
}
|
|
116
|
+
const serialized = this._compileBackend(cfg, program);
|
|
117
|
+
const uplcProgram = parseUPLC(serialized);
|
|
118
|
+
return Machine.eval(uplcProgram.body);
|
|
119
|
+
}
|
|
87
120
|
_compileBackend(cfg, program) {
|
|
88
121
|
// backend starts here
|
|
89
122
|
const ir = compileTypedProgram(cfg, program);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DiagnosticMessage } from "../diagnostics/DiagnosticMessage.js";
|
|
2
|
+
import { TirType } from "./tir/types/TirType.js";
|
|
3
|
+
import { TypedProgram } from "./tir/program/TypedProgram.js";
|
|
4
|
+
export interface TypeEntry {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
type: TirType;
|
|
8
|
+
name?: string;
|
|
9
|
+
/** "type-reference" marks constructor/type names; default is "expression" */
|
|
10
|
+
kind?: "expression" | "type-reference";
|
|
11
|
+
}
|
|
12
|
+
export interface MemberInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
type: TirType;
|
|
15
|
+
kind: "field" | "method";
|
|
16
|
+
}
|
|
17
|
+
export interface CheckResult {
|
|
18
|
+
diagnostics: DiagnosticMessage[];
|
|
19
|
+
program: TypedProgram;
|
|
20
|
+
sourceTypeMap: SourceTypeMap;
|
|
21
|
+
}
|
|
22
|
+
export declare class SourceTypeMap {
|
|
23
|
+
readonly program: TypedProgram;
|
|
24
|
+
private entries;
|
|
25
|
+
private sorted;
|
|
26
|
+
constructor(program: TypedProgram);
|
|
27
|
+
buildFromProgram(): void;
|
|
28
|
+
private addEntry;
|
|
29
|
+
private ensureSorted;
|
|
30
|
+
typeAtOffset(offset: number): TypeEntry | undefined;
|
|
31
|
+
allEntries(): readonly TypeEntry[];
|
|
32
|
+
membersOfType(type: TirType): MemberInfo[];
|
|
33
|
+
private structMembers;
|
|
34
|
+
private methodsFromMap;
|
|
35
|
+
private listMembers;
|
|
36
|
+
private bytesMembers;
|
|
37
|
+
private stringMembers;
|
|
38
|
+
private linearMapMembers;
|
|
39
|
+
private walkFuncExpr;
|
|
40
|
+
private walkExpr;
|
|
41
|
+
private walkStmt;
|
|
42
|
+
private walkVarDecl;
|
|
43
|
+
}
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { isInternalName } from "./internalVar.js";
|
|
2
|
+
import { TirAliasType } from "./tir/types/TirAliasType.js";
|
|
3
|
+
import { isTirStructType } from "./tir/types/TirStructType.js";
|
|
4
|
+
import { TirFuncT } from "./tir/types/TirNativeType/native/function.js";
|
|
5
|
+
import { TirListT } from "./tir/types/TirNativeType/native/list.js";
|
|
6
|
+
import { TirLinearMapT } from "./tir/types/TirNativeType/native/linearMap.js";
|
|
7
|
+
import { TirBytesT } from "./tir/types/TirNativeType/native/bytes.js";
|
|
8
|
+
import { TirStringT } from "./tir/types/TirNativeType/native/string.js";
|
|
9
|
+
import { TirBoolT } from "./tir/types/TirNativeType/native/bool.js";
|
|
10
|
+
import { TirIntT } from "./tir/types/TirNativeType/native/int.js";
|
|
11
|
+
import { TirDataT } from "./tir/types/TirNativeType/native/data.js";
|
|
12
|
+
import { TirVoidT } from "./tir/types/TirNativeType/native/void.js";
|
|
13
|
+
import { TirSopOptT } from "./tir/types/TirNativeType/native/Optional/sop.js";
|
|
14
|
+
import { int_t, bool_t, bytes_t, string_t } from "./tir/program/stdScope/stdScope.js";
|
|
15
|
+
import { TirFuncExpr } from "./tir/expressions/TirFuncExpr.js";
|
|
16
|
+
import { TirBlockStmt } from "./tir/statements/TirBlockStmt.js";
|
|
17
|
+
import { TirIfStmt } from "./tir/statements/TirIfStmt.js";
|
|
18
|
+
import { TirReturnStmt } from "./tir/statements/TirReturnStmt.js";
|
|
19
|
+
import { TirAssertStmt } from "./tir/statements/TirAssertStmt.js";
|
|
20
|
+
import { TirForStmt } from "./tir/statements/TirForStmt.js";
|
|
21
|
+
import { TirForOfStmt } from "./tir/statements/TirForOfStmt.js";
|
|
22
|
+
import { TirWhileStmt } from "./tir/statements/TirWhileStmt.js";
|
|
23
|
+
import { TirMatchStmt } from "./tir/statements/TirMatchStmt.js";
|
|
24
|
+
import { TirAssignmentStmt } from "./tir/statements/TirAssignmentStmt.js";
|
|
25
|
+
import { TirTraceStmt } from "./tir/statements/TirTraceStmt.js";
|
|
26
|
+
import { TirSimpleVarDecl } from "./tir/statements/TirVarDecl/TirSimpleVarDecl.js";
|
|
27
|
+
import { TirNamedDeconstructVarDecl } from "./tir/statements/TirVarDecl/TirNamedDeconstructVarDecl.js";
|
|
28
|
+
import { TirSingleDeconstructVarDecl } from "./tir/statements/TirVarDecl/TirSingleDeconstructVarDecl.js";
|
|
29
|
+
import { TirArrayLikeDeconstr } from "./tir/statements/TirVarDecl/TirArrayLikeDeconstr.js";
|
|
30
|
+
import { TirCallExpr } from "./tir/expressions/TirCallExpr.js";
|
|
31
|
+
import { TirPropAccessExpr } from "./tir/expressions/TirPropAccessExpr.js";
|
|
32
|
+
import { TirVariableAccessExpr } from "./tir/expressions/TirVariableAccessExpr.js";
|
|
33
|
+
import { TirCaseExpr } from "./tir/expressions/TirCaseExpr.js";
|
|
34
|
+
import { TirElemAccessExpr } from "./tir/expressions/TirElemAccessExpr.js";
|
|
35
|
+
import { TirTernaryExpr } from "./tir/expressions/TirTernaryExpr.js";
|
|
36
|
+
import { TirParentesizedExpr } from "./tir/expressions/TirParentesizedExpr.js";
|
|
37
|
+
import { TirTypeConversionExpr } from "./tir/expressions/TirTypeConversionExpr.js";
|
|
38
|
+
import { TirLettedExpr } from "./tir/expressions/TirLettedExpr.js";
|
|
39
|
+
import { TirHoistedExpr } from "./tir/expressions/TirHoistedExpr.js";
|
|
40
|
+
import { TirFromDataExpr } from "./tir/expressions/TirFromDataExpr.js";
|
|
41
|
+
import { TirToDataExpr } from "./tir/expressions/TirToDataExpr.js";
|
|
42
|
+
import { TirAssertAndContinueExpr } from "./tir/expressions/TirAssertAndContinueExpr.js";
|
|
43
|
+
import { TirTraceIfFalseExpr } from "./tir/expressions/TirTraceIfFalseExpr.js";
|
|
44
|
+
import { TirTraceExpr } from "./tir/expressions/TirTraceExpr.js";
|
|
45
|
+
import { isTirBinaryExpr } from "./tir/expressions/binary/TirBinaryExpr.js";
|
|
46
|
+
import { isTirUnaryPrefixExpr } from "./tir/expressions/unary/TirUnaryPrefixExpr.js";
|
|
47
|
+
import { TirTypeParam } from "./tir/types/TirTypeParam.js";
|
|
48
|
+
import { isTirOptType } from "./tir/types/TirNativeType/native/Optional/isTirOptType.js";
|
|
49
|
+
export class SourceTypeMap {
|
|
50
|
+
program;
|
|
51
|
+
entries = [];
|
|
52
|
+
sorted = false;
|
|
53
|
+
constructor(program) {
|
|
54
|
+
this.program = program;
|
|
55
|
+
}
|
|
56
|
+
buildFromProgram() {
|
|
57
|
+
this.entries = [];
|
|
58
|
+
for (const [name, func] of this.program.functions) {
|
|
59
|
+
if (func instanceof TirFuncExpr) {
|
|
60
|
+
this.walkFuncExpr(func);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const [name, cnst] of this.program.constants) {
|
|
64
|
+
this.walkVarDecl(cnst);
|
|
65
|
+
}
|
|
66
|
+
this.sorted = false;
|
|
67
|
+
}
|
|
68
|
+
addEntry(start, end, type, name, kind) {
|
|
69
|
+
if (start >= 0 && end > start) {
|
|
70
|
+
this.entries.push({ start, end, type, name, kind });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
ensureSorted() {
|
|
74
|
+
if (!this.sorted) {
|
|
75
|
+
// sort by start ascending, then by range size ascending (smallest/most specific first for ties)
|
|
76
|
+
this.entries.sort((a, b) => a.start - b.start || (a.end - a.start) - (b.end - b.start));
|
|
77
|
+
this.sorted = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
typeAtOffset(offset) {
|
|
81
|
+
this.ensureSorted();
|
|
82
|
+
// find the most specific (smallest range) entry containing the offset
|
|
83
|
+
let best = undefined;
|
|
84
|
+
for (const entry of this.entries) {
|
|
85
|
+
if (entry.start > offset)
|
|
86
|
+
break; // sorted by start, so no more matches
|
|
87
|
+
if (offset >= entry.start && offset < entry.end) {
|
|
88
|
+
if (!best || (entry.end - entry.start) < (best.end - best.start)) {
|
|
89
|
+
best = entry;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return best;
|
|
94
|
+
}
|
|
95
|
+
allEntries() {
|
|
96
|
+
this.ensureSorted();
|
|
97
|
+
return this.entries;
|
|
98
|
+
}
|
|
99
|
+
membersOfType(type) {
|
|
100
|
+
// unwrap aliases
|
|
101
|
+
while (type instanceof TirAliasType) {
|
|
102
|
+
const aliasMembers = this.methodsFromMap(type.methodsNamesPtr);
|
|
103
|
+
if (aliasMembers.length > 0) {
|
|
104
|
+
// get fields from aliased + methods from alias
|
|
105
|
+
const innerMembers = this.membersOfType(type.aliased);
|
|
106
|
+
const fieldMembers = innerMembers.filter(m => m.kind === "field");
|
|
107
|
+
return [...fieldMembers, ...aliasMembers];
|
|
108
|
+
}
|
|
109
|
+
type = type.aliased;
|
|
110
|
+
}
|
|
111
|
+
if (type instanceof TirTypeParam)
|
|
112
|
+
return [];
|
|
113
|
+
if (isTirStructType(type))
|
|
114
|
+
return this.structMembers(type);
|
|
115
|
+
if (type instanceof TirVoidT)
|
|
116
|
+
return [];
|
|
117
|
+
if (type instanceof TirBoolT)
|
|
118
|
+
return [];
|
|
119
|
+
if (type instanceof TirIntT)
|
|
120
|
+
return [];
|
|
121
|
+
if (type instanceof TirBytesT)
|
|
122
|
+
return this.bytesMembers();
|
|
123
|
+
if (type instanceof TirStringT)
|
|
124
|
+
return this.stringMembers();
|
|
125
|
+
if (type instanceof TirDataT)
|
|
126
|
+
return [];
|
|
127
|
+
if (isTirOptType(type))
|
|
128
|
+
return [];
|
|
129
|
+
if (type instanceof TirFuncT)
|
|
130
|
+
return [];
|
|
131
|
+
if (type instanceof TirListT)
|
|
132
|
+
return this.listMembers(type.typeArg);
|
|
133
|
+
if (type instanceof TirLinearMapT)
|
|
134
|
+
return this.linearMapMembers(type.keyTypeArg, type.valTypeArg);
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
structMembers(type) {
|
|
138
|
+
const result = [];
|
|
139
|
+
// single-constructor structs expose fields directly
|
|
140
|
+
if (type.constructors.length === 1) {
|
|
141
|
+
const constr = type.constructors[0];
|
|
142
|
+
for (const field of constr.fields) {
|
|
143
|
+
result.push({ name: field.name, type: field.type, kind: "field" });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// methods
|
|
147
|
+
result.push(...this.methodsFromMap(type.methodNamesPtr));
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
methodsFromMap(methodsPtr) {
|
|
151
|
+
const result = [];
|
|
152
|
+
for (const [astName, tirName] of methodsPtr) {
|
|
153
|
+
const funcExpr = this.program.functions.get(tirName);
|
|
154
|
+
if (!funcExpr)
|
|
155
|
+
continue;
|
|
156
|
+
const fullSig = funcExpr.sig();
|
|
157
|
+
// method sig: drop first arg (self)
|
|
158
|
+
const methodSig = new TirFuncT(fullSig.argTypes.slice(1), fullSig.returnType);
|
|
159
|
+
result.push({ name: astName, type: methodSig, kind: "method" });
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
listMembers(elemType) {
|
|
164
|
+
const mapReturnT = new TirTypeParam("T");
|
|
165
|
+
return [
|
|
166
|
+
{ name: "length", type: new TirFuncT([], int_t), kind: "method" },
|
|
167
|
+
{ name: "isEmpty", type: new TirFuncT([], bool_t), kind: "method" },
|
|
168
|
+
{ name: "show", type: new TirFuncT([], bytes_t), kind: "method" },
|
|
169
|
+
{ name: "head", type: new TirFuncT([], elemType), kind: "method" },
|
|
170
|
+
{ name: "tail", type: new TirFuncT([], new TirListT(elemType)), kind: "method" },
|
|
171
|
+
{ name: "reverse", type: new TirFuncT([], new TirListT(elemType)), kind: "method" },
|
|
172
|
+
{ name: "find", type: new TirFuncT([new TirFuncT([elemType], bool_t)], new TirSopOptT(elemType)), kind: "method" },
|
|
173
|
+
{ name: "filter", type: new TirFuncT([new TirFuncT([elemType], bool_t)], new TirListT(elemType)), kind: "method" },
|
|
174
|
+
{ name: "prepend", type: new TirFuncT([elemType], new TirListT(elemType)), kind: "method" },
|
|
175
|
+
{ name: "map", type: new TirFuncT([new TirFuncT([elemType], mapReturnT)], new TirListT(mapReturnT)), kind: "method" },
|
|
176
|
+
{ name: "every", type: new TirFuncT([new TirFuncT([elemType], bool_t)], bool_t), kind: "method" },
|
|
177
|
+
{ name: "some", type: new TirFuncT([new TirFuncT([elemType], bool_t)], bool_t), kind: "method" },
|
|
178
|
+
{ name: "includes", type: new TirFuncT([elemType], bool_t), kind: "method" },
|
|
179
|
+
];
|
|
180
|
+
}
|
|
181
|
+
bytesMembers() {
|
|
182
|
+
return [
|
|
183
|
+
{ name: "length", type: new TirFuncT([], int_t), kind: "method" },
|
|
184
|
+
{ name: "subByteString", type: new TirFuncT([int_t, int_t], bytes_t), kind: "method" },
|
|
185
|
+
{ name: "slice", type: new TirFuncT([int_t, int_t], bytes_t), kind: "method" },
|
|
186
|
+
{ name: "show", type: new TirFuncT([], bytes_t), kind: "method" },
|
|
187
|
+
{ name: "decodeUtf8", type: new TirFuncT([], string_t), kind: "method" },
|
|
188
|
+
{ name: "prepend", type: new TirFuncT([int_t], bytes_t), kind: "method" },
|
|
189
|
+
];
|
|
190
|
+
}
|
|
191
|
+
stringMembers() {
|
|
192
|
+
return [
|
|
193
|
+
...this.bytesMembers(),
|
|
194
|
+
{ name: "encodeUtf8", type: new TirFuncT([], bytes_t), kind: "method" },
|
|
195
|
+
];
|
|
196
|
+
}
|
|
197
|
+
linearMapMembers(kT, vT) {
|
|
198
|
+
return [
|
|
199
|
+
{ name: "lookup", type: new TirFuncT([kT], new TirSopOptT(vT)), kind: "method" },
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
// --- TIR tree walkers ---
|
|
203
|
+
walkFuncExpr(func) {
|
|
204
|
+
// skip top-level entry for internal/compiler-generated functions
|
|
205
|
+
// (names starting with § or other internal prefixes)
|
|
206
|
+
// their range covers the whole contract body and pollutes typeAtOffset
|
|
207
|
+
if (!func.name || !func.name.startsWith("§")) {
|
|
208
|
+
this.addEntry(func.range.start, func.range.end, func.type, func.name);
|
|
209
|
+
}
|
|
210
|
+
for (const param of func.params) {
|
|
211
|
+
this.walkVarDecl(param);
|
|
212
|
+
}
|
|
213
|
+
this.walkStmt(func.body);
|
|
214
|
+
}
|
|
215
|
+
walkExpr(expr) {
|
|
216
|
+
if (!expr)
|
|
217
|
+
return;
|
|
218
|
+
// all expressions have range and type
|
|
219
|
+
try {
|
|
220
|
+
this.addEntry(expr.range.start, expr.range.end, expr.type);
|
|
221
|
+
}
|
|
222
|
+
catch { }
|
|
223
|
+
// recurse into sub-expressions
|
|
224
|
+
if (expr instanceof TirCallExpr) {
|
|
225
|
+
this.walkExpr(expr.func);
|
|
226
|
+
for (const arg of expr.args)
|
|
227
|
+
this.walkExpr(arg);
|
|
228
|
+
}
|
|
229
|
+
else if (expr instanceof TirPropAccessExpr) {
|
|
230
|
+
this.walkExpr(expr.object);
|
|
231
|
+
}
|
|
232
|
+
else if (expr instanceof TirVariableAccessExpr) {
|
|
233
|
+
// leaf — name is the variable name
|
|
234
|
+
this.addEntry(expr.range.start, expr.range.end, expr.type, expr.resolvedValue.variableInfos.name);
|
|
235
|
+
}
|
|
236
|
+
else if (expr instanceof TirFuncExpr) {
|
|
237
|
+
this.walkFuncExpr(expr);
|
|
238
|
+
}
|
|
239
|
+
else if (expr instanceof TirCaseExpr) {
|
|
240
|
+
this.walkExpr(expr.matchExpr);
|
|
241
|
+
for (const c of expr.cases) {
|
|
242
|
+
if (c.pattern)
|
|
243
|
+
this.walkVarDecl(c.pattern);
|
|
244
|
+
this.walkExpr(c.body);
|
|
245
|
+
}
|
|
246
|
+
if (expr.wildcardCase) {
|
|
247
|
+
this.walkExpr(expr.wildcardCase.body);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
else if (expr instanceof TirElemAccessExpr) {
|
|
251
|
+
this.walkExpr(expr.arrLikeExpr);
|
|
252
|
+
this.walkExpr(expr.indexExpr);
|
|
253
|
+
}
|
|
254
|
+
else if (expr instanceof TirTernaryExpr) {
|
|
255
|
+
this.walkExpr(expr.condition);
|
|
256
|
+
this.walkExpr(expr.ifTrue);
|
|
257
|
+
this.walkExpr(expr.ifFalse);
|
|
258
|
+
}
|
|
259
|
+
else if (expr instanceof TirParentesizedExpr) {
|
|
260
|
+
this.walkExpr(expr.expr);
|
|
261
|
+
}
|
|
262
|
+
else if (expr instanceof TirTypeConversionExpr) {
|
|
263
|
+
this.walkExpr(expr.expr);
|
|
264
|
+
}
|
|
265
|
+
else if (expr instanceof TirLettedExpr) {
|
|
266
|
+
this.walkExpr(expr.expr);
|
|
267
|
+
}
|
|
268
|
+
else if (expr instanceof TirHoistedExpr) {
|
|
269
|
+
this.walkExpr(expr.expr);
|
|
270
|
+
}
|
|
271
|
+
else if (expr instanceof TirFromDataExpr) {
|
|
272
|
+
this.walkExpr(expr.expr);
|
|
273
|
+
}
|
|
274
|
+
else if (expr instanceof TirToDataExpr) {
|
|
275
|
+
this.walkExpr(expr.expr);
|
|
276
|
+
}
|
|
277
|
+
else if (expr instanceof TirAssertAndContinueExpr) {
|
|
278
|
+
this.walkExpr(expr.condition);
|
|
279
|
+
this.walkExpr(expr.continuation);
|
|
280
|
+
}
|
|
281
|
+
else if (expr instanceof TirTraceIfFalseExpr) {
|
|
282
|
+
this.walkExpr(expr.condition);
|
|
283
|
+
this.walkExpr(expr.traceMsg);
|
|
284
|
+
}
|
|
285
|
+
else if (expr instanceof TirTraceExpr) {
|
|
286
|
+
this.walkExpr(expr.traceMsg);
|
|
287
|
+
this.walkExpr(expr.continuation);
|
|
288
|
+
}
|
|
289
|
+
else if (isTirBinaryExpr(expr)) {
|
|
290
|
+
this.walkExpr(expr.left);
|
|
291
|
+
this.walkExpr(expr.right);
|
|
292
|
+
}
|
|
293
|
+
else if (isTirUnaryPrefixExpr(expr)) {
|
|
294
|
+
this.walkExpr(expr.operand);
|
|
295
|
+
}
|
|
296
|
+
// TirLitteralExpr, TirNativeFunc, TirFailExpr, TirInlineClosedIR — leaf nodes
|
|
297
|
+
}
|
|
298
|
+
walkStmt(stmt) {
|
|
299
|
+
if (!stmt)
|
|
300
|
+
return;
|
|
301
|
+
if (stmt instanceof TirBlockStmt) {
|
|
302
|
+
for (const s of stmt.stmts)
|
|
303
|
+
this.walkStmt(s);
|
|
304
|
+
}
|
|
305
|
+
else if (stmt instanceof TirIfStmt) {
|
|
306
|
+
this.walkExpr(stmt.condition);
|
|
307
|
+
this.walkStmt(stmt.thenBranch);
|
|
308
|
+
if (stmt.elseBranch)
|
|
309
|
+
this.walkStmt(stmt.elseBranch);
|
|
310
|
+
}
|
|
311
|
+
else if (stmt instanceof TirReturnStmt) {
|
|
312
|
+
this.walkExpr(stmt.value);
|
|
313
|
+
}
|
|
314
|
+
else if (stmt instanceof TirAssertStmt) {
|
|
315
|
+
this.walkExpr(stmt.condition);
|
|
316
|
+
if (stmt.elseExpr)
|
|
317
|
+
this.walkExpr(stmt.elseExpr);
|
|
318
|
+
}
|
|
319
|
+
else if (stmt instanceof TirForStmt) {
|
|
320
|
+
for (const v of stmt.init)
|
|
321
|
+
this.walkVarDecl(v);
|
|
322
|
+
if (stmt.condition)
|
|
323
|
+
this.walkExpr(stmt.condition);
|
|
324
|
+
if (stmt.update)
|
|
325
|
+
for (const s of stmt.update)
|
|
326
|
+
this.walkStmt(s);
|
|
327
|
+
this.walkStmt(stmt.body);
|
|
328
|
+
}
|
|
329
|
+
else if (stmt instanceof TirForOfStmt) {
|
|
330
|
+
this.walkVarDecl(stmt.elemDeclaration);
|
|
331
|
+
this.walkExpr(stmt.iterable);
|
|
332
|
+
this.walkStmt(stmt.body);
|
|
333
|
+
}
|
|
334
|
+
else if (stmt instanceof TirWhileStmt) {
|
|
335
|
+
this.walkExpr(stmt.condition);
|
|
336
|
+
this.walkStmt(stmt.body);
|
|
337
|
+
}
|
|
338
|
+
else if (stmt instanceof TirMatchStmt) {
|
|
339
|
+
this.walkExpr(stmt.matchExpr);
|
|
340
|
+
for (const c of stmt.cases) {
|
|
341
|
+
this.walkVarDecl(c.pattern);
|
|
342
|
+
this.walkStmt(c.body);
|
|
343
|
+
}
|
|
344
|
+
if (stmt.wildcardCase)
|
|
345
|
+
this.walkStmt(stmt.wildcardCase.body);
|
|
346
|
+
}
|
|
347
|
+
else if (stmt instanceof TirAssignmentStmt) {
|
|
348
|
+
this.walkExpr(stmt.varIdentifier);
|
|
349
|
+
this.walkExpr(stmt.assignedExpr);
|
|
350
|
+
}
|
|
351
|
+
else if (stmt instanceof TirTraceStmt) {
|
|
352
|
+
this.walkExpr(stmt.expr);
|
|
353
|
+
}
|
|
354
|
+
else if (stmt instanceof TirSimpleVarDecl) {
|
|
355
|
+
this.walkVarDecl(stmt);
|
|
356
|
+
}
|
|
357
|
+
else if (stmt instanceof TirNamedDeconstructVarDecl) {
|
|
358
|
+
this.walkVarDecl(stmt);
|
|
359
|
+
}
|
|
360
|
+
else if (stmt instanceof TirSingleDeconstructVarDecl) {
|
|
361
|
+
this.walkVarDecl(stmt);
|
|
362
|
+
}
|
|
363
|
+
else if (stmt instanceof TirArrayLikeDeconstr) {
|
|
364
|
+
this.walkVarDecl(stmt);
|
|
365
|
+
}
|
|
366
|
+
// TirBreakStmt, TirContinueStmt, TirFailStmt — no sub-expressions to walk
|
|
367
|
+
}
|
|
368
|
+
walkVarDecl(decl, isDeconstructField = false) {
|
|
369
|
+
if (decl instanceof TirSimpleVarDecl) {
|
|
370
|
+
// skip full-range entry for deconstruct fields — their parent's fieldLabelRanges provides correct tight-range entries
|
|
371
|
+
if (!isDeconstructField) {
|
|
372
|
+
// internal-named params (§-prefixed) use sourceName if available
|
|
373
|
+
const displayName = decl.sourceName ?? (isInternalName(decl.name) ? undefined : decl.name);
|
|
374
|
+
if (displayName !== undefined) {
|
|
375
|
+
this.addEntry(decl.range.start, decl.range.end, decl.type, displayName);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
// add entry for explicit type annotation as a type reference
|
|
379
|
+
if (decl.typeAnnotationRange) {
|
|
380
|
+
this.addEntry(decl.typeAnnotationRange.start, decl.typeAnnotationRange.end, decl.type, undefined, "type-reference");
|
|
381
|
+
}
|
|
382
|
+
if (decl.initExpr)
|
|
383
|
+
this.walkExpr(decl.initExpr);
|
|
384
|
+
}
|
|
385
|
+
else if (decl instanceof TirNamedDeconstructVarDecl) {
|
|
386
|
+
// add entry for the constructor name as a type reference (for LSP coloring)
|
|
387
|
+
if (decl.constrNameRange) {
|
|
388
|
+
this.addEntry(decl.constrNameRange.start, decl.constrNameRange.end, decl.type, decl.constrName, "type-reference");
|
|
389
|
+
}
|
|
390
|
+
// add entry for explicit type annotation as a type reference
|
|
391
|
+
if (decl.typeAnnotationRange) {
|
|
392
|
+
this.addEntry(decl.typeAnnotationRange.start, decl.typeAnnotationRange.end, decl.type, undefined, "type-reference");
|
|
393
|
+
}
|
|
394
|
+
// add entries for field labels (hovering field name shows the field's type from the constructor definition)
|
|
395
|
+
if (decl.fieldLabelRanges) {
|
|
396
|
+
for (const [fieldName, labelInfo] of decl.fieldLabelRanges) {
|
|
397
|
+
this.addEntry(labelInfo.range.start, labelInfo.range.end, labelInfo.type, fieldName);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (decl.initExpr)
|
|
401
|
+
this.walkExpr(decl.initExpr);
|
|
402
|
+
for (const field of decl.fields.values()) {
|
|
403
|
+
this.walkVarDecl(field, true);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
else if (decl instanceof TirSingleDeconstructVarDecl) {
|
|
407
|
+
// add entry for explicit type annotation as a type reference
|
|
408
|
+
if (decl.typeAnnotationRange) {
|
|
409
|
+
this.addEntry(decl.typeAnnotationRange.start, decl.typeAnnotationRange.end, decl.type, undefined, "type-reference");
|
|
410
|
+
}
|
|
411
|
+
// add entries for field labels (hovering field name shows the field's type from the constructor definition)
|
|
412
|
+
if (decl.fieldLabelRanges) {
|
|
413
|
+
for (const [fieldName, labelInfo] of decl.fieldLabelRanges) {
|
|
414
|
+
this.addEntry(labelInfo.range.start, labelInfo.range.end, labelInfo.type, fieldName);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (decl.initExpr)
|
|
418
|
+
this.walkExpr(decl.initExpr);
|
|
419
|
+
for (const field of decl.fields.values()) {
|
|
420
|
+
this.walkVarDecl(field, true);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
else if (decl instanceof TirArrayLikeDeconstr) {
|
|
424
|
+
this.addEntry(decl.range.start, decl.range.end, decl.type);
|
|
425
|
+
if (decl.initExpr)
|
|
426
|
+
this.walkExpr(decl.initExpr);
|
|
427
|
+
for (const elem of decl.elements) {
|
|
428
|
+
this.walkVarDecl(elem);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|