paulstansifer / unseemly

Macros have types!
http://unseemly.github.io/
MIT License
131 stars 5 forks source link

Revise the implementation of splicing #40

Open paulstansifer opened 3 years ago

paulstansifer commented 3 years ago

Looking back over the splicing code, it's... deeply confusing. Its tendrils reach everywhere, and I don't really understand it. I think it might be best to try to come up with a different way of doing it from scratch.

The epicenter of the problem is, I think, heal__lwr_splices in ast_walk.rs.

The general idea of splice healing is that, during a LiteralLike walk, we encounter (via some kind of interpolation) a node that represents n of something. So, the grammar says Star(VariableReference), but you have a single thing (probably a name of some kind) representing n variable references. You need to evaluate that single thing (which might be inside, say, some new bindings, or some phase shifts), but then rebuild the EnvMBE representing those multiple things as a "real" repetition.

First step is to come up with a plan. Second step is to check that the plan is different from what we're currently doing.

If we're lucky, resolving issue #38 might open up a new and better way of doing things.

paulstansifer commented 3 years ago

Maybe part of the problem is with the language; we're writing ...[,value, >> ,[value], ]... instead of ,,,[value],,,. After all, Scheme has unquote-splicing (good ol' ,@).

This means that we can't express ...[,value, >> ,[value], + 1]... directly, but I don't think that's much of a loss in practice. Also, ...[,value, >> ,[value],]... is super-unwieldy.

paulstansifer commented 3 years ago

Actually, no, I don't think we can merge splicing and unquote. The motivating example for #38, '[Expr | .[ ...[,a, >> ,[a], : Int ]... . <something> ].]', is a case where (a) splicing without immediately unquoting is useful (probably will be very common, even), and (b) we can't solve the problem by calculating [???| ,[a], : Int] separately, because there's no nonterminal for name-followed-by-colon-followed-by-type.

paulstansifer commented 3 years ago

Maybe we could, at the dotdotdot, squirrel away an index 0 somehow, start evaluating, and, when we come to the driven interpolation, pick the indexed result from its output. The same place that holds the index could also memoize the interpolation itself so it doesn’t get reevaluated (the wrapper would, but usually that wouldn’t be a problem, I think).

Or, we could, at the dotdotdot, immediately evaluate the drivers (well, I guess they’re values already, since they have to be variable references), and then perhaps just do a syntax transformation where we copy the wrapper n times with a different index into the driven name where it’s referred to.

paulstansifer commented 3 years ago

I'd forgotten: splice healing isn't even used by ...[ ]... (it does roughly the second suggestion in the previous comment). The only place it's needed is for subtyping :::[ ]:::. But maybe we could do the same sort of thing, and eliminate splice healing altogether? It's been a while since I remembered how subtyping works.