Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update spec to split out partials and "macros"
Summary: Partial applications today have some glaring problems: 1. Must be in a new file even if they are used once. 2. Assume the context of the call-site, making it impossible to discern what the *inputs* of a partial are supposed to be. Partial blocks (as currently specified) were introduced to address these issues but it was never implemented (as it was under specified and its value was unclear at the time). **This diff attempts to specify the feature such that it can actually be implemented** (later in the stack). --- ## 1. Current `partial` are renamed to `macro`. Why? The main reason to split out the names of existing partial applications (bad) and what is proposed here (better) is simple: **they are very different semantically and sharing a name makes it very confusing to discuss**. I've decided that `partial` (what most people are familiar with) should be the "good" feature and make use of the `partial` keyword in the language. The older "bad" feature gets the name `macro` because: - It somewhat resembles macros from the C preprocessor, especially its lack of input / output hygiene. One other big difference is that (as of the current proposal), `partial`s are used *within one file* while macros are *across files*. This can change in the future, but it's another reason to give them different names. --- ## 2. Why `{{#partial}}` instead of `{{> }}` like what we have already? 1. `macro` names are file names (`path-component`) which is *not* an `identifier` like the rest of Whisker. This is for legacy reasons and ideally we should try to move away from it. 2. `{{#partial}}` is more explicit and matches the definition of *statement* that we have today. 3. In the current dichotomy of `path-component` vs. `identifier`, it would be a mess to specify named arguments syntax that we want. **Notably, `path-component` and `identifier` are ambiguous with each other.** --- ## 3. Why `{{#let partial}}` and `{{#partial}}`? `{{#let}}` is an existing mechanism for binding names in Whisker so `{{#let partial}}` seems like a natural extension. Note that `partial` is a keyword (not allowed an identifier) so it does not conflict with existing syntax. `{{#let partial}}` and `{{#partial}}` clearly show that these are coupled language features. --- ## 4. Why are `{{#let partial}}` blocks limited to be at the top of files? This limitation makes name resolution *much* *much* simpler. One of the patterns we're trying to solve is the use of recursive and mutually recursive partials (I've noticed their use in C++, Python, and JSON codegen already). This means that partials might need to refer to names that are defined *after* it. ``` {{#let partial mutual-1 as |...|}} ... {{#partial mutual-2 ...}} {{/let partial}} {{#let partial mutual-2 as |...|}} ... {{#partial mutual-1 ...}} {{/let partial}} ``` By keeping everything in one scope (the top of the file), we don't have to specify complicated name resolution rules etc. Every file "just" has a simple `map<identifier, partial>` and that's it! We can relax this restriction in the future if needed. For now I think this solves the problems we need it for. --- Reviewed By: rmakheja Differential Revision: D68424875 fbshipit-source-id: 686a7fb523fb5408e784ab358ad1e50e5374deeb
- Loading branch information