[wg-camlp4] On domain-specific foreign syntaxes

Alain Frisch alain.frisch at lexifi.com
Fri Feb 1 12:08:01 GMT 2013


On 02/01/2013 12:02 PM, Leo White wrote:
> 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 can see cases where the notion of "extension" is only used to inject 
syntactic expressions in a different category (module, pattern, type) 
but is also "scoped" by an outer extension which provides the namespace. 
See the "bitstring" example, where we need to put an expression inside a 
pattern, but the interpretation of this is given by the surrounding 
marker on the pattern matching.

Note that even if we choose "type extension = expression", we can 
provide a special namespaced syntax.  E.g.:

  (:lid e)   ====>  (# lid (e))

(i.e. we inject the lid/expression pair into either a function or 
constructor application.)  But the syntactic gain is rather small.

Alternatively, if we choose to make "type extension = longident * 
expression option" as you suggest, we can also support a different syntax:

  (# e)  ====>  (* empty identifier in the Parsetree *)

but this sounds a little bit less natural to me.  I like the 
minimalistic approach of having "extension = expression" in all 
syntactic categories (including expression themselves).  But I will 
certainly not fight the other solution.


-- Alain


>
>
>> 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 syntax:
>>
>>   (# 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.
>
> _______________________________________________
> wg-camlp4 mailing list
> wg-camlp4 at lists.ocaml.org
> http://lists.ocaml.org/listinfo/wg-camlp4



More information about the wg-camlp4 mailing list