@mojir/dvala 0.0.16 → 0.0.18
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/cli/cli.js +365 -18
- package/package.json +1 -1
package/dist/cli/cli.js
CHANGED
|
@@ -118,7 +118,8 @@ const NodeTypes = {
|
|
|
118
118
|
SpecialBuiltinSymbol: 7,
|
|
119
119
|
ReservedSymbol: 8,
|
|
120
120
|
Binding: 9,
|
|
121
|
-
Spread: 10
|
|
121
|
+
Spread: 10,
|
|
122
|
+
TemplateString: 11
|
|
122
123
|
};
|
|
123
124
|
const NodeTypesSet = new Set(Object.values(NodeTypes));
|
|
124
125
|
function getNodeTypeName(type) {
|
|
@@ -477,7 +478,7 @@ function findAllOccurrences(input, pattern) {
|
|
|
477
478
|
}
|
|
478
479
|
//#endregion
|
|
479
480
|
//#region package.json
|
|
480
|
-
var version = "0.0.
|
|
481
|
+
var version = "0.0.18";
|
|
481
482
|
//#endregion
|
|
482
483
|
//#region src/typeGuards/string.ts
|
|
483
484
|
function isString(value, options = {}) {
|
|
@@ -24998,8 +24999,13 @@ const datatype = {
|
|
|
24998
24999
|
datatype: true,
|
|
24999
25000
|
title: "string",
|
|
25000
25001
|
category: "datatype",
|
|
25001
|
-
description: "A `string`",
|
|
25002
|
-
examples: [
|
|
25002
|
+
description: "A `string`. Strings are written with double quotes. Template strings use backticks and support `${...}` interpolation — any expression can appear inside the braces.",
|
|
25003
|
+
examples: [
|
|
25004
|
+
"\"hello\"",
|
|
25005
|
+
"\"\"",
|
|
25006
|
+
"`Hello, World!`",
|
|
25007
|
+
"`${2} * ${3} = ${2 * 3}`"
|
|
25008
|
+
]
|
|
25003
25009
|
},
|
|
25004
25010
|
"-type-object": {
|
|
25005
25011
|
datatype: true,
|
|
@@ -25810,6 +25816,94 @@ const tokenizeShebang = (input, position) => {
|
|
|
25810
25816
|
}
|
|
25811
25817
|
return NO_MATCH;
|
|
25812
25818
|
};
|
|
25819
|
+
const tokenizeTemplateString = (input, position) => {
|
|
25820
|
+
if (input[position] !== "`") return NO_MATCH;
|
|
25821
|
+
let value = "`";
|
|
25822
|
+
let length = 1;
|
|
25823
|
+
while (position + length < input.length) {
|
|
25824
|
+
const char = input[position + length];
|
|
25825
|
+
if (char === "`") {
|
|
25826
|
+
value += "`";
|
|
25827
|
+
length += 1;
|
|
25828
|
+
return [length, ["TemplateString", value]];
|
|
25829
|
+
}
|
|
25830
|
+
if (char === "$" && input[position + length + 1] === "{") {
|
|
25831
|
+
value += "${";
|
|
25832
|
+
length += 2;
|
|
25833
|
+
let braceDepth = 1;
|
|
25834
|
+
while (position + length < input.length && braceDepth > 0) {
|
|
25835
|
+
const c = input[position + length];
|
|
25836
|
+
if (c === "{") {
|
|
25837
|
+
braceDepth += 1;
|
|
25838
|
+
value += c;
|
|
25839
|
+
length += 1;
|
|
25840
|
+
} else if (c === "}") {
|
|
25841
|
+
braceDepth -= 1;
|
|
25842
|
+
value += c;
|
|
25843
|
+
length += 1;
|
|
25844
|
+
} else if (c === "\"") {
|
|
25845
|
+
value += c;
|
|
25846
|
+
length += 1;
|
|
25847
|
+
let escaping = false;
|
|
25848
|
+
while (position + length < input.length) {
|
|
25849
|
+
const sc = input[position + length];
|
|
25850
|
+
value += sc;
|
|
25851
|
+
length += 1;
|
|
25852
|
+
if (escaping) escaping = false;
|
|
25853
|
+
else if (sc === "\\") escaping = true;
|
|
25854
|
+
else if (sc === "\"") break;
|
|
25855
|
+
}
|
|
25856
|
+
} else if (c === "'") {
|
|
25857
|
+
value += c;
|
|
25858
|
+
length += 1;
|
|
25859
|
+
let escaping = false;
|
|
25860
|
+
while (position + length < input.length) {
|
|
25861
|
+
const sc = input[position + length];
|
|
25862
|
+
value += sc;
|
|
25863
|
+
length += 1;
|
|
25864
|
+
if (escaping) escaping = false;
|
|
25865
|
+
else if (sc === "\\") escaping = true;
|
|
25866
|
+
else if (sc === "'") break;
|
|
25867
|
+
}
|
|
25868
|
+
} else if (c === "`") {
|
|
25869
|
+
const [nestedLength, nestedToken] = tokenizeTemplateString(input, position + length);
|
|
25870
|
+
if (nestedLength === 0 || !nestedToken) return [length, [
|
|
25871
|
+
"Error",
|
|
25872
|
+
value,
|
|
25873
|
+
void 0,
|
|
25874
|
+
`Unclosed nested template string at position ${position + length}`
|
|
25875
|
+
]];
|
|
25876
|
+
if (nestedToken[0] === "Error") return [length + nestedLength, [
|
|
25877
|
+
"Error",
|
|
25878
|
+
value + nestedToken[1],
|
|
25879
|
+
void 0,
|
|
25880
|
+
nestedToken[3]
|
|
25881
|
+
]];
|
|
25882
|
+
value += nestedToken[1];
|
|
25883
|
+
length += nestedLength;
|
|
25884
|
+
} else {
|
|
25885
|
+
value += c;
|
|
25886
|
+
length += 1;
|
|
25887
|
+
}
|
|
25888
|
+
}
|
|
25889
|
+
if (braceDepth > 0) return [length, [
|
|
25890
|
+
"Error",
|
|
25891
|
+
value,
|
|
25892
|
+
void 0,
|
|
25893
|
+
`Unclosed interpolation in template string at position ${position}`
|
|
25894
|
+
]];
|
|
25895
|
+
} else {
|
|
25896
|
+
value += char;
|
|
25897
|
+
length += 1;
|
|
25898
|
+
}
|
|
25899
|
+
}
|
|
25900
|
+
return [length, [
|
|
25901
|
+
"Error",
|
|
25902
|
+
value,
|
|
25903
|
+
void 0,
|
|
25904
|
+
`Unclosed template string at position ${position}`
|
|
25905
|
+
]];
|
|
25906
|
+
};
|
|
25813
25907
|
const tokenizeSingleLineComment = (input, position) => {
|
|
25814
25908
|
if (input[position] === "/" && input[position + 1] === "/") {
|
|
25815
25909
|
let length = 2;
|
|
@@ -25834,6 +25928,7 @@ const tokenizers = [
|
|
|
25834
25928
|
tokenizeLBrace,
|
|
25835
25929
|
tokenizeRBrace,
|
|
25836
25930
|
tokenizeString,
|
|
25931
|
+
tokenizeTemplateString,
|
|
25837
25932
|
tokenizeRegexpShorthand,
|
|
25838
25933
|
tokenizeBasePrefixedNumber,
|
|
25839
25934
|
tokenizeNumber,
|
|
@@ -26628,6 +26723,11 @@ function findUnresolvedSymbolsInNode(node, contextStack, builtin) {
|
|
|
26628
26723
|
});
|
|
26629
26724
|
}
|
|
26630
26725
|
case NodeTypes.Spread: return findUnresolvedSymbolsInNode(node[1], contextStack, builtin);
|
|
26726
|
+
case NodeTypes.TemplateString: {
|
|
26727
|
+
const unresolvedSymbols = /* @__PURE__ */ new Set();
|
|
26728
|
+
for (const segment of node[1]) findUnresolvedSymbolsInNode(segment, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
|
|
26729
|
+
return unresolvedSymbols;
|
|
26730
|
+
}
|
|
26631
26731
|
default: throw new DvalaError(`Unhandled node type: ${nodeType}`, node[2]);
|
|
26632
26732
|
}
|
|
26633
26733
|
}
|
|
@@ -26733,6 +26833,9 @@ function isStringToken(token) {
|
|
|
26733
26833
|
function isA_BinaryOperatorToken(token) {
|
|
26734
26834
|
return token?.[0] === "Operator" && isBinaryOperator(token[1]);
|
|
26735
26835
|
}
|
|
26836
|
+
function isTemplateStringToken(token) {
|
|
26837
|
+
return token?.[0] === "TemplateString";
|
|
26838
|
+
}
|
|
26736
26839
|
function throwUnexpectedToken(expected, expectedValue, actual) {
|
|
26737
26840
|
throw new DvalaError(`Unexpected token: ${actual ? `${actual[0]} '${actual[1]}'` : "end of input"}, expected ${expected}${expectedValue ? ` '${expectedValue}'` : ""}`, actual?.[2]);
|
|
26738
26841
|
}
|
|
@@ -27027,6 +27130,176 @@ function parseNumber(ctx) {
|
|
|
27027
27130
|
return withSourceCodeInfo([NodeTypes.Number, negative ? -Number(numberString) : Number(numberString)], token[2]);
|
|
27028
27131
|
}
|
|
27029
27132
|
//#endregion
|
|
27133
|
+
//#region src/tokenizer/minifyTokenStream.ts
|
|
27134
|
+
function minifyTokenStream(tokenStream, { removeWhiteSpace }) {
|
|
27135
|
+
const tokens = tokenStream.tokens.filter((token) => {
|
|
27136
|
+
if (isSingleLineCommentToken(token) || isMultiLineCommentToken(token) || isShebangToken(token) || removeWhiteSpace && isWhitespaceToken(token)) return false;
|
|
27137
|
+
return true;
|
|
27138
|
+
});
|
|
27139
|
+
return {
|
|
27140
|
+
...tokenStream,
|
|
27141
|
+
tokens
|
|
27142
|
+
};
|
|
27143
|
+
}
|
|
27144
|
+
//#endregion
|
|
27145
|
+
//#region src/parser/subParsers/parseTemplateString.ts
|
|
27146
|
+
/**
|
|
27147
|
+
* Scan from `start` inside a `${...}` interpolation until the matching `}`.
|
|
27148
|
+
* Returns the expression source text (without the outer `${` and `}`) and
|
|
27149
|
+
* the number of characters consumed (including the closing `}`).
|
|
27150
|
+
*/
|
|
27151
|
+
function scanExpression(raw, start) {
|
|
27152
|
+
let i = start;
|
|
27153
|
+
let expr = "";
|
|
27154
|
+
let depth = 1;
|
|
27155
|
+
while (i < raw.length && depth > 0) {
|
|
27156
|
+
const c = raw[i];
|
|
27157
|
+
if (c === "{") {
|
|
27158
|
+
depth++;
|
|
27159
|
+
expr += c;
|
|
27160
|
+
i++;
|
|
27161
|
+
} else if (c === "}") {
|
|
27162
|
+
depth--;
|
|
27163
|
+
if (depth > 0) expr += c;
|
|
27164
|
+
i++;
|
|
27165
|
+
} else if (c === "\"") {
|
|
27166
|
+
const { str, consumed } = scanString(raw, i);
|
|
27167
|
+
expr += str;
|
|
27168
|
+
i += consumed;
|
|
27169
|
+
} else if (c === "'") {
|
|
27170
|
+
const { str, consumed } = scanQuotedSymbol(raw, i);
|
|
27171
|
+
expr += str;
|
|
27172
|
+
i += consumed;
|
|
27173
|
+
} else if (c === "`") {
|
|
27174
|
+
const { str, consumed } = scanNestedTemplate(raw, i);
|
|
27175
|
+
expr += str;
|
|
27176
|
+
i += consumed;
|
|
27177
|
+
} else {
|
|
27178
|
+
expr += c;
|
|
27179
|
+
i++;
|
|
27180
|
+
}
|
|
27181
|
+
}
|
|
27182
|
+
return {
|
|
27183
|
+
expr,
|
|
27184
|
+
consumed: i - start
|
|
27185
|
+
};
|
|
27186
|
+
}
|
|
27187
|
+
function scanString(raw, start) {
|
|
27188
|
+
let i = start + 1;
|
|
27189
|
+
let str = "\"";
|
|
27190
|
+
let escaping = false;
|
|
27191
|
+
while (i < raw.length) {
|
|
27192
|
+
const c = raw[i];
|
|
27193
|
+
str += c;
|
|
27194
|
+
i++;
|
|
27195
|
+
if (escaping) escaping = false;
|
|
27196
|
+
else if (c === "\\") escaping = true;
|
|
27197
|
+
else if (c === "\"") break;
|
|
27198
|
+
}
|
|
27199
|
+
return {
|
|
27200
|
+
str,
|
|
27201
|
+
consumed: i - start
|
|
27202
|
+
};
|
|
27203
|
+
}
|
|
27204
|
+
function scanQuotedSymbol(raw, start) {
|
|
27205
|
+
let i = start + 1;
|
|
27206
|
+
let str = "'";
|
|
27207
|
+
let escaping = false;
|
|
27208
|
+
while (i < raw.length) {
|
|
27209
|
+
const c = raw[i];
|
|
27210
|
+
str += c;
|
|
27211
|
+
i++;
|
|
27212
|
+
if (escaping) escaping = false;
|
|
27213
|
+
else if (c === "\\") escaping = true;
|
|
27214
|
+
else if (c === "'") break;
|
|
27215
|
+
}
|
|
27216
|
+
return {
|
|
27217
|
+
str,
|
|
27218
|
+
consumed: i - start
|
|
27219
|
+
};
|
|
27220
|
+
}
|
|
27221
|
+
/**
|
|
27222
|
+
* Scan a full nested template string starting at `start` (pointing at the opening backtick).
|
|
27223
|
+
* Handles ${...} spans inside the template recursively.
|
|
27224
|
+
*/
|
|
27225
|
+
function scanNestedTemplate(raw, start) {
|
|
27226
|
+
let i = start + 1;
|
|
27227
|
+
let str = "`";
|
|
27228
|
+
while (i < raw.length) {
|
|
27229
|
+
const c = raw[i];
|
|
27230
|
+
if (c === "`") {
|
|
27231
|
+
str += c;
|
|
27232
|
+
i++;
|
|
27233
|
+
break;
|
|
27234
|
+
} else if (c === "$" && raw[i + 1] === "{") {
|
|
27235
|
+
str += "${";
|
|
27236
|
+
i += 2;
|
|
27237
|
+
const { expr, consumed } = scanExpression(raw, i);
|
|
27238
|
+
str += `${expr}}`;
|
|
27239
|
+
i += consumed;
|
|
27240
|
+
} else {
|
|
27241
|
+
str += c;
|
|
27242
|
+
i++;
|
|
27243
|
+
}
|
|
27244
|
+
}
|
|
27245
|
+
return {
|
|
27246
|
+
str,
|
|
27247
|
+
consumed: i - start
|
|
27248
|
+
};
|
|
27249
|
+
}
|
|
27250
|
+
/**
|
|
27251
|
+
* Split the raw content of a template string (between the surrounding backticks)
|
|
27252
|
+
* into alternating literal and expression segments.
|
|
27253
|
+
*/
|
|
27254
|
+
function splitSegments(raw) {
|
|
27255
|
+
const segments = [];
|
|
27256
|
+
let i = 0;
|
|
27257
|
+
let literal = "";
|
|
27258
|
+
while (i < raw.length) if (raw[i] === "$" && raw[i + 1] === "{") {
|
|
27259
|
+
if (literal.length > 0) {
|
|
27260
|
+
segments.push({
|
|
27261
|
+
type: "literal",
|
|
27262
|
+
value: literal
|
|
27263
|
+
});
|
|
27264
|
+
literal = "";
|
|
27265
|
+
}
|
|
27266
|
+
i += 2;
|
|
27267
|
+
const { expr, consumed } = scanExpression(raw, i);
|
|
27268
|
+
i += consumed;
|
|
27269
|
+
segments.push({
|
|
27270
|
+
type: "expression",
|
|
27271
|
+
value: expr
|
|
27272
|
+
});
|
|
27273
|
+
} else {
|
|
27274
|
+
literal += raw[i];
|
|
27275
|
+
i++;
|
|
27276
|
+
}
|
|
27277
|
+
if (literal.length > 0) segments.push({
|
|
27278
|
+
type: "literal",
|
|
27279
|
+
value: literal
|
|
27280
|
+
});
|
|
27281
|
+
return segments;
|
|
27282
|
+
}
|
|
27283
|
+
function parseTemplateString(ctx, token) {
|
|
27284
|
+
ctx.advance();
|
|
27285
|
+
const sourceCodeInfo = token[2];
|
|
27286
|
+
const segments = splitSegments(token[1].slice(1, -1));
|
|
27287
|
+
if (segments.length === 0) return withSourceCodeInfo([NodeTypes.String, ""], sourceCodeInfo);
|
|
27288
|
+
if (segments.length === 1 && segments[0].type === "literal") return withSourceCodeInfo([NodeTypes.String, segments[0].value], sourceCodeInfo);
|
|
27289
|
+
const segmentNodes = [];
|
|
27290
|
+
for (const segment of segments) if (segment.type === "literal") {
|
|
27291
|
+
if (segment.value.length === 0) continue;
|
|
27292
|
+
segmentNodes.push(withSourceCodeInfo([NodeTypes.String, segment.value], sourceCodeInfo));
|
|
27293
|
+
} else {
|
|
27294
|
+
if (segment.value.trim().length === 0) throw new DvalaError("Empty interpolation in template string", sourceCodeInfo);
|
|
27295
|
+
const minified = minifyTokenStream(tokenize(segment.value, false, sourceCodeInfo?.filePath), { removeWhiteSpace: true });
|
|
27296
|
+
for (const t of minified.tokens) if (t[0] === "Error") throw new DvalaError(`Template string interpolation error: ${t[3]}`, sourceCodeInfo);
|
|
27297
|
+
const expr = parseExpression(createParserContext(minified), 0);
|
|
27298
|
+
segmentNodes.push(expr);
|
|
27299
|
+
}
|
|
27300
|
+
return withSourceCodeInfo([NodeTypes.TemplateString, segmentNodes], sourceCodeInfo);
|
|
27301
|
+
}
|
|
27302
|
+
//#endregion
|
|
27030
27303
|
//#region src/parser/subParsers/parseBindingTarget.ts
|
|
27031
27304
|
function parseBindingTarget(ctx, { requireDefaultValue, noRest, allowLiteralPatterns } = {}) {
|
|
27032
27305
|
const firstToken = ctx.tryPeek();
|
|
@@ -27039,6 +27312,10 @@ function parseBindingTarget(ctx, { requireDefaultValue, noRest, allowLiteralPatt
|
|
|
27039
27312
|
const node = parseNumber(ctx);
|
|
27040
27313
|
return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
|
|
27041
27314
|
}
|
|
27315
|
+
if (isTemplateStringToken(firstToken)) {
|
|
27316
|
+
const node = parseTemplateString(ctx, firstToken);
|
|
27317
|
+
return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
|
|
27318
|
+
}
|
|
27042
27319
|
if (isStringToken(firstToken)) {
|
|
27043
27320
|
const node = parseString(ctx, firstToken);
|
|
27044
27321
|
return withSourceCodeInfo([bindingTargetTypes.literal, [node]], firstToken[2]);
|
|
@@ -27156,7 +27433,7 @@ function parseOptionalDefaulValue(ctx) {
|
|
|
27156
27433
|
}
|
|
27157
27434
|
}
|
|
27158
27435
|
function isLiteralToken(token) {
|
|
27159
|
-
return isNumberToken(token) || isBasePrefixedNumberToken(token) || isStringToken(token) || isReservedSymbolToken(token, "true") || isReservedSymbolToken(token, "false") || isReservedSymbolToken(token, "null");
|
|
27436
|
+
return isNumberToken(token) || isBasePrefixedNumberToken(token) || isStringToken(token) || isTemplateStringToken(token) || isReservedSymbolToken(token, "true") || isReservedSymbolToken(token, "false") || isReservedSymbolToken(token, "null");
|
|
27160
27437
|
}
|
|
27161
27438
|
//#endregion
|
|
27162
27439
|
//#region src/parser/subParsers/parseLet.ts
|
|
@@ -27536,7 +27813,8 @@ function parseObject(ctx) {
|
|
|
27536
27813
|
params.push(withSourceCodeInfo([NodeTypes.Spread, ctx.parseExpression()], ctx.peekSourceCodeInfo()));
|
|
27537
27814
|
} else {
|
|
27538
27815
|
const token = ctx.tryPeek();
|
|
27539
|
-
if (
|
|
27816
|
+
if (isTemplateStringToken(token)) params.push(parseTemplateString(ctx, token));
|
|
27817
|
+
else if (isStringToken(token)) {
|
|
27540
27818
|
const stringNode = parseString(ctx, token);
|
|
27541
27819
|
params.push(withSourceCodeInfo([NodeTypes.String, stringNode[1]], token[2]));
|
|
27542
27820
|
} else if (isSymbolToken(token)) {
|
|
@@ -27616,6 +27894,7 @@ function parseOperandPart(ctx) {
|
|
|
27616
27894
|
case "Number":
|
|
27617
27895
|
case "BasePrefixedNumber": return parseNumber(ctx);
|
|
27618
27896
|
case "string": return parseString(ctx, token);
|
|
27897
|
+
case "TemplateString": return parseTemplateString(ctx, token);
|
|
27619
27898
|
case "Symbol": {
|
|
27620
27899
|
ctx.storePosition();
|
|
27621
27900
|
const lamdaFunction = parseLambdaFunction(ctx);
|
|
@@ -27747,18 +28026,6 @@ function parse(tokenStream) {
|
|
|
27747
28026
|
return nodes;
|
|
27748
28027
|
}
|
|
27749
28028
|
//#endregion
|
|
27750
|
-
//#region src/tokenizer/minifyTokenStream.ts
|
|
27751
|
-
function minifyTokenStream(tokenStream, { removeWhiteSpace }) {
|
|
27752
|
-
const tokens = tokenStream.tokens.filter((token) => {
|
|
27753
|
-
if (isSingleLineCommentToken(token) || isMultiLineCommentToken(token) || isShebangToken(token) || removeWhiteSpace && isWhitespaceToken(token)) return false;
|
|
27754
|
-
return true;
|
|
27755
|
-
});
|
|
27756
|
-
return {
|
|
27757
|
-
...tokenStream,
|
|
27758
|
-
tokens
|
|
27759
|
-
};
|
|
27760
|
-
}
|
|
27761
|
-
//#endregion
|
|
27762
28029
|
//#region src/evaluator/effectTypes.ts
|
|
27763
28030
|
const SUSPENDED_MESSAGE = "Program suspended";
|
|
27764
28031
|
/**
|
|
@@ -28439,9 +28706,33 @@ function stepNode(node, env, k) {
|
|
|
28439
28706
|
};
|
|
28440
28707
|
case NodeTypes.NormalExpression: return stepNormalExpression(node, env, k);
|
|
28441
28708
|
case NodeTypes.SpecialExpression: return stepSpecialExpression(node, env, k);
|
|
28709
|
+
case NodeTypes.TemplateString: return stepTemplateString(node, env, k);
|
|
28442
28710
|
default: throw new DvalaError(`${getNodeTypeName(node[0])}-node cannot be evaluated`, node[2]);
|
|
28443
28711
|
}
|
|
28444
28712
|
}
|
|
28713
|
+
function stepTemplateString(node, env, k) {
|
|
28714
|
+
const segments = node[1];
|
|
28715
|
+
const sourceCodeInfo = node[2];
|
|
28716
|
+
if (segments.length === 0) return {
|
|
28717
|
+
type: "Value",
|
|
28718
|
+
value: "",
|
|
28719
|
+
k
|
|
28720
|
+
};
|
|
28721
|
+
const frame = {
|
|
28722
|
+
type: "TemplateStringBuild",
|
|
28723
|
+
segments,
|
|
28724
|
+
index: 0,
|
|
28725
|
+
result: "",
|
|
28726
|
+
env,
|
|
28727
|
+
sourceCodeInfo
|
|
28728
|
+
};
|
|
28729
|
+
return {
|
|
28730
|
+
type: "Eval",
|
|
28731
|
+
node: segments[0],
|
|
28732
|
+
env,
|
|
28733
|
+
k: [frame, ...k]
|
|
28734
|
+
};
|
|
28735
|
+
}
|
|
28445
28736
|
/**
|
|
28446
28737
|
* Normal expressions: evaluate arguments left-to-right, then dispatch.
|
|
28447
28738
|
* Push EvalArgsFrame + NanCheckFrame, then start evaluating the first arg.
|
|
@@ -29371,6 +29662,7 @@ function applyFrame(frame, value, k) {
|
|
|
29371
29662
|
case "And": return applyAnd(frame, value, k);
|
|
29372
29663
|
case "Or": return applyOr(frame, value, k);
|
|
29373
29664
|
case "Qq": return applyQq(frame, value, k);
|
|
29665
|
+
case "TemplateStringBuild": return applyTemplateStringBuild(frame, value, k);
|
|
29374
29666
|
case "ArrayBuild": return applyArrayBuild(frame, value, k);
|
|
29375
29667
|
case "ObjectBuild": return applyObjectBuild(frame, value, k);
|
|
29376
29668
|
case "LetBind": return applyLetBind(frame, value, k);
|
|
@@ -29657,6 +29949,27 @@ function advanceQq(frame, k) {
|
|
|
29657
29949
|
function skipUndefinedQq(frame, k) {
|
|
29658
29950
|
return advanceQq(frame, k);
|
|
29659
29951
|
}
|
|
29952
|
+
function applyTemplateStringBuild(frame, value, k) {
|
|
29953
|
+
const { segments, env } = frame;
|
|
29954
|
+
const result = frame.result + String(value);
|
|
29955
|
+
const nextIndex = frame.index + 1;
|
|
29956
|
+
if (nextIndex >= segments.length) return {
|
|
29957
|
+
type: "Value",
|
|
29958
|
+
value: result,
|
|
29959
|
+
k
|
|
29960
|
+
};
|
|
29961
|
+
const newFrame = {
|
|
29962
|
+
...frame,
|
|
29963
|
+
index: nextIndex,
|
|
29964
|
+
result
|
|
29965
|
+
};
|
|
29966
|
+
return {
|
|
29967
|
+
type: "Eval",
|
|
29968
|
+
node: segments[nextIndex],
|
|
29969
|
+
env,
|
|
29970
|
+
k: [newFrame, ...k]
|
|
29971
|
+
};
|
|
29972
|
+
}
|
|
29660
29973
|
function applyArrayBuild(frame, value, k) {
|
|
29661
29974
|
const { nodes, result, env, sourceCodeInfo } = frame;
|
|
29662
29975
|
if (frame.isSpread) {
|
|
@@ -31702,6 +32015,13 @@ var Cache = class {
|
|
|
31702
32015
|
* a Dvala instance.
|
|
31703
32016
|
*/
|
|
31704
32017
|
/**
|
|
32018
|
+
* Tokenize a Dvala source string into a token stream.
|
|
32019
|
+
* Pass `debug: true` to capture source positions (needed for the debugger).
|
|
32020
|
+
*/
|
|
32021
|
+
function tokenizeSource(source, debug = false, filePath) {
|
|
32022
|
+
return tokenize(source, debug, filePath);
|
|
32023
|
+
}
|
|
32024
|
+
/**
|
|
31705
32025
|
* Get all undefined symbols in a Dvala program.
|
|
31706
32026
|
*
|
|
31707
32027
|
* @param source - Dvala source code
|
|
@@ -33441,11 +33761,38 @@ const getInlineCodeRule = (fmt) => (text, index) => {
|
|
|
33441
33761
|
formattedText: ""
|
|
33442
33762
|
};
|
|
33443
33763
|
};
|
|
33764
|
+
function getTemplateStringRule(fmt) {
|
|
33765
|
+
return (text, index) => {
|
|
33766
|
+
if (text[index] !== "`") return noMatch;
|
|
33767
|
+
try {
|
|
33768
|
+
const { tokens } = tokenizeSource(text.slice(index));
|
|
33769
|
+
const first = tokens[0];
|
|
33770
|
+
if (!first || first[0] !== "TemplateString") return noMatch;
|
|
33771
|
+
const count = first[1].length;
|
|
33772
|
+
const segments = splitSegments(first[1].slice(1, -1));
|
|
33773
|
+
let formattedText = `${Colors.FgRed}\`${Colors.Reset}`;
|
|
33774
|
+
for (const seg of segments) if (seg.type === "literal") formattedText += Colors.FgRed + seg.value + Colors.Reset;
|
|
33775
|
+
else {
|
|
33776
|
+
formattedText += `${Colors.Bright}${Colors.FgWhite}\${${Colors.Reset}`;
|
|
33777
|
+
formattedText += getDvalaFormatter(fmt)(seg.value);
|
|
33778
|
+
formattedText += `${Colors.Bright}${Colors.FgWhite}}${Colors.Reset}`;
|
|
33779
|
+
}
|
|
33780
|
+
formattedText += `${Colors.FgRed}\`${Colors.Reset}`;
|
|
33781
|
+
return {
|
|
33782
|
+
count,
|
|
33783
|
+
formattedText
|
|
33784
|
+
};
|
|
33785
|
+
} catch {
|
|
33786
|
+
return noMatch;
|
|
33787
|
+
}
|
|
33788
|
+
};
|
|
33789
|
+
}
|
|
33444
33790
|
function getDvalaExpressionRules(cli) {
|
|
33445
33791
|
return [
|
|
33446
33792
|
commentRule,
|
|
33447
33793
|
stringRule,
|
|
33448
33794
|
shortcutStringRule,
|
|
33795
|
+
getTemplateStringRule(cli),
|
|
33449
33796
|
functionNameRule,
|
|
33450
33797
|
getNumberRule(cli),
|
|
33451
33798
|
dvalaKeywordRule,
|