Skip to content

Commit 551b312

Browse files
authored
Add shortcuts for some non-tagged string templates (#2014)
1 parent 75890dc commit 551b312

File tree

4 files changed

+1896
-1740
lines changed

4 files changed

+1896
-1740
lines changed

src/compiler.ts

+81-25
Original file line numberDiff line numberDiff line change
@@ -8156,16 +8156,71 @@ export class Compiler extends DiagnosticEmitter {
81568156
var expressions = expression.expressions;
81578157
assert(numParts - 1 == expressions.length);
81588158

8159-
// Shortcut if just a (multi-line) string
8160-
if (tag === null && numParts == 1) {
8161-
return this.ensureStaticString(parts[0]);
8162-
}
8163-
81648159
var module = this.module;
8165-
var stringType = this.program.stringInstance.type;
8160+
var stringInstance = this.program.stringInstance;
8161+
var stringType = stringInstance.type;
81668162

8167-
// Compile to a `StaticArray<string>#join("")` if untagged
81688163
if (tag === null) {
8164+
// Shortcut if just a (multi-line) string
8165+
if (numParts == 1) {
8166+
return this.ensureStaticString(parts[0]);
8167+
}
8168+
8169+
// Shortcut for `${expr}`, `<prefix>${expr}`, `${expr}<suffix>`
8170+
if (numParts == 2) {
8171+
let expression = expressions[0];
8172+
let lhsLen = parts[0].length;
8173+
let rhsLen = parts[1].length;
8174+
// Shortcut for `${expr}` -> expr.toString()
8175+
if (!lhsLen && !rhsLen) {
8176+
return this.makeToString(
8177+
this.compileExpression(expression, stringType),
8178+
this.currentType, expression
8179+
);
8180+
}
8181+
// Shortcuts for
8182+
// `<prefix>${expr}` -> "<prefix>" + expr.toString()
8183+
// `${expr}<suffix>` -> expr.toString() + "<suffix>"
8184+
let hasPrefix = lhsLen != 0;
8185+
// @ts-ignore: cast
8186+
if (hasPrefix ^ (rhsLen != 0)) {
8187+
let lhs: ExpressionRef;
8188+
let rhs: ExpressionRef;
8189+
let expr = this.makeToString(
8190+
this.compileExpression(expression, stringType),
8191+
this.currentType, expression
8192+
);
8193+
if (hasPrefix) {
8194+
lhs = this.ensureStaticString(parts[0]);
8195+
rhs = expr;
8196+
} else {
8197+
// suffix
8198+
lhs = expr;
8199+
rhs = this.ensureStaticString(parts[1]);
8200+
}
8201+
let concatMethod = assert(stringInstance.getMethod("concat"));
8202+
return this.makeCallDirect(concatMethod, [ lhs, rhs ], expression);
8203+
}
8204+
}
8205+
8206+
// Shortcut for `${exprA}${exprB}` -> exprA.toString() + exprB.toString()
8207+
if (numParts == 3 && !parts[0].length && !parts[1].length && !parts[2].length) {
8208+
let exprA = expressions[0];
8209+
let exprB = expressions[1];
8210+
8211+
let lhs = this.makeToString(
8212+
this.compileExpression(exprA, stringType),
8213+
this.currentType, exprA
8214+
);
8215+
let rhs = this.makeToString(
8216+
this.compileExpression(exprB, stringType),
8217+
this.currentType, exprB
8218+
);
8219+
let concatMethod = assert(stringInstance.getMethod("concat"));
8220+
return this.makeCallDirect(concatMethod, [ lhs, rhs ], expression);
8221+
}
8222+
8223+
// Compile to a `StaticArray<string>#join("") for general case
81698224
let length = 2 * numParts - 1;
81708225
let values = new Array<usize>(length);
81718226
values[0] = this.ensureStaticString(parts[0]);
@@ -8178,26 +8233,22 @@ export class Compiler extends DiagnosticEmitter {
81788233
let offset = i64_add(segment.offset, i64_new(this.program.totalOverhead));
81798234
let joinInstance = assert(arrayInstance.getMethod("join"));
81808235
let indexedSetInstance = assert(arrayInstance.lookupOverload(OperatorKind.INDEXED_SET, true));
8181-
let stmts = new Array<ExpressionRef>();
8236+
let stmts = new Array<ExpressionRef>(numParts);
81828237
for (let i = 0, k = numParts - 1; i < k; ++i) {
81838238
let expression = expressions[i];
8184-
stmts.push(
8185-
this.makeCallDirect(indexedSetInstance, [
8186-
module.usize(offset),
8187-
module.i32(2 * i + 1),
8188-
this.makeToString(
8189-
this.compileExpression(expression, stringType),
8190-
this.currentType, expression
8191-
)
8192-
], expression)
8193-
);
8194-
}
8195-
stmts.push(
8196-
this.makeCallDirect(joinInstance, [
8239+
stmts[i] = this.makeCallDirect(indexedSetInstance, [
81978240
module.usize(offset),
8198-
this.ensureStaticString("")
8199-
], expression)
8200-
);
8241+
module.i32(2 * i + 1),
8242+
this.makeToString(
8243+
this.compileExpression(expression, stringType),
8244+
this.currentType, expression
8245+
)
8246+
], expression);
8247+
}
8248+
stmts[numParts - 1] = this.makeCallDirect(joinInstance, [
8249+
module.usize(offset),
8250+
this.ensureStaticString("")
8251+
], expression);
82018252
return module.flatten(stmts, stringType.toRef());
82028253
}
82038254

@@ -8210,7 +8261,12 @@ export class Compiler extends DiagnosticEmitter {
82108261
if (target) {
82118262
switch (target.kind) {
82128263
case ElementKind.FUNCTION_PROTOTYPE: {
8213-
let instance = this.resolver.resolveFunction(<FunctionPrototype>target, null, uniqueMap<string,Type>(), ReportMode.SWALLOW);
8264+
let instance = this.resolver.resolveFunction(
8265+
<FunctionPrototype>target,
8266+
null,
8267+
uniqueMap<string,Type>(),
8268+
ReportMode.SWALLOW
8269+
);
82148270
if (!instance) break;
82158271
target = instance;
82168272
// fall-through

0 commit comments

Comments
 (0)