Simple string interpolation.

This allows "%(...)" inside a string literal to interpolate the
stringified result of an expression.

It doesn't support custom interpolators or format strings, but we can
consider extending that later.
This commit is contained in:
Bob Nystrom
2015-11-11 07:55:48 -08:00
parent 71575d9179
commit 78655c68b0
41 changed files with 321 additions and 129 deletions
+2 -2
View File
@@ -1,9 +1,9 @@
for (i in 0..2) {
System.print("outer " + i.toString)
System.print("outer %(i)")
if (i > 1) break
for (j in 0..2) {
System.print("inner " + j.toString)
System.print("inner %(j)")
if (j > 1) break
}
}
+2 -2
View File
@@ -1,11 +1,11 @@
var i = 0
while (true) {
System.print("outer " + i.toString)
System.print("outer %(i)")
if (i > 1) break
var j = 0
while (true) {
System.print("inner " + j.toString)
System.print("inner %(j)")
if (j > 1) break
j = j + 1
+2 -2
View File
@@ -1,6 +1,6 @@
class A {
construct new(arg) {
System.print("new A " + arg)
System.print("new A %(arg)")
_field = arg
}
@@ -10,7 +10,7 @@ class A {
class B is A {
construct new(arg1, arg2) {
super(arg2)
System.print("new B " + arg1)
System.print("new B %(arg1)")
_field = arg1
}
+2
View File
@@ -0,0 +1,2 @@
// expect error line 3
" %() "
@@ -0,0 +1,15 @@
// Full string.
System.print("%(1 + 2)") // expect: 3
// Multiple in one string.
System.print("str%(1 + 2)(%(3 + 4)\%%(5 + 6)") // expect: str3(7%11
// Nested.
System.print("[%("{%("in" + "ner")}")]") // expect: [{inner}]
// Ignore newlines in template.
System.print("[%(
"template"
)]") // expect: [template]
@@ -0,0 +1 @@
System.print("%(123.badMethod)") // expect runtime error: Num does not implement 'badMethod'.
@@ -0,0 +1,8 @@
var fiber = Fiber.new {
System.print("in fiber")
Fiber.yield("result")
}
System.print("outer %(fiber.call()) string")
// expect: in fiber
// expect: outer result string
@@ -0,0 +1,2 @@
" %(
// expect error
@@ -0,0 +1,2 @@
// expect error line 2
" %(123"
+2 -2
View File
@@ -1,7 +1,7 @@
class Foo {
construct new() {}
method(a, b) { "method " + a + " " + b }
[a, b] { "subscript " + a + " " + b }
method(a, b) { "method %(a) %(b)" }
[a, b] { "subscript %(a) %(b)" }
}
var foo = Foo.new()
+14 -14
View File
@@ -1,20 +1,20 @@
class Foo {
construct new() {}
+(other) { "infix + " + other }
-(other) { "infix - " + other }
*(other) { "infix * " + other }
/(other) { "infix / " + other }
%(other) { "infix % " + other }
<(other) { "infix < " + other }
>(other) { "infix > " + other }
<=(other) { "infix <= " + other }
>=(other) { "infix >= " + other }
==(other) { "infix == " + other }
!=(other) { "infix != " + other }
&(other) { "infix & " + other }
|(other) { "infix | " + other }
is(other) { "infix is " + other }
+(other) { "infix + %(other)" }
-(other) { "infix - %(other)" }
*(other) { "infix * %(other)" }
/(other) { "infix / %(other)" }
%(other) { "infix \% %(other)" }
<(other) { "infix < %(other)" }
>(other) { "infix > %(other)" }
<=(other) { "infix <= %(other)" }
>=(other) { "infix >= %(other)" }
==(other) { "infix == %(other)" }
!=(other) { "infix != %(other)" }
&(other) { "infix & %(other)" }
|(other) { "infix | %(other)" }
is(other) { "infix is %(other)" }
! { "prefix !" }
~ { "prefix ~" }
+2 -2
View File
@@ -3,8 +3,8 @@ class Foo {
bar { "on instance" }
static bar { "on metaclass" }
bar(arg) { "on instance " + arg }
static bar(arg) { "on metaclass " + arg }
bar(arg) { "on instance %(arg)" }
static bar(arg) { "on metaclass %(arg)" }
}
System.print(Foo.new().bar) // expect: on instance
@@ -1,11 +1,11 @@
class Foo {
construct new() {}
[a] { "1-subscript " + a }
[a, b] { "2-subscript " + a + " " + b }
[a, b, c] { "3-subscript " + a + " " + b + " " + c }
[a]=(value) { "1-subscript setter " + a + " = " + value }
[a, b]=(value) { "2-subscript setter " + a + " " + b + " = " + value }
[a, b, c]=(value) { "3-subscript setter " + a + " " + b + " " + c + " = " + value }
[a] { "1-subscript %(a)" }
[a, b] { "2-subscript %(a) %(b)" }
[a, b, c] { "3-subscript %(a) %(b) %(c)" }
[a]=(value) { "1-subscript setter %(a) = %(value)" }
[a, b]=(value) { "2-subscript setter %(a) %(b) = %(value)" }
[a, b, c]=(value) { "3-subscript setter %(a) %(b) %(c) = %(value)" }
}
var foo = Foo.new()
+3 -3
View File
@@ -2,8 +2,8 @@
System.print("start a")
var A = "a value"
System.print("a defined " + A)
System.print("a defined %(A)")
import "b" for B
System.print("a imported " + B)
System.print("a imported %(B)")
System.print("end a")
System.print("end a")
+2 -2
View File
@@ -2,8 +2,8 @@
System.print("start b")
var B = "b value"
System.print("b defined " + B)
System.print("b defined %(B)")
import "a" for A
System.print("b imported " + A)
System.print("b imported %(A)")
System.print("end b")
+1 -1
View File
@@ -1,5 +1,5 @@
// nontest
System.print("a")
import "shared" for Shared
var A = "a " + Shared
var A = "a %(Shared)"
System.print("a done")
+1 -1
View File
@@ -1,5 +1,5 @@
// nontest
System.print("b")
import "shared" for Shared
var B = "b " + Shared
var B = "b %(Shared)"
System.print("b done")
+2 -1
View File
@@ -2,6 +2,7 @@
System.print("\"") // expect: "
System.print("\\") // expect: \
System.print("(\n)") // expect: (
// expect: )
// expect: )
System.print("\%") // expect: %
// TODO: Non-printing escapes like \t.