Skip to content

Commit 1789577

Browse files
authored
feat: Initial support for template literals (#1715)
1 parent 231a8dc commit 1789577

27 files changed

+12377
-134
lines changed

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ lib/parse/index.js
55
out/
66
raw/
77
tests/parser/
8+
9+
# FIXME: Tagged template literal tests with invalid escapes
10+
tests/compiler/templateliteral.ts

src/ast.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ import {
3333
isTrivialAlphanum
3434
} from "./util";
3535

36+
import {
37+
ExpressionRef
38+
} from "./module";
39+
40+
import {
41+
Type
42+
} from "./types";
43+
3644
/** Indicates the kind of a node. */
3745
export enum NodeKind {
3846

@@ -69,6 +77,7 @@ export enum NodeKind {
6977
CONSTRUCTOR,
7078
UNARYPOSTFIX,
7179
UNARYPREFIX,
80+
COMPILED,
7281

7382
// statements
7483
BLOCK,
@@ -378,6 +387,16 @@ export abstract class Node {
378387
return new SuperExpression(range);
379388
}
380389

390+
static createTemplateLiteralExpression(
391+
tag: Expression | null,
392+
parts: string[],
393+
rawParts: string[],
394+
expressions: Expression[],
395+
range: Range
396+
): TemplateLiteralExpression {
397+
return new TemplateLiteralExpression(tag, parts, rawParts, expressions, range);
398+
}
399+
381400
static createThisExpression(
382401
range: Range
383402
): ThisExpression {
@@ -406,6 +425,14 @@ export abstract class Node {
406425
return new UnaryPrefixExpression(operator, operand, range);
407426
}
408427

428+
static createCompiledExpression(
429+
expr: ExpressionRef,
430+
type: Type,
431+
range: Range
432+
): Expression {
433+
return new CompiledExpression(expr, type, range);
434+
}
435+
409436
// statements
410437

411438
static createBlockStatement(
@@ -1087,6 +1114,7 @@ export enum LiteralKind {
10871114
FLOAT,
10881115
INTEGER,
10891116
STRING,
1117+
TEMPLATE,
10901118
REGEXP,
10911119
ARRAY,
10921120
OBJECT
@@ -1443,6 +1471,24 @@ export class SuperExpression extends IdentifierExpression {
14431471
}
14441472
}
14451473

1474+
/** Represents a template literal expression. */
1475+
export class TemplateLiteralExpression extends LiteralExpression {
1476+
constructor(
1477+
/** Tag expression, if any. */
1478+
public tag: Expression | null,
1479+
/** String parts. */
1480+
public parts: string[],
1481+
/** Raw string parts. */
1482+
public rawParts: string[],
1483+
/** Expression parts. */
1484+
public expressions: Expression[],
1485+
/** Source range. */
1486+
range: Range
1487+
) {
1488+
super(LiteralKind.TEMPLATE, range);
1489+
}
1490+
}
1491+
14461492
/** Represents a `this` expression. */
14471493
export class ThisExpression extends IdentifierExpression {
14481494
constructor(
@@ -1520,6 +1566,20 @@ export class UnaryPrefixExpression extends UnaryExpression {
15201566
}
15211567
}
15221568

1569+
/** Represents a special pre-compiled expression. If the expression has side-effects, special care has to be taken. */
1570+
export class CompiledExpression extends Expression {
1571+
constructor(
1572+
/** Compiled expression. */
1573+
public expr: ExpressionRef,
1574+
/** Type of the compiled expression. */
1575+
public type: Type,
1576+
/** Source range. */
1577+
range: Range
1578+
) {
1579+
super(NodeKind.COMPILED, range);
1580+
}
1581+
}
1582+
15231583
// statements
15241584

15251585
/** Base class of all statement nodes. */

src/builtins.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,9 @@ export namespace BuiltinNames {
649649
export const Float32Array = "~lib/typedarray/Float32Array";
650650
export const Float64Array = "~lib/typedarray/Float64Array";
651651

652+
// std/string.ts
653+
export const String_raw = "~lib/string/String.raw";
654+
652655
// std/bindings/wasi.ts
653656
export const wasiAbort = "~lib/wasi/index/abort";
654657
export const wasiTrace = "~lib/wasi/index/trace";
@@ -3337,6 +3340,19 @@ function builtin_function_call(ctx: BuiltinContext): ExpressionRef {
33373340
}
33383341
function_builtins.set("call", builtin_function_call);
33393342

3343+
// String.raw(parts: TemplateStringsArray, ...values: unknown[]): string
3344+
function builtin_string_raw(ctx: BuiltinContext): ExpressionRef {
3345+
var compiler = ctx.compiler;
3346+
var module = compiler.module;
3347+
compiler.currentType = ctx.compiler.program.stringInstance.type;
3348+
compiler.error(
3349+
DiagnosticCode.Not_implemented_0,
3350+
ctx.reportNode.range, "String.raw"
3351+
);
3352+
return module.unreachable();
3353+
}
3354+
builtins.set(BuiltinNames.String_raw, builtin_string_raw);
3355+
33403356
// === Portable type conversions ==============================================================
33413357

33423358
function builtin_conversion(ctx: BuiltinContext, toType: Type): ExpressionRef {

src/common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ export namespace CommonNames {
222222
export const Uint64Array = "Uint64Array";
223223
export const Float32Array = "Float32Array";
224224
export const Float64Array = "Float64Array";
225+
export const TemplateStringsArray = "TemplateStringsArray";
225226
export const Error = "Error";
226227
// runtime
227228
export const abort = "abort";

0 commit comments

Comments
 (0)