-
Notifications
You must be signed in to change notification settings - Fork 13
Adding a New Form to the Language
Adding a new form to the language entails, at a high level:
- the syntax and semantics of the new form
- tests
- documentation, both user and, if applicable, developer
- benchmarks, both local and, if applicable, nonlocal
Add the macro definition in flow/extended/forms.rkt
using one of the usual Qi macro definition forms.
Add the macro definition in flow/list.rkt
using define-deforestable
.
- Add the form grammar to the syntax specification in
flow/extended/expander.rkt
. - If there is just one variant of the syntax, add the pattern and the code generation template to the
qi0->racket
macro (inflow/core/compiler/1000-qi0.rkt
) directly. - If there is more than one variant, write a syntax class (in
flow/core/syntax.rkt
) to match these patterns, and use it in a singleqi0->racket
clause, delegating to a parser defined in the same file that provides templates for each pattern. - If the implementation is nontrivial, favor writing a runtime function in
flow/core/runtime.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?).
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/runtime.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.
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.
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.
- Write local benchmarks in
qi-sdk/benchmarks/local
- 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 thevlibench
package and are run on every commit on the main branch, but as they also take time to run, only add a benchmark here if it reveals something interesting about your new form that isn't already demonstrated in the other benchmarks. For example, we don't have benchmarks forlist-ref
because, asymptotically, the behavior is no different fromcar
, which we do benchmark. - Also for when optimizations are involved, write "smoke" nonlocal benchmarks in
qi-sdk/benchmarks/nonlocal
. These are not rigorous, but they help during development to show rough performance changes, and should be added for every form.
Home | Developer's Guide | Calendar | Events | Projects | Meeting Notes