PEP 750: Tag Strings For Writing Domain-Specific Languages

We left out some normative scheme from this PEP to state what the specific DSL is, and its dialect.

But it clearly should not be hardcoded, whether it’s to an r prefix or to a html function. This discussion on the pre PEP was helpful, Tag string use-case: language marker for syntax highlight · Issue #18 · jimbaker/tagstr · GitHub, including the idea of using Annotated to make the connection to some registry, such as for GitHub’s Linguist. I imagine there could be more than one registry out there, although GitHub’s looks comprehensive for agreeing on a specific common name.

Let’s sketch out some possiblities with the Template approach:

class HTML(Protocol):
  # some basic things we would expect here

HTML = Annotated[HTML, {
  'language': 'html',
  'registry': 'https://github.com/github-linguist/linguist/blob/master/lib/linguist/languages.yml'
})

def html(template: Template[HTML]) -> HTML:
  # parses the provided template into an AST
  # contextually fills in any interpolations using the AST
  # builds the desired object of type HTML, such as a DOM repr

Now let’s try the following:

some_html: Template[HTML] = t'<li>{name}</li>'

So this looks good - we can infer the expected DSL from the type here. Syntax highlighting can be provided, as well as syntax checking of the target DSL. It also recursively composes to any expressions in the template. Same with

html(t'<li>{name}</li>')

If it were actually incorrect syntax, this can be highlighted by the IDE or linter. Of course the only time we know that it’s actually an HTML object is when it’s returned - Template[HTML] simply is used by html to build HTML objects.

@steve.dower I’m not certain if this addresses the concerns here, but hopefully it’s getting closer. I could still see some advantages of the original tag string approach - we know it’s html when built with it (or else it raise some exception). Separating in this two parts, with a t-string and a function that consumes the resulting further specifed template (Template[HTML]) should work here.

I have of course left out a lot of details in this sketch, but hopefully it can support a good developer experience.

4 Likes