@harmoniclabs/pebble 0.1.3-dev3 → 0.1.3-dev6
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 +233 -11
- 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/io/CompilerIoApi.js +1 -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
|
@@ -11,7 +11,11 @@ export declare class SimpleVarDecl implements HasSourceRange, HasInitExpr {
|
|
|
11
11
|
initExpr: PebbleExpr | undefined;
|
|
12
12
|
flags: CommonFlags;
|
|
13
13
|
readonly range: SourceRange;
|
|
14
|
-
|
|
14
|
+
/** original source name when the identifier was renamed internally (for LSP) */
|
|
15
|
+
readonly sourceName?: string | undefined;
|
|
16
|
+
constructor(name: Identifier, type: AstTypeExpr | undefined, initExpr: PebbleExpr | undefined, flags: CommonFlags, range: SourceRange,
|
|
17
|
+
/** original source name when the identifier was renamed internally (for LSP) */
|
|
18
|
+
sourceName?: string | undefined);
|
|
15
19
|
isConst(): boolean;
|
|
16
20
|
static onlyIdentifier(identifier: Identifier, flags: CommonFlags): SimpleVarDecl;
|
|
17
21
|
static onlyNameConst(name: string, range: SourceRange): SimpleVarDecl;
|
|
@@ -6,12 +6,16 @@ export class SimpleVarDecl {
|
|
|
6
6
|
initExpr;
|
|
7
7
|
flags;
|
|
8
8
|
range;
|
|
9
|
-
|
|
9
|
+
sourceName;
|
|
10
|
+
constructor(name, type, initExpr, flags, range,
|
|
11
|
+
/** original source name when the identifier was renamed internally (for LSP) */
|
|
12
|
+
sourceName) {
|
|
10
13
|
this.name = name;
|
|
11
14
|
this.type = type;
|
|
12
15
|
this.initExpr = initExpr;
|
|
13
16
|
this.flags = flags;
|
|
14
17
|
this.range = range;
|
|
18
|
+
this.sourceName = sourceName;
|
|
15
19
|
}
|
|
16
20
|
isConst() {
|
|
17
21
|
return (this.flags & CommonFlags.Const) !== 0;
|
|
@@ -9,6 +9,7 @@ import { AstFuncName, AstScope, TirFuncName } from "./scope/AstScope.js";
|
|
|
9
9
|
import { TypedProgram } from "../tir/program/TypedProgram.js";
|
|
10
10
|
import { ResolveStackNode } from "./utils/deps/ResolveStackNode.js";
|
|
11
11
|
import { TirType } from "../tir/types/TirType.js";
|
|
12
|
+
import { CheckResult } from "../SourceTypeMap.js";
|
|
12
13
|
export interface AstTypeDefCompilationResult {
|
|
13
14
|
sop: TirType | undefined;
|
|
14
15
|
data: TirType | undefined;
|
|
@@ -54,6 +55,20 @@ export declare class AstCompiler extends DiagnosticEmitter {
|
|
|
54
55
|
* inside a function body.
|
|
55
56
|
*/
|
|
56
57
|
run(): Promise<TypedProgram>;
|
|
58
|
+
/**
|
|
59
|
+
* like `run()` but omits the return type annotation on the wrapping function
|
|
60
|
+
* and turns the last non-declaration statement into a `return` expression,
|
|
61
|
+
* allowing the type to be inferred from the expression.
|
|
62
|
+
*/
|
|
63
|
+
runRepl(): Promise<TypedProgram>;
|
|
64
|
+
/**
|
|
65
|
+
* runs the frontend only (parsing + semantic analysis + type checking)
|
|
66
|
+
* without requiring a contract and without throwing on diagnostics.
|
|
67
|
+
*
|
|
68
|
+
* returns `CheckResult` with diagnostics, the typed program,
|
|
69
|
+
* and a `SourceTypeMap` for querying types at source positions.
|
|
70
|
+
*/
|
|
71
|
+
check(): Promise<CheckResult>;
|
|
57
72
|
/**
|
|
58
73
|
* compiles the entry file specified in the config
|
|
59
74
|
*
|
|
@@ -35,6 +35,7 @@ import { _deriveContractBody } from "./internal/_deriveContractBody/_deriveContr
|
|
|
35
35
|
import { DiagnosticCategory } from "../../diagnostics/DiagnosticCategory.js";
|
|
36
36
|
import { VarStmt } from "../../ast/nodes/statements/VarStmt.js";
|
|
37
37
|
import { _compileSimpleVarDecl } from "./internal/statements/_compileVarStmt.js";
|
|
38
|
+
import { SourceTypeMap } from "../SourceTypeMap.js";
|
|
38
39
|
import { isIdentifier } from "../../utils/text.js";
|
|
39
40
|
/*
|
|
40
41
|
Handling type expressions that depend on other types
|
|
@@ -85,6 +86,12 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
85
86
|
this.cfg = cfg;
|
|
86
87
|
this.io = io;
|
|
87
88
|
this.program = new TypedProgram(this.diagnostics);
|
|
89
|
+
// normalize entry to absolute path so import resolution works correctly
|
|
90
|
+
if (typeof cfg.entry === "string" && typeof cfg.root === "string") {
|
|
91
|
+
const resolved = getEnvRelativePath(cfg.entry, cfg.root);
|
|
92
|
+
if (resolved)
|
|
93
|
+
cfg.entry = resolved;
|
|
94
|
+
}
|
|
88
95
|
this._isExporting = false;
|
|
89
96
|
}
|
|
90
97
|
_isExporting;
|
|
@@ -115,9 +122,6 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
115
122
|
* inside a function body.
|
|
116
123
|
*/
|
|
117
124
|
async run() {
|
|
118
|
-
const RUN_FUNC_NAME = "__pebble_run__";
|
|
119
|
-
this._isExporting = true;
|
|
120
|
-
this.program.contractTirFuncName = RUN_FUNC_NAME;
|
|
121
125
|
const filePath = this.cfg.entry;
|
|
122
126
|
if (!filePath) {
|
|
123
127
|
this.error(DiagnosticCode.File_0_not_found, undefined, this.cfg.entry);
|
|
@@ -128,21 +132,86 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
128
132
|
const src = await this.getAbsoulteProjPathSource(filePath);
|
|
129
133
|
if (!src)
|
|
130
134
|
throw new Error("AstCompiler.run: could not read source: " + filePath);
|
|
135
|
+
const funcName = _uniqueFuncName("__pebble_run__", src.text);
|
|
136
|
+
this._isExporting = true;
|
|
137
|
+
this.program.contractTirFuncName = funcName;
|
|
131
138
|
// 1) Rewrite the source text: wrap non-declaration statements in a function
|
|
132
|
-
src.text = _wrapSourceTextForRun(src.text,
|
|
139
|
+
src.text = _wrapSourceTextForRun(src.text, funcName);
|
|
133
140
|
// update range to match the new text length
|
|
134
141
|
src.range.end = src.text.length;
|
|
135
142
|
// 2) Use the normal compilation pipeline (parse + semantic analysis)
|
|
136
143
|
// which now sees the entry source as having a top-level function
|
|
137
144
|
return await this.compile();
|
|
138
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* like `run()` but omits the return type annotation on the wrapping function
|
|
148
|
+
* and turns the last non-declaration statement into a `return` expression,
|
|
149
|
+
* allowing the type to be inferred from the expression.
|
|
150
|
+
*/
|
|
151
|
+
async runRepl() {
|
|
152
|
+
const filePath = this.cfg.entry;
|
|
153
|
+
if (!filePath) {
|
|
154
|
+
this.error(DiagnosticCode.File_0_not_found, undefined, this.cfg.entry);
|
|
155
|
+
throw new Error("entry file not found");
|
|
156
|
+
}
|
|
157
|
+
if (!this.io.exsistSync(filePath))
|
|
158
|
+
throw new Error("AstCompiler.runRepl: entry file does not exist: " + filePath);
|
|
159
|
+
const src = await this.getAbsoulteProjPathSource(filePath);
|
|
160
|
+
if (!src)
|
|
161
|
+
throw new Error("AstCompiler.runRepl: could not read source: " + filePath);
|
|
162
|
+
const funcName = _uniqueFuncName("__pebble_repl__", src.text);
|
|
163
|
+
this._isExporting = true;
|
|
164
|
+
this.program.contractTirFuncName = funcName;
|
|
165
|
+
// 1) Rewrite the source text: wrap non-declaration statements in a function
|
|
166
|
+
// with no return type annotation, and turn the last statement into a return
|
|
167
|
+
src.text = _wrapSourceTextForRepl(src.text, funcName);
|
|
168
|
+
// update range to match the new text length
|
|
169
|
+
src.range.end = src.text.length;
|
|
170
|
+
// 2) Use the normal compilation pipeline (parse + semantic analysis)
|
|
171
|
+
return await this.compile();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* runs the frontend only (parsing + semantic analysis + type checking)
|
|
175
|
+
* without requiring a contract and without throwing on diagnostics.
|
|
176
|
+
*
|
|
177
|
+
* returns `CheckResult` with diagnostics, the typed program,
|
|
178
|
+
* and a `SourceTypeMap` for querying types at source positions.
|
|
179
|
+
*/
|
|
180
|
+
async check() {
|
|
181
|
+
const filePath = this.cfg.entry;
|
|
182
|
+
if (!filePath) {
|
|
183
|
+
this.error(DiagnosticCode.File_0_not_found, undefined, this.cfg.entry);
|
|
184
|
+
return {
|
|
185
|
+
diagnostics: this.diagnostics.slice(),
|
|
186
|
+
program: this.program,
|
|
187
|
+
sourceTypeMap: new SourceTypeMap(this.program)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (!this.io.exsistSync(filePath)) {
|
|
191
|
+
this.error(DiagnosticCode.File_0_not_found, undefined, filePath);
|
|
192
|
+
return {
|
|
193
|
+
diagnostics: this.diagnostics.slice(),
|
|
194
|
+
program: this.program,
|
|
195
|
+
sourceTypeMap: new SourceTypeMap(this.program)
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
await this.compileFile(filePath, true);
|
|
199
|
+
// no contract check, no throw — just collect diagnostics
|
|
200
|
+
const typeMap = new SourceTypeMap(this.program);
|
|
201
|
+
typeMap.buildFromProgram();
|
|
202
|
+
return {
|
|
203
|
+
diagnostics: this.diagnostics.slice(),
|
|
204
|
+
program: this.program,
|
|
205
|
+
sourceTypeMap: typeMap
|
|
206
|
+
};
|
|
207
|
+
}
|
|
139
208
|
/**
|
|
140
209
|
* compiles the entry file specified in the config
|
|
141
210
|
*
|
|
142
211
|
* the result is store in `this.program`
|
|
143
212
|
*/
|
|
144
213
|
async compile() {
|
|
145
|
-
const filePath = this.cfg.entry;
|
|
214
|
+
const filePath = this.cfg.entry;
|
|
146
215
|
if (!filePath) {
|
|
147
216
|
this.error(DiagnosticCode.File_0_not_found, undefined, this.cfg.entry);
|
|
148
217
|
throw new Error("entry file not found");
|
|
@@ -154,14 +223,15 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
154
223
|
let msg;
|
|
155
224
|
const fstErrorMsg = this.diagnostics[0].toString();
|
|
156
225
|
const nDiags = this.diagnostics.length;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.io.stdout.write(
|
|
226
|
+
for (msg of this.diagnostics) {
|
|
227
|
+
//*
|
|
228
|
+
this.io.stdout.write(msg.toString() + "\n");
|
|
160
229
|
/*/
|
|
161
|
-
console.log(msg);
|
|
162
|
-
console.log(msg.toString());
|
|
230
|
+
console.log( msg );
|
|
231
|
+
console.log( msg.toString() );
|
|
163
232
|
//*/
|
|
164
233
|
}
|
|
234
|
+
// return this.program;
|
|
165
235
|
throw new Error("AstCompiler.compile: failed with " + nDiags + " diagnostic messages; first message: " + fstErrorMsg);
|
|
166
236
|
}
|
|
167
237
|
const mainFuncExpr = this.program.functions.get(this.program.contractTirFuncName);
|
|
@@ -690,7 +760,8 @@ export class AstCompiler extends DiagnosticEmitter {
|
|
|
690
760
|
const internalName = getUniqueInternalName(param.name.text);
|
|
691
761
|
paramsInternalNamesMap.set(astName, internalName);
|
|
692
762
|
funcParams[i] = new SimpleVarDecl(new Identifier(internalName, param.name.range), astType, undefined, // initExpr
|
|
693
|
-
CommonFlags.Const, param.range
|
|
763
|
+
CommonFlags.Const, param.range, astName // original source name for LSP
|
|
764
|
+
);
|
|
694
765
|
}
|
|
695
766
|
const scriptContextName = getUniqueInternalName("ctx");
|
|
696
767
|
funcParams[contractDecl.params.length] = new SimpleVarDecl(new Identifier(scriptContextName, contractDecl.name.range), new AstNamedTypeExpr(new Identifier("ScriptContext", contractDecl.name.range), [], contractDecl.name.range), undefined, // initExpr
|
|
@@ -721,6 +792,18 @@ const _declKeywords = new Set([
|
|
|
721
792
|
"data",
|
|
722
793
|
"runtime",
|
|
723
794
|
]);
|
|
795
|
+
/**
|
|
796
|
+
* Returns a function name that does not appear in the source text.
|
|
797
|
+
* Starts with `baseName` and appends an incrementing suffix if needed.
|
|
798
|
+
*/
|
|
799
|
+
function _uniqueFuncName(baseName, sourceText) {
|
|
800
|
+
let name = baseName;
|
|
801
|
+
let i = 0;
|
|
802
|
+
while (sourceText.includes(name)) {
|
|
803
|
+
name = baseName + "_" + (i++);
|
|
804
|
+
}
|
|
805
|
+
return name;
|
|
806
|
+
}
|
|
724
807
|
/**
|
|
725
808
|
* Splits source text into declaration blocks and body blocks
|
|
726
809
|
* using a simple character scanner, then wraps body blocks
|
|
@@ -842,6 +925,145 @@ function _wrapSourceTextForRun(text, funcName) {
|
|
|
842
925
|
bodyParts.join("\n") + "\n" +
|
|
843
926
|
"}\n");
|
|
844
927
|
}
|
|
928
|
+
/**
|
|
929
|
+
* Like `_wrapSourceTextForRun` but:
|
|
930
|
+
* - omits the return type annotation (no `: void`)
|
|
931
|
+
* - turns the last non-declaration statement into a `return` expression
|
|
932
|
+
*
|
|
933
|
+
* This allows the compiler to infer the return type from the expression,
|
|
934
|
+
* used by the REPL to evaluate and return expression values.
|
|
935
|
+
*/
|
|
936
|
+
function _wrapSourceTextForRepl(text, funcName) {
|
|
937
|
+
const len = text.length;
|
|
938
|
+
const ranges = [];
|
|
939
|
+
let pos = 0;
|
|
940
|
+
while (pos < len) {
|
|
941
|
+
// skip whitespace
|
|
942
|
+
while (pos < len && _isWhitespace(text.charCodeAt(pos)))
|
|
943
|
+
pos++;
|
|
944
|
+
if (pos >= len)
|
|
945
|
+
break;
|
|
946
|
+
const stmtStart = pos;
|
|
947
|
+
// read the first word to determine if this is a declaration
|
|
948
|
+
const word = _readWord(text, pos);
|
|
949
|
+
const isDecl = _declKeywords.has(word);
|
|
950
|
+
// find the end of this statement:
|
|
951
|
+
// track brace/paren depth, respect strings and comments
|
|
952
|
+
let braceDepth = 0;
|
|
953
|
+
let parenDepth = 0;
|
|
954
|
+
let ended = false;
|
|
955
|
+
while (pos < len && !ended) {
|
|
956
|
+
const ch = text.charCodeAt(pos);
|
|
957
|
+
// single-line comment
|
|
958
|
+
if (ch === 0x2F /* / */ && pos + 1 < len && text.charCodeAt(pos + 1) === 0x2F /* / */) {
|
|
959
|
+
pos += 2;
|
|
960
|
+
while (pos < len && text.charCodeAt(pos) !== 0x0A /* \n */)
|
|
961
|
+
pos++;
|
|
962
|
+
continue;
|
|
963
|
+
}
|
|
964
|
+
// multi-line comment
|
|
965
|
+
if (ch === 0x2F /* / */ && pos + 1 < len && text.charCodeAt(pos + 1) === 0x2A /* * */) {
|
|
966
|
+
pos += 2;
|
|
967
|
+
while (pos < len && !(text.charCodeAt(pos) === 0x2A && pos + 1 < len && text.charCodeAt(pos + 1) === 0x2F))
|
|
968
|
+
pos++;
|
|
969
|
+
pos += 2; // skip */
|
|
970
|
+
continue;
|
|
971
|
+
}
|
|
972
|
+
// string literals
|
|
973
|
+
if (ch === 0x22 /* " */ || ch === 0x27 /* ' */ || ch === 0x60 /* ` */) {
|
|
974
|
+
pos++;
|
|
975
|
+
while (pos < len) {
|
|
976
|
+
const sc = text.charCodeAt(pos);
|
|
977
|
+
if (sc === 0x5C /* \ */) {
|
|
978
|
+
pos += 2;
|
|
979
|
+
continue;
|
|
980
|
+
} // escaped char
|
|
981
|
+
if (sc === ch) {
|
|
982
|
+
pos++;
|
|
983
|
+
break;
|
|
984
|
+
}
|
|
985
|
+
pos++;
|
|
986
|
+
}
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (ch === 0x28 /* ( */) {
|
|
990
|
+
parenDepth++;
|
|
991
|
+
pos++;
|
|
992
|
+
}
|
|
993
|
+
else if (ch === 0x29 /* ) */) {
|
|
994
|
+
parenDepth--;
|
|
995
|
+
pos++;
|
|
996
|
+
}
|
|
997
|
+
else if (ch === 0x7B /* { */) {
|
|
998
|
+
braceDepth++;
|
|
999
|
+
pos++;
|
|
1000
|
+
}
|
|
1001
|
+
else if (ch === 0x7D /* } */) {
|
|
1002
|
+
braceDepth--;
|
|
1003
|
+
pos++;
|
|
1004
|
+
if (braceDepth <= 0 && parenDepth <= 0) {
|
|
1005
|
+
// consume optional trailing semicolon
|
|
1006
|
+
let p2 = pos;
|
|
1007
|
+
while (p2 < len && _isWhitespace(text.charCodeAt(p2)))
|
|
1008
|
+
p2++;
|
|
1009
|
+
if (p2 < len && text.charCodeAt(p2) === 0x3B /* ; */)
|
|
1010
|
+
pos = p2 + 1;
|
|
1011
|
+
ended = true;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
else if (ch === 0x3B /* ; */ && braceDepth === 0 && parenDepth === 0) {
|
|
1015
|
+
pos++;
|
|
1016
|
+
ended = true;
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
pos++;
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
const stmtEnd = pos;
|
|
1023
|
+
// skip empty ranges
|
|
1024
|
+
if (stmtEnd > stmtStart) {
|
|
1025
|
+
ranges.push({ start: stmtStart, end: stmtEnd, isDecl });
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
// If there are no body ranges, nothing to wrap
|
|
1029
|
+
if (ranges.every(r => r.isDecl)) {
|
|
1030
|
+
return text;
|
|
1031
|
+
}
|
|
1032
|
+
// Build the new source text
|
|
1033
|
+
const declarations = [];
|
|
1034
|
+
const bodyParts = [];
|
|
1035
|
+
for (const r of ranges) {
|
|
1036
|
+
const slice = text.substring(r.start, r.end);
|
|
1037
|
+
if (r.isDecl)
|
|
1038
|
+
declarations.push(slice);
|
|
1039
|
+
else
|
|
1040
|
+
bodyParts.push(slice);
|
|
1041
|
+
}
|
|
1042
|
+
// turn the last body part into a return statement
|
|
1043
|
+
// (if it isn't already one and doesn't start with a statement keyword)
|
|
1044
|
+
if (bodyParts.length > 0) {
|
|
1045
|
+
let last = bodyParts[bodyParts.length - 1].trim();
|
|
1046
|
+
// remove trailing semicolon for wrapping
|
|
1047
|
+
if (last.endsWith(";"))
|
|
1048
|
+
last = last.slice(0, -1).trim();
|
|
1049
|
+
const firstWord = last.match(/^([a-zA-Z_]\w*)/);
|
|
1050
|
+
const isStmtKeyword = firstWord && _stmtKeywords.has(firstWord[1]);
|
|
1051
|
+
if (!isStmtKeyword && !last.startsWith("return")) {
|
|
1052
|
+
bodyParts[bodyParts.length - 1] = "return " + last + ";";
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return (declarations.join("\n") +
|
|
1056
|
+
(declarations.length > 0 ? "\n" : "") +
|
|
1057
|
+
"function " + funcName + "() {\n" +
|
|
1058
|
+
bodyParts.join("\n") + "\n" +
|
|
1059
|
+
"}\n");
|
|
1060
|
+
}
|
|
1061
|
+
const _stmtKeywords = new Set([
|
|
1062
|
+
"let", "var", "const", "using",
|
|
1063
|
+
"if", "for", "while", "match",
|
|
1064
|
+
"return", "break", "continue",
|
|
1065
|
+
"trace", "assert", "fail", "test",
|
|
1066
|
+
]);
|
|
845
1067
|
function _isWhitespace(ch) {
|
|
846
1068
|
return ch === 0x20 || ch === 0x09 || ch === 0x0A || ch === 0x0D;
|
|
847
1069
|
}
|
|
@@ -44,6 +44,7 @@ import { TraceStmt } from "../../../../ast/nodes/statements/TraceStmt.js";
|
|
|
44
44
|
import { UsingStmt } from "../../../../ast/nodes/statements/UsingStmt.js";
|
|
45
45
|
import { VarStmt } from "../../../../ast/nodes/statements/VarStmt.js";
|
|
46
46
|
import { WhileStmt } from "../../../../ast/nodes/statements/WhileStmt.js";
|
|
47
|
+
import { SourceRange } from "../../../../ast/Source/SourceRange.js";
|
|
47
48
|
import { CommonFlags } from "../../../../common.js";
|
|
48
49
|
import { DiagnosticCode } from "../../../../diagnostics/diagnosticMessages.generated.js";
|
|
49
50
|
import { getUniqueInternalName } from "../../../internalVar.js";
|
|
@@ -89,6 +90,9 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
89
90
|
//
|
|
90
91
|
// so we only have 3 statements in the body
|
|
91
92
|
const bodyStmts = [];
|
|
93
|
+
// generated identifiers/declarations use mock ranges so they don't
|
|
94
|
+
// produce SourceTypeMap entries (which would span the entire contract)
|
|
95
|
+
const mockRange = SourceRange.mock;
|
|
92
96
|
const txUniqueName = getUniqueInternalName("tx");
|
|
93
97
|
const purposeUniqueName = getUniqueInternalName("purpose");
|
|
94
98
|
const redeemerUniqueName = getUniqueInternalName("redeemer");
|
|
@@ -96,20 +100,20 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
96
100
|
// fields
|
|
97
101
|
new Map([
|
|
98
102
|
[
|
|
99
|
-
new Identifier("tx",
|
|
100
|
-
SimpleVarDecl.onlyNameConst(txUniqueName,
|
|
103
|
+
new Identifier("tx", mockRange),
|
|
104
|
+
SimpleVarDecl.onlyNameConst(txUniqueName, mockRange)
|
|
101
105
|
],
|
|
102
106
|
[
|
|
103
|
-
new Identifier("purpose",
|
|
104
|
-
SimpleVarDecl.onlyNameConst(purposeUniqueName,
|
|
107
|
+
new Identifier("purpose", mockRange),
|
|
108
|
+
SimpleVarDecl.onlyNameConst(purposeUniqueName, mockRange)
|
|
105
109
|
],
|
|
106
110
|
[
|
|
107
|
-
new Identifier("redeemer",
|
|
108
|
-
SimpleVarDecl.onlyNameConst(redeemerUniqueName,
|
|
111
|
+
new Identifier("redeemer", mockRange),
|
|
112
|
+
SimpleVarDecl.onlyNameConst(redeemerUniqueName, mockRange)
|
|
109
113
|
],
|
|
110
114
|
]), undefined, // rest
|
|
111
115
|
undefined, // type (inferred from initExpr)
|
|
112
|
-
new Identifier(scriptContextName,
|
|
116
|
+
new Identifier(scriptContextName, mockRange), // initExpr
|
|
113
117
|
CommonFlags.Const, contractRange)], contractRange));
|
|
114
118
|
/*
|
|
115
119
|
const { data: scriptInfo_t } = defineMultiConstructorStruct(
|
|
@@ -144,12 +148,12 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
144
148
|
const optionalDatumUniqueName = getUniqueInternalName("optionalDatum");
|
|
145
149
|
const fields = new Map([
|
|
146
150
|
[
|
|
147
|
-
new Identifier("ref",
|
|
148
|
-
SimpleVarDecl.onlyNameConst(spendingRefUniqueName,
|
|
151
|
+
new Identifier("ref", mockRange),
|
|
152
|
+
SimpleVarDecl.onlyNameConst(spendingRefUniqueName, mockRange)
|
|
149
153
|
],
|
|
150
154
|
[
|
|
151
|
-
new Identifier("optionalDatum",
|
|
152
|
-
SimpleVarDecl.onlyNameConst(optionalDatumUniqueName,
|
|
155
|
+
new Identifier("optionalDatum", mockRange),
|
|
156
|
+
SimpleVarDecl.onlyNameConst(optionalDatumUniqueName, mockRange)
|
|
153
157
|
],
|
|
154
158
|
]);
|
|
155
159
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.spendMethods, paramsInternalNamesMap,
|
|
@@ -163,7 +167,7 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
163
167
|
}), "SpendRedeemer", contractRange);
|
|
164
168
|
if (!Array.isArray(bodyStmts))
|
|
165
169
|
return undefined;
|
|
166
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Spend",
|
|
170
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Spend", mockRange), fields, undefined, // rest
|
|
167
171
|
undefined, // type (inferred from initExpr)
|
|
168
172
|
undefined, // initExpr
|
|
169
173
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
@@ -172,8 +176,8 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
172
176
|
const policyUniqueName = getUniqueInternalName("policy");
|
|
173
177
|
const fields = new Map([
|
|
174
178
|
[
|
|
175
|
-
new Identifier("policy",
|
|
176
|
-
SimpleVarDecl.onlyNameConst(policyUniqueName,
|
|
179
|
+
new Identifier("policy", mockRange),
|
|
180
|
+
SimpleVarDecl.onlyNameConst(policyUniqueName, mockRange)
|
|
177
181
|
],
|
|
178
182
|
]);
|
|
179
183
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.mintMethods, paramsInternalNamesMap,
|
|
@@ -186,7 +190,7 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
186
190
|
}), "MintRedeemer", contractRange);
|
|
187
191
|
if (!Array.isArray(bodyStmts))
|
|
188
192
|
return undefined;
|
|
189
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Mint",
|
|
193
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Mint", mockRange), fields, undefined, // rest
|
|
190
194
|
undefined, // type (inferred from initExpr)
|
|
191
195
|
undefined, // initExpr
|
|
192
196
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
@@ -195,8 +199,8 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
195
199
|
const credentialUniqueName = getUniqueInternalName("credential");
|
|
196
200
|
const fields = new Map([
|
|
197
201
|
[
|
|
198
|
-
new Identifier("credential",
|
|
199
|
-
SimpleVarDecl.onlyNameConst(credentialUniqueName,
|
|
202
|
+
new Identifier("credential", mockRange),
|
|
203
|
+
SimpleVarDecl.onlyNameConst(credentialUniqueName, mockRange)
|
|
200
204
|
],
|
|
201
205
|
]);
|
|
202
206
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.withdrawMethods, paramsInternalNamesMap,
|
|
@@ -209,7 +213,7 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
209
213
|
}), "WithdrawRedeemer", contractRange);
|
|
210
214
|
if (!Array.isArray(bodyStmts))
|
|
211
215
|
return undefined;
|
|
212
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Withdraw",
|
|
216
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Withdraw", mockRange), fields, undefined, // rest
|
|
213
217
|
undefined, // type (inferred from initExpr)
|
|
214
218
|
undefined, // initExpr
|
|
215
219
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
@@ -219,12 +223,12 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
219
223
|
const certificateUniqueName = getUniqueInternalName("certificate");
|
|
220
224
|
const fields = new Map([
|
|
221
225
|
[
|
|
222
|
-
new Identifier("certificateIndex",
|
|
223
|
-
SimpleVarDecl.onlyNameConst(indexUniqueName,
|
|
226
|
+
new Identifier("certificateIndex", mockRange),
|
|
227
|
+
SimpleVarDecl.onlyNameConst(indexUniqueName, mockRange)
|
|
224
228
|
],
|
|
225
229
|
[
|
|
226
|
-
new Identifier("certificate",
|
|
227
|
-
SimpleVarDecl.onlyNameConst(certificateUniqueName,
|
|
230
|
+
new Identifier("certificate", mockRange),
|
|
231
|
+
SimpleVarDecl.onlyNameConst(certificateUniqueName, mockRange)
|
|
228
232
|
],
|
|
229
233
|
]);
|
|
230
234
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.certifyMethods, paramsInternalNamesMap,
|
|
@@ -238,7 +242,7 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
238
242
|
}), "CertifyRedeemer", contractRange);
|
|
239
243
|
if (!Array.isArray(bodyStmts))
|
|
240
244
|
return undefined;
|
|
241
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Certificate",
|
|
245
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Certificate", mockRange), fields, undefined, // rest
|
|
242
246
|
undefined, // type (inferred from initExpr)
|
|
243
247
|
undefined, // initExpr
|
|
244
248
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
@@ -248,12 +252,12 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
248
252
|
const proposalUniqueName = getUniqueInternalName("proposal");
|
|
249
253
|
const fields = new Map([
|
|
250
254
|
[
|
|
251
|
-
new Identifier("proposalIndex",
|
|
252
|
-
SimpleVarDecl.onlyNameConst(indexUniqueName,
|
|
255
|
+
new Identifier("proposalIndex", mockRange),
|
|
256
|
+
SimpleVarDecl.onlyNameConst(indexUniqueName, mockRange)
|
|
253
257
|
],
|
|
254
258
|
[
|
|
255
|
-
new Identifier("proposal",
|
|
256
|
-
SimpleVarDecl.onlyNameConst(proposalUniqueName,
|
|
259
|
+
new Identifier("proposal", mockRange),
|
|
260
|
+
SimpleVarDecl.onlyNameConst(proposalUniqueName, mockRange)
|
|
257
261
|
],
|
|
258
262
|
]);
|
|
259
263
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.proposeMethods, paramsInternalNamesMap,
|
|
@@ -267,7 +271,7 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
267
271
|
}), "ProposeRedeemer", contractRange);
|
|
268
272
|
if (!Array.isArray(bodyStmts))
|
|
269
273
|
return undefined;
|
|
270
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Propose",
|
|
274
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Propose", mockRange), fields, undefined, // rest
|
|
271
275
|
undefined, // type (inferred from initExpr)
|
|
272
276
|
undefined, // initExpr
|
|
273
277
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
@@ -276,8 +280,8 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
276
280
|
const voterUniqueName = getUniqueInternalName("voter");
|
|
277
281
|
const fields = new Map([
|
|
278
282
|
[
|
|
279
|
-
new Identifier("voter",
|
|
280
|
-
SimpleVarDecl.onlyNameConst(voterUniqueName,
|
|
283
|
+
new Identifier("voter", mockRange),
|
|
284
|
+
SimpleVarDecl.onlyNameConst(voterUniqueName, mockRange)
|
|
281
285
|
],
|
|
282
286
|
]);
|
|
283
287
|
const bodyStmts = _getMatchedPurposeBlockStatements(compiler, contractDecl.voteMethods, paramsInternalNamesMap,
|
|
@@ -290,12 +294,12 @@ export function _deriveContractBody(compiler, contractDecl, paramsInternalNamesM
|
|
|
290
294
|
}), "VoteRedeemer", contractRange);
|
|
291
295
|
if (!Array.isArray(bodyStmts))
|
|
292
296
|
return undefined;
|
|
293
|
-
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Vote",
|
|
297
|
+
purposeMatchCases.push(new MatchStmtCase(new NamedDeconstructVarDecl(new Identifier("Vote", mockRange), fields, undefined, // rest
|
|
294
298
|
undefined, // type (inferred from initExpr)
|
|
295
299
|
undefined, // initExpr
|
|
296
300
|
CommonFlags.Const, contractRange), new BlockStmt(bodyStmts, contractRange), contractRange));
|
|
297
301
|
}
|
|
298
|
-
bodyStmts.push(new MatchStmt(new Identifier(purposeUniqueName,
|
|
302
|
+
bodyStmts.push(new MatchStmt(new Identifier(purposeUniqueName, mockRange), purposeMatchCases, new MatchStmtElseCase(new FailStmt(undefined, contractRange), contractRange), contractRange));
|
|
299
303
|
bodyStmts.push(new FailStmt(undefined, contractRange)); // unreachable in theory (else case)
|
|
300
304
|
return new BlockStmt(bodyStmts, contractRange);
|
|
301
305
|
}
|
|
@@ -336,8 +340,9 @@ function _getMatchedPurposeBlockStatements(compiler, methods, paramsInternalName
|
|
|
336
340
|
CommonFlags.Const, method.expr.name.range), new BlockStmt(stmts, contractRange), method.expr.range));
|
|
337
341
|
}
|
|
338
342
|
return [
|
|
339
|
-
new MatchStmt(new TypeConversionExpr(new Identifier(contextVarsMapping.redeemerData,
|
|
340
|
-
contractRange)
|
|
343
|
+
new MatchStmt(new TypeConversionExpr(new Identifier(contextVarsMapping.redeemerData, SourceRange.mock), new AstNamedTypeExpr(new Identifier(redeemerTypeDef.name.text, SourceRange.mock), [], // typeArgs
|
|
344
|
+
contractRange), SourceRange.mock // mock range: generated expression should not appear in SourceTypeMap
|
|
345
|
+
), redeemerMatchCases, new MatchStmtElseCase(new FailStmt(undefined, contractRange), contractRange), contractRange),
|
|
341
346
|
new FailStmt(undefined, contractRange) // unreachable in theory (else case)
|
|
342
347
|
];
|
|
343
348
|
}
|
|
@@ -759,7 +764,7 @@ function _deriveRedeemerTypeDef(redeemerName, methods, contractRange) {
|
|
|
759
764
|
if (methods.length <= 1)
|
|
760
765
|
defFlags |= StructDeclAstFlags.untaggedSingleConstructor;
|
|
761
766
|
const uniqueName = getUniqueInternalName(redeemerName);
|
|
762
|
-
return new StructDecl(new Identifier(uniqueName,
|
|
767
|
+
return new StructDecl(new Identifier(uniqueName, SourceRange.mock), [], // typeParams
|
|
763
768
|
methods.map(m => {
|
|
764
769
|
const methodParams = m.expr.signature.params;
|
|
765
770
|
if (!methodParams.every(p => p instanceof SimpleVarDecl && !p.initExpr && p.type))
|
|
@@ -23,7 +23,11 @@ export declare function _compileSingleDeconstructVarDecl(ctx: AstCompilationCtx,
|
|
|
23
23
|
export declare function _compileArrayLikeDeconstr(ctx: AstCompilationCtx, decl: ArrayLikeDeconstr, typeHint: TirType | undefined): TirArrayLikeDeconstr | undefined;
|
|
24
24
|
export declare function _getDeconstructedFields(ctx: AstCompilationCtx, astDeconstruct: ISingleDeconstructVarDecl, ctorDef: TirStructConstr): [
|
|
25
25
|
fields: Map<string, TirVarDecl>,
|
|
26
|
-
rest: string | undefined
|
|
26
|
+
rest: string | undefined,
|
|
27
|
+
fieldLabelRanges: Map<string, {
|
|
28
|
+
range: SourceRange;
|
|
29
|
+
type: TirType;
|
|
30
|
+
}>
|
|
27
31
|
] | undefined;
|
|
28
32
|
export declare function _getVarDeclTypeAndExpr(ctx: AstCompilationCtx, decl: {
|
|
29
33
|
type: AstTypeExpr | undefined;
|
|
@@ -31,5 +35,6 @@ export declare function _getVarDeclTypeAndExpr(ctx: AstCompilationCtx, decl: {
|
|
|
31
35
|
range: SourceRange;
|
|
32
36
|
}, deconstructTypeHint: TirType | undefined): [
|
|
33
37
|
varType: TirType,
|
|
34
|
-
varInitExpr: TirExpr | undefined
|
|
38
|
+
varInitExpr: TirExpr | undefined,
|
|
39
|
+
typeAnnotationRange: SourceRange | undefined
|
|
35
40
|
] | undefined;
|