@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.
@@ -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
- constructor(name: Identifier, type: AstTypeExpr | undefined, initExpr: PebbleExpr | undefined, flags: CommonFlags, range: SourceRange);
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
- constructor(name, type, initExpr, flags, range) {
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, RUN_FUNC_NAME);
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; // getEnvRelativePath( this.cfg.entry, this.rootPath );
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
- while (msg = this.diagnostics.shift()) {
158
- /*
159
- this.io.stdout.write( msg.toString() + "\n" );
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", contractRange),
100
- SimpleVarDecl.onlyNameConst(txUniqueName, contractRange)
103
+ new Identifier("tx", mockRange),
104
+ SimpleVarDecl.onlyNameConst(txUniqueName, mockRange)
101
105
  ],
102
106
  [
103
- new Identifier("purpose", contractRange),
104
- SimpleVarDecl.onlyNameConst(purposeUniqueName, contractRange)
107
+ new Identifier("purpose", mockRange),
108
+ SimpleVarDecl.onlyNameConst(purposeUniqueName, mockRange)
105
109
  ],
106
110
  [
107
- new Identifier("redeemer", contractRange),
108
- SimpleVarDecl.onlyNameConst(redeemerUniqueName, contractRange)
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, contractRange), // initExpr
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", contractRange),
148
- SimpleVarDecl.onlyNameConst(spendingRefUniqueName, contractRange)
151
+ new Identifier("ref", mockRange),
152
+ SimpleVarDecl.onlyNameConst(spendingRefUniqueName, mockRange)
149
153
  ],
150
154
  [
151
- new Identifier("optionalDatum", contractRange),
152
- SimpleVarDecl.onlyNameConst(optionalDatumUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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", contractRange),
176
- SimpleVarDecl.onlyNameConst(policyUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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", contractRange),
199
- SimpleVarDecl.onlyNameConst(credentialUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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", contractRange),
223
- SimpleVarDecl.onlyNameConst(indexUniqueName, contractRange)
226
+ new Identifier("certificateIndex", mockRange),
227
+ SimpleVarDecl.onlyNameConst(indexUniqueName, mockRange)
224
228
  ],
225
229
  [
226
- new Identifier("certificate", contractRange),
227
- SimpleVarDecl.onlyNameConst(certificateUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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", contractRange),
252
- SimpleVarDecl.onlyNameConst(indexUniqueName, contractRange)
255
+ new Identifier("proposalIndex", mockRange),
256
+ SimpleVarDecl.onlyNameConst(indexUniqueName, mockRange)
253
257
  ],
254
258
  [
255
- new Identifier("proposal", contractRange),
256
- SimpleVarDecl.onlyNameConst(proposalUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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", contractRange),
280
- SimpleVarDecl.onlyNameConst(voterUniqueName, contractRange)
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", contractRange), fields, undefined, // rest
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, contractRange), purposeMatchCases, new MatchStmtElseCase(new FailStmt(undefined, contractRange), contractRange), contractRange));
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, contractRange), new AstNamedTypeExpr(new Identifier(redeemerTypeDef.name.text, contractRange), [], // typeArgs
340
- contractRange)), redeemerMatchCases, new MatchStmtElseCase(new FailStmt(undefined, contractRange), contractRange), 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, contractRange), [], // typeParams
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;