[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