123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866(*_ This file is manually imported from the Jane Street version of the
OCaml compiler. Don't make changes directly to this file. *)[@@@ocaml.warning"-missing-record-field-pattern"]open!Shadow_compiler_distribution(** As mentioned in the .mli file, there are some gory details around the
particular translation scheme we adopt for moving to and from OCaml ASTs
([Parsetree.expression], etc.). The general idea is that we adopt a scheme
where each novel piece of syntax is represented using one of two embeddings:
1. As an AST item carrying an attribute. The AST item serves as the "body"
of the syntax indicated by the attribute.
2. As a pair of an extension node and an AST item that serves as the "body".
Here, the "pair" is embedded as a pair-like construct in the relevant AST
category, e.g. [include sig [%jane.ERASABILITY.EXTNAME];; BODY end] for
signature items.
In particular, for an language extension named [EXTNAME] (i.e., one that is
enabled by [-extension EXTNAME] on the command line), the attribute (if
used) must be [[@jane.ERASABILITY.EXTNAME]], and the extension node (if
used) must be [[%jane.ERASABILITY.EXTNAME]]. For built-in syntax, we use
[_builtin] instead of an language extension name.
The [ERASABILITY] component indicates to tools such as ocamlformat and
ppxlib whether or not the attribute is erasable. See the documentation of
[Erasability] for more information on how tools make use of this
information.
In the below example, we use attributes an examples, but it applies equally
to extensions. We also provide utilities for further desugaring similar
applications where the embeddings have the longer form
[[@jane.ERASABILITY.FEATNAME.ID1.ID2.….IDn]] (with the outermost one being
the [n = 0] case), as these might be used inside the [EXPR]. (For example,
within the outermost [[@jane.non_erasable.comprehensions]] term for list and
array comprehensions, we can also use
[[@jane.non_erasable.comprehensions.list]],
[[@jane.non_erasable.comprehensions.array]],
[[@jane.non_erasable.comprehensions.for.in]], etc.).
As mentioned, we represent terms as a "pair" and don't use the extension
node or attribute payload; this is so that ppxen can see inside these
extension nodes or attributes. If we put the subexpressions inside the
payload, then we couldn't write something like [[[%string "Hello, %{x}!"]
for x in names]], as [ppx_string] wouldn't traverse inside the payload to
find the [[%string]] extension node.
Our novel syntactic features are of course allowed to impose extra
constraints on what legal bodies are; we're also happy for this translation
to error in various ways on malformed input, since nobody should ever be
writing these forms directly. They're just an implementation detail.
See modules of type AST below to see how different syntactic categories
are represented. For example, expressions are encoded using an attribute.
We provide one module per syntactic category (e.g., [Expression]), of module
type [AST]. They also provide some simple machinery for working with the
general [@jane.ERASABILITY.FEATNAME.ID1.ID2.….IDn] wrapped forms. To
construct one, we provide [make_jane_syntax]; to destructure one, we provide
[match_jane_syntax] (which we expose via [make_of_ast]). Users of this
module still have to write the transformations in both directions for all
new syntax, lowering it to extension nodes or attributes and then lifting it
back out. *)(** How did we choose between using the attribute embedding and the extension
node embedding for a particular syntactic category?
Generally, we prefer the attribute embedding: it's more compatible with
ppxes that aren't aware of Jane Syntax. (E.g., if a type looks like a tuple,
it truly is a tuple and not an extension node embedding.)
We can't apply the attribute embedding everywhere because some syntactic
categories, like structure items, don't carry attributes. For these, we
use extension nodes.
However, the attribute embedding is more inconvenient in some ways than
the extension node embedding. For example, the attribute embedding requires
callers to strip out Jane Syntax-related attributes from the attribute list
before processing it. We've tried to make this obvious from the signature
of, say, [Jane_syntax.Expression.of_ast], but this is somewhat more
inconvenient than just operating on the [expr_desc]. Nonetheless, because
of the advantages with ppxlib interoperability, we've opted for the
attribute embedding where possible.
*)openParsetree(** We carefully regulate which bindings we import from [Language_extension]
to ensure that we can import this file into the Jane Street internal
repo with no changes.
*)moduleLanguage_extension=structincludeLanguage_extension_kernelinclude(Language_extension:Language_extension_kernel.Language_extension_for_jane_syntax)end(******************************************************************************)moduleFeature:sigtypet=|Language_extension:_Language_extension.t->t|Builtintypeerror=|Disabled_extension:_Language_extension.t->error|Unknown_extensionofstringvaldescribe_uppercase:t->stringvalextension_component:t->stringvalof_component:string->(t,error)resultvalis_erasable:t->boolend=structtypet=|Language_extension:_Language_extension.t->t|Builtintypeerror=|Disabled_extension:_Language_extension.t->error|Unknown_extensionofstringletbuiltin_component="_builtin"letdescribe_uppercase=function|Language_extensionext->"The extension \""^Language_extension.to_stringext^"\""|Builtin->"Built-in syntax";;letextension_component=function|Language_extensionext->Language_extension.to_stringext|Builtin->builtin_component;;letof_componentstr=ifString.equalstrbuiltin_componentthenOkBuiltinelse(matchLanguage_extension.of_stringstrwith|Some(Packext)->ifLanguage_extension.is_enabledextthenOk(Language_extensionext)elseError(Disabled_extensionext)|None->Error(Unknown_extensionstr));;letis_erasable=function|Language_extensionext->Language_extension.is_erasableext(* Builtin syntax changes don't involve additions or changes to concrete
syntax and are always erasable.
*)|Builtin->true;;end(** Was this embedded as an [[%extension_node]] or an [[@attribute]]? Not
exported. Used only for error messages. *)moduleEmbedding_syntax=structtypet=|Extension_node|Attributeletname=function|Extension_node->"extension node"|Attribute->"attribute";;letname_indefinite=function|Extension_node->"an extension node"|Attribute->"an attribute";;letname_plural=function|Extension_node->"extension nodes"|Attribute->"attributes";;letppppf(t,name)=letsigil=matchtwith|Extension_node->"%"|Attribute->"@"inFormat_doc.fprintfppf"[%s%s]"sigilname;;end(******************************************************************************)moduleMisnamed_embedding_error=structtypet=|No_erasability|No_feature|Unknown_erasabilityofstringletto_string=function|No_erasability->"Missing erasability and feature components"|No_feature->"Missing a feature component"|Unknown_erasabilitystr->Printf.sprintf"Unrecognized component where erasability was expected: `%s'"str;;end(** The component of an attribute or extension name that identifies whether or
not the embedded syntax is *erasable*; that is, whether or not the
upstream OCaml compiler can safely interpret the AST while ignoring the
attribute or extension. (This means that syntax encoded as extension
nodes should always be non-erasable.) Tools that consume the parse tree
we generate can make use of this information; for instance, ocamlformat
will use it to guide how we present code that can be run with both our
compiler and the upstream compiler, and ppxlib can use it to decide
whether it's ok to allow ppxes to construct syntax that uses this
emedding. In particular, the upstream version of ppxlib will allow ppxes
to produce [[@jane.erasable.*]] attributes, but will report an error if a
ppx produces a [[@jane.non_erasable.*]] attribute.
As mentioned above, unlike for attributes, the erasable/non-erasable
distinction is not meaningful for extension nodes, as the compiler will
always error if it sees an uninterpreted extension node. So, for purposes
of tools in the wider OCaml ecosystem, it is irrelevant whether embeddings
that use extension nodes indicate [Erasable] or [Non_erasable] for this
component, but the semantically correct choice and the one we've settled
on is to use [Non_erasable]. *)moduleErasability=structtypet=|Erasable|Non_erasableletto_string=function|Erasable->"erasable"|Non_erasable->"non_erasable";;letof_string=function|"erasable"->OkErasable|"non_erasable"->OkNon_erasable|_->Error();;end(** An AST-style representation of the names used when generating extension
nodes or attributes for modular syntax; see the .mli file for more
details. *)moduleEmbedded_name:sig(** A nonempty list of name components, without the first two components.
(That is, without the leading root component that identifies it as part of
the modular syntax mechanism, and without the next component that
identifies the erasability.) See the .mli file for more details. *)typecomponents=(::)ofstring*stringlisttypet={erasability:Erasability.t;components:components}(** See the mli. *)valof_feature:Feature.t->stringlist->tvalcomponents:t->components(** See the mli. *)valto_string:t->string(** Parse a Jane syntax name from the OCaml AST, either as the name of an
extension node or an attribute:
- [Some (Ok _)] if it's a legal Jane-syntax name;
- [Some (Error _)] if the root is present, but the name has fewer than 3
components or the erasability component is malformed; and
- [None] if it doesn't start with the leading root name and isn't part
of our Jane-syntax machinery.
Not exposed. *)valof_string:string->(t,Misnamed_embedding_error.t)resultoption(** Print out the embedded form of a Jane-syntax name, in quotes; for use in
error messages. *)valpp_quoted_name:Format_doc.formatter->t->unit(** Print out an empty extension node or attribute with a Jane-syntax name,
accompanied by an indefinite article; for use in error messages. Not
exposed. *)valpp_a_term:Format_doc.formatter->Embedding_syntax.t*t->unitend=struct(** The three parameters that control how we encode Jane-syntax extension node
names. When updating these, update comments that refer to them by their
contents! *)moduleConfig=struct(** The separator between name components *)letseparator='.'(** The leading namespace that identifies this extension node or attribute
as reserved for a piece of modular syntax *)letroot="jane"(** For printing purposes, the appropriate indefinite article for [root] *)letarticle="a"endincludeConfigletseparator_str=String.make1separatortypecomponents=(::)ofstring*stringlisttypet={erasability:Erasability.t;components:components}letof_featurefeaturetrailing_components=letfeature_component=Feature.extension_componentfeatureinleterasability:Erasability.t=ifFeature.is_erasablefeaturethenErasableelseNon_erasablein{erasability;components=feature_component::trailing_components};;letcomponentst=t.componentsletto_string{erasability;components=feat::subparts}=String.concatseparator_str(root::Erasability.to_stringerasability::feat::subparts);;letof_stringstr:(t,Misnamed_embedding_error.t)resultoption=matchString.split_on_charseparatorstrwith|root'::partswhenString.equalrootroot'->(matchpartswith|[]->Some(ErrorNo_erasability)|[_]->Some(ErrorNo_feature)|erasability::feat::subparts->(matchErasability.of_stringerasabilitywith|Okerasability->Some(Ok{erasability;components=feat::subparts})|Error()->Some(Error(Unknown_erasabilityerasability))))|_::_|[]->None;;letpp_quoted_nameppft=Format_doc.fprintfppf"\"%s\""(to_stringt)letpp_a_termppf(esyn,t)=Format_doc.fprintfppf"%s %a"articleEmbedding_syntax.pp(esyn,to_stringt);;end(******************************************************************************)moduleError=struct(** An error triggered when desugaring a language extension from an OCaml
AST; should always be fatal *)typeerror=|Introduction_has_payloadofEmbedding_syntax.t*Embedded_name.t*payload|Unknown_extensionofEmbedding_syntax.t*Erasability.t*string|Disabled_extension:{ext:_Language_extension.t;maturity:Language_extension.maturityoption}->error|Wrong_syntactic_categoryofFeature.t*string|Misnamed_embeddingofMisnamed_embedding_error.t*string*Embedding_syntax.t|Bad_introductionofEmbedding_syntax.t*Embedded_name.t(** The exception type thrown when desugaring a piece of modular syntax from
an OCaml AST *)exceptionErrorofLocation.t*errorendopenErrorletassert_extension_enabled(typea)~loc(ext:aLanguage_extension.t)(setting:a)=ifnot(Language_extension.is_at_leastextsetting)then(letmaturity:Language_extension.maturityoption=matchextwith|Layouts->Some(setting:Language_extension.maturity)|_->Noneinraise(Error(loc,Disabled_extension{ext;maturity})));;letreport_error~loc=function|Introduction_has_payload(what,name,_payload)->Location.errorf~loc"@[Modular syntax %s are not allowed to have a payload,@ but %a does@]"(Embedding_syntax.name_pluralwhat)Embedded_name.pp_quoted_namename|Unknown_extension(what,erasability,name)->letembedded_name={Embedded_name.erasability;components=[name]}inLocation.errorf~loc"@[Unknown extension \"%s\" referenced via@ %a %s@]"nameEmbedded_name.pp_a_term(what,embedded_name)(Embedding_syntax.namewhat)|Disabled_extension{ext;maturity}->(matchmaturitywith|None->Location.errorf~loc"The extension \"%s\" is disabled and cannot be used"(Language_extension.to_stringext)|Somematurity->Location.errorf~loc"This construct requires the %s version of the extension \"%s\", which is \
disabled and cannot be used"(Language_extension.maturity_to_stringmaturity)(Language_extension.to_stringext))|Wrong_syntactic_category(feat,cat)->Location.errorf~loc"%s cannot appear in %s"(Feature.describe_uppercasefeat)cat|Misnamed_embedding(err,name,what)->Location.errorf~loc"Cannot have %s named %a: %s"(Embedding_syntax.name_indefinitewhat)Embedding_syntax.pp(what,name)(Misnamed_embedding_error.to_stringerr)|Bad_introduction(what,({components=ext::_;_}asname))->Location.errorf~loc"@[The extension \"%s\" was referenced improperly; it started with@ %a %s,@ not %a \
one@]"extEmbedded_name.pp_a_term(what,name)(Embedding_syntax.namewhat)Embedded_name.pp_a_term(what,{namewithcomponents=[ext]});;let()=Location.register_error_of_exn(function|Error(loc,err)->Some(report_error~locerr)|_->None);;(******************************************************************************)(** Generically find and create the OCaml AST syntax used to encode one of our
novel syntactic features. One module per variety of AST (expressions,
patterns, etc.). *)(** The parameters that define how to look for [[%jane.*.FEATNAME]] and
[[@jane.*.FEATNAME]] inside ASTs of a certain syntactic category. This
module type describes the input to the [Make_with_attribute] and
[Make_with_extension_node] functors (though they stipulate additional
requirements for their inputs).
*)moduletypeAST_syntactic_category=sig(** The AST type (e.g., [Parsetree.expression]) *)typeast(** The name for this syntactic category in the plural form; used for error
messages (e.g., "expressions") *)valplural:string(** How to get the location attached to an AST node. Should just be
[fun tm -> tm.pCAT_loc] for the appropriate syntactic category [CAT]. *)vallocation:ast->Location.t(** Set the location of an AST node. *)valwith_location:ast->Location.t->astendmoduletypeAST_internal=sigincludeAST_syntactic_categoryvalembedding_syntax:Embedding_syntax.tvalmake_jane_syntax:Embedded_name.t->?payload:payload->ast->ast(** Given an AST node, check if it's a representation of a term from one of
our novel syntactic features; if it is, split it back up into its name,
the location of the extension/attribute, any payload, and the body. If
the embedded term is malformed in any way, raises an error; if the input
isn't an embedding of one of our novel syntactic features, returns [None].
Partial inverse of [make_jane_syntax]. *)valmatch_jane_syntax:ast->(Embedded_name.t*Location.t*Parsetree.payload*ast)optionend(* Parses the embedded name from an embedding, raising if
the embedding is malformed. Malformed means that
NAME is missing; e.g. the attribute is just [[@jane]].
*)letparse_embedding_exn~loc~name~embedding_syntax=letraise_errorerr=raise(Error(loc,err))inmatchEmbedded_name.of_stringnamewith|Some(Okname)->Somename|Some(Errorerr)->raise_error(Misnamed_embedding(err,name,embedding_syntax))|None->None;;letfind_and_remove_jane_syntax_attribute=(* Recurs on [rev_prefix] *)letrecloop~rev_prefix~suffix=matchrev_prefixwith|[]->None|attr::rev_prefix->let{attr_name={txt=name;loc=attr_loc};attr_payload}=attrin(matchparse_embedding_exn~loc:attr_loc~name~embedding_syntax:Attributewith|None->loop~rev_prefix~suffix:(attr::suffix)|Somename->letunconsumed_attributes=List.rev_appendrev_prefixsuffixinSome(name,attr_loc,attr_payload,unconsumed_attributes))infunattributes->loop~rev_prefix:(List.revattributes)~suffix:[];;letmake_jane_syntax_attributenamepayload={attr_name={txt=Embedded_name.to_stringname;loc=!Ast_helper.default_loc};attr_loc=!Ast_helper.default_loc;attr_payload=payload};;(** For a syntactic category, produce translations into and out of
our novel syntax, using parsetree attributes as the encoding.
*)moduleMake_with_attribute(AST_syntactic_category:sigincludeAST_syntactic_categoryvalattributes:ast->attributesvalwith_attributes:ast->attributes->astend):AST_internalwithtypeast=AST_syntactic_category.ast=structincludeAST_syntactic_categoryletembedding_syntax=Embedding_syntax.Attributeletmake_jane_syntaxname?(payload=PStr[])ast=letattr=make_jane_syntax_attributenamepayloadin(* See Note [Outer attributes at end] in jane_syntax.ml *)with_attributesast(attributesast@[attr]);;letmatch_jane_syntaxast=matchfind_and_remove_jane_syntax_attribute(attributesast)with|None->None|Some(name,loc,payload,attrs)->Some(name,loc,payload,with_attributesastattrs);;end(** For a syntactic category, produce translations into and out of
our novel syntax, using extension nodes as the encoding.
*)moduleMake_with_extension_node(AST_syntactic_category:sigincludeAST_syntactic_category(** How to construct an extension node for this AST (something of the
shape [[%name]]). Should just be [Ast_helper.CAT.extension] for the
appropriate syntactic category [CAT]. (This means that [?loc] should
default to [!Ast_helper.default_loc.].) *)valmake_extension_node:?loc:Location.t->?attrs:attributes->extension->ast(** Given an extension node (as created by [make_extension_node]) with an
appropriately-formed name and a body, combine them into the special
syntactic form we use for novel syntactic features in this syntactic
category. Partial inverse of [match_extension_use]. *)valmake_extension_use:extension_node:ast->ast->ast(** Given an AST node, check if it's of the special syntactic form
indicating that this is one of our novel syntactic features (as
created by [make_extension_node]), split it back up into the extension
node and the possible body. Doesn't do any checking about the
name/format of the extension or the possible body terms (for which see
[AST.match_extension]). Partial inverse of [make_extension_use]. *)valmatch_extension_use:ast->(extension*ast)optionend):AST_internalwithtypeast=AST_syntactic_category.ast=structincludeAST_syntactic_categoryletembedding_syntax=Embedding_syntax.Extension_nodeletmake_jane_syntaxname?(payload=PStr[])ast=make_extension_useast~extension_node:(make_extension_node({txt=Embedded_name.to_stringname;loc=!Ast_helper.default_loc},payload));;letmatch_jane_syntaxast=matchmatch_extension_useastwith|None->None|Some(({txt=name;loc=ext_loc},ext_payload),body)->(matchparse_embedding_exn~loc:ext_loc~name~embedding_syntaxwith|None->None|Somename->Some(name,ext_loc,ext_payload,body));;end(********************************************************)(* Modules representing individual syntactic categories *)(* Note [Hiding internal details]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Each such module is first written with a '0' suffix. These '0'
modules are used internally as arguments to [Make_ast] to produce
non-'0' modules which are exported. This approach allows us to
hide details of these modules necessary for [Make_ast] but
unnecessary for external uses.
*)(** The AST parameters for every subset of types; embedded with attributes. *)moduleType_AST_syntactic_category=structtypeast=core_type(* Missing [plural] *)letlocationtyp=typ.ptyp_locletwith_locationtypl={typwithptyp_loc=l}letattributestyp=typ.ptyp_attributesletwith_attributestypptyp_attributes={typwithptyp_attributes}end(** Types; embedded with attributes. *)moduleCore_type0=Make_with_attribute(structincludeType_AST_syntactic_categoryletplural="types"end)(** Constructor arguments; the same as types, but used in fewer places *)moduleConstructor_argument0=Make_with_attribute(structincludeType_AST_syntactic_categoryletplural="constructor arguments"end)(** Expressions; embedded using an attribute on the expression. *)moduleExpression0=Make_with_attribute(structtypeast=expressionletplural="expressions"letlocationexpr=expr.pexp_locletwith_locationexprl={exprwithpexp_loc=l}letattributesexpr=expr.pexp_attributesletwith_attributesexprpexp_attributes={exprwithpexp_attributes}end)(** Patterns; embedded using an attribute on the pattern. *)modulePattern0=Make_with_attribute(structtypeast=patternletplural="patterns"letlocationpat=pat.ppat_locletwith_locationpatl={patwithppat_loc=l}letattributespat=pat.ppat_attributesletwith_attributespatppat_attributes={patwithppat_attributes}end)(** Module types; embedded using an attribute on the module type. *)moduleModule_type0=Make_with_attribute(structtypeast=module_typeletplural="module types"letlocationmty=mty.pmty_locletwith_locationmtyl={mtywithpmty_loc=l}letattributesmty=mty.pmty_attributesletwith_attributesmtypmty_attributes={mtywithpmty_attributes}end)(** Extension constructors; embedded using an attribute. *)moduleExtension_constructor0=Make_with_attribute(structtypeast=extension_constructorletplural="extension constructors"letlocationext=ext.pext_locletwith_locationextl={extwithpext_loc=l}letattributesext=ext.pext_attributesletwith_attributesextpext_attributes={extwithpext_attributes}end)(** Signature items; embedded as
[include sig [%%extension.EXTNAME];; BODY end]. Signature items don't have
attributes or we'd use them instead.
*)moduleSignature_item0=Make_with_extension_node(structtypeast=signature_itemletplural="signature items"letlocationsigi=sigi.psig_locletwith_locationsigil={sigiwithpsig_loc=l}letmake_extension_node=Ast_helper.Sig.extensionletmake_extension_use~extension_nodesigi=Ast_helper.Sig.include_{pincl_mod=Ast_helper.Mty.signature[extension_node;sigi];pincl_loc=!Ast_helper.default_loc;pincl_attributes=[]};;letmatch_extension_usesigi=matchsigi.psig_descwith|Psig_include{pincl_mod={pmty_desc=Pmty_signature[{psig_desc=Psig_extension(ext,[]);_};sigi];_};_}->Some(ext,sigi)|_->None;;end)(** Structure items; embedded as
[include struct [%%extension.EXTNAME];; BODY end]. Structure items don't
have attributes or we'd use them instead.
*)moduleStructure_item0=Make_with_extension_node(structtypeast=structure_itemletplural="structure items"letlocationstri=stri.pstr_locletwith_locationstril={striwithpstr_loc=l}letmake_extension_node=Ast_helper.Str.extensionletmake_extension_use~extension_nodestri=Ast_helper.Str.include_{pincl_mod=Ast_helper.Mod.structure[extension_node;stri];pincl_loc=!Ast_helper.default_loc;pincl_attributes=[]};;letmatch_extension_usestri=matchstri.pstr_descwith|Pstr_include{pincl_mod={pmod_desc=Pmod_structure[{pstr_desc=Pstr_extension(ext,[]);_};stri];_};_}->Some(ext,stri)|_->None;;end)(** Constructor declarations; embedded with attributes. *)moduleConstructor_declaration0=Make_with_attribute(structtypeast=Parsetree.constructor_declarationletplural="constructor declarations"letlocationpcd=pcd.pcd_locletwith_locationpcdloc={pcdwithpcd_loc=loc}letattributespcd=pcd.pcd_attributesletwith_attributespcdpcd_attributes={pcdwithpcd_attributes}end)(** Type declarations; embedded with attributes. *)moduleType_declaration0=Make_with_attribute(structtypeast=Parsetree.type_declarationletplural="type declarations"letlocationptype=ptype.ptype_locletwith_locationptypeloc={ptypewithptype_loc=loc}letattributesptype=ptype.ptype_attributesletwith_attributesptypeptype_attributes={ptypewithptype_attributes}end)(******************************************************************************)(* Main exports *)moduletypeAST=sigtypeastvalmake_jane_syntax:Feature.t->stringlist->?payload:payload->ast->astvalmake_entire_jane_syntax:loc:Location.t->Feature.t->(unit->ast)->astvalmake_of_ast:of_ast_internal:(Feature.t->ast->'aoption)->ast->'aoptionend(* Most of our features make full use of the Jane Syntax framework, which
encodes information in a specific way (e.g., payload left empty on purpose).
It is therefore nice to check that these conditions are met. This functions
returns [true] if the given feature needs these extra checks. *)letneeds_extra_checks=function|Feature.Language_extensionMode->false|_->true;;(* See Note [Hiding internal details] *)moduleMake_ast(AST:AST_internal):ASTwithtypeast=AST.ast=structincludeASTletmake_jane_syntaxfeaturetrailing_components?payloadast=AST.make_jane_syntax(Embedded_name.of_featurefeaturetrailing_components)?payloadast;;letmake_entire_jane_syntax~locfeatureast=AST.with_location(* We can't call [Location.ghostify] here, as we need
[jane_syntax_parsing.ml] to build with the upstream compiler; see
Note [Buildable with upstream] in jane_syntax.mli for details. *)(Ast_helper.with_default_loc{locwithloc_ghost=true}(fun()->make_jane_syntaxfeature[](ast())))loc;;(** Generically lift our custom ASTs for our novel syntax from OCaml ASTs. *)letmake_of_ast~of_ast_internal=letof_astast=letloc=AST.locationastinletraise_errorlocerr=raise(Error(loc,err))inmatchAST.match_jane_syntaxastwith|Some(({erasability;components=[name]}asembedded_name),syntax_loc,payload,ast)->(matchFeature.of_componentnamewith|Okfeat->ifneeds_extra_checksfeatthen(matchpayloadwith|PStr[]->()|_->raise_errorsyntax_loc(Introduction_has_payload(AST.embedding_syntax,embedded_name,payload)));(matchof_ast_internalfeatastwith|Someext_ast->Someext_ast|None->ifneeds_extra_checksfeatthenraise_errorloc(Wrong_syntactic_category(feat,AST.plural))elseNone)|Errorerr->raise_errorloc(matcherrwith|Disabled_extensionext->Disabled_extension{ext;maturity=None}|Unknown_extensionname->Unknown_extension(AST.embedding_syntax,erasability,name)))|Some(({components=_::_::_;_}asname),_,_,_)->raise_errorloc(Bad_introduction(AST.embedding_syntax,name))|None->Noneinof_ast;;endletmake_jane_syntax_attributefeaturetrailing_componentspayload=make_jane_syntax_attribute(Embedded_name.of_featurefeaturetrailing_components)payload;;(* See Note [Hiding internal details] *)moduleExpression=Make_ast(Expression0)modulePattern=Make_ast(Pattern0)moduleModule_type=Make_ast(Module_type0)moduleSignature_item=Make_ast(Signature_item0)moduleStructure_item=Make_ast(Structure_item0)moduleCore_type=Make_ast(Core_type0)moduleConstructor_argument=Make_ast(Constructor_argument0)moduleExtension_constructor=Make_ast(Extension_constructor0)moduleConstructor_declaration=Make_ast(Constructor_declaration0)moduleType_declaration=Make_ast(Type_declaration0)