Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement template literals #1715

Merged
merged 15 commits into from
Mar 26, 2021
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ lib/parse/index.js
out/
raw/
tests/parser/

# FIXME: Tagged template literal tests with invalid escapes
tests/compiler/templateliteral.ts
60 changes: 60 additions & 0 deletions src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ import {
isTrivialAlphanum
} from "./util";

import {
ExpressionRef
} from "./module";

import {
Type
} from "./types";

/** Indicates the kind of a node. */
export enum NodeKind {

Expand Down Expand Up @@ -69,6 +77,7 @@ export enum NodeKind {
CONSTRUCTOR,
UNARYPOSTFIX,
UNARYPREFIX,
COMPILED,

// statements
BLOCK,
Expand Down Expand Up @@ -378,6 +387,16 @@ export abstract class Node {
return new SuperExpression(range);
}

static createTemplateLiteralExpression(
tag: Expression | null,
parts: string[],
rawParts: string[],
expressions: Expression[],
range: Range
): TemplateLiteralExpression {
return new TemplateLiteralExpression(tag, parts, rawParts, expressions, range);
}

static createThisExpression(
range: Range
): ThisExpression {
Expand Down Expand Up @@ -406,6 +425,14 @@ export abstract class Node {
return new UnaryPrefixExpression(operator, operand, range);
}

static createCompiledExpression(
expr: ExpressionRef,
type: Type,
range: Range
): Expression {
return new CompiledExpression(expr, type, range);
}

// statements

static createBlockStatement(
Expand Down Expand Up @@ -1087,6 +1114,7 @@ export enum LiteralKind {
FLOAT,
INTEGER,
STRING,
TEMPLATE,
REGEXP,
ARRAY,
OBJECT
Expand Down Expand Up @@ -1443,6 +1471,24 @@ export class SuperExpression extends IdentifierExpression {
}
}

/** Represents a template literal expression. */
export class TemplateLiteralExpression extends LiteralExpression {
constructor(
/** Tag expression, if any. */
public tag: Expression | null,
/** String parts. */
public parts: string[],
/** Raw string parts. */
public rawParts: string[],
/** Expression parts. */
public expressions: Expression[],
/** Source range. */
range: Range
) {
super(LiteralKind.TEMPLATE, range);
}
}

/** Represents a `this` expression. */
export class ThisExpression extends IdentifierExpression {
constructor(
Expand Down Expand Up @@ -1520,6 +1566,20 @@ export class UnaryPrefixExpression extends UnaryExpression {
}
}

/** Represents a special pre-compiled expression. If the expression has side-effects, special care has to be taken. */
export class CompiledExpression extends Expression {
constructor(
/** Compiled expression. */
public expr: ExpressionRef,
/** Type of the compiled expression. */
public type: Type,
/** Source range. */
range: Range
) {
super(NodeKind.COMPILED, range);
}
}

// statements

/** Base class of all statement nodes. */
Expand Down
16 changes: 16 additions & 0 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,9 @@ export namespace BuiltinNames {
export const Float32Array = "~lib/typedarray/Float32Array";
export const Float64Array = "~lib/typedarray/Float64Array";

// std/string.ts
export const String_raw = "~lib/string/String.raw";

// std/bindings/wasi.ts
export const wasiAbort = "~lib/wasi/index/abort";
export const wasiTrace = "~lib/wasi/index/trace";
Expand Down Expand Up @@ -3337,6 +3340,19 @@ function builtin_function_call(ctx: BuiltinContext): ExpressionRef {
}
function_builtins.set("call", builtin_function_call);

// String.raw(parts: TemplateStringsArray, ...values: unknown[]): string
function builtin_string_raw(ctx: BuiltinContext): ExpressionRef {
var compiler = ctx.compiler;
var module = compiler.module;
compiler.currentType = ctx.compiler.program.stringInstance.type;
compiler.error(
DiagnosticCode.Not_implemented_0,
ctx.reportNode.range, "String.raw"
);
return module.unreachable();
}
builtins.set(BuiltinNames.String_raw, builtin_string_raw);

// === Portable type conversions ==============================================================

function builtin_conversion(ctx: BuiltinContext, toType: Type): ExpressionRef {
Expand Down
1 change: 1 addition & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ export namespace CommonNames {
export const Uint64Array = "Uint64Array";
export const Float32Array = "Float32Array";
export const Float64Array = "Float64Array";
export const TemplateStringsArray = "TemplateStringsArray";
export const Error = "Error";
// runtime
export const abort = "abort";
Expand Down
Loading