Skip to content

Commit

Permalink
String interpolation support (#1083)
Browse files Browse the repository at this point in the history
Enhancements:
- Support string interpolation in literals delimited with double quotes (see #1071)

Notes:
- This changes how string literals are interpreted. Existing code with string literals that contain `{` and `}` will need to be updated to quote them. See linked issue for details.

Bumps #minor version
  • Loading branch information
degory committed Feb 21, 2024
1 parent d78277f commit 33c0e19
Show file tree
Hide file tree
Showing 39 changed files with 311 additions and 303 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
]
},
"ghul.compiler": {
"version": "0.7.12",
"version": "0.7.13",
"commands": [
"ghul-compiler"
]
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>0.7.11-alpha.19</Version>
<Version>0.7.13-alpha.2</Version>
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>

Expand Down
1 change: 0 additions & 1 deletion integration-tests/execution/integer-literals/ghul.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{
"compiler": "dotnet ../../../publish/ghul.dll",
"other_flags": "--v3",
"source": [
"."
]
Expand Down
96 changes: 48 additions & 48 deletions integration-tests/execution/integer-literals/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -30,102 +30,102 @@ namespace Test is

Std.out.write_line("signed byte");

test("0B", 0B, "{0}");
test("0B", 0B, "{{0}}");
sb = 123b;
test("123b", sb, "{0}");
test("123b", sb, "{{0}}");

test("87sb", 87sb, "{0}");
test("0x0sb", 0x0sB, "{0}");
test("0x6B_Sb", 0x6B_Sb, "{0:X}");
test("87sb", 87sb, "{{0}}");
test("0x0sb", 0x0sB, "{{0}}");
test("0x6B_Sb", 0x6B_Sb, "{{0:X}}");

Std.out.write_line("unsigned byte");

test("0Ub", 0Ub, "{0}");
test("0Ub", 0Ub, "{{0}}");

ub = 123ub;
test("123uB", ub, "{0}");
test("0xA_1_uB", 0xA_1_uB, "{0:X}");
test("123uB", ub, "{{0}}");
test("0xA_1_uB", 0xA_1_uB, "{{0:X}}");

Std.out.write_line("signed short");

test("0s", 0s, "{0}");
test("0s", 0s, "{{0}}");

ss = 4567s;
test("4567s", ss, "{0}");
test("0x52_CD_s", 0x52CDs, "{0:X}");
test("4567s", ss, "{{0}}");
test("0x52_CD_s", 0x52CDs, "{{0:X}}");

Std.out.write_line("unsigned short");
test("0us", 0us, "{0}");
test("0us", 0us, "{{0}}");

us = 7890uS;
test("7890uS", us, "{0}");
test("0xABCDUs", 0xABCDUs, "{0:X}");
test("7890uS", us, "{{0}}");
test("0xABCDUs", 0xABCDUs, "{{0:X}}");

Std.out.write_line("signed int");
test("0", 0, "{0}");

si_ = 123;
test("123", si_, "{0}");
test("123_456", 123_456, "{0}");
test("123", si_, "{{0}}");
test("123_456", 123_456, "{{0}}");

test("0i", 0i, "{0}");
test("222I", 222I, "{0}");
test("33__44__55__si", 33__44__55__si, "{0}");
test("0i", 0i, "{{0}}");
test("222I", 222I, "{{0}}");
test("33__44__55__si", 33__44__55__si, "{{0}}");

Std.out.write_line("unsigned int");
test("0u", 0u, "{0}");
test("0u", 0u, "{{0}}");

ui = 123u;
test("123u", ui, "{0}");
test("123_456u", 123_456u, "{0}");
test("123u", ui, "{{0}}");
test("123_456u", 123_456u, "{{0}}");

test("0ui", 0ui, "{0}");
test("333UI", 333UI, "{0}");
test("33__44__55_ui", 33__44__55_ui, "{0}");
test("0ui", 0ui, "{{0}}");
test("333UI", 333UI, "{{0}}");
test("33__44__55_ui", 33__44__55_ui, "{{0}}");

Std.out.write_line("signed long");
test("0l", 0l, "{0}");

sl = 1234567890123456l;
test("1234567890123456l", sl, "{0}");
test("1_234_567_890_123_456L", 1_234_567_890_123_456L, "{0}");
test("1234567890123456l", sl, "{{0}}");
test("1_234_567_890_123_456L", 1_234_567_890_123_456L, "{{0}}");

test("0sl", 0sl, "{0}");
test("222sL", 222sL, "{0}");
test("3344__55Sl", 3344__55Sl, "{0}");
test("0sl", 0sl, "{{0}}");
test("222sL", 222sL, "{{0}}");
test("3344__55Sl", 3344__55Sl, "{{0}}");

Std.out.write_line("unsigned long");
test("0ul", 0ul, "{0}");
test("0ul", 0ul, "{{0}}");

ul = 123uL;
test("123uL", ul, "{0}");
test("123_456Ul", 123_456Ul, "{0}");
test("123uL", ul, "{{0}}");
test("123_456Ul", 123_456Ul, "{{0}}");

test("0UL", 0UL, "{0}");
test("444UL", 444UL, "{0}");
test("33__44__55__UL", 33__44__55__UL, "{0}");
test("0UL", 0UL, "{{0}}");
test("444UL", 444UL, "{{0}}");
test("33__44__55__UL", 33__44__55__UL, "{{0}}");

Std.out.write_line("signed word");
test("0w", 0w, "{0}");
test("0w", 0w, "{{0}}");

sw = 123W;
test("123W", sw, "{0}");
test("0x1234_5678_ABCD_EF01w", 0x1234_5678_ABCD_EF01w, "{0}");
test("123W", sw, "{{0}}");
test("0x1234_5678_ABCD_EF01w", 0x1234_5678_ABCD_EF01w, "{{0}}");

test("0sw", 0sw, "{0}");
test("222sW", 222sW, "{0}");
test("3344__55Sw", 3344__55Sw, "{0}");
test("0sw", 0sw, "{{0}}");
test("222sW", 222sW, "{{0}}");
test("3344__55Sw", 3344__55Sw, "{{0}}");

Std.out.write_line("unsigned word");
test("0uw", 0uw, "{0}");
test("0uw", 0uw, "{{0}}");

uw = 123uW;
test("123uW", uw, "{0}");
test("123_456Uw", 123_456Uw, "{0}");
test("123uW", uw, "{{0}}");
test("123_456Uw", 123_456Uw, "{{0}}");

test("0uw", 0UW, "{0}");
test("222uw", 123UW, "{0}");
test("33__44__55__uw", 33__44__55__UW, "{0}");
test("0uw", 0UW, "{{0}}");
test("222uw", 123UW, "{{0}}");
test("33__44__55__uw", 33__44__55__UW, "{{0}}");
si

test(expected_string: string, value: object, format: string) static is
Expand Down
8 changes: 4 additions & 4 deletions integration-tests/execution/named-tuple-elements/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,28 @@ namespace Test is
let index: int = iv_explicit.index;
let value: string = iv_explicit.value;

write_line("index: {0}, value: {1}", [index, value]);
write_line("index: {{0}}, value: {{1}}", [index, value]);

let iv_implicit = create_tuple_implicit_return_type(2, "two");

index = iv_implicit.index;
value = iv_implicit.value;

write_line("index: {0}, value: {1}", [index, value]);
write_line("index: {{0}}, value: {{1}}", [index, value]);

iv_explicit = create_create_tuple_explicit_return_type(3, "three")();

index = iv_explicit.index;
value = iv_explicit.value;

write_line("index: {0}, value: {1}", [index, value]);
write_line("index: {{0}}, value: {{1}}", [index, value]);

iv_implicit = create_create_tuple_implicit_return_type(4, "four")();

index = iv_implicit.index;
value = iv_implicit.value;

write_line("index: {0}, value: {1}", [index, value]);
write_line("index: {{0}}, value: {{1}}", [index, value]);
si
si
si
8 changes: 4 additions & 4 deletions integration-tests/execution/string-interpolation-1/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ entry() is
let x = 10;
let y = 20;

write_line({interpolate {x+y} and {x-y} together});
write_line("interpolate {x+y} and {x-y} together");

write_line({{x+x} at the beginning and {y-y} in the middle});
write_line("{x+x} at the beginning and { y - y } in the middle");

write_line({now {x+y+x} in the middle and end with {x + x + y}});
write_line("now {x + y + x} in the middle and end with {x + x + y}");

write_line({{x + 3}{x - y + 5}});
write_line("{x + 3}{x - y + 5}");
si

8 changes: 4 additions & 4 deletions integration-tests/execution/string-interpolation-2/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ entry() is
let x = 11;
let y = 22;

write_line({interpolate {test(x)+y} and {x-test(y)} together});
write_line("interpolate {test(x)+y} and {x-test(y)} together");

write_line({{test(x)+test(x)} at the beginning and {test(y-y)} in the middle});
write_line("{test(x)+test(x)} at the beginning and {test(y-y)} in the middle");

write_line({now {x+test(y)+x} in the middle and end with {test(x) + x + test(y)}});
write_line("now {x+test(y)+x} in the middle and end with {test(x) + x + test(y)}");

write_line({{x + test(3)}{x - test(y) + 5}});
write_line("{x + test(3)}{x - test(y) + 5}");
si

4 changes: 2 additions & 2 deletions integration-tests/execution/string-interpolation-3/test.ghul
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use IO.Std.write_line;

test(x: string) -> string => {/{x}/};
test(x: string) -> string => "/{x}/";

entry() is
let x = 11;
let y = 22;

test("hello");

write_line({interpolate {test({interpolate x: {x}})} and {test({interpolate y: {y}})} together});
write_line("interpolate {test("interpolate x: {x}")} and {test("interpolate y: {y}")} together");
si

8 changes: 4 additions & 4 deletions integration-tests/execution/string-interpolation-4/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ entry() is
let x = 10;
let y = 20;

write_line({interpolate {x+y} and {x-y} together});
write_line("interpolate {x+y} and {x-y} together");

write_line({{x+x} at the beginning and {y-y} in the middle});
write_line("{x+x} at the beginning and {y-y} in the middle");

write_line({now {x+y+x} in the middle and end with {x + x + y}});
write_line("now {x+y+x} in the middle and end with {x + x + y}");

write_line({{x + 3}{x - y + 5}});
write_line("{x + 3}{x - y + 5}");
si

Original file line number Diff line number Diff line change
@@ -1 +1 @@
test.ghul: 6,5..7,1: error: newline in interpolation
test.ghul: 6,5..7,1: error: newline in string literal
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ entry() is
let x = 10;
let y = 20;

{interpolate
"interpolate
si

Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
test.ghul: 7,19..8,1: error: in primary expression: expected (, [, cast, char literal, false, float literal, identifier, if, int literal, isa, new, null, self, string literal, super, true, typeof or { but found cancel string
test.ghul: 7,19..8,1: error: in primary expression: expected (, [, cast, char literal, false, float literal, identifier, if, int literal, isa, new, null, self, string literal, super, true, typeof or { but found cancel string
test.ghul: 7,19..8,1: error: newline in interpolation
test.ghul: 7,19..8,1: error: syntax error: expected ; but found cancel string
test.ghul: 7,19..8,1: error: newline in string literal
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ entry() is
let y = 20;

// FIXME we need better error recovery here
{interpolate {}
"interpolate {}
si

4 changes: 2 additions & 2 deletions integration-tests/parse/string-brace-escaping/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ entry() is
let x = 10;
let y = 20;

"{{ { { } }}}";
"{{ {{ {{ }} }} }}";

"{{{{ { } {} {}} {{{ }} { { } }}}}}";
"{{{{ {{ }} {{ {{ {{ }} {{ }} {{ {{ }}}}";
si

2 changes: 1 addition & 1 deletion integration-tests/parse/string-interpolation-1/test.ghul
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
entry() is
{this is a plain string literal};
"this is a plain string literal";
si
8 changes: 4 additions & 4 deletions integration-tests/parse/string-interpolation-2/test.ghul
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
entry() is
let x = 10;
let y = 20;
{interpolate {x} and {y} together};
"interpolate {x} and {y} together";

{{x} at the beginning and {y} in the middle};
"{x} at the beginning and {y} in the middle";

{now {x} in the middle and end with {y}};
"now {x} in the {{ middle }} and {{ end with {y}";

{{x}{y}};
"{x}{y}";
si
8 changes: 4 additions & 4 deletions integration-tests/parse/string-interpolation-3/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ entry() is
let x = 10;
let y = 20;

{interpolate {10} and {20} together};
"interpolate {"" + 10 + "hello"} and {"{20}"} together";

{{10} at the beginning and {20} in the middle};
"{["{1 * 10}"]} at the beginning and {"//{20 + 20 + (10 / 3)}//"} in the middle";

{now {10} in the middle and end with {20}};
"now {10} in the middle and end with {20}";

{{10}{20}};
"+++{"---{10}---{20}---"}+++";
si
8 changes: 4 additions & 4 deletions integration-tests/parse/string-interpolation-4/test.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ entry() is
let x = 10;
let y = 20;

{interpolate {x+y} and {x/y} together};
"interpolate {x+y} and {x/y} together";

{{x*y} at the beginning and {x-y} in the middle};
"{x*y} at the beginning and {x-y} in the middle";

{now {x+(y/x)} in the middle and end with {x + x + y}};
"now {x+(y/x)} in the middle and end with {x + x + y}";

{{x / 3}{x * y}};
"{x / 3}{x * y}";
si

2 changes: 1 addition & 1 deletion project-tests/runtime-pipes/common.ghul
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Tests is
iv[T](index: int, value: T) -> INDEXED_VALUE[T] => new INDEXED_VALUE[T](index, value);

expect_equal[T](a: T, b: T) is
write_line("expect_equal: {0} == {1}", a, b);
write_line("expect_equal: {{0}} == {{1}}", a, b);
si

assert_are_equal[T](expected: Iterable[T], actual: Pipe[T]) is
Expand Down
Loading

0 comments on commit 33c0e19

Please sign in to comment.