From 5bde04db4c4aae483dcc63869e6427c689f46ee2 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Mon, 23 Nov 2015 07:08:14 -0800 Subject: [PATCH] Eagerly evaluate interpolated expressions. If we ever support custom string templates, we'll need to go back to compiling them to functions. But, for now, they can be evaluated eagerly, leading to simpler code. --- src/vm/wren_compiler.c | 28 ++++++++++++++-------------- src/vm/wren_core.wren | 13 ------------- src/vm/wren_core.wren.inc | 13 ------------- 3 files changed, 14 insertions(+), 40 deletions(-) diff --git a/src/vm/wren_compiler.c b/src/vm/wren_compiler.c index 2ccf4bca..341d8e48 100644 --- a/src/vm/wren_compiler.c +++ b/src/vm/wren_compiler.c @@ -2208,12 +2208,18 @@ static void literal(Compiler* compiler, bool allowAssignment) emitConstant(compiler, compiler->parser->previous.value); } +// A string literal that contains interpolated expressions. +// +// Interpolation is syntactic sugar for calling ".join()" on a list. So the +// string: +// +// "a %(b + c) d" +// +// is compiled roughly like: +// +// ["a ", b + c, " d"].join() static void stringInterpolation(Compiler* compiler, bool allowAssignment) { - // TODO: Allow other expressions here so that user-defined classes can control - // interpolation processing like "tagged template strings" in ES6. - loadCoreVariable(compiler, "String"); - // Instantiate a new list. loadCoreVariable(compiler, "List"); callMethod(compiler, 0, "new()", 5); @@ -2224,15 +2230,9 @@ static void stringInterpolation(Compiler* compiler, bool allowAssignment) literal(compiler, false); callMethod(compiler, 1, "addCore_(_)", 11); + // The interpolated expression. ignoreNewlines(compiler); - - // Compile the interpolated expression part to a function. - Compiler fnCompiler; - initCompiler(&fnCompiler, compiler->parser, compiler, true); - expression(&fnCompiler); - emit(&fnCompiler, CODE_RETURN); - endCompiler(&fnCompiler, "interpolation", 9); - + expression(compiler); callMethod(compiler, 1, "addCore_(_)", 11); ignoreNewlines(compiler); @@ -2243,8 +2243,8 @@ static void stringInterpolation(Compiler* compiler, bool allowAssignment) literal(compiler, false); callMethod(compiler, 1, "addCore_(_)", 11); - // Call .interpolate() with the list of interpolation parts. - callMethod(compiler, 1, "interpolate_(_)", 15); + // The list of interpolated parts. + callMethod(compiler, 0, "join()", 6); } static void super_(Compiler* compiler, bool allowAssignment) diff --git a/src/vm/wren_core.wren b/src/vm/wren_core.wren index 303bcb52..e88808cf 100644 --- a/src/vm/wren_core.wren +++ b/src/vm/wren_core.wren @@ -131,19 +131,6 @@ class WhereSequence is Sequence { class String is Sequence { bytes { StringByteSequence.new(this) } codePoints { StringCodePointSequence.new(this) } - - static interpolate_(parts) { - var result = "" - for (part in parts) { - if (part is String) { - result = result + part - } else { - result = result + part.call().toString - } - } - - return result - } } class StringByteSequence is Sequence { diff --git a/src/vm/wren_core.wren.inc b/src/vm/wren_core.wren.inc index d8f97f2f..4c420683 100644 --- a/src/vm/wren_core.wren.inc +++ b/src/vm/wren_core.wren.inc @@ -133,19 +133,6 @@ static const char* coreModuleSource = "class String is Sequence {\n" " bytes { StringByteSequence.new(this) }\n" " codePoints { StringCodePointSequence.new(this) }\n" -"\n" -" static interpolate_(parts) {\n" -" var result = \"\"\n" -" for (part in parts) {\n" -" if (part is String) {\n" -" result = result + part\n" -" } else {\n" -" result = result + part.call().toString\n" -" }\n" -" }\n" -"\n" -" return result\n" -" }\n" "}\n" "\n" "class StringByteSequence is Sequence {\n"