From 5993771f0512f0aced685d60223e686c2ad1bb9f Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Wed, 25 Aug 2021 17:54:06 -0400 Subject: [PATCH] Sync changes from master --- docs/User-Manual.md | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/User-Manual.md b/docs/User-Manual.md index 1866bf05..5484dcd8 100644 --- a/docs/User-Manual.md +++ b/docs/User-Manual.md @@ -15,6 +15,10 @@ title: User Manual - [Generated Files](#generated-files) - [Interpreter](#interpreter) - [Language Details](#language-details) +- [Macros](#macros) + - [Syntax Rules](#syntax-rules) + - [Explicit Renaming](#explicit-renaming) + - [Debugging](#debugging) - [Multithreaded Programming](#multithreaded-programming) - [Thread Safety](#thread-safety) - [Foreign Function Interface](#foreign-function-interface) @@ -163,6 +167,50 @@ A [R7RS Compliance Chart](Scheme-Language-Compliance) lists differenc [API Documentation](API) is available for the libraries provided by Cyclone. +# Macros + +## Syntax Rules + +High-level hygienic macros may be created using `syntax-rules`. This system is based on a template language specified by R7RS. The specification goes into more detail on how to work with these macros: + + (define-syntax when + (syntax-rules () + ((when test result1 result2 ...) + (if test + (begin result1 result2 ...))))) + +## Explicit Renaming + +Alternatively a low-level explicit renaming (ER) system is provided that allows defining macros using Scheme code, in a similar manner as `defmacro`. + +This macro system provides the convenience functions `(rename identifier)` to hygienically rename an identifier and `(compare identifier1 identifier2)` to compare two identifiers: + + (define-syntax when + (er-macro-transformer + (lambda (exp rename compare) + (if (null? (cdr exp)) (error/loc "empty when" exp)) + (if (null? (cddr exp)) (error/loc "no when body" exp)) + `(if ,(cadr exp) + ((lambda () ,@(cddr exp))))))) + +## Debugging + +- A file may be compiled with the `-t` option which will write all of the intermediate transformations - including macro expansions - out to the `.c` file. +- From the interpreter one can use `expand`: + + cyclone> (expand '(when #t (+ 1 2 3))) + (if #t ((lambda () (+ 1 2 3))) ) + +- Alternatively when developing an ER macro, since its just a Scheme function, the macro can be defined as a `lambda` and passed a quoted expression to debug: + + (pretty-print + ((lambda (exp rename compare) + (if (null? (cdr exp)) (error/loc "empty when" exp)) + (if (null? (cddr exp)) (error/loc "no when body" exp)) + `(if ,(cadr exp) + ((lambda () ,@(cddr exp))))) + '(when #t (write 1) (write 2)) #f #f)) + # Multithreaded Programming ## Overview