This latest refactor adds "extractor macros" in place of the
very-confusing-even-to-the-DSL-author reverse-rules-as-extractors
concept. It was beautifully symmetric but also just too mind-bending to
be practical.
It also adds argument polarity to external extractors. This is inspired
by Prolog's similar notion (see e.g. the "+x" vs. "-x" argument notation
in library documentation) where the unification-based semantics allow
for bidirectional flow through arguments. We don't want polymorphism
or dynamism w.r.t. directions/polarities here; the polarities are
static; but it is useful to be able to feed values *into* an extractor
(aside from the one value being extracted). Semantically this still
correlates to a term-rewriting/value-equivalence world since we can
still translate all of this to a list of equality constraints.
To make that work, this change also adds expressions into patterns,
specifically only for extractor "input" args. This required quite a bit
of internal refactoring but is only a small addition to the language
semantics.
I plan to build out the little instruction-selector sketch further but
the one that is here (in `test3.isle`) is starting to get interesting
already with the current DSL semantics.
See long block comment in codegen.rs. In brief, I think we actually want
to compile to a trie with priority-intervals, a sort of hybrid of a
priority tree and a trie representing decisions keyed on match-ops
(PatternInsts).
The reasons are:
1. The lexicographic ordering that is fundamental to the FSM-building in
the Peepmatic view of the problem is sort of fundamentally limited
w.r.t. our notion of rule priorities. See the example in the block
comment.
2. While the FSM is nice for interpreter-based execution, when compiling
to a language with structured control flow, what we really want is a
tree; otherwise, if we want to form DAGs to share substructure, we
need something like a "diamond-recovery" algorithm that finds common
suffixes of *input match-op sequences*, and then we need to
incorporate something like phi-nodes in order to allow captures from
either side of the diamond to be used.
3. One of the main advantages of the automaton/transducer approach,
namely sharing suffixes of the *output* sequence (emitting partial
output at each state transition), is unfortunately not applicable if
we allow the overall function to be partial. Otherwise, there is
always the possibility that we fail at the last match op, so we
cannot allow any external constructors to be called until we reach
the final state anyway.
4. Pragmatically, I found I was having to significantly edit the
peepmatic_automata implementation to adapt to this use-case
(compilation to Rust), and it seemed more practical to design the
data structure we want than to try to shoehorn the existing thing
into the new problem.
WIP, hopefully working soon.
This opcode was removed as part of the old-backend cleanup in #3446.
While this opcode will definitely go away eventually, it is
unfortunately still used today in Lucet (as we just discovered while
working to upgrade Lucet's pinned Cranelift version). Lucet is
deprecated and slated to eventually be completely sunset in favor of
Wasmtime; but until that happens, we need to keep this opcode.
This should be faster by avoiding matching on InstructionData to get the
Opcode, then on Opcode and then finally on the InstructionData again to
get the arguments
With the old backends, this would log the lowered+legalized clif, but the log is
useles now with the new backends. Logging the disasm is the new moral
equivalent.
* Adjust dependency directives between crates
This commit is a preparation for the release process for Wasmtime. The
specific changes here are to delineate which crates are "public", and
all version requirements on non-public crates will now be done with
`=A.B.C` version requirements instead of today's `A.B.C` version
requirements.
The purpose for doing this is to assist with patch releases that might
happen in the future. Patch releases of wasmtime are already required to
not break the APIs of "public" crates, but no such guarantee is given
about "internal" crates. This means that a patch release runs the risk,
for example, of breaking an internal API. In doing so though we would
also need to release a new major version of the internal crate, but we
wouldn't have a great hole in the number scheme of major versions to do
so. By using `=A.B.C` requirements for internal crates it means we can
safely ignore strict semver-compatibility between releases of internal
crates for patch releases, since the only consumers of the crate will be
the corresponding patch release of the `wasmtime` crate itself (or other
public crates).
The `publish.rs` script has been updated with a check to verify that
dependencies on internal crates are all specified with an `=`
dependency, and dependnecies on all public crates are without a `=`
dependency. This will hopefully make it so we don't have to worry about
what to use where, we just let CI tell us what to do. Using this
modification all version dependency declarations have been updated.
Note that some crates were adjusted to simply remove their `version`
requirement in cases such as the crate wasn't published anyway (`publish
= false` was specified) or it's in the `dev-dependencies` section which
doesn't need version specifiers for path dependencies.
* Switch to normal sever deps for cranelift dependencies
These crates will now all be considered "public" where in patch releases
they will be guaranteed to not have breaking changes.
This eagerly evaluates the `format!` and produces a `String` with a heap
allocation, regardless whether `foo` is `Some`/`Ok` or `None`/`Err`. Using
`foo.unwrap_or_else(|| panic!(...))` makes it so that the error message
formatting is only evaluated if `foo` is `None`/`Err`.