Skip to content

refactor: introduce TemplateProgram between AST and CompiledProgram - #388

Open
apoelstra wants to merge 8 commits into
BlockstreamResearch:masterfrom
apoelstra:2026-08/add-template-program
Open

refactor: introduce TemplateProgram between AST and CompiledProgram#388
apoelstra wants to merge 8 commits into
BlockstreamResearch:masterfrom
apoelstra:2026-08/add-template-program

Conversation

@apoelstra

Copy link
Copy Markdown
Contributor

This PR does a number of refactors ahead of introducing quoting and canonical CMRs. The goal of these changes is to rearrange compilation.

Rather than the process being

Templated AST (TemplateProgram) -> instantiated AST -> compiled program

instead it will be

Templated AST -> Templated compiled program -> compiled program

I tried to reduce churn but there are a couple renames that come with this:

  1. TemplateProgram becomes TemplateAst (and a new TemplateProgram type is introduced)
  2. WitnessNames, which is the name of the witness type for our compiled programs, becomes TemplateProgramWitness, and is expanded to track both witness names and parameters

In fact, WitnessNames is already (ab)used to store both witness names and parameters, which makes these refactors a little easier. But this appears to be a form a code reuse rather than a deliberate API choice; the current WitnessName struct is just a wrapper around Arc<str> that does not track what kind of object it's holding, and we distinguish based on what context it appears in. Because we instatiate before compiling, any remaining WitnessNames in a compiled program are definitely witness names and not parameter names. This PR changes that, so we need to extend the type.

Once these refactors are done, the actual rearranging of the instantiation step is suprisingly easy. But it will have to wait for the next PR.

This PR has no behavior changes, does not introduce any new functionality, and does not use any features of the upcoming rust-simplicity.

@apoelstra
apoelstra requested a review from delta1 as a code owner August 13, 2026 23:31
Changes the `as_inner` method to return an `&Arc` rather than an `&str`,
which makes more sense given the name, and is also useful in a couple of
places. Then

* Add `PartialEq` between the wrapper types and `str`, eliminating a ton
  of .as_inner calls entirely.
* Add a `from_ident` method which converts an `Identifier` into the type,
  which is a common operation throughout the codebase to "strongly type"
  an identifier.
* Add a `from_str` method to cover the remaining cases where we really
  do need an explicit &str
The existing code has an interesting sort of type confusion: we parse
Arguments, UnresolvedValues, and WitnessValues by means of a ParserVisitor
which calls into chumsky to parse the key.

For each of these cases, we expect an identifier, which depending on the
map, may reference either a parameter or a witness. In both cases, we
put them into the WitnessName type, which covers both but does not
distinguish between them.

To achieve this, in src/parse.rs we implement ChumskyParse on WitnessName,
by parsing an identifier and then interpreting it as a WitnessName. (We
never use this codepath when parsing actual programs; in actual programs
identifiers are just Identifiers until a later resolution stage; this
ChumsyParse impl is only used as a helper for serde-deserialization of
.args and .wit files.) (In programs, witnesses and parameters must be
prefixed with `witness::` or `param::`, and these have their own parsing
path.)

*However*, in the following commits, we will update WitnessNames so that
it distinguishes between parameters and witnesses, because we are going
to delay parameter resolution until after compilation. Once we do this,
the ChumskyParse impl for WitnessName will no longer be tenable, because
it needs to construct a WitnessName but it doesn't know whether the
identifier it's converting is supposed to be a parameter or a witness
name.

This commit simply refactors code and does not change any data
structures or behavior.
Our "template program" is really a "templated SimplicityHL AST". I'd
like to introduce a new "templated Simplicity Program" for which the
name TemplateProgram would be a better fit. So rename this out of the
way.

This commit can be reproduced with

find bitcoind-tests external-jet-lib-example src fuzz tests \
    -type f \
    \( -name '*.rs' -o -name '*.md' \) \
    -exec sed -i s/TemplateProgram/TemplateAst/g {} \;
Over the next couple commits I am going to generalize WitnessName to
cover multiple possibilities (both named witnesses and parameters, in
a new "template program" type). Start by moving stuff around, and
replacing the macro-generated accessors with hand-written ones.
We are already using this type for both parameters and witnesses. Update
the name to reflect that.

This commit is just a search-and-replace. It is hopefully easy to review
even though it's big, for that reason.
There are two purposes to this trait:

* Moves a bunch of function definitions out of macro-generated code and
  into default trait methods; this is easier to read and improves LSP
  integration
* Introduces the ident_to_key method, which will allow Arguments and
  WitnessValues to both be created from the UnresolvedValues map.
  Currently this is done using a From<HashMap> bound, but when we extend
  WitnessNames to hold parameters as well as witness names, this From
  bound won't be sufficient.

Also, change UnresolvedValues to be keyed by Identifier rather than by
WitnessName. Until we resolve the name, we don't know whether we have a
parameter name or a witness name, so until then, Identifier is the more
correct type.
After all our prep work this is fairly easy to do.
@apoelstra
apoelstra force-pushed the 2026-08/add-template-program branch 2 times, most recently from 1d0a572 to 4881f30 Compare August 13, 2026 23:45
Currently this doesn't do anything. It just adds an extra step to
compilation. The next commit will rearrange things such that
instantiation happens -after- compilation.
@apoelstra
apoelstra force-pushed the 2026-08/add-template-program branch from 4881f30 to 9942a5a Compare August 14, 2026 02:54

@stringhandler stringhandler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 9942a5a Ran cargo test locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants