---
# System prepended metadata

title: String templates with control flow
tags: [strings, proposal]

---

---
tags: [strings, proposal]
---

# String templates with control flow

It's nice to be able to specify embedded content with tagged string templates.

```kotlin=
html"""
<h1>${ title }</h1>
Do the things:

<ul>${ listItems }</ul>
"""
```

This works because the tag, `html` in this case, receives the literal parts and the interpolated parts:

1. Literal part `"<h1>"`
2. Interpolation `title`
3. Literal part `"</h1>\nDo the things:\n\n<ul>"`
4. Interpolation `listItems`
5. Literal part `"</ul>"`

PHP allows embedding flow control in interpolations.

```php=
<h1><?php echo($title) ?></h1>
Do the things:

<ul><?php
    foreach ($listItems as $listItem) {
        ?>
    <li><?php
            echo($listItem)
        ?></li><?php
    }
?></ul>
```

Some [JS tag libraries](https://lit.dev/docs/v1/lit-html/template-reference/#control-flow-with-javascript) have struggled with flow control.

What would we need to provide a tag with a sequence of literal parts and interpolations using regular Temper control flow?

PHP has two parts:

- transitions from template fragments to PHP code and back
- an `echo` function that emits an interpolated value.

Let's consider some hand-wavy code in the Temper style and how it might desugar to simpler constructs.

```
html"""(out);;
    <h1>${ title }$</h1>

    Do the things:

    <ul>
    ${
        for (let item of items) {
    }$    <li>${ out.emit(item) }$</li>${ 
        }
    }$
    </ul>
    """
```

This differs from our current interpolated strings in a few ways:

1. `(out);;` after the opening quotes, like a block lambda formal parameter list, gives code inside interpolations something to refer to.  Like `echo` in PHP.
2. `${` pairs with `}$` instead of with `}` which means `for (let item of items) {` is not ended by the `}` immediately following it.

How could we manipulate this to produce a series of literal text and interpolated values for the `html` tag to process?

This could transform to:

```C=
// Introduce a block to preserve
// apparent scope boundaries.
{
    // Capture the tag to preserve
    // the order of operations.
    let tag#0 = html;
    // Create an object to collect parts.
    let collector#1 = new TagPartsCollector();
    // based on (out);;
    // Let user code add interpolations
    // but not literal sections.
    let out = collector#1.interpolations;
    collector#1.literal("<h1>");
    // Maybe some convention can let
    // us recognize and auto-emit
    // "simple" interpolations.
    out.emit(title);
    
    collector#1.literal("""
        </h1>

        Do the things:

        <ul>
                        
        """);
    // Here, the tokens for
    for (let item of items) {
        collector#1.literal("\n    <li>");
        out.emit(item);
        collector#1.literal("</li>");
    }
    collector#1.literal("\n</ul>");

    // Finally, invoke the tag
    tag#0(collector#1.build())
}
```

So allowing tagged templates with embedded flow controls requires:

- a way to define a name to which code can send interpolated values, `out` in this example.  This could be defaulted à la Kotlin `it`
- a way to identify when an interpolation ends independent of flow control constructs block endings

and benefits from

- a way to identify which interpolations are "simple", which should be implicitly emitted.
  One rule of thumb could be, if there is no statement level token (`{`, `}`, `;`) outside non-statement-level brackets, nor a reference to the output channel.

but otherwise, the desugaring is fairly straightforward.

----

Problems: if `html` were a macro, it would need to do flow-sensitive analysis if it wanted to, at compile time, pick escapers based on the structure of HTML produced.  If `out` were passed into other functions that might be impossible.

Specifically providing for branching and looping operations might simplify things.

## Generic tag-based control flow

Suppose we have generic structure based on tags that map to blocks:

```
let q = 
  Bob"""
  Text.
  $<for let a of x>$
     Repeated line: $a
  $</for>$
  """
```

This might desugar to:

```
let q = Bob() { bob;;
   bob.emit("Text.");
   bob.for(let a of x) { bob2;;
      bob2.emit("Repeated line: ");
      bob2.arg(a); 
   }
}
```

Pros and cons:
 * Con: you have to recreate all the Temper control flow structures.
 * Pro: more direct control allows static analysis and optimization.
 * Pro/con: won't have the flexibility of a full language