Commit Graph

86 Commits (1cf54887565cd46dccc97b98ee0b9696235e1a52)

Author SHA1 Message Date
Mike Gerwitz 1cf5488756 tamer: asg::air::EnvScopeKind::Pool: Remove (Visible is sufficient)
At least, I think so.

See previous commit for more information, and the commit that follows for
actually using it at Root.

DEV-13146
2023-05-16 23:28:45 -04:00
Mike Gerwitz 33f34bf244 tamer: asg: Initial identifier scoping
Okay, this is finally distilling into something fairly simple and
reasonable, but I'm not quite there yet.

In particular, the responsibility is simply between `Asg` (as the owner of
the index) and `AirAggregateCtx` (as the owner of the stack frames from
which environments and scope are derived).  This was inevitable and I was
waiting for it, but now I have a good idea of how to clean it up and
proceed.

This also doesn't index in root yet (`active_rooting_oi` is still `None` for
`Root`), and I think I may remove `Pool` and just make it `Visible` at that
point, since it won't be going any further anyway.  I don't think the
distinction is meaningful and will just complicate implementations.

The tests also need some more cleanup---the assertions ideally would live in
independent tests, and the assertion failure is in a function call rather
than the test (function) itself, so requires a Rust backtrace to locate the
line number of (unless you look at the failure data).

So I suppose this is more of a mental synchronization point than
anything.  Nothing's broken, though.

DEV-13162
2023-05-16 14:58:21 -04:00
Mike Gerwitz 9fb2169a06 tamer: asg::air: Begin to introduce explicit scope testing
There's a lot of documentation on this in the commit itself, but this stems
from

  a) frustration with trying to understand how the system needs to operate
     with all of the objects involved; and
  b) recognizing that if I'm having difficulty, then others reading the
     system later on (including myself) and possibly looking to improve upon
     it are going to have a whole lot of trouble.

Identifier scope is something I've been mulling over for years, and more
formally for the past couple of months.  This finally begins to formalize
that, out of frustration with package imports.  But it will be a weight
lifted off of me as well, with issues of scope always looming.

This demonstrates a declarative means of testing for scope by scanning the
entire graph in tests to determine where an identifier has been
scoped.  Since no such scoping has been implemented yet, the tests
demonstrate how they will look, but otherwise just test for current
behavior.  There is more existing behavior to check, and further there will
be _references_ to check, as they'll also leave a trail of scope indexing
behind as part of the resolution process.

See the documentation introduced by this commit for more information on
that part of this commit.

Introducing the graph scanning, with the ASG's static assurances, required
more lowering of dynamic types into the static types required by the
API.  This was itself a confusing challenge that, while not all that bad in
retrospect, was something that I initially had some trouble with.  The
documentation includes clarifying remarks that hopefully make it all
understandable.

DEV-13162
2023-05-12 14:07:29 -04:00
Mike Gerwitz dd6a6dd196 tamer: asg::air::ir::AirPkg::PkgStart: Require name
This requires the name as part of the package definition, which in turn
removes a state (and all the combinations resulting from it) from
AirAggregate, which results in significant complexity reduction for a very
complex part of the system.

Pushing this complexity outward results in a reduction of overall
complexity, and obviates the question of where NIR will receive a generated
name.

DEV-13162
2023-05-10 13:57:45 -04:00
Mike Gerwitz 4510de38ed tamer: asg::air::pkg: Extract AirPkgAggregate from AirAggregate
This is something I've wanted to do for some time, but the system is
becoming hard enough to reason about (with some attempted future changes)
that I require the consistency afforded by this change.

It's not entirely done---as noted by the TODO for `UnnamedPkg`---but it's
close, and then `AirAggregate` will just be a delegating superstate, like
`ele_parse!`.

Importantly, this also puts a package parser on the stack, which will work
better with the stack-based scoping system being developed.  It will also
make it easier to fall back to a base case that I had really wanted to
avoid, and will have more information on in the future: root indexing for a
shared global environment for package-level identifiers.  (Imports are still
package-scoped, but only in appearance, by contributing to the global
environment of the compilation unit during import.  Well, it doesn't do that
yet.  The XSLT compiler works in that way.)

DEV-13162
2023-05-10 13:57:39 -04:00
Mike Gerwitz 5f275fb801 tamer: asg::air::air: Eliminate todo! for unexpected AirIdent
I had apparently forgotten about this, because I didn't benefit from the
exhaustiveness check; this needs to be eliminated so that this doesn't
happen again, and to provide a proper non-panicking error.

DEV-13162
2023-05-09 12:35:06 -04:00
Mike Gerwitz 4ec4857360 Revert "tamer: asg::air::ir::AirBind::RefIdent: New optional canonical name"
This reverts commit da7fe96254e425bc7b75f8cf454465b71e27e372.

I'm a fool---this would be pursuant to a future plan that removes AirIdent
opaque tokens.  But for now, I need it on IdentDecl and others, which
currently has a `Source` (that I want to go away, as just mentioned), which
contains the same information.

So maybe more to come on this...

DEV-13162
2023-05-09 12:35:06 -04:00
Mike Gerwitz 572337505c tamer: asg::air::ir::AirBind::RefIdent: New optional canonical name
This allows for a canonical package name to be optionally provided to
explicitly resolve a reference against, avoiding a lexical lookup.

This change doesn't actually utilize this new value yet; it just
retains BC.  The new argument will be used for the linker, since it already
knows the package that defined an identifier while reading the object file's
symbol table.  It will also be used by tamec for the same purposes while
processing package imports.

DEV-13162

-- squashed with --

tamer: asg::air::ir::RefIdent: CanonicalName=SPair

The use of CanonicalName created an asymmetry between RefIdent and
BindIdent.  The hope was to move CanonicalName instantiation outside of AIR
and into NIR, but doing so would be confusing and awkward without doing
something with BindIdent.

I don't have the time to deal with that for now, so let's observe how the
system continues to evolve and see whether hoisting it out makes sense in the
end.  For now, this works just fine and I need to move on with the actual
goal of finishing package imports so that I can expand templates.

DEV-13162
2023-05-09 12:35:06 -04:00
Mike Gerwitz 48bcb0cdab tamer: asg: Integrate package CanonicalName
This change requires every package to have a canonical name, and performs
namespec canonicalization on imports.

Since all package names are canonicalized, this opens the door to being able
to index package names at import, allowing the object to be shared on the
graph and properly reference a package after it has been resolved.

Note that the system tests' canonicalization is relative to the hard-coded
`/TODO` presently; that will change in the near future once `tamec`
generates names from the provided path.

DEV-13162
2023-05-05 10:26:58 -04:00
Mike Gerwitz 670c5d3a5d tamer: asg::graph: Require name for non-imports
NOTE: This temporarily breaks `tameld`.  It is fixed in a future commit when
names are bound.  This was an oversight when breaking apart changes into
separate commits, because the linker does not yet have system tests like
tamec does.

This is preparing for a full transition to requiring a canonical package
name.  The previous `Unnamed` variant has been removed and `AirAggregate`
will provide a default `WS_EMPTY` name, as `Pkg` had done before.

The intent of this change is to allow for consulting the index before a
new `Pkg` object is created on the graph, but we're not quite ready for that
yet.

Well, that's not entirely true---the linker can be ready for that.  But the
compiler needs to canonicalize import paths relative to the active package
canonical name, which it can't even do yet because tamec isn't generating a
name.

So maybe the linker will be first; it's useful to have that in a separate
commit anyway to emphasize the change.

DEV-13162
2023-05-05 10:24:47 -04:00
Mike Gerwitz 7cfe6a6f8d tamer: asg::graph: Index Root->Pkg with canonical names
The previous commit introduced canonical names, and this uses them to index.

The next step will be to utilize those names to look up packages on
definition rather than creating a new package node, so that references to
yet-to-be-defined (or yet-to-be-imported) packages can be resolved on the
graph.

DEV-13162
2023-05-02 16:15:07 -04:00
Mike Gerwitz 92c9c9ba2f tamer: asg: Introduce package canonical name concept
This is already a concept in the XSLT-based compiler, where each package has
a `package/@name` generated from its path.  The same will happen with tamec.

Before we can load packages into the graph, we need canonical identifiers so
that they can be indexed.  The next commit will handle indexing using this
information.

DEV-13162
2023-05-02 16:08:39 -04:00
Mike Gerwitz 48d9bca3b7 tamer: obj::xmlo: Add Pkg nodes for identifiers
This modifies the xmlo reader, xmlo->AIR lowering, and AIR->ASG to introduce
a package for identifiers.  It does not yet, however, add edges from the
package to the identifier.

Once edges are added, the DFS will change in undesirable ways, which will
require a new implementation.  This is desirable to decouple from Petgraph
anyway, and then will be able to restore the prior single-pass sort+cycle
check.

That will also encapsulate visiting behavior within the `asg::graph` module
and, in turn, allow encapsulating `Asg.graph` finally.

DEV-13162
2023-04-21 16:24:11 -04:00
Mike Gerwitz 34dad122fd tamer: asg::air::test: Remove `Air` and `Parsed` enum prefixes from variants
Same spirit as previous commits.  This is committed separately from the
changes that follow to eliminate its distraction.

DEv-13162
2023-04-21 15:37:27 -04:00
Mike Gerwitz f183600c3a tamer: asg: Move Ident-specific methods off of Asg
Historically, the ASG was better described as a "dependency graph",
containing only identifiers (which are simply called "symbols" in the
XSLT-based compiler).  Consequently, it was appropriate for the graph to
have operations specific to identifiers.  (Indeed, that's the only type of
object the graph supported.)

Much has changed since then.  This cleans things up, and makes parenting
identifiers to root an _explicit_ operation.  This will make it easier to
move forward with handling of scope, and importing identifiers into
packages, and removing `Source`, and so on.

DEV-13162
2023-04-19 12:40:35 -04:00
Mike Gerwitz 778e90c81d tamer: asg::air: Index package identifiers on `Pkg` rather than `Root`
I've been torturing myself trying to figure out how I want to generalize
indexing, lookups, and value numbering in a way that is appropriate for this
project (that is, not over-engineered relative to my needs).

Before I can do much of anything, though, I need to stop having indexing
only as a `Root` thing (previously it wasn't even tied to `Root`).  This
makes that change for tamec, but temporarily removes scoping concerns until
I can add more specific types of indexing.

Not only does this allow cleaning up some `Ident`-specific stuff from `Asg`,
but the cleanup also helps to show that portions of the system aren't still
using Root-based globals.

The linker (`tameld`) still uses the old `global` methods for now; those
will eventually go away, but this needs to change to unify both tamec and
tameld once we get to imports as part of the compiler.

DEV-13162
2023-04-19 12:40:34 -04:00
Mike Gerwitz 590c4b7b06 tamer: NIR->xmli: Support template/@desc
This is needed to then support `@desc` for shorthand desugaring; it's
required by the XSLT-based compiler (and will eventually be required by
TAMER too).

DEV-13708
2023-04-12 15:53:16 -04:00
Mike Gerwitz e88800af42 tamer: asg: Basic `Doc::Text` support
This supports arbitrary documentation as sibling text (mixed content, in XML
terms).  The motivation behind this change is to permit existing system
tests to succeed when `Todo | TodoAttr` are both rejected, rather than
having to ignore this.

TAME has always had a philosophy of literate documentation, however it was
never fully realized.  This just maintains the status quo; the text is
unstructured, and maybe will be parsed in the future.

Unfortunately, this does _not_ include the output in the `xmli` file or the
system tests.  The reason has nothing to do with TAMER---`xmllint` does not
format the output when there is mixed content, it seems, and I need to move
on for now; I'll consider my options in the future.  But, it's available on
the graph and ready to go.

DEV-13708
2023-04-12 12:04:12 -04:00
Mike Gerwitz 9cb6195046 tamer: asg: Add basic Doc support (for @desc)
This introduces a new `Doc` object that can be owned by `Expr` (only atm)
and contain what it describes as a concise independent clause.  This
construction is not enforced, and is only really obvious today via the
Summary Pages.

There's a lot of latent and unrealized potential in TAME's documentation
philosophy that was never realized, so this will certainly evolve over
time.  But for now, the primary purpose was to get `@desc` working on things
like classifications so that `xmli` output can compile for certain
packages.

DEV-13708
2023-04-12 11:59:48 -04:00
Mike Gerwitz f4653790da tamer: NIR->xmli: Represent package imports
This doesn't do the actual hard work yet of resolving and loading a package,
but it does place it on the graph and re-derive it into the xmli output.

DEV-13708
2023-04-07 09:44:16 -04:00
Mike Gerwitz c0e5b1d750 tamer: asg::air: Template application within expressions
This recognizes template application within expressions.  Since expressions
can occur within templates, this can occur arbitrarily deeply.

And with that, we have the core of the template system represented on the
graph.  Of course, there are some glaring scoping issues to be resolved, but
those aren't unique to template application.

DEV-13708
2023-04-05 15:49:25 -04:00
Mike Gerwitz daa8c6967b tamer: asg: Initial nested template supported
I had hoped this would be considerably easier to implement, but there are
some confounding factors.

First of all: this accomplishes the initial task of getting nested template
applications and definitions re-output in the `xmli` file.  But to do so
successfully, some assumptions had to be made.

The primary issue is that of scope.  The old (XSLT-based) TAME relied on the
output JS to handle lexical scope for it at runtime in most situations.  In
the case of the template system, when scoping/shadowing were needed, complex
and buggy XPaths were used to make a best effort.  The equivalent here would
be a graph traversal, which is not ideal.

I had begun going down the rabbit hole of formalizing lexical scope for
TAMER with environments, but I want to get this committed and working first;
I've been holding onto this and breaking off changes for some time now.

DEV-13708
2023-04-05 15:46:44 -04:00
Mike Gerwitz 6d35e8776c tamer: asg::air: InvalidExpansionContext in place of TODO
There are no such invalid expansion contexts yet, but this gets rid of the
final remaining TODO from introducing the stack.  With the existing feature
set, at least.

DEV-13708
2023-03-31 14:23:26 -04:00
Mike Gerwitz e3d60750a9 tamer: asg::air: Errors for rooting_ci() TODOs
This eliminates the TODOs that existed when looking for an OI for rooting an
identifier.

The change to `rooting_ci` is ridiculous, but I want to get other things
done before I jump down the rabbit hole of generalizing that (indexing local
identifiers).  Though I have an approach in mind.

DEV-13708
2023-03-31 13:57:11 -04:00
Mike Gerwitz 558f1c96b1 tamer: asg::air: Extra AirExpr parsing from AirTplAggregate
This has AirAggregate preempt Expr parsing in the same way as templates,
rather than having `AirTplAggregate` concern itself with expression
tokens.  This continues to simplify `AirTplAggregate`, which was getting
quite complex not too long ago.

A pattern is now emerging for the call/ret convention for preemption.  That
was intentional, but it's nice to see it manifest so obviously before I
abstract it away.

DEV-13708
2023-03-30 15:44:14 -04:00
Mike Gerwitz f29e3cfce1 tamer: asg::air: Use StateStack
This was extracted from xir::parse::ele in previous commits.  The
conventions help to ensure that pushing and returns are being performed
correctly.  The abstraction will continue to evolve.

This ends up using `Ready` as the dead state.  I need to determine if this
is ideal, and if so, maybe just use `Default`, otherwise yield an error.

DEV-13708
2023-03-30 15:44:14 -04:00
Mike Gerwitz d091103983 tamer: asg::air::tpl: Remove Expr delegation (move to parent)
`AirAggregate` now handles all delegation to `AirExprAggregate`.  This is
possible because `AirAggregate` is now the superstate for each of these
parsers, so `AirTplAggregate` is able to transition to a state that is not
its own.

This does not go so far as reaching the ultimate objective---having nested
template support---even though it'd be fairly simple to do now; there's
going to be a number of interesting consequences to these changes, and a bit
of cleanup is still needed, and I want tests observing this functionality to
accompany those changes.  That is: let's keep this a refactoring, to the
extent that it's possible.

Things are getting much easier to understand now, and much cleaner.

DEV-13708
2023-03-30 09:26:11 -04:00
Mike Gerwitz 15fd2de437 tamer: asg::air::expr: Eliminate RootStrategy
I love deleting code I just wrote...

This doesn't solve the underlying problems with identifiers, but it does at
least lift it into the `AirAggregateCtx`, allowing `AirExprAggregate` to be
even further simplified.  Now the `From` implementation is not specialized
and we can readily convert to a SuperState.

There's still a lot of TODOs here, though.  And some of them will
unfortunately require runtime checks where there was previously a
compile-time check.  But that's okay in a lot of the cases, because the
empty behavior will replace existing error checks.

DEV-13708
2023-03-29 13:49:05 -04:00
Mike Gerwitz 26ddb2ae9d tamer: asg::air::expr: Remove RootStrategy::hold_dangling
Whether or not dangling expressions are permitted is now based solely off of
the stack context, which is also much more intuitive.

`RootStrategy` now only does one thing, and the existing comments describe
why it exists despite that one thing seeming very similar.

`RootStrategy` further alludes to how `ExprStack` could also be
eliminated, should it be worth doing so.  It is a tad redundant now with the
new stack.

DEV-13708
2023-03-29 13:02:01 -04:00
Mike Gerwitz 525adb8a6c tamer: asg::air: Eliminate parent context from AirExprAggregate
This does the same thing to `AirExprAggregate` that was previously done for
`AirAggregate`, taking all parent context from the stack.

This results in a fairly significant simplification of the code, which is
nice, and it makes the `RootStrategy` obviously obsolete in the dangling
case, which will result in more refactoring to simplify it even more.

I regret not taking this route to begin with, but not only was I hoping I
wouldn't need to, but I was still deriving the graph structure and wasn't
sure how this would eventually turn out.  These commits serve as a proof of
necessity.  Or, at least, concrete rationale.

It's worth noting that this also introduces `From` implementations for
`AirAggregate` and the child parsers, and then uses _that_ to push context
from the `AirTplAggregate` parser.  This means that we're just about ready
for it to serve as a superstate.  But there is still a specialization of
`AirExprAggregate` in that `From` impl, which must be removed.

DEV-13708
2023-03-29 13:02:00 -04:00
Mike Gerwitz 755c91e04a tamer: asg::air: Merge AirStack into AirAggregateCtx
Having an extra layer of abstraction was inconvenient, and unnecessary.

DEV-13708
2023-03-29 12:58:36 -04:00
Mike Gerwitz 1ef1290ee9 tamer: asg::air: Begin to derive context from stack
This begins to introduce `AirStack` and starts to migrate context away from
the individual `ParseState`s onto the stack.

I should have started to commit earlier; this is getting a bit large and
makes it hard to follow what I'm doing so, hopefully stopping a little bit
short will allow the following commit to show that.

This is a work-in-progress change.  All tests pass, but the refactoring is
incomplete.  The `AirStack` abstraction is _also_ incomplete and will have
better, more domain-specific operations that make it harder to mess up
pairing pushes with pops.

The purpose of doing this is to allow `AirAggregate` to serve exclusively as
a sum state, which can then become a SuperState, much like `ele_parse!`'s
approach.

The _end_ goal of all of this is arbitrary template nesting.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz 2ae33a1dfa tamer: asg::graph::object: ObjectIndexTo and ObjectIndexRelTo
The graph's ontology is defined in the direction of the edge: from OA
to OB.  This is enforced by the type system to ensure that no code path is
able to generate an invalid graph.

But that also makes it very difficult to work with a generic source to a
specific target.

This introduces a `ObjectIndexRelTo` trait that says whether `Self` is able
to be related to some `ObjectKind` `OB`, implements it for `ObjectIndex
where ObjectRelTo<OB>`, and introduces a new semi-opaque type
`ObjectIndexTo` that allows for the source `ObjectIndex` to be generic.

This then redefines some existing graph primitives in terms of
`ObjectIndexRelTo`, in particular creating edges, so that `ObjectIndex` can
be used as today, and the new `ObjectIndexTo` can be used in the same way
with the same API, without violating the graph ontology.

This will be used by `AirAggregate` to create dynamic targets for rooting
and splicing/expansion.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz b1ce7aaf29 tamer: asg::air: AirAggregateCtx: New AirAggregate::Context
Future changes to `AirAggregate` are going to require additional context (a
stack, specifically), but the `Context` is currently utilized
by `Asg`.  This introduces a layer of abstraction that will allow us to add
the stack.

Alongside these changes, `ParseState` has been augmented with a `PubContext`
type that is utilized on public APIs, both maintaining BC with existing code
and keeping these implementation details encapsulated.

This does make a bit of a mess of the internal implementation, though, with
`asg_mut()` sprinkled about, so maybe the next commit can clean that up a
bit.  EDIT: After adding `AsMut` to a bunch of asg::graph::object::*
methods, I decided against it, because it messes with the inferred
ownership, requiring explicit borrows via `as_mut()` where they were not
required before.  I think the existing code is easier to reason about than
what would otherwise result from having `mut asg: impl AsMut<Asg>`
everwhere.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz fc569f7551 tamer: asg::air::tpl: Distinct, generalized root and targets
Previously, `AirTplAggregate` worked only in a `Pkg` context, being able to
root `Tpl` `Ident`s in `Pkg` and expand only into `Pkg`.  This still does
the same, but generalizes to allow for different roots and expansion
targets.

This will be utilized to parse nested templates.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz 9c0e20e58c tamer: asg: Shorthand and long-form template arguments
This applies to template application only; there's still some work to do for
template parameters in definitions (well, for deriving them in `xmli` at
least).  And, as you can see, there's still a lot of TODO items here.

I ended up backtracking on tree edges to Meta, and even on cross edges to
Meta, because it complicated xmli derivation with no benefit right now;
maybe a cross edge will be re-added in the future, but I need to move on and
see where this takes me.

But, it works.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz fcd25d581c tamer: asg::air::expr: Do not cache (globally) identifiers created with StoreDangling
I'm not happy with this implementation.  The linear search is undesirable,
but not too bad (and maybe wouldn't even be worth caching, if this were the
whole story), but we _also_ need to prevent duplicate identifiers.  We are
not going to want to perform a linear search of a linked list (effectively)
every time we add an identifier to check for uniqueness, so I think the
caching is going to have to be generalized very shortly anyway.

As it stands now, a duplicate identifier would cause an error at expansion
time.  That's not what we want, but it's not terrible, because you can have
that same problem in normal circumstances without local conflicts.

But this'll be used for metavariables as well, where we absolutely _do_ want
to fail at template definition time.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz 1c7df894ea tamer: asg::graph: *lookup{=>_global}*
Identifier lookups, as done using the graph methods today, look up from a
cache representing the global environment.

Templates must not contribute to this environment until expansion.  Further,
metavariables will not be present in this environment.  To avoid confusion
and help obviate accidental contributions to this environment, the methods
have been renamed.  This will also allow for the creation of more general
methods down the line.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz 25121c1086 tamer: asg::air: Test formatting (token nesting)
This makes the tests quite a bit easier to understand visually.  I've been
doing this with all new tests but had to go back to some old ones, and still
have more to go back to.  Baby steps.

DEV-13708
2023-03-29 12:58:35 -04:00
Mike Gerwitz 3e9f407527 tamer: asg::air::ir: Remove TplApply
The implementation decided upon in the previous commits have made this
unnecessary, using `RefIdent` to produce `Tpl->Ident[->Tpl]` instead.

DEV-13708
2023-03-29 12:58:34 -04:00
Mike Gerwitz 893da0ed20 tamer: asg: Dynamically determined cross edges
Previous to this commit, ontological cross edges were declared
statically.  But this doesn't fare well with the decided implementation for
template application.

The documentation details it, but we have Tpl->Ident which could mean "I
define this Ident once expanded", or it could mean "this is a reference to a
template I will be applying".  The former is a tree edge, the latter is a
cross edge, and that determination can only be made by inspecting edge data
at runtime.

It could have been resolved by introducing new Object types, but that is a
lot of work for little benefit, especially given that only (right now) the
visitor uses this information.

DEV-13708
2023-03-29 12:58:34 -04:00
Mike Gerwitz e132f108e8 tamer: asg::air: {=>diagnostic_}todo!
I forgot about my `diagnostic_todo!` macro!  The purpose was to help guide
development by obviating what comes next in test failures.

DEV-13708
2023-03-29 12:58:34 -04:00
Mike Gerwitz 9d50157f8e tamer: Very basic support for template application NIR -> xmli
This this a big change that's difficult to break up, and I don't have the
energy after it.

This introduces nullary template application, short- and long-form.  Note
that a body of the short form is a `@values@` argument, so that's not
supported yet.

This continues to formalize the idea of what "template application" and
"template expansion" mean in TAMER.  It makes a separate `TplApply`
unnecessary, because now application is simply a reference to a
template.  Expansion and application are one and the same: when a template
expands, it'll re-bind metavariables to the parent context.  So in a
template context, this amounts to application.

But applying a closed template will have nothing to bind, and so is
equivalent to expansion.  And since `Meta` objects are not valid outside of
a `Tpl` context, applying a non-closed template outside of another template
will be invalid.

So we get all of this with a single primitive (getting the "value" of a
template).

The expansion is conceptually like `,@` in Lisp, where we're splicing trees.

It's a mess in some spots, but I want to get this committed before I do a
little bit of cleanup.
2023-03-29 12:58:32 -04:00
Mike Gerwitz 03b46ebeff tamer: asg::air::tpl::TplState: Explicitly store reachability of active template
This is a small part of a larger change that I'm still working on.

DEV-13708
2023-03-16 15:08:15 -04:00
Mike Gerwitz d930b26487 tamer: asg::air::ir: Decide on TplApply and expansion
This chooses Option B, as stated would likely be the case in the previous
commit.  The reasons are practical---I intend to support partial application
if doing so is worth it, either in implementation of the compiler or the
source language.

Closed templates can be referenced using `IdentRef` to trigger
expansion---their value is what they expand into, and they are spliced into
that point in the tree, like `,@` in Lisp.  We are able to overload this
behavior because we have the necessary type information.

However, I don't want to have to generate an Ident for every single template
expansion; there are many tens of thousands of them in our production
system.  Since AIR doesn't presently have a way to deal with this situation,
I'll for now add a special token that will close and expand a template in
place; it can be replaced with two separate tokens (`TplEnd` + `Ref`, for
example) in the future if such a need arises.

Are we there yet...?

DEV-13708
2023-03-15 16:40:08 -04:00
Mike Gerwitz be81878dd7 tamer: src::asg: Scaffolding for metasyntactic variables
Also known as metavariables or template parameters.

This is a bit of a tortured excursion, trying to figure out how I want to
best represent this.  I have a number of pages of hand-written notes that
I'd like to distill over time, but the rendered graph ontology (via
`asg-ontviz`) demonstrates the broad idea.

`AirTpl::TplApply` highlights some remaining questions.  What I had _wanted_
to do is to separate the concepts of application and expansion, and support
partial application and such.  But it's going to be too much work for now,
when it isn't needed---partial application can be worked around by simply
creating new templates and duplicating params, as we do today, although that
sucks and is a maintenance issue.  But I'd rather address that head-on in
the future.

So it's looking like Option B is going to be the approach for now, with
templates being closed (as in, no free metavariables) and expanded at the
same time.  This simplifies the parser and error conditions significantly
and makes it easier to utilize anonymous templates, since it'll still be the
active context.

My intent is to get at least the graph construction sorted out---not the
actual expansion and binding yet---enough that I can use templates to
represent parts of NIR that do not have proper graph representations or
desugaring yet, so that I can spit them back out again in the `xmli` file
and incrementally handle them.  That was an option I had considered some
months ago, but didn't want to entertain it at the time because I wasn't
sure what doing so would look like; while it was an attractive approach
since it pushes existing primitives into the template system (something I've
wanted to do for years), I didn't want to potentially tank performance or
compromise the design for it after I had spent so much effort on all of this
so far.

But my efforts have yielded a system that significantly exceeds my initial
performance expectations, with a decent abstractions, and so this seems
viable.

DEV-13708
2023-03-15 16:40:07 -04:00
Mike Gerwitz 9e5958d89e tamer: asg::air::ir::Air: Open/Close => Start/End in token names
See the Air docblock for more information.  I'm introducing new tokens for
the template system, which uses the terms "free" and "closed".  I prefer
open/close for delimiters, as I've expressed elsewhere, but unfortunately it
conflicts too much (and too confusingly) with other standard terminology as
we get more into the formal side of the language.

DEV-13708
2023-03-15 10:59:25 -04:00
Mike Gerwitz 0e42788dcc tamer: asg::air: Restrict AirTplAggregate token domain to new AirTemplatable
This removes special cases, but it does complicate the parent `AirAggregate`
parser.  A pattern of delegation is forming, though abstracting it may be an
interesting challenge, given Rust's limitation on macro invocations as match
arms.  But, I think I can manage by generating the entire match using a
macro with a match-compatible syntax, augmenting where
needed...maybe.  This'll be messy.

...but if I can write the nightmare that is `ele_parse!`, I'm sure I can
manage this.  I just prefer to avoid complex macros unless I really need
them.

DEV-13708
2023-03-11 00:58:08 -05:00
Mike Gerwitz 343f5b34b3 tamer: asg::air: Template support for dangling expressions
The intent was to have a very simple implementation of `hold_dangling` and
have everything work.  But, I had a nasty surprise when the system tests
caught bug caused by some interesting depth interactions as it relates to
`xmli` and auto-closing.

I added an extra test/example in `asg::graph::visit::test` to illustrate the
situation; it was difficult to derive from the traces, but trivially obvious
once I wrote it out as an example.

With that, templates can now aggregate tokens for dangling expressions.

DEV-13708
2023-03-10 14:27:59 -05:00
Mike Gerwitz 5c60c5fd15 tamer: asg::air::tpl: Parse template body expressions
And finally we have tokens aggregated onto the ASG in the context of a
template.  I expected to arrive here much more quickly, but there was a lot
of necessary refactoring.  There's a lot more that could be done, but I need
to continue; I had wanted this done a week ago.

It is worth noting, though, that this finally achieves something I had been
wondering about since the inception of this project---how I'd represent
templates on the graph.  I think this worked out rather nicely.  It wasn't
even until a few months ago that I decided to use AIR instead of NIR for
that purpose (NIR wouldn't have worked).

And note how I didn't have to touch the program derivation at all---the
system test just works with the AIR change, because of the consistent
construction of the graph.  Beautiful.

DEV-13708
2023-03-10 14:27:59 -05:00