Skip to content

Adding a New Form to the Language

Siddhartha Kasivajhula edited this page Jan 13, 2025 · 5 revisions

Adding a new form to the language entails, at a high level:

  1. the syntax and semantics of the new form
  2. tests
  3. documentation, both user and, if applicable, developer
  4. benchmarks, both local and, if applicable, nonlocal

Syntax and Semantics

Adding a Macro

Add the macro definition in flow/extended/forms.rkt using one of the usual Qi macro definition forms.

Adding a Deforestable list operation

Add the macro definition in flow/list.rkt using define-deforestable.

Adding a Core Form

  1. Add the form grammar to the syntax specification in flow/extended/expander.rkt.
  2. If there is just one variant of the syntax, add the pattern and the code generation template to the qi0->racket macro directly.
  3. If there is more than one variant, write a syntax class to match these patterns, and use it in a single qi->racket clause, delegating to a parser defined in the same file that provides templates for each pattern.
  4. If the implementation is nontrivial, favor writing a runtime function in flow/core/impl.rkt and using that in the template (this reduces the generated code size -- TODO: elaborate on precisely how reducing code size helps performance. Is it just memory use? Or also running time? Does it help only compilation performance? Or also runtime performance?).

Adding a Qi function

You may want to implement your form simply as a "Qi function," that is, a function bound in the Qi binding space, but otherwise identical to Racket functions. There may be a few different reasons for doing this -- either to provide an optimized runtime for a built-in Qi macro (see A Loophole in Qi Space), or just as a standard library function, the way that Racket provides many standard library functions.

To do the former, add the implementation to flow/extended/impl.rkt. For the latter, we don't yet have any examples of this (though perhaps range would be a good candidate?), so there are no conventions for this at the moment.

Tests

Add tests in the appropriate modules in qi-test. Consult the organization of test modules to get an idea of which components are affected and where adding tests would be advisable.

Documentation

Start by documenting the form in qi-doc/scribblings/forms.scrbl. See Writing Qi Docs for guidelines on fully integrating the new form into the docs.

Benchmarks

  1. Write local benchmarks in qi-sdk/benchmarks/local
  2. If you're adding a core form and if there are optimizations involved (e.g., deforestation), write a new benchmark (if applicable) in qi-sdk/benchmarks/competitive (these are rigorous benchmarks that use the vlibench package and are run on every commit on the main branch).
  3. Also for when optimizations are involved, write "smoke" nonlocal benchmarks in qi-sdk/benchmarks/nonlocal (these are not rigorous but help during development to show rough performance changes).
Clone this wiki locally