paper

Fortifying Macros

  • Authors:

📜 Abstract

Existing macro systems force programmers to make a choice between clarity of specification and robustness. If they choose clarity, they must forgo validating significant parts of the specification and thus produce low-quality language extensions. If they choose robustness, they must write in a style that mingles the implementation with the specification and therefore obscures the latter. This paper introduces a new language for writing macros. With the new macro system, programmers naturally write robust language extensions using easy-to-understand specifications. The system translates these specifications into validators that detect misuses—including violations of context-sensitive constraints—and automatically synthesize appropriate feedback, eliminating the need for ad hoc validation code.

✨ Summary

Summary

The paper introduces syntax-parse, a domain-specific language for specifying and implementing robust Racket macros. It addresses a central limitation of Macro-By-Example systems such as syntax-rules and syntax-case: declarative patterns can describe basic structure, but complex validation and precise error reporting often require procedural parsing and hand-written checks.

The proposed system extends syntax patterns with annotated pattern variables, reusable and parameterized syntax classes, side conditions carrying failure explanations, action patterns, head patterns, and ellipsis-head patterns. These features allow macro authors to express context-sensitive constraints—including identifier uniqueness, optional and repeated keyword clauses, mutually exclusive options, and dependencies between syntax components—while keeping the specification close to the intended grammar.

A central technical contribution is its failure-reporting algorithm. Alternative parses are explored with backtracking, and failures are ranked by a tree-based notion of parsing progress. The most informative failure, or combined failures when progress is tied, is reported together with an explicitly supplied description or side-condition message. This enables errors to be reported in terms of the macro’s public syntax rather than the lower-level forms produced by expansion.

The paper gives a formal semantics based on a single-elimination backtracking monad whose failures contain progress information and error reasons. Its case studies show practical benefits: rewriting the loop macro substantially improved validation and error handling without the expected doubling of code size, while rewriting the parser macro reduced parsing-related code from an estimated 270 lines to 124 lines while retaining comparable error-reporting quality.

Subsequent influence

The paper’s principal contribution became part of Racket’s macro-programming infrastructure. Current Racket documentation describes syntax/parse as a framework for syntax patterns, syntax-parse, and reusable syntax classes, with automatic error generation based on descriptions and embedded messages. (docs.racket-lang.org) Racket also provides an introductory tutorial centered on writing robust macros with syntax-parse and syntax classes. (docs.racket-lang.org)

The approach has been adopted in teaching materials and reusable example packages, including a package containing illustrative macros written with syntax/parse. (docs.racket-lang.org) Later work on Racket-based domain-specific languages explicitly uses syntax-parse annotations to generate descriptive syntax errors, indicating that the paper’s techniques became a practical method for implementing embedded DSLs. (www2.ccs.neu.edu)