<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tauto Blog</title><link>https://blog.tauto.run/</link><description>Tauto blog.</description><language>en</language><atom:link href="https://blog.tauto.run/feed.xml" rel="self" type="application/rss+xml"/><item><title>For Macro Lovers: Could Tauto Have the World&#39;s Most Powerful Macro System?</title><link>https://blog.tauto.run/tauto-macros/</link><guid isPermaLink="true">https://blog.tauto.run/tauto-macros/</guid><pubDate>03 Nov 2026 00:00:00 GMT</pubDate><category>tauto</category><category>macros</category><category>dsl</category><category>formalverification</category><description>&lt;p&gt;Tauto combines a dependently typed proof system with a runtime featuring algebraic effects and ownership. This article introduces its &lt;strong&gt;macro system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;“The world&#39;s most powerful” is a bold claim for a title. The aim is to bring everything I want from macros into a single design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add new syntax and DSLs as libraries, complete with registered formatters and syntax highlighting.&lt;/li&gt;
&lt;li&gt;Write macros that transform code based on its types and macros that build proofs, called tactics, using the same mechanism.&lt;/li&gt;
&lt;li&gt;Keep expansion hygienic, so macros do not capture the caller&#39;s variables.&lt;/li&gt;
&lt;li&gt;Run untrusted macros without giving them file access, without unbounded execution, and without compromising proof soundness.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Hihaheho/tauto&quot;&gt;Tauto on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;nav aria-label=&quot;Table of contents&quot; class=&quot;toc&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#ordinary-functions&quot;&gt;Macros are ordinary functions that return syntax values&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#macro-kinds&quot;&gt;Macro kinds and when to use them&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#syntax-macros&quot;&gt;Syntax macros: write in your own grammar&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#untyped-macros&quot;&gt;Untyped macros: reinterpret an expression&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#typed-macros&quot;&gt;Typed macros: inspect types and context&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#tactics&quot;&gt;Tactics: macros that construct proofs&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#attribute-macros&quot;&gt;Attribute macros: generate declarations&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#generated-declarations&quot;&gt;Why list generated declarations?&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#hygiene&quot;&gt;Hygiene: macros do not capture the caller&amp;#39;s names&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#effects&quot;&gt;Using effect analysis to contain macro execution&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#nontermination&quot;&gt;What about infinite loops?&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#syntax-system&quot;&gt;A powerful syntax-macro system&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#generated-ast&quot;&gt;Write a grammar, get a typed AST and parser&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#left-recursion&quot;&gt;Left recursion: LL(k) and LALR(1)&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#syntax-errors&quot;&gt;Syntax errors report locations and expectations&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#formatting-and-highlighting&quot;&gt;Registering formatters and syntax highlighting&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#embedded-expressions&quot;&gt;Embedding Tauto expressions in a grammar&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#proving-language-tools&quot;&gt;Build and prove a language implementation&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#other-features&quot;&gt;More useful properties&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#expansion-tracing&quot;&gt;Every expansion can be traced&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#declaration-environment&quot;&gt;Typed macros do not change the declaration environment&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#typing-judgments&quot;&gt;Write typing judgments in a DSL&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#expansion-order&quot;&gt;Macro execution is ordered by file&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#deliberate-restrictions&quot;&gt;Deliberate restrictions&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#design-priorities&quot;&gt;Design priorities&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#limits&quot;&gt;What is not guaranteed&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/nav&gt;&lt;h2 id=&quot;ordinary-functions&quot;&gt;Macros are ordinary functions that return syntax values&lt;/h2&gt;&lt;p&gt;Tauto macros are &lt;strong&gt;ordinary functions&lt;/strong&gt;, rather than programs in a separate macro or template language. They take and return syntax values, represented by AST data types such as &lt;code&gt;SynExpr&lt;/code&gt; and &lt;code&gt;SynStmt&lt;/code&gt;, assembled with &lt;code&gt;quote { … }&lt;/code&gt; and &lt;code&gt;$x&lt;/code&gt;. Calls are always explicit: &lt;code&gt;NAME!(…)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Whatever a macro produces, the expanded program goes through the same path as a handwritten program: the kernel and a second, independently implemented kernel. You do not need to trust the macro&#39;s generation logic to preserve type or proof soundness.&lt;/p&gt;
&lt;h2 id=&quot;macro-kinds&quot;&gt;Macro kinds and when to use them&lt;/h2&gt;&lt;p&gt;There are four kinds of macros. &lt;strong&gt;The function&#39;s input type alone determines the kind.&lt;/strong&gt; There is no keyword such as &lt;code&gt;typed macro&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Syntax macro:&lt;/strong&gt; takes a typed AST generated from a grammar. Call it as &lt;code&gt;name!(`…`)&lt;/code&gt; to introduce notation or a DSL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Untyped macro:&lt;/strong&gt; takes &lt;code&gt;SynExpr&lt;/code&gt;. Call it as &lt;code&gt;name!(a + b)&lt;/code&gt; to reinterpret an expression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typed macro:&lt;/strong&gt; takes &lt;code&gt;Judgement&lt;/code&gt;. Call it as &lt;code&gt;name!(e)&lt;/code&gt; to transform code using its type and context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tactic:&lt;/strong&gt; takes &lt;code&gt;ProofStep&lt;/code&gt;. Call it as &lt;code&gt;by name!(…): G { … }&lt;/code&gt; to automate proofs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;syntax-macros&quot;&gt;Syntax macros: write in your own grammar&lt;/h3&gt;&lt;p&gt;A syntax macro parses its input using a grammar declared with &lt;code&gt;syntax!&lt;/code&gt;. As an example, here is &lt;code&gt;swap!&lt;/code&gt;, which swaps two variables.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;swp&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;_&lt;span class=&quot;hl-punctuation&quot;&gt;][&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;_&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;*/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;

pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;SynStmt&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; a &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Syn&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;ident&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Syn&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;ident&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;name_2&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote stmts &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; tmp &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;$a&lt;/span&gt;
    &lt;span class=&quot;hl-variable&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;$b&lt;/span&gt;
    &lt;span class=&quot;hl-variable&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; tmp
  &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The grammar lives in a fenced block tagged &lt;code&gt;par&lt;/code&gt;. It automatically generates a typed AST called &lt;code&gt;swp::Pair&lt;/code&gt;, which becomes the macro function&#39;s input.&lt;/p&gt;
&lt;p&gt;After &lt;code&gt;=&amp;gt;&lt;/code&gt;, the source lists the exact kinds and names of the declarations that will be generated. You do not need to write these lists by hand: &lt;code&gt;tauto fmt --fill-generated main.taut&lt;/code&gt; fills in missing lists and corrects mismatched ones in that file and the files it imports, writing the results back to source.&lt;/p&gt;
&lt;p&gt;The list is required for &lt;code&gt;syntax!&lt;/code&gt;, &lt;code&gt;inductive_syntax!&lt;/code&gt;, attribute macros, and other declaration-generating calls. Generating an unlisted declaration is an error, as is listing a declaration that is not generated. “Why list generated declarations?” below explains why the list remains explicit in the source.&lt;/p&gt;
&lt;p&gt;Here is the caller:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;swap.taut&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; tmp &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; other &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hl-macro&quot;&gt;swap!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`tmp other`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;perform&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;tmp&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tmp&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;perform&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;other&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; other&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto macro expand main.taut
var tmp :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
var other :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
let tmp&lt;span class=&quot;hl-comment&quot;&gt;#1 := tmp&lt;/span&gt;
tmp :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; other
other :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;hl-comment&quot;&gt;#1&lt;/span&gt;
perform show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;tmp&amp;quot;&lt;/span&gt;, tmp&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
perform show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;other&amp;quot;&lt;/span&gt;, other&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;

$ tauto run main.taut
tmp &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
other &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The macro&#39;s temporary variable &lt;code&gt;tmp&lt;/code&gt; becomes &lt;code&gt;tmp#1&lt;/code&gt;, avoiding a collision with the caller&#39;s &lt;code&gt;tmp&lt;/code&gt;. The &lt;code&gt;#1&lt;/code&gt; is a display name; when &lt;code&gt;--write&lt;/code&gt; writes the expansion back to source, it becomes an ordinary name that does not collide. This illustrates the hygiene mechanism discussed below. You can inspect expansions at any time with &lt;code&gt;tauto macro expand&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The DSL inside the backtick fences can also have its own formatter and syntax highlighting. Register the functions with &lt;code&gt;with&lt;/code&gt; at the end of &lt;code&gt;syntax!&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;swp&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
…
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp_fmt&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tokens&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp_tokens&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;fmt&lt;/code&gt; is called when &lt;code&gt;tauto fmt&lt;/code&gt; formats the contents of a syntax literal such as &lt;code&gt;swp`…` &lt;/code&gt;. &lt;code&gt;tokens&lt;/code&gt; is called when the language server highlights it. The grammar author defines &lt;code&gt;swp_fmt&lt;/code&gt; and &lt;code&gt;swp_tokens&lt;/code&gt; as ordinary Tauto functions. Without registration, the contents are left unformatted and highlighting is inferred from terminal names. More details appear in “Registering formatters and syntax highlighting” below.&lt;/p&gt;
&lt;h3 id=&quot;untyped-macros&quot;&gt;Untyped macros: reinterpret an expression&lt;/h3&gt;&lt;p&gt;An untyped macro receives anything that parses as a Tauto expression as a syntax value, &lt;strong&gt;without type-checking it first&lt;/strong&gt;. The standard library&#39;s &lt;code&gt;nat!&lt;/code&gt; reinterprets &lt;code&gt;==&lt;/code&gt; as propositional equality &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; as &lt;code&gt;Nat::add&lt;/code&gt;, allowing theorem statements to look like mathematical expressions:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;add_comm_stmt&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;nat!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;==&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_comm&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Because it runs before checking, it cannot inspect types. In return, it can accept expressions that would not otherwise type-check, such as an expression using &lt;code&gt;==&lt;/code&gt; where that operator is not defined.&lt;/p&gt;
&lt;h3 id=&quot;typed-macros&quot;&gt;Typed macros: inspect types and context&lt;/h3&gt;&lt;p&gt;A typed macro receives a checked expression as an opaque &lt;code&gt;Judgement&lt;/code&gt; value containing its context, term, type, effect row, and variable usage. It runs only after the declaration containing the call has been checked once without macro expansion. &lt;strong&gt;User code never runs in the middle of type inference.&lt;/strong&gt; This structurally rules out a cycle in which a macro inspects a type and then changes the type based on what it finds.&lt;/p&gt;
&lt;p&gt;The output is accepted only if its type is &lt;strong&gt;definitionally equal&lt;/strong&gt; to the original expression&#39;s type, its effect row is a &lt;strong&gt;subset of the original row&lt;/strong&gt;, and the &lt;strong&gt;entire declaration passes checking again&lt;/strong&gt;. Ownership, borrowing, and linearity are also checked across the whole expanded declaration. Matching types alone is not treated as a sufficient safety check.&lt;/p&gt;
&lt;p&gt;If you also want to preserve meaning, you can choose the &lt;code&gt;Proved&lt;/code&gt; result form, which returns a proof of equality &lt;code&gt;e = e&#39;&lt;/code&gt; alongside the transformation. The kernel checks that proof.&lt;/p&gt;
&lt;h3 id=&quot;tactics&quot;&gt;Tactics: macros that construct proofs&lt;/h3&gt;&lt;p&gt;A macro taking &lt;code&gt;ProofStep&lt;/code&gt; can be used inside a proof. The kernel checks the term it constructs &lt;strong&gt;against the explicitly written goal&lt;/strong&gt;. Even if a tactic produces an incorrect proof, the kernel decides whether to accept it; the tactic itself does not need to be trusted.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;rewrite!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_comm&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;),&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  ⊢ &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;),&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; from &lt;span class=&quot;hl-keyword&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;rewrite!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_succ_left&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
    ⊢ &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; from &lt;span class=&quot;hl-type&quot;&gt;Refl&lt;/span&gt;
  &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;rewrite!&lt;/code&gt; is a standard-library tactic. Since the goal is written at every step, readers can follow the proof without knowing how the tactic is implemented.&lt;/p&gt;
&lt;h3 id=&quot;attribute-macros&quot;&gt;Attribute macros: generate declarations&lt;/h3&gt;&lt;p&gt;Writing &lt;code&gt;@name!(…)&lt;/code&gt; before a declaration lets a macro generate declarations. This is a separate axis from the four kinds above: “attribute macro” describes the call&#39;s position, rather than a kind determined by its input type. The macro itself is a syntax macro or an untyped macro.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-operator&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;hl-macro&quot;&gt;mode!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`lookup(rec G, in i, out A) -&amp;gt; Looked { HasFound | HasNone }`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Looked&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;lookup&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Has&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Ty&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Ty&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prop&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This uses the standard library&#39;s &lt;code&gt;mode!&lt;/code&gt; to turn the inductive relation below it into a decision function with uniquely determined outputs and a result type carrying a proof of correctness. It cannot transform arbitrary relations: the generator imposes conditions on the shapes of rules it accepts. The kernel checks the generated types and terms as usual.&lt;/p&gt;
&lt;p&gt;The list after &lt;code&gt;=&amp;gt;&lt;/code&gt; names the declarations generated &lt;strong&gt;in addition to&lt;/strong&gt; the original declaration, following the same listing rule. By default, the original declaration remains exactly as written. Rewriting it requires an explicit &lt;code&gt;replace&lt;/code&gt;. A handwritten declaration cannot silently turn into something else.&lt;/p&gt;
&lt;h3 id=&quot;generated-declarations&quot;&gt;Why list generated declarations?&lt;/h3&gt;&lt;p&gt;A declaration-generating macro must list its generated declarations after &lt;code&gt;=&amp;gt;&lt;/code&gt; at every call. The macro already knows what it generates, so this could seem like something to infer automatically. Requiring it is deliberate: people and AI tools reading the source should be able to trace where a name came from &lt;strong&gt;without expanding the macro&lt;/strong&gt;. Without the list, the origin of &lt;code&gt;Looked&lt;/code&gt; or &lt;code&gt;lookup&lt;/code&gt; would only become apparent after expansion. A mismatch between the list and the actual output is an error, so stale lists cannot remain unnoticed.&lt;/p&gt;
&lt;p&gt;You do not, however, need to write the list by hand:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto fmt --fill-generated main.taut
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This fills in missing or incorrect lists using the fixes suggested by the diagnostics. The completed list is written into the source, where readers can see it without expanding anything.&lt;/p&gt;
&lt;h2 id=&quot;hygiene&quot;&gt;Hygiene: macros do not capture the caller&amp;#39;s names&lt;/h2&gt;&lt;p&gt;Identifiers carry both a name and a set of scopes. Each expansion adds and removes a fresh scope on its output. This gives the following behavior:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identifiers introduced by a macro&#39;s &lt;code&gt;quote&lt;/code&gt; do not capture the caller&#39;s variables.&lt;/li&gt;
&lt;li&gt;Identifiers that came from the input resolve to the bindings intended by the caller.&lt;/li&gt;
&lt;li&gt;Global names written in the macro refer to declarations in its definition file, even if the caller has declarations with the same names.&lt;/li&gt;
&lt;li&gt;Intentional capture is possible only through an explicit operation, &lt;code&gt;Syn::ident_like&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Captures are marked as such in &lt;code&gt;tauto macro trace&lt;/code&gt; and are prohibited by lint in the standard library. The policy is to make hidden bindings visible.&lt;/p&gt;
&lt;h2 id=&quot;effects&quot;&gt;Using effect analysis to contain macro execution&lt;/h2&gt;&lt;p&gt;Macros execute arbitrary code at compile time. Rust procedural macros run with the compiler process&#39;s privileges, so they can access files and the network. Tauto restricts this through &lt;strong&gt;effect rows in the type system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A macro function&#39;s effect row must be a subset of &lt;code&gt;{macro_error, macro_warn, elab, Div}&lt;/code&gt;. A function with any other effect cannot be registered as a macro.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;leak&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;SynExpr&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;macro_error&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; _ &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; read_file&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;/etc/passwd&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FAILED  macro: main.taut:2:10: macro.row: the function of a macro may perform macro_error, macro_warn, elab and Div, and `leak` performs fs_read
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Reading a file performs &lt;code&gt;fs_read&lt;/code&gt;, which is not allowed in a macro&#39;s row, so the macro is rejected. The same applies to networking, environment variables, the clock, randomness, and standard output.&lt;/p&gt;
&lt;p&gt;Even if a standard effect were about to execute despite this check, the host running the macro would refuse to handle it and report an error. Directly calling built-in functions that access files or the network is rejected too.&lt;/p&gt;
&lt;h3 id=&quot;nontermination&quot;&gt;What about infinite loops?&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Div&lt;/code&gt; marks functions that may diverge. It is allowed in macros so they can use recursion and &lt;code&gt;while&lt;/code&gt;, but macro execution is subject to budgets.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;spin&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; i64&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; i64 &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; spin&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;loopy&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;SynExpr&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;macro_error&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; _ &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; spin&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FAILED  macro: main2.taut:2:10: macro.budget_exceeded: macro loopy took more than 10000000 steps
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Budgets cover steps per call (10⁷ by default), the total per file (10⁸), expansion depth (64), output nodes (10⁵), and evaluator memory allocations (10⁷). Exceeding one produces a diagnostic and fails that declaration, while checking continues with the next declaration. Huge outputs and chains in which macros keep calling more macros are stopped in the same way. DSL strings are also limited to 1 MiB, and the parsing stack to a depth of 10⁴.&lt;/p&gt;
&lt;p&gt;Macros also cannot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emit &lt;code&gt;axiom&lt;/code&gt;, &lt;code&gt;extern&lt;/code&gt;, or &lt;code&gt;import&lt;/code&gt;, silently extending the set of things that must be trusted.&lt;/li&gt;
&lt;li&gt;Create a hole such as &lt;code&gt;?h&lt;/code&gt;: syntax values have no constructor for holes.&lt;/li&gt;
&lt;li&gt;Put &lt;code&gt;include_text!&lt;/code&gt; into their output to read a file. Includes run before macro expansion, and only for calls explicitly written in the source.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even a malicious macro from a dependency can only emit code that could be written by hand, within the allowed effects and execution budgets. Those effects include diagnostics. You can inspect its output with &lt;code&gt;tauto macro expand&lt;/code&gt;, and the kernel ultimately checks it.&lt;/p&gt;
&lt;h2 id=&quot;syntax-system&quot;&gt;A powerful syntax-macro system&lt;/h2&gt;&lt;h3 id=&quot;generated-ast&quot;&gt;Write a grammar, get a typed AST and parser&lt;/h3&gt;&lt;p&gt;A grammar passed to &lt;code&gt;syntax!&lt;/code&gt; automatically produces a typed AST using &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt; for its nonterminals, together with a &lt;code&gt;parse&lt;/code&gt; function that is also usable at runtime. It can even be used directly as a syntax literal, without invoking a macro: &lt;code&gt;math`1 + 2 = 3` &lt;/code&gt; produces a &lt;code&gt;math::Eqn&lt;/code&gt; value without running a macro.&lt;/p&gt;
&lt;p&gt;The grammar notation is the same parol format used by &lt;code&gt;tauto.par&lt;/code&gt;, which defines Tauto&#39;s own syntax. Users can therefore add their own languages using the same notation used for Tauto itself. Parsing is table-driven. The tables generated from a grammar are ordinary files that can be committed under &lt;code&gt;.tauto-syntax/&lt;/code&gt;; the grammar generator does not have to run on every build.&lt;/p&gt;
&lt;h3 id=&quot;left-recursion&quot;&gt;Left recursion: LL(k) and LALR(1)&lt;/h3&gt;&lt;p&gt;The default grammar class is LL(k), with lookahead k ≤ 3. Since left recursion is not allowed there, operators are expressed using repetition, such as &lt;code&gt;{ Plus Term }&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more natural left recursion or operator precedence, specify &lt;code&gt;%grammar_type &#39;LALR(1)&#39;&lt;/code&gt; to generate an LALR(1) table:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;grammar_type &amp;#39;&lt;span class=&quot;hl-type&quot;&gt;LALR&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&amp;#39;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; r &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; ex&lt;span class=&quot;hl-string&quot;&gt;`1 + 2 + 3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The left-recursive production &lt;code&gt;E: E Plus T&lt;/code&gt; works as written. Removing the &lt;code&gt;%grammar_type&lt;/code&gt; line makes the grammar LL(k); lookahead conflicts then cause &lt;code&gt;tauto syntax gen&lt;/code&gt; to reject it.&lt;/p&gt;
&lt;p&gt;Both kinds of tables are generated by programs written in Tauto itself, in Nib: &lt;code&gt;totes/llkgen&lt;/code&gt; and &lt;code&gt;totes/lalrgen&lt;/code&gt;. The LALR(1) generator is written to construct the same states as lalry, the library used by parol, and tests compare their outputs. This is part of self-hosting Tauto&#39;s grammar infrastructure.&lt;/p&gt;
&lt;p&gt;Ambiguous grammars are reported as conflicts. They are not accepted by retaining multiple parse results or hiding the ambiguity behind ordered choice. This keeps the typed AST unambiguous.&lt;/p&gt;
&lt;h3 id=&quot;syntax-errors&quot;&gt;Syntax errors report locations and expectations&lt;/h3&gt;&lt;p&gt;An error inside a DSL points to the actual line and column within the call&#39;s string and lists the terminals expected there:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;2 + * 3 =&amp;gt; error: macro.syntax_error: in calc: expected Num or LParen, found Star
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For indented multiline literals, locations are adjusted for the indentation removed during parsing, so they still point to what the user wrote.&lt;/p&gt;
&lt;h3 id=&quot;formatting-and-highlighting&quot;&gt;Registering formatters and syntax highlighting&lt;/h3&gt;&lt;p&gt;&lt;code&gt;syntax!&lt;/code&gt; accepts &lt;code&gt;with(fmt: …, tokens: …)&lt;/code&gt; to attach functions that handle text in that syntax:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;layout&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;title &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;layout&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Comma&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Word&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Word&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;a&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;z&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Comma&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; layout_fmt&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tokens&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; layout_tokens&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Doc_Rep1&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; d &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; layout&lt;span class=&quot;hl-string&quot;&gt;`1,2 ,   foo,3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When &lt;code&gt;tauto fmt&lt;/code&gt; finds a literal in this syntax, it calls &lt;code&gt;layout_fmt&lt;/code&gt; to format the contents:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; d &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; layout&lt;span class=&quot;hl-string&quot;&gt;`1, 2, foo, 3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;layout_fmt&lt;/code&gt; and &lt;code&gt;layout_tokens&lt;/code&gt; are ordinary Tauto functions that take a list of &lt;code&gt;SynTok&lt;/code&gt; values (a token stream including whitespace and comments) or a lossless concrete syntax tree, &lt;code&gt;SynCst&lt;/code&gt;. The ranges returned by &lt;code&gt;tokens&lt;/code&gt; determine the language server&#39;s highlighting. Without a registered function, highlighting is inferred from terminal names.&lt;/p&gt;
&lt;p&gt;The only effects these functions may have are &lt;code&gt;Div&lt;/code&gt; and &lt;code&gt;macro_error&lt;/code&gt;. They cannot access files or other external resources.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$name&lt;/code&gt; and &lt;code&gt;${…}&lt;/code&gt; inside a DSL are always highlighted as Tauto, whether or not &lt;code&gt;tokens&lt;/code&gt; is registered. Any ranges returned by &lt;code&gt;tokens&lt;/code&gt; that overlap these interpolations are trimmed. If the token function fails type checking, reports an error, or returns a range outside the text, the literal falls back to highlighting based on terminal names and gets a warning explaining why.&lt;/p&gt;
&lt;p&gt;Formatters are also constrained. Before writing a result back, &lt;code&gt;tauto fmt&lt;/code&gt; checks three things, keeping the original text and issuing a warning if any check fails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The result parses as the same syntax.&lt;/li&gt;
&lt;li&gt;The token sequence, excluding whitespace, is unchanged.&lt;/li&gt;
&lt;li&gt;Formatting again leaves the result unchanged: the formatter is idempotent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A formatter bug therefore cannot change tokens or leave the literal unparsable. These checks are not sufficient, however, for syntax where whitespace changes can change meaning, such as an indentation-sensitive grammar. Authors of &lt;code&gt;fmt&lt;/code&gt; functions for such grammars still need to handle that carefully.&lt;/p&gt;
&lt;h3 id=&quot;embedded-expressions&quot;&gt;Embedding Tauto expressions in a grammar&lt;/h3&gt;&lt;p&gt;The reserved terminal &lt;code&gt;TautoExpr&lt;/code&gt; lets you embed a Tauto expression inside a DSL with &lt;code&gt;${ … }&lt;/code&gt;. The standard library&#39;s &lt;code&gt;nat!&lt;/code&gt; uses this to embed Tauto expressions in mathematical notation:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;mul_comm&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;nat!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`$n * $m = $m * $n`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;$n&lt;/code&gt; refers to the variable &lt;code&gt;n&lt;/code&gt;, while &lt;code&gt;${Succ(k)}&lt;/code&gt; is an expression. Embedded expressions retain their actual source locations.&lt;/p&gt;
&lt;h3 id=&quot;proving-language-tools&quot;&gt;Build and prove a language implementation&lt;/h3&gt;&lt;p&gt;In addition to the &lt;code&gt;struct&lt;/code&gt;/&lt;code&gt;enum&lt;/code&gt; AST, &lt;code&gt;inductive_syntax!&lt;/code&gt; generates proof-side &lt;code&gt;inductive&lt;/code&gt; types, with an &lt;code&gt;::I&lt;/code&gt; suffix such as &lt;code&gt;Expr::I&lt;/code&gt;, and conversion functions such as &lt;code&gt;Expr::to_i&lt;/code&gt;. You can then state theorems about the AST generated from the grammar.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;examples/calc&lt;/code&gt; is a small language implementation that reads arithmetic expressions with addition and multiplication from text:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;inductive_syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;arith&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;title &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;calc&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Star&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Paren&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Paren&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;LParen&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;RParen&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Star&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;*&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;LParen&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;RParen&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;to_i&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; …
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto check examples/calc/proof/calc.taut
&lt;span class=&quot;hl-number&quot;&gt;10&lt;/span&gt; ok, &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; failed, &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; incomplete&lt;span class=&quot;hl-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; skipped, &lt;span class=&quot;hl-number&quot;&gt;124&lt;/span&gt; from imports&lt;span class=&quot;hl-operator&quot;&gt;;&lt;/span&gt; axioms: none
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Among the properties proved here is &lt;code&gt;calc_run_correct&lt;/code&gt;: for any syntax tree, the compiled code runs without a stack underflow and leaves the value represented by that tree on the stack. The proofs check without additional axioms: &lt;code&gt;axioms: none&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Some parts remain unproved. The text-to-tree parser &lt;code&gt;arith::parse&lt;/code&gt; and the conversion &lt;code&gt;to_i&lt;/code&gt; are outside these proofs. The parser is a driver over the tables produced by the grammar generator, and its correctness has not yet been formally established. There is no formal proof yet that the text has the meaning represented by the tree. What can currently be proved is soundness and completeness &lt;strong&gt;from the tree returned by the parser onward&lt;/strong&gt;. Getting the AST as an &lt;code&gt;inductive&lt;/code&gt; type makes it possible to start writing a proof of the parser itself; that proof is not complete.&lt;/p&gt;
&lt;h2 id=&quot;other-features&quot;&gt;More useful properties&lt;/h2&gt;&lt;h3 id=&quot;expansion-tracing&quot;&gt;Every expansion can be traced&lt;/h3&gt;&lt;p&gt;Every node generated by a macro carries provenance: its call site, definition site, whether it was generated, and the chain of nested expansions. Diagnostics follow that chain to show which macro introduced what, for example: “&lt;code&gt;x&lt;/code&gt; (introduced by expansion of &lt;code&gt;math&lt;/code&gt;).”&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;tauto macro expand &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--all &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --at LINE:COL &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --write &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --json&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; FILE   &lt;span class=&quot;hl-comment&quot;&gt;# inspect or write back the expansion&lt;/span&gt;
tauto macro trace &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--json &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --diff&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; FILE                    &lt;span class=&quot;hl-comment&quot;&gt;# trace expansion steps&lt;/span&gt;
tauto macro inspect FILE --at LINE:COL &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--json&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;
tauto check --json                                           &lt;span class=&quot;hl-comment&quot;&gt;# list expansions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With &lt;code&gt;--write&lt;/code&gt;, you can write an expansion back to source and keep a version that no longer uses the macro. All these commands support &lt;code&gt;--json&lt;/code&gt;, allowing AI agents to inspect macro expansion programmatically.&lt;/p&gt;
&lt;h3 id=&quot;declaration-environment&quot;&gt;Typed macros do not change the declaration environment&lt;/h3&gt;&lt;p&gt;Only syntax macros and attribute macros can generate declarations. A typed macro changes only the expression at its call site.&lt;/p&gt;
&lt;h3 id=&quot;typing-judgments&quot;&gt;Write typing judgments in a DSL&lt;/h3&gt;&lt;p&gt;In &lt;code&gt;examples/lambda&lt;/code&gt;, theorems about typing and reduction in the simply typed lambda calculus can be written directly in the calculus&#39;s notation. A syntax named &lt;code&gt;lc&lt;/code&gt; parses contextual judgments using a grammar containing &lt;code&gt;|-&lt;/code&gt; and &lt;code&gt;~&amp;gt;*&lt;/code&gt;, and is also used inside proofs:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;k_star&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;lc!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`(fun x: unit. fun y: unit. x) star ~&amp;gt;* fun y: unit. star`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;expansion-order&quot;&gt;Macro execution is ordered by file&lt;/h3&gt;&lt;p&gt;You can only use macros defined in an earlier file or in a dependency tote (a package). Defining and using a macro in the same file is an error. This makes the timing of macro execution visible at a unit a reader can understand.&lt;/p&gt;
&lt;h2 id=&quot;deliberate-restrictions&quot;&gt;Deliberate restrictions&lt;/h2&gt;&lt;p&gt;Here are the restrictions discussed above. These are freedoms found in some other macro systems that Tauto deliberately does not provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access files, the network, environment variables, time, randomness, or standard output from a macro.&lt;/strong&gt; Instead, &lt;code&gt;include_text!&lt;/code&gt; reads a file only at an explicitly written call site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate declarations or change the environment from a typed macro.&lt;/strong&gt; Instead, syntax and attribute macros generate declarations, with the generated names listed in advance after &lt;code&gt;=&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run a macro in the middle of type inference.&lt;/strong&gt; Instead, a typed macro receives a checked expression as a &lt;code&gt;Judgement&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Put &lt;code&gt;axiom&lt;/code&gt;, &lt;code&gt;extern&lt;/code&gt;, &lt;code&gt;import&lt;/code&gt;, or a hole such as &lt;code&gt;?h&lt;/code&gt; in macro output.&lt;/strong&gt; Instead, emit code that can be written by hand, subject to these output restrictions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silently replace a handwritten declaration.&lt;/strong&gt; Instead, explicitly request replacement with &lt;code&gt;replace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a macro in the same file where it is defined.&lt;/strong&gt; Instead, use a macro from an earlier file or a dependency tote.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silently capture a variable.&lt;/strong&gt; Instead, explicitly capture it with &lt;code&gt;Syn::ident_like&lt;/code&gt;, leaving a trace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guarantee the output&#39;s type when the macro itself is written.&lt;/strong&gt; Instead, check the expansion with the same checkers used for handwritten code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these freedoms can be useful. Tauto draws these boundaries to keep the trusted implementation small and expansions readable.&lt;/p&gt;
&lt;h2 id=&quot;design-priorities&quot;&gt;Design priorities&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Soundness: do not accept invalid types, proofs, or authority.&lt;/li&gt;
&lt;li&gt;Minimalism: minimize concepts, special rules, and trusted implementation.&lt;/li&gt;
&lt;li&gt;Composability.&lt;/li&gt;
&lt;li&gt;Expressiveness.&lt;/li&gt;
&lt;li&gt;Security.&lt;/li&gt;
&lt;li&gt;Readability for AI: machine-readable ASTs, types, errors, and expansion steps.&lt;/li&gt;
&lt;li&gt;Performance.&lt;/li&gt;
&lt;li&gt;Self-hosting.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;limits&quot;&gt;What is not guaranteed&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Proving the runtime evaluator correct is planned at the model level in Lean; correspondence with the Rust evaluator is checked by tests. A flaw in the evaluator could break macro isolation.&lt;/li&gt;
&lt;li&gt;Macros are not prevented from &lt;strong&gt;generating&lt;/strong&gt; code that performs dangerous actions. That code is treated the same way as the equivalent handwritten code, and can be inspected with &lt;code&gt;tauto macro expand&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A macro close to a resource budget may succeed or fail differently after an evaluator version change. Usage above 90% of the limit produces a warning.&lt;/li&gt;
&lt;li&gt;As noted above, the correctness of the grammar-generated parser remains unproved.&lt;/li&gt;
&lt;li&gt;The language is still experimental. Syntax and diagnostic messages shown here may change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Macros are ordinary functions returning syntax values. Their input types determine their kinds.&lt;/li&gt;
&lt;li&gt;Expansions are checked by the same checkers as handwritten code, keeping macros out of the trusted base.&lt;/li&gt;
&lt;li&gt;Hygiene uses scope sets. Capture requires an explicit operation and leaves a trace.&lt;/li&gt;
&lt;li&gt;Effect rows prevent file and network access. Macros may use &lt;code&gt;Div&lt;/code&gt;, but execution budgets turn nontermination into diagnostics.&lt;/li&gt;
&lt;li&gt;Writing an LL(k) or LALR(1) grammar gives a syntax macro a typed AST, parser, and syntax literals. Formatters and highlighting can also be registered.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inductive_syntax!&lt;/code&gt; brings ASTs into the proof world, making it possible to state theorems about language implementations. The parser itself remains unproved.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Hihaheho/tauto&quot;&gt;Tauto on GitHub&lt;/a&gt;&lt;/p&gt;
</description><content:encoded>&lt;p&gt;Tauto combines a dependently typed proof system with a runtime featuring algebraic effects and ownership. This article introduces its &lt;strong&gt;macro system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;“The world&#39;s most powerful” is a bold claim for a title. The aim is to bring everything I want from macros into a single design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add new syntax and DSLs as libraries, complete with registered formatters and syntax highlighting.&lt;/li&gt;
&lt;li&gt;Write macros that transform code based on its types and macros that build proofs, called tactics, using the same mechanism.&lt;/li&gt;
&lt;li&gt;Keep expansion hygienic, so macros do not capture the caller&#39;s variables.&lt;/li&gt;
&lt;li&gt;Run untrusted macros without giving them file access, without unbounded execution, and without compromising proof soundness.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Hihaheho/tauto&quot;&gt;Tauto on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;nav aria-label=&quot;Table of contents&quot; class=&quot;toc&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#ordinary-functions&quot;&gt;Macros are ordinary functions that return syntax values&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#macro-kinds&quot;&gt;Macro kinds and when to use them&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#syntax-macros&quot;&gt;Syntax macros: write in your own grammar&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#untyped-macros&quot;&gt;Untyped macros: reinterpret an expression&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#typed-macros&quot;&gt;Typed macros: inspect types and context&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#tactics&quot;&gt;Tactics: macros that construct proofs&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#attribute-macros&quot;&gt;Attribute macros: generate declarations&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#generated-declarations&quot;&gt;Why list generated declarations?&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#hygiene&quot;&gt;Hygiene: macros do not capture the caller&amp;#39;s names&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#effects&quot;&gt;Using effect analysis to contain macro execution&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#nontermination&quot;&gt;What about infinite loops?&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#syntax-system&quot;&gt;A powerful syntax-macro system&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#generated-ast&quot;&gt;Write a grammar, get a typed AST and parser&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#left-recursion&quot;&gt;Left recursion: LL(k) and LALR(1)&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#syntax-errors&quot;&gt;Syntax errors report locations and expectations&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#formatting-and-highlighting&quot;&gt;Registering formatters and syntax highlighting&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#embedded-expressions&quot;&gt;Embedding Tauto expressions in a grammar&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#proving-language-tools&quot;&gt;Build and prove a language implementation&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#other-features&quot;&gt;More useful properties&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#expansion-tracing&quot;&gt;Every expansion can be traced&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#declaration-environment&quot;&gt;Typed macros do not change the declaration environment&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#typing-judgments&quot;&gt;Write typing judgments in a DSL&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#expansion-order&quot;&gt;Macro execution is ordered by file&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#deliberate-restrictions&quot;&gt;Deliberate restrictions&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#design-priorities&quot;&gt;Design priorities&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#limits&quot;&gt;What is not guaranteed&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;ul&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/nav&gt;&lt;h2 id=&quot;ordinary-functions&quot;&gt;Macros are ordinary functions that return syntax values&lt;/h2&gt;&lt;p&gt;Tauto macros are &lt;strong&gt;ordinary functions&lt;/strong&gt;, rather than programs in a separate macro or template language. They take and return syntax values, represented by AST data types such as &lt;code&gt;SynExpr&lt;/code&gt; and &lt;code&gt;SynStmt&lt;/code&gt;, assembled with &lt;code&gt;quote { … }&lt;/code&gt; and &lt;code&gt;$x&lt;/code&gt;. Calls are always explicit: &lt;code&gt;NAME!(…)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Whatever a macro produces, the expanded program goes through the same path as a handwritten program: the kernel and a second, independently implemented kernel. You do not need to trust the macro&#39;s generation logic to preserve type or proof soundness.&lt;/p&gt;
&lt;h2 id=&quot;macro-kinds&quot;&gt;Macro kinds and when to use them&lt;/h2&gt;&lt;p&gt;There are four kinds of macros. &lt;strong&gt;The function&#39;s input type alone determines the kind.&lt;/strong&gt; There is no keyword such as &lt;code&gt;typed macro&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Syntax macro:&lt;/strong&gt; takes a typed AST generated from a grammar. Call it as &lt;code&gt;name!(`…`)&lt;/code&gt; to introduce notation or a DSL.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Untyped macro:&lt;/strong&gt; takes &lt;code&gt;SynExpr&lt;/code&gt;. Call it as &lt;code&gt;name!(a + b)&lt;/code&gt; to reinterpret an expression.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typed macro:&lt;/strong&gt; takes &lt;code&gt;Judgement&lt;/code&gt;. Call it as &lt;code&gt;name!(e)&lt;/code&gt; to transform code using its type and context.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tactic:&lt;/strong&gt; takes &lt;code&gt;ProofStep&lt;/code&gt;. Call it as &lt;code&gt;by name!(…): G { … }&lt;/code&gt; to automate proofs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;syntax-macros&quot;&gt;Syntax macros: write in your own grammar&lt;/h3&gt;&lt;p&gt;A syntax macro parses its input using a grammar declared with &lt;code&gt;syntax!&lt;/code&gt;. As an example, here is &lt;code&gt;swap!&lt;/code&gt;, which swaps two variables.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;swp&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;_&lt;span class=&quot;hl-punctuation&quot;&gt;][&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;\p&lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;_&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;*/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;

pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;swap&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;SynStmt&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; a &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Syn&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;ident&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Syn&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;ident&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;name_2&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote stmts &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; tmp &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;$a&lt;/span&gt;
    &lt;span class=&quot;hl-variable&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-variable&quot;&gt;$b&lt;/span&gt;
    &lt;span class=&quot;hl-variable&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; tmp
  &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The grammar lives in a fenced block tagged &lt;code&gt;par&lt;/code&gt;. It automatically generates a typed AST called &lt;code&gt;swp::Pair&lt;/code&gt;, which becomes the macro function&#39;s input.&lt;/p&gt;
&lt;p&gt;After &lt;code&gt;=&amp;gt;&lt;/code&gt;, the source lists the exact kinds and names of the declarations that will be generated. You do not need to write these lists by hand: &lt;code&gt;tauto fmt --fill-generated main.taut&lt;/code&gt; fills in missing lists and corrects mismatched ones in that file and the files it imports, writing the results back to source.&lt;/p&gt;
&lt;p&gt;The list is required for &lt;code&gt;syntax!&lt;/code&gt;, &lt;code&gt;inductive_syntax!&lt;/code&gt;, attribute macros, and other declaration-generating calls. Generating an unlisted declaration is an error, as is listing a declaration that is not generated. “Why list generated declarations?” below explains why the list remains explicit in the source.&lt;/p&gt;
&lt;p&gt;Here is the caller:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;swap.taut&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; tmp &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; other &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;hl-macro&quot;&gt;swap!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`tmp other`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;perform&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;tmp&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tmp&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;perform&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;other&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; other&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto macro expand main.taut
var tmp :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
var other :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
let tmp&lt;span class=&quot;hl-comment&quot;&gt;#1 := tmp&lt;/span&gt;
tmp :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; other
other :&lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;hl-comment&quot;&gt;#1&lt;/span&gt;
perform show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;tmp&amp;quot;&lt;/span&gt;, tmp&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
perform show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;other&amp;quot;&lt;/span&gt;, other&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;

$ tauto run main.taut
tmp &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;2&lt;/span&gt;
other &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The macro&#39;s temporary variable &lt;code&gt;tmp&lt;/code&gt; becomes &lt;code&gt;tmp#1&lt;/code&gt;, avoiding a collision with the caller&#39;s &lt;code&gt;tmp&lt;/code&gt;. The &lt;code&gt;#1&lt;/code&gt; is a display name; when &lt;code&gt;--write&lt;/code&gt; writes the expansion back to source, it becomes an ordinary name that does not collide. This illustrates the hygiene mechanism discussed below. You can inspect expansions at any time with &lt;code&gt;tauto macro expand&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The DSL inside the backtick fences can also have its own formatter and syntax highlighting. Register the functions with &lt;code&gt;with&lt;/code&gt; at the end of &lt;code&gt;syntax!&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;swp&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
…
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp_fmt&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tokens&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp_tokens&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;fmt&lt;/code&gt; is called when &lt;code&gt;tauto fmt&lt;/code&gt; formats the contents of a syntax literal such as &lt;code&gt;swp`…` &lt;/code&gt;. &lt;code&gt;tokens&lt;/code&gt; is called when the language server highlights it. The grammar author defines &lt;code&gt;swp_fmt&lt;/code&gt; and &lt;code&gt;swp_tokens&lt;/code&gt; as ordinary Tauto functions. Without registration, the contents are left unformatted and highlighting is inferred from terminal names. More details appear in “Registering formatters and syntax highlighting” below.&lt;/p&gt;
&lt;h3 id=&quot;untyped-macros&quot;&gt;Untyped macros: reinterpret an expression&lt;/h3&gt;&lt;p&gt;An untyped macro receives anything that parses as a Tauto expression as a syntax value, &lt;strong&gt;without type-checking it first&lt;/strong&gt;. The standard library&#39;s &lt;code&gt;nat!&lt;/code&gt; reinterprets &lt;code&gt;==&lt;/code&gt; as propositional equality &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; as &lt;code&gt;Nat::add&lt;/code&gt;, allowing theorem statements to look like mathematical expressions:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;add_comm_stmt&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;nat!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;==&lt;/span&gt; b &lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_comm&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Because it runs before checking, it cannot inspect types. In return, it can accept expressions that would not otherwise type-check, such as an expression using &lt;code&gt;==&lt;/code&gt; where that operator is not defined.&lt;/p&gt;
&lt;h3 id=&quot;typed-macros&quot;&gt;Typed macros: inspect types and context&lt;/h3&gt;&lt;p&gt;A typed macro receives a checked expression as an opaque &lt;code&gt;Judgement&lt;/code&gt; value containing its context, term, type, effect row, and variable usage. It runs only after the declaration containing the call has been checked once without macro expansion. &lt;strong&gt;User code never runs in the middle of type inference.&lt;/strong&gt; This structurally rules out a cycle in which a macro inspects a type and then changes the type based on what it finds.&lt;/p&gt;
&lt;p&gt;The output is accepted only if its type is &lt;strong&gt;definitionally equal&lt;/strong&gt; to the original expression&#39;s type, its effect row is a &lt;strong&gt;subset of the original row&lt;/strong&gt;, and the &lt;strong&gt;entire declaration passes checking again&lt;/strong&gt;. Ownership, borrowing, and linearity are also checked across the whole expanded declaration. Matching types alone is not treated as a sufficient safety check.&lt;/p&gt;
&lt;p&gt;If you also want to preserve meaning, you can choose the &lt;code&gt;Proved&lt;/code&gt; result form, which returns a proof of equality &lt;code&gt;e = e&#39;&lt;/code&gt; alongside the transformation. The kernel checks that proof.&lt;/p&gt;
&lt;h3 id=&quot;tactics&quot;&gt;Tactics: macros that construct proofs&lt;/h3&gt;&lt;p&gt;A macro taking &lt;code&gt;ProofStep&lt;/code&gt; can be used inside a proof. The kernel checks the term it constructs &lt;strong&gt;against the explicitly written goal&lt;/strong&gt;. Even if a tactic produces an incorrect proof, the kernel decides whether to accept it; the tactic itself does not need to be trusted.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;rewrite!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_comm&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;),&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  ⊢ &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;),&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; from &lt;span class=&quot;hl-keyword&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;rewrite!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add_succ_left&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
    ⊢ &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Succ&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;add&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; a&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; from &lt;span class=&quot;hl-type&quot;&gt;Refl&lt;/span&gt;
  &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;rewrite!&lt;/code&gt; is a standard-library tactic. Since the goal is written at every step, readers can follow the proof without knowing how the tactic is implemented.&lt;/p&gt;
&lt;h3 id=&quot;attribute-macros&quot;&gt;Attribute macros: generate declarations&lt;/h3&gt;&lt;p&gt;Writing &lt;code&gt;@name!(…)&lt;/code&gt; before a declaration lets a macro generate declarations. This is a separate axis from the four kinds above: “attribute macro” describes the call&#39;s position, rather than a kind determined by its input type. The macro itself is a syntax macro or an untyped macro.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-operator&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;hl-macro&quot;&gt;mode!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`lookup(rec G, in i, out A) -&amp;gt; Looked { HasFound | HasNone }`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Looked&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;lookup&lt;/span&gt;
&lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Has&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Ty&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Ty&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prop&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This uses the standard library&#39;s &lt;code&gt;mode!&lt;/code&gt; to turn the inductive relation below it into a decision function with uniquely determined outputs and a result type carrying a proof of correctness. It cannot transform arbitrary relations: the generator imposes conditions on the shapes of rules it accepts. The kernel checks the generated types and terms as usual.&lt;/p&gt;
&lt;p&gt;The list after &lt;code&gt;=&amp;gt;&lt;/code&gt; names the declarations generated &lt;strong&gt;in addition to&lt;/strong&gt; the original declaration, following the same listing rule. By default, the original declaration remains exactly as written. Rewriting it requires an explicit &lt;code&gt;replace&lt;/code&gt;. A handwritten declaration cannot silently turn into something else.&lt;/p&gt;
&lt;h3 id=&quot;generated-declarations&quot;&gt;Why list generated declarations?&lt;/h3&gt;&lt;p&gt;A declaration-generating macro must list its generated declarations after &lt;code&gt;=&amp;gt;&lt;/code&gt; at every call. The macro already knows what it generates, so this could seem like something to infer automatically. Requiring it is deliberate: people and AI tools reading the source should be able to trace where a name came from &lt;strong&gt;without expanding the macro&lt;/strong&gt;. Without the list, the origin of &lt;code&gt;Looked&lt;/code&gt; or &lt;code&gt;lookup&lt;/code&gt; would only become apparent after expansion. A mismatch between the list and the actual output is an error, so stale lists cannot remain unnoticed.&lt;/p&gt;
&lt;p&gt;You do not, however, need to write the list by hand:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto fmt --fill-generated main.taut
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This fills in missing or incorrect lists using the fixes suggested by the diagnostics. The completed list is written into the source, where readers can see it without expanding anything.&lt;/p&gt;
&lt;h2 id=&quot;hygiene&quot;&gt;Hygiene: macros do not capture the caller&amp;#39;s names&lt;/h2&gt;&lt;p&gt;Identifiers carry both a name and a set of scopes. Each expansion adds and removes a fresh scope on its output. This gives the following behavior:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identifiers introduced by a macro&#39;s &lt;code&gt;quote&lt;/code&gt; do not capture the caller&#39;s variables.&lt;/li&gt;
&lt;li&gt;Identifiers that came from the input resolve to the bindings intended by the caller.&lt;/li&gt;
&lt;li&gt;Global names written in the macro refer to declarations in its definition file, even if the caller has declarations with the same names.&lt;/li&gt;
&lt;li&gt;Intentional capture is possible only through an explicit operation, &lt;code&gt;Syn::ident_like&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Captures are marked as such in &lt;code&gt;tauto macro trace&lt;/code&gt; and are prohibited by lint in the standard library. The policy is to make hidden bindings visible.&lt;/p&gt;
&lt;h2 id=&quot;effects&quot;&gt;Using effect analysis to contain macro execution&lt;/h2&gt;&lt;p&gt;Macros execute arbitrary code at compile time. Rust procedural macros run with the compiler process&#39;s privileges, so they can access files and the network. Tauto restricts this through &lt;strong&gt;effect rows in the type system&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A macro function&#39;s effect row must be a subset of &lt;code&gt;{macro_error, macro_warn, elab, Div}&lt;/code&gt;. A function with any other effect cannot be registered as a macro.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;leak&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;SynExpr&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;macro_error&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; _ &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; read_file&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;&amp;quot;/etc/passwd&amp;quot;&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FAILED  macro: main.taut:2:10: macro.row: the function of a macro may perform macro_error, macro_warn, elab and Div, and `leak` performs fs_read
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Reading a file performs &lt;code&gt;fs_read&lt;/code&gt;, which is not allowed in a macro&#39;s row, so the macro is rejected. The same applies to networking, environment variables, the clock, randomness, and standard output.&lt;/p&gt;
&lt;p&gt;Even if a standard effect were about to execute despite this check, the host running the macro would refuse to handle it and report an error. Directly calling built-in functions that access files or the network is rejected too.&lt;/p&gt;
&lt;h3 id=&quot;nontermination&quot;&gt;What about infinite loops?&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Div&lt;/code&gt; marks functions that may diverge. It is allowed in macros so they can use recursion and &lt;code&gt;while&lt;/code&gt;, but macro execution is subject to budgets.&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;spin&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; i64&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; i64 &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; spin&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
pub &lt;span class=&quot;hl-keyword&quot;&gt;macro&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;loopy&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; swp&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;SynExpr&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;macro_error&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Div&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; _ &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; spin&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  quote &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;FAILED  macro: main2.taut:2:10: macro.budget_exceeded: macro loopy took more than 10000000 steps
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Budgets cover steps per call (10⁷ by default), the total per file (10⁸), expansion depth (64), output nodes (10⁵), and evaluator memory allocations (10⁷). Exceeding one produces a diagnostic and fails that declaration, while checking continues with the next declaration. Huge outputs and chains in which macros keep calling more macros are stopped in the same way. DSL strings are also limited to 1 MiB, and the parsing stack to a depth of 10⁴.&lt;/p&gt;
&lt;p&gt;Macros also cannot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emit &lt;code&gt;axiom&lt;/code&gt;, &lt;code&gt;extern&lt;/code&gt;, or &lt;code&gt;import&lt;/code&gt;, silently extending the set of things that must be trusted.&lt;/li&gt;
&lt;li&gt;Create a hole such as &lt;code&gt;?h&lt;/code&gt;: syntax values have no constructor for holes.&lt;/li&gt;
&lt;li&gt;Put &lt;code&gt;include_text!&lt;/code&gt; into their output to read a file. Includes run before macro expansion, and only for calls explicitly written in the source.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even a malicious macro from a dependency can only emit code that could be written by hand, within the allowed effects and execution budgets. Those effects include diagnostics. You can inspect its output with &lt;code&gt;tauto macro expand&lt;/code&gt;, and the kernel ultimately checks it.&lt;/p&gt;
&lt;h2 id=&quot;syntax-system&quot;&gt;A powerful syntax-macro system&lt;/h2&gt;&lt;h3 id=&quot;generated-ast&quot;&gt;Write a grammar, get a typed AST and parser&lt;/h3&gt;&lt;p&gt;A grammar passed to &lt;code&gt;syntax!&lt;/code&gt; automatically produces a typed AST using &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt; for its nonterminals, together with a &lt;code&gt;parse&lt;/code&gt; function that is also usable at runtime. It can even be used directly as a syntax literal, without invoking a macro: &lt;code&gt;math`1 + 2 = 3` &lt;/code&gt; produces a &lt;code&gt;math::Eqn&lt;/code&gt; value without running a macro.&lt;/p&gt;
&lt;p&gt;The grammar notation is the same parol format used by &lt;code&gt;tauto.par&lt;/code&gt;, which defines Tauto&#39;s own syntax. Users can therefore add their own languages using the same notation used for Tauto itself. Parsing is table-driven. The tables generated from a grammar are ordinary files that can be committed under &lt;code&gt;.tauto-syntax/&lt;/code&gt;; the grammar generator does not have to run on every build.&lt;/p&gt;
&lt;h3 id=&quot;left-recursion&quot;&gt;Left recursion: LL(k) and LALR(1)&lt;/h3&gt;&lt;p&gt;The default grammar class is LL(k), with lookahead k ≤ 3. Since left recursion is not allowed there, operators are expressed using repetition, such as &lt;code&gt;{ Plus Term }&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more natural left recursion or operator precedence, specify &lt;code&gt;%grammar_type &#39;LALR(1)&#39;&lt;/code&gt; to generate an LALR(1) table:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;ex&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;grammar_type &amp;#39;&lt;span class=&quot;hl-type&quot;&gt;LALR&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&amp;#39;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;E&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; r &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; ex&lt;span class=&quot;hl-string&quot;&gt;`1 + 2 + 3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The left-recursive production &lt;code&gt;E: E Plus T&lt;/code&gt; works as written. Removing the &lt;code&gt;%grammar_type&lt;/code&gt; line makes the grammar LL(k); lookahead conflicts then cause &lt;code&gt;tauto syntax gen&lt;/code&gt; to reject it.&lt;/p&gt;
&lt;p&gt;Both kinds of tables are generated by programs written in Tauto itself, in Nib: &lt;code&gt;totes/llkgen&lt;/code&gt; and &lt;code&gt;totes/lalrgen&lt;/code&gt;. The LALR(1) generator is written to construct the same states as lalry, the library used by parol, and tests compare their outputs. This is part of self-hosting Tauto&#39;s grammar infrastructure.&lt;/p&gt;
&lt;p&gt;Ambiguous grammars are reported as conflicts. They are not accepted by retaining multiple parse results or hiding the ambiguity behind ordered choice. This keeps the typed AST unambiguous.&lt;/p&gt;
&lt;h3 id=&quot;syntax-errors&quot;&gt;Syntax errors report locations and expectations&lt;/h3&gt;&lt;p&gt;An error inside a DSL points to the actual line and column within the call&#39;s string and lists the terminals expected there:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;2 + * 3 =&amp;gt; error: macro.syntax_error: in calc: expected Num or LParen, found Star
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For indented multiline literals, locations are adjusted for the indentation removed during parsing, so they still point to what the user wrote.&lt;/p&gt;
&lt;h3 id=&quot;formatting-and-highlighting&quot;&gt;Registering formatters and syntax highlighting&lt;/h3&gt;&lt;p&gt;&lt;code&gt;syntax!&lt;/code&gt; accepts &lt;code&gt;with(fmt: …, tokens: …)&lt;/code&gt; to attach functions that handle text in that syntax:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;layout&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;title &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;layout&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Comma&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Word&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Word&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;a&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;z&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Comma&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fmt&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; layout_fmt&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; tokens&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; layout_tokens&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Doc&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Doc_Rep1&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; d &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; layout&lt;span class=&quot;hl-string&quot;&gt;`1,2 ,   foo,3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When &lt;code&gt;tauto fmt&lt;/code&gt; finds a literal in this syntax, it calls &lt;code&gt;layout_fmt&lt;/code&gt; to format the contents:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;let&lt;/span&gt; d &lt;span class=&quot;hl-operator&quot;&gt;:=&lt;/span&gt; layout&lt;span class=&quot;hl-string&quot;&gt;`1, 2, foo, 3`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;layout_fmt&lt;/code&gt; and &lt;code&gt;layout_tokens&lt;/code&gt; are ordinary Tauto functions that take a list of &lt;code&gt;SynTok&lt;/code&gt; values (a token stream including whitespace and comments) or a lossless concrete syntax tree, &lt;code&gt;SynCst&lt;/code&gt;. The ranges returned by &lt;code&gt;tokens&lt;/code&gt; determine the language server&#39;s highlighting. Without a registered function, highlighting is inferred from terminal names.&lt;/p&gt;
&lt;p&gt;The only effects these functions may have are &lt;code&gt;Div&lt;/code&gt; and &lt;code&gt;macro_error&lt;/code&gt;. They cannot access files or other external resources.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$name&lt;/code&gt; and &lt;code&gt;${…}&lt;/code&gt; inside a DSL are always highlighted as Tauto, whether or not &lt;code&gt;tokens&lt;/code&gt; is registered. Any ranges returned by &lt;code&gt;tokens&lt;/code&gt; that overlap these interpolations are trimmed. If the token function fails type checking, reports an error, or returns a range outside the text, the literal falls back to highlighting based on terminal names and gets a warning explaining why.&lt;/p&gt;
&lt;p&gt;Formatters are also constrained. Before writing a result back, &lt;code&gt;tauto fmt&lt;/code&gt; checks three things, keeping the original text and issuing a warning if any check fails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The result parses as the same syntax.&lt;/li&gt;
&lt;li&gt;The token sequence, excluding whitespace, is unchanged.&lt;/li&gt;
&lt;li&gt;Formatting again leaves the result unchanged: the formatter is idempotent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A formatter bug therefore cannot change tokens or leave the literal unparsable. These checks are not sufficient, however, for syntax where whitespace changes can change meaning, such as an indentation-sensitive grammar. Authors of &lt;code&gt;fmt&lt;/code&gt; functions for such grammars still need to handle that carefully.&lt;/p&gt;
&lt;h3 id=&quot;embedded-expressions&quot;&gt;Embedding Tauto expressions in a grammar&lt;/h3&gt;&lt;p&gt;The reserved terminal &lt;code&gt;TautoExpr&lt;/code&gt; lets you embed a Tauto expression inside a DSL with &lt;code&gt;${ … }&lt;/code&gt;. The standard library&#39;s &lt;code&gt;nat!&lt;/code&gt; uses this to embed Tauto expressions in mathematical notation:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;mul_comm&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; m&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;nat!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`$n * $m = $m * $n`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;$n&lt;/code&gt; refers to the variable &lt;code&gt;n&lt;/code&gt;, while &lt;code&gt;${Succ(k)}&lt;/code&gt; is an expression. Embedded expressions retain their actual source locations.&lt;/p&gt;
&lt;h3 id=&quot;proving-language-tools&quot;&gt;Build and prove a language implementation&lt;/h3&gt;&lt;p&gt;In addition to the &lt;code&gt;struct&lt;/code&gt;/&lt;code&gt;enum&lt;/code&gt; AST, &lt;code&gt;inductive_syntax!&lt;/code&gt; generates proof-side &lt;code&gt;inductive&lt;/code&gt; types, with an &lt;code&gt;::I&lt;/code&gt; suffix such as &lt;code&gt;Expr::I&lt;/code&gt;, and conversion functions such as &lt;code&gt;Expr::to_i&lt;/code&gt;. You can then state theorems about the AST generated from the grammar.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;examples/calc&lt;/code&gt; is a small language implementation that reads arithmetic expressions with addition and multiplication from text:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;&lt;span class=&quot;hl-macro&quot;&gt;inductive_syntax!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;arith&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`par
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;start &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%&lt;/span&gt;title &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;calc&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hl-operator&quot;&gt;%%&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Prod&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Star&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Paren&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Paren&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;LParen&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;RParen&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;hl-number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;+/&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Plus&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;+&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;Star&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-operator&quot;&gt;*&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;LParen&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-type&quot;&gt;RParen&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&amp;#39;&lt;span class=&quot;hl-punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hl-string&quot;&gt;``&lt;/span&gt;`&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-operator&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Atom&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;inductive&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;I&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;Expr&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;::&lt;/span&gt;to_i&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; …
&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;$ tauto check examples/calc/proof/calc.taut
&lt;span class=&quot;hl-number&quot;&gt;10&lt;/span&gt; ok, &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; failed, &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; incomplete&lt;span class=&quot;hl-operator&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;hl-number&quot;&gt;0&lt;/span&gt; skipped, &lt;span class=&quot;hl-number&quot;&gt;124&lt;/span&gt; from imports&lt;span class=&quot;hl-operator&quot;&gt;;&lt;/span&gt; axioms: none
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Among the properties proved here is &lt;code&gt;calc_run_correct&lt;/code&gt;: for any syntax tree, the compiled code runs without a stack underflow and leaves the value represented by that tree on the stack. The proofs check without additional axioms: &lt;code&gt;axioms: none&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Some parts remain unproved. The text-to-tree parser &lt;code&gt;arith::parse&lt;/code&gt; and the conversion &lt;code&gt;to_i&lt;/code&gt; are outside these proofs. The parser is a driver over the tables produced by the grammar generator, and its correctness has not yet been formally established. There is no formal proof yet that the text has the meaning represented by the tree. What can currently be proved is soundness and completeness &lt;strong&gt;from the tree returned by the parser onward&lt;/strong&gt;. Getting the AST as an &lt;code&gt;inductive&lt;/code&gt; type makes it possible to start writing a proof of the parser itself; that proof is not complete.&lt;/p&gt;
&lt;h2 id=&quot;other-features&quot;&gt;More useful properties&lt;/h2&gt;&lt;h3 id=&quot;expansion-tracing&quot;&gt;Every expansion can be traced&lt;/h3&gt;&lt;p&gt;Every node generated by a macro carries provenance: its call site, definition site, whether it was generated, and the chain of nested expansions. Diagnostics follow that chain to show which macro introduced what, for example: “&lt;code&gt;x&lt;/code&gt; (introduced by expansion of &lt;code&gt;math&lt;/code&gt;).”&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-console&quot;&gt;tauto macro expand &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--all &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --at LINE:COL &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --write &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --json&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; FILE   &lt;span class=&quot;hl-comment&quot;&gt;# inspect or write back the expansion&lt;/span&gt;
tauto macro trace &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--json &lt;span class=&quot;hl-operator&quot;&gt;|&lt;/span&gt; --diff&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; FILE                    &lt;span class=&quot;hl-comment&quot;&gt;# trace expansion steps&lt;/span&gt;
tauto macro inspect FILE --at LINE:COL &lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;--json&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt;
tauto check --json                                           &lt;span class=&quot;hl-comment&quot;&gt;# list expansions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With &lt;code&gt;--write&lt;/code&gt;, you can write an expansion back to source and keep a version that no longer uses the macro. All these commands support &lt;code&gt;--json&lt;/code&gt;, allowing AI agents to inspect macro expansion programmatically.&lt;/p&gt;
&lt;h3 id=&quot;declaration-environment&quot;&gt;Typed macros do not change the declaration environment&lt;/h3&gt;&lt;p&gt;Only syntax macros and attribute macros can generate declarations. A typed macro changes only the expression at its call site.&lt;/p&gt;
&lt;h3 id=&quot;typing-judgments&quot;&gt;Write typing judgments in a DSL&lt;/h3&gt;&lt;p&gt;In &lt;code&gt;examples/lambda&lt;/code&gt;, theorems about typing and reduction in the simply typed lambda calculus can be written directly in the calculus&#39;s notation. A syntax named &lt;code&gt;lc&lt;/code&gt; parses contextual judgments using a grammar containing &lt;code&gt;|-&lt;/code&gt; and &lt;code&gt;~&amp;gt;*&lt;/code&gt;, and is also used inside proofs:&lt;/p&gt;
&lt;pre class=&quot;hl&quot;&gt;&lt;code class=&quot;language-tauto&quot;&gt;pub &lt;span class=&quot;hl-keyword&quot;&gt;theorem&lt;/span&gt; &lt;span class=&quot;hl-function&quot;&gt;k_star&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;hl-operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-macro&quot;&gt;lc!&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl-string&quot;&gt;`(fun x: unit. fun y: unit. x) star ~&amp;gt;* fun y: unit. star`&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;{&lt;/span&gt; … &lt;span class=&quot;hl-punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;expansion-order&quot;&gt;Macro execution is ordered by file&lt;/h3&gt;&lt;p&gt;You can only use macros defined in an earlier file or in a dependency tote (a package). Defining and using a macro in the same file is an error. This makes the timing of macro execution visible at a unit a reader can understand.&lt;/p&gt;
&lt;h2 id=&quot;deliberate-restrictions&quot;&gt;Deliberate restrictions&lt;/h2&gt;&lt;p&gt;Here are the restrictions discussed above. These are freedoms found in some other macro systems that Tauto deliberately does not provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Access files, the network, environment variables, time, randomness, or standard output from a macro.&lt;/strong&gt; Instead, &lt;code&gt;include_text!&lt;/code&gt; reads a file only at an explicitly written call site.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generate declarations or change the environment from a typed macro.&lt;/strong&gt; Instead, syntax and attribute macros generate declarations, with the generated names listed in advance after &lt;code&gt;=&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run a macro in the middle of type inference.&lt;/strong&gt; Instead, a typed macro receives a checked expression as a &lt;code&gt;Judgement&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Put &lt;code&gt;axiom&lt;/code&gt;, &lt;code&gt;extern&lt;/code&gt;, &lt;code&gt;import&lt;/code&gt;, or a hole such as &lt;code&gt;?h&lt;/code&gt; in macro output.&lt;/strong&gt; Instead, emit code that can be written by hand, subject to these output restrictions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silently replace a handwritten declaration.&lt;/strong&gt; Instead, explicitly request replacement with &lt;code&gt;replace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use a macro in the same file where it is defined.&lt;/strong&gt; Instead, use a macro from an earlier file or a dependency tote.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Silently capture a variable.&lt;/strong&gt; Instead, explicitly capture it with &lt;code&gt;Syn::ident_like&lt;/code&gt;, leaving a trace.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guarantee the output&#39;s type when the macro itself is written.&lt;/strong&gt; Instead, check the expansion with the same checkers used for handwritten code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these freedoms can be useful. Tauto draws these boundaries to keep the trusted implementation small and expansions readable.&lt;/p&gt;
&lt;h2 id=&quot;design-priorities&quot;&gt;Design priorities&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Soundness: do not accept invalid types, proofs, or authority.&lt;/li&gt;
&lt;li&gt;Minimalism: minimize concepts, special rules, and trusted implementation.&lt;/li&gt;
&lt;li&gt;Composability.&lt;/li&gt;
&lt;li&gt;Expressiveness.&lt;/li&gt;
&lt;li&gt;Security.&lt;/li&gt;
&lt;li&gt;Readability for AI: machine-readable ASTs, types, errors, and expansion steps.&lt;/li&gt;
&lt;li&gt;Performance.&lt;/li&gt;
&lt;li&gt;Self-hosting.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;limits&quot;&gt;What is not guaranteed&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Proving the runtime evaluator correct is planned at the model level in Lean; correspondence with the Rust evaluator is checked by tests. A flaw in the evaluator could break macro isolation.&lt;/li&gt;
&lt;li&gt;Macros are not prevented from &lt;strong&gt;generating&lt;/strong&gt; code that performs dangerous actions. That code is treated the same way as the equivalent handwritten code, and can be inspected with &lt;code&gt;tauto macro expand&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A macro close to a resource budget may succeed or fail differently after an evaluator version change. Usage above 90% of the limit produces a warning.&lt;/li&gt;
&lt;li&gt;As noted above, the correctness of the grammar-generated parser remains unproved.&lt;/li&gt;
&lt;li&gt;The language is still experimental. Syntax and diagnostic messages shown here may change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Macros are ordinary functions returning syntax values. Their input types determine their kinds.&lt;/li&gt;
&lt;li&gt;Expansions are checked by the same checkers as handwritten code, keeping macros out of the trusted base.&lt;/li&gt;
&lt;li&gt;Hygiene uses scope sets. Capture requires an explicit operation and leaves a trace.&lt;/li&gt;
&lt;li&gt;Effect rows prevent file and network access. Macros may use &lt;code&gt;Div&lt;/code&gt;, but execution budgets turn nontermination into diagnostics.&lt;/li&gt;
&lt;li&gt;Writing an LL(k) or LALR(1) grammar gives a syntax macro a typed AST, parser, and syntax literals. Formatters and highlighting can also be registered.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inductive_syntax!&lt;/code&gt; brings ASTs into the proof world, making it possible to state theorems about language implementations. The parser itself remains unproved.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Hihaheho/tauto&quot;&gt;Tauto on GitHub&lt;/a&gt;&lt;/p&gt;
</content:encoded></item>
</channel></rss>
