[wg-camlp4] On domain-specific foreign syntaxes

Leo White lpw25 at cam.ac.uk
Fri Feb 1 11:02:55 GMT 2013

>We can choose:
>type annotation = expression
>and extension = expression
>or maybe:
>type annotation = string * expression
>and extension = string * expression
>I think I prefer to use bare expressions, and encode in them the 
>"markers", because this does not force to hard-code the nature of 
>markers. An argument in favor of keeping an explicit "string" is to 
>define more explicitly the "namespace" of the extension, though.

I think that it is very important to define the "namespace" of extensions. 
I was thinking something like:

type annotation = expression
and extension = longident * expression option

So the extension has the same type as a constructor application. I don't 
think annotations should necessarily be namespaced because they will 
probably be very useful within an extension, in which case they will 
already be namespaced by that extension.

>I don't believe we should add a further distinction between the 
>annotations which can actually be ignored by the compiler and those on 
>which the type-checker must complain.  This can be left to a choice of
>syntax which combines an annotation and an extension.

I agree.

>Similarly, I'm not sure we should hard-code/enforce the fact that an AST 
>mapper should only be able to expand "under" extensions.  Extensions 
>could also be used as markers which can trigger "local enough" 
>rewriting. (See examples "Bolt" and "PG'OCaml" below.)

I agree.

>Only to fix the ideas, let's give some examples, assuming the following 
>   (# e)       ->  extension
>   ... (+ e)   ->  annotation (with light postfix syntax)
>   (@ e) ...   ->  annotation (with light prefix syntax)
>   (@(e) ...)  ->  annotation (explicit scope, prefix syntax)
>and maybe a derived "non-ignorable annotation":
>   ... (& e)  ===  ... (+ (# e))
>and syntactic variants such as:
>   let(+e) p = ... === (@ e)(let p = ...)
>and also something which combine an extension + quotation:
>   (:id x[...]x)   === (# id {x{...}x})

This certainly seems to be along the right lines. If we really prefer {, ( 
or [ for delimiters then perhaps:

Quotation:  {x{ ... }x} 

Extension:  (:longid expr)

Annotation:  (@ expr)  (and maybe others for prefix etc.)

Then some abbreviated forms for common cases:

Quotation Extension:  
  {:longid x{ ... }x}  ==  (:longid {x{ .. {x})

Let Extension:  
  let:longid foo = ... in ...  
    ==  (:longid let foo = ... in ...)

Match Extension: 
  match:longid expr with ...  
   ==  (:longid match expr with ...)

Type-Conv Annotation: 
  type foo = ... with longid( expr ), longid ... 
   == type foo = ... (@ longid expr) (@ longid) ...

We could provide special-cases in ast_mapper to make these abbreviated 
forms particularly easy to work with.

The downside of this abbreviated syntax for quotation extensions (as 
opposed to {:foo| ... |} )is that it does not provide an alternative 
delimiter to "}". However it probably fits in better.

More information about the wg-camlp4 mailing list