<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Helixbassment</title>
    <description>Is this the Internet?</description>
    <link>https://helixbass.net</link>
    <atom:link href="https://helixbass.net/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>A unifying theory of visual and listening art/execution</title>
        <description>&lt;p&gt;As I’m learning Adobe Illustrator I am confident asserting a theory of
the underlying “skill set being exercised” in both visual “art” and
being good at playing music&lt;/p&gt;

&lt;p&gt;I’ve understood for years (via jazz training) that really what you’re
good at when you’re actually good at music is &lt;em&gt;your ear&lt;/em&gt; aka &lt;em&gt;listening&lt;/em&gt;.
Playing an instrument is secondary/flows from that. And voila I in fact
can play multiple instruments in a cool way because my ear is strong&lt;/p&gt;

&lt;p&gt;So really the music you make/the playing you do is an expression of what
your ear is capable of/thinks is cool. And you’re constantly improvising
against that ear. Again this is taught/well-understood in jazz training&lt;/p&gt;

&lt;p&gt;Ok so I’ll assert that it’s the same with visual arts. But with your eye
instead of your ear. So presumably then (symmetrically) it’s not really
about the mechanics of drawing/etc, it’s about having a visually stylish
eye. I’ve noticed/believed for years that people who are visually artistic
tend to have good eyesight and perhaps correspondingly cool-looking eyes&lt;/p&gt;

&lt;p&gt;Ya no sh** they probably live in a world of visual gag. And so then
“the ideas in their head” (aka their “eye”) are cooler than yours visually.
And more “precise”/”high-fidelity”&lt;/p&gt;

&lt;p&gt;So ya they probably don’t sit there violently tearing the paper attempting
to somehow all of a sudden be good at drawing when they make art. They
probably see what they’re going for clearly in their head/”eye” and then
get good-enough at expressing what they visually “see”/”judge” in whatever
visual-art medium&lt;/p&gt;

&lt;p&gt;Also if you don’t know visually artistic people tend to be good at &lt;em&gt;all&lt;/em&gt;
visual-art media&lt;/p&gt;
</description>
        <pubDate>Mon, 09 Feb 2026 00:00:00 -0500</pubDate>
        <link>https://helixbass.net//unifying-theory-visual-listening/</link>
        <guid isPermaLink="true">https://helixbass.net//unifying-theory-visual-listening/</guid>
      </item>
    
      <item>
        <title>We&apos;re all ill</title>
        <description>&lt;p&gt;This is a premise&lt;/p&gt;

&lt;p&gt;It goes hand-in-hand with the idea that
&lt;a href=&quot;/illness-recognized-as-illness&quot;&gt;illness recognized as illness tends to resolve&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We get taught frameworks that “we’re usually healthy” and that
“being sick” is just a little “dip in the road” and then we “get back to normal”
(with the help of things like medicine)&lt;/p&gt;

&lt;p&gt;Ya no&lt;/p&gt;

&lt;p&gt;All of us are quite ill&lt;/p&gt;

&lt;p&gt;You won’t be able to reason about what you’re observing as far as
people’s behavior until you recognize that&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//were-all-ill/</link>
        <guid isPermaLink="true">https://helixbass.net//were-all-ill/</guid>
      </item>
    
      <item>
        <title>Sagginess</title>
        <description>&lt;p&gt;This is very related to &lt;a href=&quot;/physically-spatial-mistake&quot;&gt;the mistake of thinking
that things are physically spatial that aren’t&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, “non-sagginess”:&lt;/p&gt;

&lt;p&gt;When someone is actually connected to reality, they get a lot
of energy from doing so. It’s characteristic of reality that
your interactions with it are very “rich” and enjoyable&lt;/p&gt;

&lt;p&gt;Whereas if a person &lt;em&gt;thinks they’re interacting with reality but in fact
are putting their energy into trying to interact with something that isn’t
actually there&lt;/em&gt;, they get no energy from doing so&lt;/p&gt;

&lt;p&gt;(because… it’s not actually there. How you can expect something that’s not
there to eg “give you energy”?)&lt;/p&gt;

&lt;p&gt;So “sagginess” describes that “outside perspective” of seeing someone think
that they’re interacting with something but in fact it’s not there, and
the physical space that they think they’re in is a stagnant pocket of
unprocessed sh**. Because that absence of them getting anything from
this supposed interaction just looks like them completely “sagging out”&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//sagginess/</link>
        <guid isPermaLink="true">https://helixbass.net//sagginess/</guid>
      </item>
    
      <item>
        <title>The mistake of thinking that things are physically spatial that aren&apos;t</title>
        <description>
&lt;p&gt;This is called a “logic flex”&lt;/p&gt;

&lt;p&gt;We have the idea that &lt;a href=&quot;/illness-recognized-as-illness&quot;&gt;illness recognized as illness tends to resolve&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And so the converse of that idea is that “illness not recognized as illness doesn’t (necessarily)
tend to resolve”&lt;/p&gt;

&lt;p&gt;We also have the idea that &lt;a href=&quot;/illness-as-the-accumulation-of-unprocessed-sh**&quot;&gt;illness is the accumulation of unprocessed sh**&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So combining those two ideas (by in a math-y sense “substituting” that definition of illness into the first idea), we get:&lt;/p&gt;

&lt;p&gt;“The accumulation of unprocessed sh** not recognized as the accumulation of unprocessed sh** doesn’t tend to resolve”&lt;/p&gt;

&lt;p&gt;Then combine that with the premise/idea that &lt;a href=&quot;/were-all-ill&quot;&gt;we are all pretty ill&lt;/a&gt; (and it doesn’t
seem to be “tending to resolve”)&lt;/p&gt;

&lt;p&gt;That spells out that “there is a lot of accumulated unprocessed sh** not being recognized as unprocessed sh**”&lt;/p&gt;

&lt;p&gt;Ok so in what sense is it not being recognized as unprocessed sh**?&lt;/p&gt;

&lt;p&gt;Well let’s pull in the idea of &lt;a href=&quot;/sagginess&quot;&gt;sagginess&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically I felt like I started noticing a couple years ago that people
seemed to be thinking that things were actual “physical objects” that from
an outside perspective were clearly something “internal” (to their body)&lt;/p&gt;

&lt;p&gt;And that correspondingly the supposed “physical space” within which they
were thinking those physical objects were there in was actually like a 
“stagnant pocket” inside their body&lt;/p&gt;

&lt;p&gt;(and so then “sagginess” describes how from an outside perspective, a person
who’s “making that mistake” appears to energetically “sag” (because they are
getting no energy from trying to interact with something that isn’t actually
there))&lt;/p&gt;

&lt;p&gt;Think “tripping” (which is close to a synonym for “illness”)&lt;/p&gt;

&lt;p&gt;So the answer to the above question is:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Because it’s being mistaken for being stuff that is physically spatially there&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See how that works?&lt;/p&gt;

&lt;p&gt;People are mistaking unprocessed sh** for being something that is “physically
spatially there” (like “physical objects that are there in front of them or
whatever”), and correspondingly are mistaking stagnant pockets of unprocessed
sh** for being “actual physical spaces” (that they think that they’re in)&lt;/p&gt;

&lt;p&gt;And that explains why that unprocessed sh** isn’t getting processed, because
it’s not being recognized as unprocessed sh**!&lt;/p&gt;

&lt;p&gt;Whoa whoa whoa that is a major revelation&lt;/p&gt;

&lt;p&gt;I legitimately believe that is the accurate explanation for the mechanics of
the illness that everyone is tending to suffer from&lt;/p&gt;

&lt;p&gt;Also it’s f***ing nasty&lt;/p&gt;

&lt;p&gt;Thinking of unprocessed sh** as something that’s physically spatially
there is really really gross&lt;/p&gt;

&lt;p&gt;Ok so let’s play with that idea a little bit&lt;/p&gt;

&lt;p&gt;Why are people tending to mistake unprocessed sh** for “physical spatial stuff”?&lt;/p&gt;

&lt;p&gt;Well to be clear I don’t think we need to answer that question in order to be able
to “do something about it”&lt;/p&gt;

&lt;p&gt;Because just recognizing that as the &lt;em&gt;pattern&lt;/em&gt; of what’s going on is enough to
start recognizing it (and helping others recognize it) as unprocessed sh**&lt;/p&gt;

&lt;p&gt;(Which per the above idea would mean that then it should start getting processed)&lt;/p&gt;

&lt;p&gt;(Which per the above definition of illness would mean “starting to become less ill”
aka “healing”)&lt;/p&gt;

&lt;p&gt;See what I’m doing here I’m effectively anointing myself as the greatest healer
of our time&lt;/p&gt;

&lt;p&gt;And how am I accomplishing it?&lt;/p&gt;

&lt;p&gt;Not with something “soft” and corny&lt;/p&gt;

&lt;p&gt;No with male energy flex&lt;/p&gt;

&lt;p&gt;It is brutally clear that it has been an absence of certain things
that male energy “should” be doing (aka “wants” to be doing, not
“should” in an obligated sense) that has us in the current
state of illness&lt;/p&gt;

&lt;p&gt;(really this goes with the idea that the illness takes the form
of parasiting off of male energy but we will get into that
another time)&lt;/p&gt;

&lt;p&gt;Why because what is needed is a “breaking-down” process&lt;/p&gt;

&lt;p&gt;And male energy takes great great enjoyment in
“pulverizing”/breaking things down&lt;/p&gt;

&lt;p&gt;So it’s really just a question of male energy becoming
aware enough of what’s going on to then do its natural
enjoyable thing (aka “let it “flow”/”flex””) and
just break down all the sh** that has been wanting for
absence of being broken down&lt;/p&gt;
</description>
        <pubDate>Tue, 18 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//physically-spatial-mistake/</link>
        <guid isPermaLink="true">https://helixbass.net//physically-spatial-mistake/</guid>
      </item>
    
      <item>
        <title>Using Rust proc macros to explore the &quot;fully populated collection&quot; pattern</title>
        <description>&lt;p&gt;This is an exploration of a pattern that I’ve only vaguely come across in whatever languages
(but may well be a known named thing?) that I’ll call the “fully populated collection”
pattern, in the context of a Rust code-base&lt;/p&gt;

&lt;p&gt;Also a bit of a tutorial on Rust &lt;a href=&quot;https://doc.rust-lang.org/reference/procedural-macros.html&quot;&gt;procedural macros&lt;/a&gt;,
being applied to this pattern-exploration&lt;/p&gt;

&lt;p&gt;So we’ll start with the conceptual exploration but if you prefer you can jump straight to the
&lt;a href=&quot;#proc-macros&quot;&gt;proc macro “intro” tutorial&lt;/a&gt; or &lt;a href=&quot;#fully-populated-collection-proc-macros&quot;&gt;description of the proc macros used for the
“fully populated collections” pattern&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-fully-populated-collection-pattern&quot;&gt;The “fully populated collection” pattern&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree-sitter-grep&lt;/code&gt;&lt;/a&gt; we currently have a
hard-coded list of supported “target languages” (eg Rust, Typescript, …) and there are a
couple of collection data structures that should be populated with a corresponding value
“for every supported target language”&lt;/p&gt;

&lt;p&gt;For example, we “lazily” try and parse the provided tree-sitter &lt;a href=&quot;https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries&quot;&gt;query&lt;/a&gt;
against different supported target languages if you don’t explicitly specify the target
language (on the command-line)&lt;/p&gt;

&lt;p&gt;Currently that is represented using a &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/54a6a567cc7d46241e297de0362e7f247fc3d703/src/lib.rs#L87&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct CachedQueries(HashMap&amp;lt;SupportedLanguageName, OnceLock&amp;lt;Result&amp;lt;Arc&amp;lt;Query&amp;gt;, QueryError&amp;gt;&amp;gt;&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But so basically it’s an invariant that that collection should always be populated with &lt;em&gt;all&lt;/em&gt; of the supported
target languages (with one key-value per supported target language)&lt;/p&gt;

&lt;p&gt;So we currently just &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/54a6a567cc7d46241e297de0362e7f247fc3d703/src/lib.rs#L145&quot;&gt;iterate through all of the supported languages&lt;/a&gt;
when we construct the type:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;impl Default for CachedQueries {
    fn default() -&amp;gt; Self {
        Self(
            ALL_SUPPORTED_LANGUAGES
                .iter()
                .map(|supported_language| (supported_language.name, Default::default()))
                .collect(),
        )
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then the “access pattern” of the collection is just a normal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap::get()&lt;/code&gt; followed by a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.unwrap()&lt;/code&gt;
(since we know that “every key” should be present)&lt;/p&gt;

&lt;p&gt;But so there’s a smell there, specifically the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.unwrap()&lt;/code&gt; seems to be telling us “there’s a missing abstraction”&lt;/p&gt;

&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt; is designed for dynamic-sized collections with unknown keys&lt;/p&gt;

&lt;p&gt;But what we have is really a fixed-size collection with a known “fixed”/”enumerable” set of keys&lt;/p&gt;

&lt;p&gt;I’m not really familiar with where/if this concept “exists” in Rust-world&lt;/p&gt;

&lt;p&gt;The closest thing I’ve probably encountered to it is in Typescript when you use a &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Record&lt;/code&gt;&lt;/a&gt;
whose “key” type is eg a “union of string literals”, eg from those docs:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;interface CatInfo {
  age: number;
  breed: string;
}
 
type CatName = &quot;miffy&quot; | &quot;boris&quot; | &quot;mordred&quot;;
 
const cats: Record&amp;lt;CatName, CatInfo&amp;gt; = {
  miffy: { age: 10, breed: &quot;Persian&quot; },
  boris: { age: 5, breed: &quot;Maine Coon&quot; },
  mordred: { age: 16, breed: &quot;British Shorthair&quot; },
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And Typescript will yell at you if you try to instantiate that type without providing &lt;em&gt;all&lt;/em&gt; of the expected keys&lt;/p&gt;

&lt;p&gt;So that’s nice because the type system is statically guaranteeing the invariant that &lt;em&gt;all&lt;/em&gt; keys will be present
in any instance of that type, which seems like it should enable a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.get()&lt;/code&gt;-style access pattern that doesn’t
require a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.unwrap()&lt;/code&gt; (ie &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.get()&lt;/code&gt; should return an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;T&lt;/code&gt;, not an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Option&amp;lt;&amp;amp;T&amp;gt;&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Ok so that’s the starting point is basically thinking about “how could we encode that in Rust”&lt;/p&gt;

&lt;h3 id=&quot;exploring-the-pattern-in-rust&quot;&gt;Exploring the pattern in Rust&lt;/h3&gt;

&lt;p&gt;So I think there are various ways to probably think about encoding this pattern as an abstraction
in Rust. Where I landed was basically:&lt;/p&gt;
&lt;ul&gt;
  &lt;li style=&quot;position: relative&quot;&gt; have a simple &quot;token&quot;&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt; &lt;code&gt;Copy&lt;/code&gt; &lt;code&gt;enum&lt;/code&gt; type that represents all of
    the (&quot;enumerated&quot;) &quot;keys&quot; of these collections
    &lt;span class=&quot;sidenote&quot;&gt;&quot;Token&quot; is probably a terrible name for this, in the context of our collections it&apos;s really going to be more of a &quot;key&quot;/&quot;index&quot;?&lt;/span&gt;
  &lt;/li&gt;
  &lt;li&gt; represent the collections themselves as fixed-size arrays (that are indexed by converting the &quot;token&quot; &lt;code&gt;enum&lt;/code&gt; &amp;rarr;
    its &lt;code&gt;usize&lt;/code&gt; equivalent)
  &lt;/li&gt;
  &lt;li&gt; plan on using macros to encapsulate the creation of the token type + collections so that
    :hand-waves and mumbles something about statically guaranteed invariants:
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s look at some bits of code from a “hand-written” (as opposed to macro-generated,
which we’ll get into next) version of this&lt;/p&gt;

&lt;p&gt;So the token type is just a simple typical &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/language.rs#L10&quot;&gt;field-less enum&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#[derive(Copy, Clone, Debug, Eq, PartialEq, ValueEnum)]
pub enum SupportedLanguage {
    Rust,
    Typescript,
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueEnum&lt;/code&gt; is &lt;a href=&quot;https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html#enumerated-values&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clap::ValueEnum&lt;/code&gt;&lt;/a&gt;,
which we’re using to be able to parse a command-line &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--language&lt;/code&gt; argument.&lt;br /&gt;
It’s interesting that per the &lt;a href=&quot;https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html#enumerated-values&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clap&lt;/code&gt; docs&lt;/a&gt;
(specifically the generated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueEnum::value_variants()&lt;/code&gt; method there) its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ValueEnum&lt;/code&gt; API
also seems to be pointing somewhat at this concept (by needing a run-time “fully-populated collection” of all of those
enum variants)?)&lt;/p&gt;

&lt;p&gt;And then (imagining these things getting macro-generated) let’s define a &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/language.rs#L47&quot;&gt;newtype wrapper
type&lt;/a&gt;
for the fixed-size collections:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pub struct BySupportedLanguage&amp;lt;T&amp;gt;([T; 22]);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;22&lt;/code&gt; is the # of enum variants from the token &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SupportedLanguage&lt;/code&gt; type above)&lt;/p&gt;

&lt;p&gt;And now let’s create a couple of these fixed-size collections&lt;/p&gt;

&lt;p&gt;Some of them (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CachedQueries&lt;/code&gt; above) don’t have “unique values” per key, so instances of
those can just be initialized via typical “uniform array initialization”, eg now for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CachedQueries&lt;/code&gt; we can &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/lib.rs#L86&quot;&gt;derive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Default&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#[derive(Default)]
struct CachedQueries(BySupportedLanguage&amp;lt;OnceLock&amp;lt;Result&amp;lt;Arc&amp;lt;Query&amp;gt;, QueryError&amp;gt;&amp;gt;&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But then some of them do have unique values for each key, eg a mapping from supported target
language to corresponding &lt;a href=&quot;https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree_sitter::Language&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the moment let’s define it by just manually doing &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/language.rs#L200&quot;&gt;array initialization of each element&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static SUPPORTED_LANGUAGE_LANGUAGES: Lazy&amp;lt;BySupportedLanguage&amp;lt;Language&amp;gt;&amp;gt; = Lazy::new(|| {
    BySupportedLanguage([
        tree_sitter_rust::language(),
        tree_sitter_typescript::language_tsx(),
        ...
    ])
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(we’re using &lt;a href=&quot;https://docs.rs/once_cell/latest/once_cell/sync/struct.Lazy.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;once_cell::sync::Lazy&lt;/code&gt;&lt;/a&gt;
to initialize this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; because I guess those &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree_sitter::Language&lt;/code&gt;-creating methods aren’t
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const&lt;/code&gt; (if I understand &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; correctly)?)&lt;/p&gt;

&lt;p&gt;But this is pretty sketchy because you have to make sure to list the values in the right order
(the type system will ensure that you supply the right &lt;em&gt;number&lt;/em&gt; of them, but has no idea how/if the
order corresponds to your “expected key ordering”)&lt;/p&gt;

&lt;p&gt;So ya we’re definitely going to want to generate
that with a macro that is somehow aware of the correct ordering based on the “enumerated” keys&lt;/p&gt;

&lt;p&gt;Ok there are some other “odds and ends” for making this fixed-size collection abstraction usable
(eg enabling easy token-type ↔ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt; “massaging”) but this gives a basic idea of where
we’re landing&lt;/p&gt;

&lt;p&gt;Before we move on though, let’s look at the specific ergonomic reason that I added that newtype
wrapper around the actual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[T; 22]&lt;/code&gt; fixed-size array type&lt;/p&gt;

&lt;h4 id=&quot;make-it-feel-more-like-a-hashmap&quot;&gt;Make it “feel” more like a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;While the collection is technically an array, the idea is really that it’s a “key-value” collection
(where the keys are our token type)&lt;/p&gt;

&lt;p&gt;We can replace the smelly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.get(...).unwrap()&lt;/code&gt; (of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt; version) with a simple (“infallible”)
indexing access:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;impl&amp;lt;T&amp;gt; Index&amp;lt;SupportedLanguage&amp;gt; for BySupportedLanguage&amp;lt;T&amp;gt; {
    type Output = T;

    fn index(&amp;amp;self, index: SupportedLanguage) -&amp;gt; &amp;amp;Self::Output {
        &amp;amp;self.0[index as usize]
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But then additionally there are places where we want to iterate over the keys and values of
these collections. Rather than doing eg &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.enumerate()&lt;/code&gt; + some clunky &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usize&lt;/code&gt; → token type conversion,
let’s “treat it like a key-value collection” and expose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HashMap&lt;/code&gt;-like iteration methods (on the
newtype wrapper type)&lt;/p&gt;

&lt;p&gt;I won’t show the whole code listing but &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/language.rs#L49&quot;&gt;here&lt;/a&gt;
is an implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.iter()&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.values()&lt;/code&gt; for the newtype wrapper type&lt;/p&gt;

&lt;p&gt;And &lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/blob/f672cca2e2646b690818e2ce7dac1dcdb6fe3f1e/src/lib.rs#L111&quot;&gt;here&lt;/a&gt;
is a place where the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CachedQueries&lt;/code&gt; type uses that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.iter()&lt;/code&gt; method to iterate over both the
token-type “pseudo-keys” and corresponding (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OnceLock&amp;lt;...&amp;gt;&lt;/code&gt;) values of its fixed-size collection&lt;/p&gt;

&lt;p&gt;Ok that’s pretty cool, this isn’t seeming like a total disaster. But we noted a couple places where
it’s begging to be “made more legitimate” via macros&lt;/p&gt;

&lt;p&gt;So let’s (after perhaps a brief pause) roll up our sleeves and get into proc-macro world…&lt;/p&gt;

&lt;h2 id=&quot;-procedural-macros-hmmmm-hum-hum-are-they-hard&quot;&gt;&lt;a name=&quot;proc-macros&quot;&gt;&lt;/a&gt; Procedural macros: hmmmm hum hum are they hard&lt;/h2&gt;

&lt;p&gt;I’ve tended to “pull up short” of just going ahead and writing procedural macros
when they seem like they might be useful because I’ve felt a bit scared of how
to wrangle them&lt;/p&gt;

&lt;p&gt;But I am starting to get to the point where I feel like I’ll be able to “land it
relatively cleanly”&lt;/p&gt;

&lt;p&gt;And in this case coming up with a rough sketch/plan for some procedural macros
to help with the fully-populated collections then came to fruition roughly how
I’d hoped&lt;/p&gt;

&lt;p&gt;So if I can do it you probably can’t because I’m much smarter than you!&lt;/p&gt;

&lt;p&gt;No wait that’s not it&lt;/p&gt;

&lt;p&gt;Don’t be skurred&lt;/p&gt;

&lt;p&gt;But yes let’s try and “drive from a place of clarity”&lt;/p&gt;

&lt;p&gt;So in order to come up with a possibly high-confidence plan we need enough
of a mental model to reason about what/how we could express it using
procedural macros (or maybe we don’t need procedural macros? But ya we kind
of do)&lt;/p&gt;

&lt;h4 id=&quot;the-mental-model&quot;&gt;The mental model&lt;/h4&gt;

&lt;p&gt;A Rust macro basically gets the chance to replace the chunk of source code
where it’s invoked with another chunk of source code&lt;/p&gt;

&lt;p&gt;At the level that macros get their hands on that source code, though, it’s
not guaranteed to actually be valid Rust code&lt;/p&gt;

&lt;p&gt;What you get and give back are “token trees”&lt;/p&gt;

&lt;p&gt;What are “token trees”?&lt;/p&gt;

&lt;p&gt;Let’s not actually even try and construct a cohesive mental model for that&lt;/p&gt;

&lt;p&gt;In practical terms, we just need (a) to be able to wrangle (aka “parse”) the
input token tree into something that holds all of the information we need
about how they invoked the macro&lt;/p&gt;

&lt;p&gt;And then (b) we always want to output valid Rust code, we just have to know
how to construct that valid Rust code and return it as a token tree&lt;/p&gt;

&lt;h3 id=&quot;a-really-dumb-function-style-procedural-macro&quot;&gt;A really dumb function-style procedural macro&lt;/h3&gt;

&lt;p&gt;So let’s narrow our scope&lt;/p&gt;

&lt;p&gt;Procedural macros can be invoked via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[derive(MyMacro)]&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#[my_macro(...)]&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(...)&lt;/code&gt;&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;sidenote&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro![...]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro! {...}&lt;/code&gt; are just
other ways of writing this, from the macro’s perspective it doesn’t care
which one you used&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I’m pretty sure that for our purposes we will only need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(...)&lt;/code&gt;
“function-style” macros&lt;/p&gt;

&lt;p&gt;So let’s only focus on those&lt;/p&gt;

&lt;p&gt;So the “input” (token tree) that our macro will get passed is everything between
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(...)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To “flex against our mental model”, let’s try and write a procedural macro
that gets very angry at you unless you just pass it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;, ie
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(&quot;cheese&quot;)&lt;/code&gt; is ok but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(anything_else)&lt;/code&gt; should fail in
whatever way procedural macros fail when you pass them things they didn’t
expect&lt;/p&gt;

&lt;p&gt;Ok cool where do we put it&lt;/p&gt;

&lt;p&gt;Well hold on let’s achieve clarity against our current mental model before
starting to write any actual code&lt;/p&gt;

&lt;p&gt;That may seem hard given that we don’t really know what procedural macro code
“looks like” but I’d argue no we can still reason about it&lt;/p&gt;

&lt;p&gt;We know that we get handed a “token tree” of whatever is between the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we know that our job is to give back a token tree that’s… valid Rust code
of some kind&lt;/p&gt;

&lt;p&gt;Ok so here our job is to ascertain whether that “token tree” that we got passed
is… whatever the token tree for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt; looks like&lt;/p&gt;

&lt;p&gt;Anything else would be uncivilized&lt;/p&gt;

&lt;p&gt;And we can look forward to figuring out how to complain if that happens&lt;/p&gt;

&lt;p&gt;And I didn’t specify that I cared what happens after that, so let’s assume we
can do some dumb sh** as far as what token tree we return&lt;/p&gt;

&lt;p&gt;Ok but feel my flex you said we need to parse the
input token tree into something that holds all of the information we need
about how they invoked the macro&lt;/p&gt;

&lt;p&gt;Juxtaposing this against the fundamental mental model
of &lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;parse-don’t-validate&lt;/a&gt;
that you want to come to mind whenever you see stuff like this,
I’d argue that in this case our “parsed representation” can be
completely empty aka &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Why because let’s assume that we complain and give up &lt;em&gt;during parsing&lt;/em&gt;
if what we see isn’t &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;. But then at that point we don’t need
any “representation” to know what state we’re in. 100% of code paths
if we get that far are “we saw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;”. So it would be redundant
to encode that fact as “state” (eg a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;struct&lt;/code&gt; or even just a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;And that’s in keeping with the spec that then we can output whatever we
want and noone will care&lt;/p&gt;

&lt;p&gt;Ok I like it we’re so into “parse-don’t-validate” that we’re still going
to think of it that way and it will feel very rigorous to describe it
as parsing into an empty (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;) representation&lt;/p&gt;

&lt;p&gt;Ok that flex is ready to pop we’re going to parse-don’t-validate the input
token tree &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt; into the representation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; or else we will complain
and give up&lt;/p&gt;

&lt;p&gt;Now we’re ready to write code&lt;/p&gt;

&lt;h4 id=&quot;where-do-you-put-a-procedural-macro&quot;&gt;Where do you put a procedural macro?&lt;/h4&gt;

&lt;p&gt;I don’t understand the “why” of this but I know the rule is “they have to go in
their own crate”&lt;/p&gt;

&lt;p&gt;And I think that crate has to get “tagged” as being a special “procedural-macro” crate
but I forget where that goes, we’ll pull up some existing example for reference to
sniff it out&lt;/p&gt;

&lt;p&gt;But let’s start with writing the core code and come back to the wiring-up&lt;/p&gt;

&lt;p&gt;So create a new crate that will become our procedural macro crate&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt;:
&lt;span class=&quot;sidenote&quot;&gt;I legit have no idea whether there’s a way to tell &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo&lt;/code&gt; “hey this is going
to be a procedural macro crate”. Maybe that would make sense?&lt;/span&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo new --lib say_cheese
$ cd say_cheese
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Ya I decided we will call our macro like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;say_cheese!(&quot;cheese&quot;)&lt;/code&gt; not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my_macro!(&quot;cheese&quot;)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And now I will feed you the specific “signature” for our procedural macro (that we’ll add to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/lib.rs&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use proc_macro::TokenStream;

#[proc_macro]
pub fn say_cheese(input: TokenStream) -&amp;gt; TokenStream {
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I don’t know where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proc_macro&lt;/code&gt; (in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;use proc_macro::TokenStream&lt;/code&gt;) “comes from”,
usually we either have to add something to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt; as a dependency or
else it has to come from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::*&lt;/code&gt; (or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alloc::*&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core::*&lt;/code&gt; I believe?)&lt;/p&gt;

&lt;p&gt;But nope here “it’s just there” somehow. Whatever makes sense maybe&lt;/p&gt;

&lt;p&gt;Ok so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt; is our “token tree” input (and output) type that
we want to parse-don’t-validate into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s encapsulate that:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fn parse_input(input: TokenStream) -&amp;gt; () {
    unimplemented!()
}

#[proc_macro]
pub fn say_cheese(input: TokenStream) -&amp;gt; TokenStream {
    let parsed_nothing = parse_input(input);

    unimplemented!()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok my editor is yelling at me about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;proc_macro&lt;/code&gt; so
let’s go ahead and inform it that this is a proc macro
crate&lt;/p&gt;

&lt;p&gt;Looks to me like all we have to do to “make this a
special procedural-macro crate” is just make
sure this is in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[lib]
proc-macro = true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And yup &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cargo check&lt;/code&gt; is passing with just a couple
unused-variable warnings&lt;/p&gt;

&lt;p&gt;Great now clearly it is time to “poke at” (aka “parse”)
that input &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;parsing-the-input&quot;&gt;Parsing the input&lt;/h4&gt;

&lt;p&gt;We could do an exploration of how to do that “manually from
scratch”&lt;/p&gt;

&lt;p&gt;I don’t actually know what that would look like&lt;/p&gt;

&lt;p&gt;The reality of proc macros from what I’ve seen is that “everyone
uses &lt;a href=&quot;https://docs.rs/syn&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt;&lt;/a&gt; to parse the input”&lt;/p&gt;

&lt;p&gt;So let’s be practical and just sort of bake &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; into our
mental model (or feel free to dig into the raw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;
API if that’s your style)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ cargo add syn&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So my mental model for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; is:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It knows how to parse “chunks” of your token-tree input
that actually look like chunks of Rust code into certain
types that correspond to that type of thing in Rust code
eg an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expr&lt;/code&gt; (for a Rust expression)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok cool so how easily does that apply in our case?&lt;/p&gt;

&lt;p&gt;Well &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt; is a chunk of Rust code, and in fact is an
expression&lt;/p&gt;

&lt;p&gt;So let’s just aim for that, we’ll start by trying to leverage
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; to parse our input token tree into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::Expr&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ya let’s temporarily change our spec to instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;
we’ll just complain if we get passed anything other than a Rust
expression&lt;/p&gt;

&lt;p&gt;Then we can try testing it and seeing if it works and come
back to refining that to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;-specific&lt;/p&gt;

&lt;p&gt;I will hold your hand of how to translate what we see in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; &lt;a href=&quot;https://docs.rs/syn/2.0.25/syn/index.html&quot;&gt;docs&lt;/a&gt;
as an example of parsing a “derive macro” input → our
“function-style macro” world:&lt;/p&gt;

&lt;p&gt;We do the same exact thing we just say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as Expr&lt;/code&gt; instead of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as DeriveInput&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use syn::{parse_macro_input, Expr};

fn parse_input(input: TokenStream) -&amp;gt; () {
    let parsed_expr = parse_macro_input!(input as Expr);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And actually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; is going to take care of the “complaining”
part for us (and do it in some way that should by default provide
helpful compiler error messages to the person trying to use this
procedural macro)&lt;/p&gt;

&lt;p&gt;So I think we’re kind of done&lt;/p&gt;

&lt;p&gt;We can literally leave the code like that because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-&amp;gt; ()&lt;/code&gt; is the same
as not returning anything&lt;/p&gt;

&lt;p&gt;It will just presumably warn us about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parsed_expr&lt;/code&gt; being unused
but we don’t care&lt;/p&gt;

&lt;p&gt;Ok on to testing… wait what’s that my editor is yelling at me?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo check
error[E0308]: mismatched types
 --&amp;gt; src/lib.rs:5:23
  |
5 |     let parsed_expr = parse_macro_input!(input as Expr);
  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `TokenStream`
  |
  = note: this error originates in the macro `parse_macro_input` (in Nightly builds, run with -Z macro-backtrace for more info)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hmm ok I legitimately thought this was going to work&lt;/p&gt;

&lt;p&gt;Ok after slight sniffing what’s going on here is that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!(...)&lt;/code&gt; is a &lt;em&gt;little&lt;/em&gt; more magic than I expected&lt;/p&gt;

&lt;p&gt;Specifically it’s hard-coding in the fact that it can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt;
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt; if it fails to parse the input&lt;/p&gt;

&lt;p&gt;So… we could either change our function signature to return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;
to make it happy&lt;/p&gt;

&lt;p&gt;Or we could not use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I’m going with the latter because we want to return the incredibly meaningful
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt; not a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;avoiding-parse_macro_input&quot;&gt;Avoiding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!()&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Ok so squinting at the definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!()&lt;/code&gt; it looks like
it’s more or less just a thin wrapper around calling
&lt;a href=&quot;https://docs.rs/syn/latest/syn/fn.parse.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::parse()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And per why it was trying to do a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; for us, that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::parse()&lt;/code&gt; call
is fallible and returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::Result&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So the appropriate return type for our function is going to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::Result&amp;lt;()&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we can write it like so:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use syn::parse;

fn parse_input(input: TokenStream) -&amp;gt; syn::Result&amp;lt;()&amp;gt; {
    let parsed_expr = parse::&amp;lt;Expr&amp;gt;(input)?;

    Ok(())
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then in our main &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;say_cheese()&lt;/code&gt; function we can mimic that
“return if it couldn’t parse it” behavior (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!()&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pub fn say_cheese(input: TokenStream) -&amp;gt; TokenStream {
    let parsed_nothing = match parse_input(input) {
        Ok(data) =&amp;gt; data,
        Err(err) =&amp;gt; return err.to_compile_error().into(),
    };

    unimplemented!()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok nice good to poke under the hood of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;parse_macro_input!()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So I think we’re ready to test it&lt;/p&gt;

&lt;h4 id=&quot;testing-the-macro&quot;&gt;Testing the macro&lt;/h4&gt;

&lt;p&gt;Let’s create a new dummy crate for testing&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;sidenote&quot;&gt;Yes writing “actual tests” sounds nice. I don’t know what to reach for for testing
macros so let’s just manually test&lt;/span&gt;
our procedural macro:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo new test-say-cheese
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We just add our proc macros crate as a dependency:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# test-say-cheese/Cargo.toml

[dependencies]
say_cheese = { path = &quot;../say_cheese&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And then try and pass some valid Rust expression to it and see if it complains:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// test-say-cheese/src/main.rs

use say_cheese::say_cheese;

fn main() {
    say_cheese!(&quot;Hello, world!&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo check
error: proc macro panicked
 --&amp;gt; src/main.rs:4:5
  |
4 |     say_cheese!(&quot;Hello, world!&quot;);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = help: message: not implemented
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok fair we said we didn’t care about what our proc macro
returns but the compiler cares a little bit&lt;/p&gt;

&lt;p&gt;So what’s the dumbest thing we can do to have our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;say_cheese()&lt;/code&gt;
function return a valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Well currently we don’t know how to create new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;’s&lt;/p&gt;

&lt;p&gt;So again feel free to dig into that yourself but I’m going to say
“see if we can just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.clone()&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenStream&lt;/code&gt;”:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// say_cheese/src/lib.rs

#[proc_macro]
pub fn say_cheese(input: TokenStream) -&amp;gt; TokenStream {
    let parsed_nothing = match parse_input(input.clone()) { // &amp;lt;-- added this .clone()
        Ok(data) =&amp;gt; data,
        Err(err) =&amp;gt; return err.to_compile_error().into(),
    };

    input // &amp;lt;-- and return this
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok (from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test-say-cheese/&lt;/code&gt;) &lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$ cargo run&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Fabulous&lt;/p&gt;

&lt;p&gt;Does it complain as well as we expected if we change it to something
that can’t be parsed as a Rust expression&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// test-say-cheese/src/main.rs

fn main() {
    say_cheese!(-&amp;gt;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo run
error: unsupported expression; enable syn&apos;s features=[&quot;full&quot;]
 --&amp;gt; src/main.rs:4:18
  |
4 |     say_cheese!(-&amp;gt;);
  |                  ^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok (first) mission accomplished&lt;/p&gt;

&lt;p&gt;So now we need to refine it to only accept &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To do that we’re going to have to sniff at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt;’s “parse-able” types
a little more closely&lt;/p&gt;

&lt;h4 id=&quot;what-does-syn-think-a-cheese-is&quot;&gt;What does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; think a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt; is?&lt;/h4&gt;

&lt;p&gt;Ok looking at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt;’s docs, I spot &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExprLit&lt;/code&gt; which says it could be
(the parsed version of) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;foo&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So that sounds like the “narrower” type than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::Expr&lt;/code&gt; that we want
to try and parse into&lt;/p&gt;

&lt;p&gt;That should get us as far as it complaining if we pass anything besides
a literal of some kind&lt;/p&gt;

&lt;p&gt;But then to check if that literal is the literal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt; I think we
will have to do ourselves based on what we see in that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExprLit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So “drilling down” through its &lt;a href=&quot;https://docs.rs/syn/latest/syn/struct.ExprLit.html&quot;&gt;docs&lt;/a&gt;,
it looks like its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lit&lt;/code&gt; field needs to be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Lit::Str&lt;/code&gt; whose &lt;a href=&quot;https://docs.rs/syn/latest/syn/struct.LitStr.html#method.value&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.value()&lt;/code&gt;&lt;/a&gt;
is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cheese&quot;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// say_cheese/src/lib.rs

use syn::{ExprLit, Lit};

fn parse_input(input: TokenStream) -&amp;gt; syn::Result&amp;lt;()&amp;gt; {
    match parse::&amp;lt;ExprLit&amp;gt;(input)?.lit {
        Lit::Str(lit_str) if lit_str.value() == &quot;cheese&quot; =&amp;gt; Ok(()),
        _ =&amp;gt; // what do we do here?
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok right I guess we need to know how to complain ourselves&lt;/p&gt;

&lt;p&gt;Reading &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt;’s &lt;a href=&quot;https://docs.rs/syn/latest/syn/parse/struct.Error.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt; docs&lt;/a&gt;
it looks like this is appropriate:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// say_cheese/src/lib.rs

use syn::Error;

fn parse_input(input: TokenStream) -&amp;gt; syn::Result&amp;lt;()&amp;gt; {
    match parse::&amp;lt;ExprLit&amp;gt;(input)?.lit {
        Lit::Str(lit_str) if lit_str.value() == &quot;cheese&quot; =&amp;gt; Ok(()),
        lit =&amp;gt; Err(Error::new(lit.span(), &quot;expected \&quot;cheese\&quot;&quot;)), // &amp;lt;-- added this
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok so to test that first the “happy path”:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// test-say-cheese/src/main.rs

fn main() {
    say_cheese!(&quot;cheese&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;…and the “unhappy path”:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// test-say-cheese/src/main.rs

fn main() {
    say_cheese!(&quot;not cheese&quot;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ cargo run
error: expected &quot;cheese&quot;
 --&amp;gt; src/main.rs:4:17
  |
4 |     say_cheese!(&quot;not cheese&quot;);
  |                 ^^^^^^^^^^^^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I just wept at its beauty&lt;/p&gt;

&lt;p&gt;Ok I’m going to call that “part 2”&lt;/p&gt;

&lt;p&gt;And now for part 3 you can let me take the
wheel and spell out the plan + execution of
the “fully-populated collection” proc macros
while you bask in the glory of what just
happened&lt;/p&gt;

&lt;h2 id=&quot;-some-proc-macros-for-fully-populated-collections&quot;&gt;&lt;a name=&quot;fully-populated-collection-proc-macros&quot;&gt;&lt;/a&gt; Some proc macros for “fully populated collections”&lt;/h2&gt;

&lt;p&gt;The “sketch” for how I’d like to be able to use these is&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sidenote&quot;&gt;I
called this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed_map!()&lt;/code&gt;, but I’m liking the “fully populated collections” name, but this macro really just
generates the “token” (which per above is also a bad name) type and &lt;em&gt;another&lt;/em&gt; macro for actually creating the
collections…&lt;/span&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fixed_map! {
    name =&amp;gt; SupportedLanguage,
    variants =&amp;gt; [
        Rust,
        Typescript,
        ...
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and then for fully-populated collections of that key type with “unique values”:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;let whatever = by_supported_language!(
    Rust =&amp;gt; tree_sitter_rust::language(),
    Typescript =&amp;gt; tree_sitter_typescript::language_tsx(),
    ...
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;(where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_supported_language!()&lt;/code&gt; is a macro that gets generated by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed_map!()&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;To implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed_map!()&lt;/code&gt; we’ll need to “cross the bridge” of parsing “custom non-Rust syntax”
(eg &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name =&amp;gt; ...&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;But really the tricky thing is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_supported_language!()&lt;/code&gt; looks like it needs to
be a procedural macro, I don’t think you could make that work as a purely declarative macro&lt;/p&gt;

&lt;p&gt;But… I don’t think you could just have one procedural macro generate another procedural macro
that you can then “immediately use” in the same file like that (because procedural macros need
to be defined in their own crate)&lt;/p&gt;

&lt;p&gt;So the trick is that there will be a “generic” version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_supported_language!()&lt;/code&gt; that’s a
procedural macro whose job is to create fully populated collection instances, call it &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_fixed_map!()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And it will have to be “parameterized” with the stuff that’s specific to &lt;em&gt;that&lt;/em&gt; fully-populated collection&lt;/p&gt;

&lt;p&gt;And we can make the generated &lt;em&gt;specific&lt;/em&gt; version eg &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_supported_language!()&lt;/code&gt; be a &lt;em&gt;declarative&lt;/em&gt;
macro that like “hard-codes”/”pre-curries” those “specific” parameters in its definition and passes them
to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_fixed_map!()&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;implementation&quot;&gt;Implementation&lt;/h4&gt;

&lt;p&gt;A type to represent the parsed version of the arguments to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed_map!()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use syn::Ident;

struct FixedMapArgs {
    name: Ident,
    variants: Vec&amp;lt;Ident&amp;gt;,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And for the actual parsing of it I just sort of “jimmied” this together:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use syn::{
    parse::{Parse, ParseStream},
    Token, Expr, ExprArray,
};

fn expr_to_ident(expr: Expr) -&amp;gt; Ident {
    match expr {
        Expr::Path(expr) =&amp;gt; expr.path.get_ident().unwrap().clone(),
        _ =&amp;gt; panic!(&quot;Expected Ident&quot;),
    }
}

fn parse_idents_array(input: ParseStream) -&amp;gt; syn::Result&amp;lt;Vec&amp;lt;Ident&amp;gt;&amp;gt; {
    Ok(input
        .parse::&amp;lt;ExprArray&amp;gt;()?
        .elems
        .into_iter()
        .map(expr_to_ident)
        .collect())
}

impl Parse for FixedMapArgs {
    fn parse(input: ParseStream) -&amp;gt; syn::Result&amp;lt;Self&amp;gt; {
        let mut name: Option&amp;lt;Ident&amp;gt; = Default::default();
        let mut variants: Option&amp;lt;Vec&amp;lt;Ident&amp;gt;&amp;gt; = Default::default();
        while !input.is_empty() {
            let key: Ident = input.parse()?;
            input.parse::&amp;lt;Token![=&amp;gt;]&amp;gt;()?;
            match &amp;amp;*key.to_string() {
                &quot;name&quot; =&amp;gt; {
                    name = Some(input.parse::&amp;lt;Ident&amp;gt;()?);
                }
                &quot;variants&quot; =&amp;gt; {
                    variants = Some(parse_idents_array(input)?);
                }
                _ =&amp;gt; panic!(&quot;didn&apos;t expect key {}&quot;, key),
            }
            input.parse::&amp;lt;Token![,]&amp;gt;()?;
        }
        Ok(FixedMapArgs {
            name: name.expect(&quot;Expected name specifier&quot;),
            variants: variants.expect(&quot;Expected variants specifier&quot;),
        })
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then for generating the output, we didn’t get into this above but
similarly to how “everyone uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn&lt;/code&gt; for parsing the input”, it seems
that “everyone uses &lt;a href=&quot;https://docs.rs/quote&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quote&lt;/code&gt;&lt;/a&gt; for generating the output”&lt;/p&gt;

&lt;p&gt;And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quote!()&lt;/code&gt; is sort of “template”-y&lt;/p&gt;

&lt;p&gt;I won’t show all of the generated stuff but here is an example of
generating the actual “token” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enum&lt;/code&gt; type definition:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#[proc_macro]
pub fn fixed_map(input: TokenStream) -&amp;gt; TokenStream {
    let FixedMapArgs { name, variants } = parse_macro_input!(input as FixedMapArgs);

    let token_enum_definition = get_token_enum_definition(&amp;amp;name, &amp;amp;variants);
    ...

    quote! {
        #token_enum_definition
        ...
    }
    .into()
}

fn get_token_enum_definition(name: &amp;amp;Ident, variants: &amp;amp;[Ident]) -&amp;gt; proc_macro2::TokenStream {
    quote! {
        #[derive(Copy, Clone, Debug, Eq, PartialEq, clap::ValueEnum)]
        pub enum #name {
            #(#variants),*
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;so that will generate in our case the&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#[derive(...)]
pub enum SupportedLanguage {
    Rust,
    Typescript,
    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok let’s take a look at the tricky part&lt;/p&gt;

&lt;p&gt;First the “generic” &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;by_fixed_map!()&lt;/code&gt; proc macro&lt;/p&gt;

&lt;p&gt;We’ll want to specifically invoke it like:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;by_fixed_map!(
    // this is the supplied argument to `by_supported_language!()`
    [
        Rust =&amp;gt; tree_sitter_rust::language(),
        Typescript =&amp;gt; tree_sitter_typescript::language_tsx(),
        ...
    ],
    // this is a list of all of the variants in the &quot;right order&quot;
    // this will be &quot;hard-coded&quot; in `by_supported_language!()`
    [
        Rust,
        Typescript,
        ...
    ],
    // this is the name of the &quot;fully-populated collection type&quot;
    // this will also be &quot;hard-coded&quot; in `by_supported_language!()`
    BySupportedLanguage
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ok its whole implementation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;struct ByFixedMapArgs {
    value_mapping: HashMap&amp;lt;Ident, Expr&amp;gt;,
    variants: Vec&amp;lt;Ident&amp;gt;,
    collection_type_name: Ident,
}

impl Parse for ByFixedMapArgs {
    fn parse(input: ParseStream) -&amp;gt; syn::Result&amp;lt;Self&amp;gt; {
        let value_mapping_content;
        bracketed!(value_mapping_content in input);
        let mut value_mapping: HashMap&amp;lt;Ident, Expr&amp;gt; = Default::default();
        while !value_mapping_content.is_empty() {
            let key: Ident = value_mapping_content.parse()?;
            value_mapping_content.parse::&amp;lt;Token![=&amp;gt;]&amp;gt;()?;
            let value: Expr = value_mapping_content.parse()?;
            if value_mapping.contains_key(&amp;amp;key) {
                panic!(&quot;Repeated key: {key}&quot;);
            }
            value_mapping.insert(key, value);
            if value_mapping_content.is_empty() {
                break;
            }
            value_mapping_content.parse::&amp;lt;Token![,]&amp;gt;()?;
        }
        input.parse::&amp;lt;Token![,]&amp;gt;()?;
        let variants = parse_idents_array(input)?;
        input.parse::&amp;lt;Token![,]&amp;gt;()?;
        let collection_type_name: Ident = input.parse()?;
        Ok(Self {
            value_mapping,
            variants,
            collection_type_name,
        })
    }
}

#[proc_macro]
pub fn by_fixed_map(input: TokenStream) -&amp;gt; TokenStream {
    let ByFixedMapArgs {
        value_mapping,
        variants,
        collection_type_name,
    } = parse_macro_input!(input as ByFixedMapArgs);

    if value_mapping.len() != variants.len() {
        panic!(&quot;Incorrect variants&quot;);
    }

    let ordered_values = variants
        .iter()
        .map(|variant| value_mapping.get(variant).expect(&quot;Incorrect variants&quot;))
        .collect::&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;();

    quote! {
        #collection_type_name([
            #(#ordered_values),*
        ])
    }
    .into()
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So again some somewhat-fiddly manual parsing,
specifically &lt;a href=&quot;https://docs.rs/syn/latest/syn/macro.bracketed.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;syn::bracketed!()&lt;/code&gt;&lt;/a&gt;
came in handy&lt;/p&gt;

&lt;p&gt;And then we are just driving generation of an array literal whose elements
are in the “correct” order as specified by the “variants” argument&lt;/p&gt;

&lt;p&gt;And then per above the piece that wires them together is to have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed_map!()&lt;/code&gt; generate
a procedural macro that hard-codes the “variants” and “collection type name” arguments:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;use quote::format_ident;

#[proc_macro]
pub fn fixed_map(input: TokenStream) -&amp;gt; TokenStream {
    let FixedMapArgs { name, variants } = parse_macro_input!(input as FixedMapArgs);

    let collection_type_name = format_ident!(&quot;By{name}&quot;); // &amp;lt;-- eg &quot;BySupportedLanguage&quot;
    ...
    let collection_generator_macro_definition =
        get_collection_generator_macro_definition(&amp;amp;collection_type_name, &amp;amp;variants);

    quote! {
        ...
        #collection_generator_macro_definition
    }
    .into()
}

fn get_collection_generator_macro_definition(
    collection_type_name: &amp;amp;Ident,
    variants: &amp;amp;[Ident],
) -&amp;gt; proc_macro2::TokenStream {
    let macro_name = format_ident!(&quot;{}&quot;, collection_type_name.to_string().to_snake_case());
    quote! {
        #[macro_export]
        macro_rules! #macro_name {
            ($($variant:ident =&amp;gt; $value:expr),* $(,)?) =&amp;gt; {
                proc_macros::by_fixed_map!(
                    [$($variant =&amp;gt; $value),*],
                    [
                        #(#variants),*
                    ],
                    #collection_type_name
                )
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And it works!&lt;/p&gt;

&lt;p&gt;If you want to see the actual code, it was split across
&lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/pull/52&quot;&gt;these&lt;/a&gt;
&lt;a href=&quot;https://github.com/helixbass/tree-sitter-grep/pull/53&quot;&gt;two&lt;/a&gt;
PR’s&lt;/p&gt;

&lt;h3 id=&quot;in-conclusion&quot;&gt;In conclusion&lt;/h3&gt;

&lt;p&gt;There wasn’t some major ergonomic nor performance reason to have to
move to the “fully-populated collection” pattern&lt;span class=&quot;sidenote-number&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;sidenote&quot;&gt;Make no mistake, this was “a version” of taking a stab at
what implementing that pattern in Rust could look like, I think there could be other
(possibly already-existing) approaches for how it might look&lt;/span&gt;
for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SupportedLanguage&lt;/code&gt; stuff in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree-sitter-grep&lt;/code&gt; code-base&lt;/p&gt;

&lt;p&gt;But I like that it feels like we’re using more appropriate/descriptive data structures
(and that should translate to higher efficiency even if perhaps negligible
in the context of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tree-sitter-grep&lt;/code&gt; - look Ma
no allocations!)&lt;/p&gt;

&lt;p&gt;And it was a good excuse to dig into procedural macros a little bit&lt;/p&gt;
</description>
        <pubDate>Sun, 16 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//proc-macros-fully-populated-collection/</link>
        <guid isPermaLink="true">https://helixbass.net//proc-macros-fully-populated-collection/</guid>
      </item>
    
      <item>
        <title>The fallacy of thinking that you&apos;re in a narrower space than you actually are</title>
        <description>&lt;p&gt;This one is based more on “feel”/observation than straight-up logic&lt;/p&gt;

&lt;p&gt;It seems like a lot of things that people do are based on the underlying mistake/fallacy
of thinking that they’re in some kind of “narrow”/small space&lt;/p&gt;

&lt;p&gt;When in fact reality is very very very spacious&lt;/p&gt;

&lt;p&gt;I think that thinking that &lt;a href=&quot;/the-good-is-not-the-absence-of-the-bad&quot;&gt;the good is the absence of the bad&lt;/a&gt;
is based on this mistake because it’s like you’re thinking that you’re
in this finite little space where there’s only room for so much stuff
and so therefore obviously you need to get rid of this bad stuff and then
things will be better&lt;/p&gt;

&lt;p&gt;Nope nope nope you’re not in a space like that though&lt;/p&gt;

&lt;p&gt;That’s clearly some form of “tripping” and I think specifically what is going
on is that &lt;a href=&quot;/physically-spatial-mistake&quot;&gt;something that is not physically spatial is being mistaken for being physically spatial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One specific category of things that I think suffer from this mistake (of thinking you’re
in a narrow space) is “competition”-y stuff in general&lt;/p&gt;

&lt;p&gt;Like most of it looks real dumb because actually “there’s plenty of room for everybody (and their ideas etc)”&lt;/p&gt;

&lt;p&gt;(The more positive/healthy version of that imo is &lt;a href=&quot;/black-culture-coexistence&quot;&gt;black culture&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Like any time anyone seems to have a “slot” for something where “there’s room for one greatest __ X __” I think
that’s what’s going on&lt;/p&gt;

&lt;p&gt;And ya therefore that’s a waste of energy because it’s based on illness&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//thinking-that-youre-in-a-narrower-space-than-you-actually-are/</link>
        <guid isPermaLink="true">https://helixbass.net//thinking-that-youre-in-a-narrower-space-than-you-actually-are/</guid>
      </item>
    
      <item>
        <title>The nature of analysis</title>
        <description>&lt;p&gt;Analysis as an “angle”/”activity”:&lt;/p&gt;

&lt;p&gt;Light-hearted. But that’s not a 
&lt;a href=&quot;/negative-definition&quot;&gt;negative definition&lt;/a&gt; (ie “light-heartedness”
doesn’t mean the absence of certain tones/”heaviness”, think of it more like
a song with a light-hearted tone)&lt;/p&gt;

&lt;p&gt;The thing that that’s calling out is that people can start “weighing down” the
activity (with what might be called “self-seriousness”) anytime you’d be thinking/talking
about something “serious”&lt;/p&gt;

&lt;p&gt;No let’s not do that it’s not cute&lt;/p&gt;

&lt;p&gt;And it’s not the point&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//the-nature-of-analysis/</link>
        <guid isPermaLink="true">https://helixbass.net//the-nature-of-analysis/</guid>
      </item>
    
      <item>
        <title>The mechanics of storytelling</title>
        <description>&lt;p&gt;I will write this soon&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//the-mechanics-of-storytelling/</link>
        <guid isPermaLink="true">https://helixbass.net//the-mechanics-of-storytelling/</guid>
      </item>
    
      <item>
        <title>The good is not the absence of the bad</title>
        <description>&lt;p&gt;I remember when this one “jumped out at me”. In Colorado
in 2013 I was sitting around playing music with Elise and
she said something like “I want this one to be like raw/stripped down”
and I immediately saw what she didn’t understand about “how that works”&lt;/p&gt;

&lt;p&gt;In that specific case, the thing I could tell from how she intoned what
she said was that she was thinking that “raw/stripped-down-ness” is
something that you achieve by “getting rid of something”&lt;/p&gt;

&lt;p&gt;Uhhhh ok I can see how you might have come to that conclusion but no
that’s not actually how you get the thing you want there&lt;/p&gt;

&lt;p&gt;“Raw/stripped-down-ness” is a “thing that you have to achieve” (eg by being
able to play with solid time). It has “vibe”, it has “feel”. And those aren’t
like defined/achieved in terms of the &lt;a href=&quot;/negative-definition&quot;&gt;absence of something that you think is
not that&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the more general statement of the fallacy (or really I guess the truth,
the negation of the fallacy) is “the good is not the absence of the bad”&lt;/p&gt;

&lt;p&gt;(I then think that the underlying fallacy is &lt;a href=&quot;/thinking-that-youre-in-a-narrower-space-than-you-actually-are&quot;&gt;thinking that you’re in a narrower/smaller
space than you actually are&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;So as with all fallacies it’s good to notice when someone might be basing what
they’re thinking on it&lt;/p&gt;

&lt;p&gt;Certainly this can apply to how people think about health and illness&lt;/p&gt;

&lt;p&gt;But thinking of health as the absence of illness would logically violate this idea&lt;/p&gt;

&lt;p&gt;So that’s kind of deep right, if you’re in a state of illness you shouldn’t be trying
to “get rid of it”&lt;/p&gt;

&lt;p&gt;So how does that work?&lt;/p&gt;

&lt;p&gt;Well that’s a good one to ponder&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//the-good-is-not-the-absence-of-the-bad/</link>
        <guid isPermaLink="true">https://helixbass.net//the-good-is-not-the-absence-of-the-bad/</guid>
      </item>
    
      <item>
        <title>The definition of respect</title>
        <description>&lt;p&gt;In my opinion “respect” = “treating things as though they’re real”&lt;/p&gt;

&lt;p&gt;Life tends to punish you for not “showing respect” in that sense&lt;/p&gt;

&lt;p&gt;It does not reward random self-indulgent sh**&lt;/p&gt;

&lt;p&gt;Why do people do random self-indulgent sh**?&lt;/p&gt;

&lt;p&gt;Clearly it’s some form of illness&lt;/p&gt;

&lt;p&gt;Here the idea/mechanism that comes to mind is that &lt;a href=&quot;/the-mechanics-of-storytelling&quot;&gt;storytelling&lt;/a&gt;
is often the culprit&lt;/p&gt;
</description>
        <pubDate>Fri, 07 Jul 2023 00:00:00 -0400</pubDate>
        <link>https://helixbass.net//respect-definition/</link>
        <guid isPermaLink="true">https://helixbass.net//respect-definition/</guid>
      </item>
    
  </channel>
</rss>
