123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117open!StdunemoduleFirst_line=Versioned_file_first_linemoduletypeS=sigtypedatamoduleLang:sigvalregister:Syntax.t->data->unitmoduleInstance:sigtypet={syntax:Syntax.t;data:data;version:Syntax.Version.t}endvalget_exn:string->Instance.tendvalload_exn:Path.t->f:(Lang.Instance.t->'aDecoder.t)->'avalload:Path.t->f:(Lang.Instance.t->'aDecoder.t)->'aOr_exn.tvalparse_contents:Lexing.lexbuf->f:(Lang.Instance.t->'aDecoder.t)->'aendmoduleMake(Data:sigtypetend)=structmoduleLang=structtypet={syntax:Syntax.t;data:Data.t}moduleInstance=structtypet={syntax:Syntax.t;data:Data.t;version:Syntax.Version.t}end(* This mutable table is safe under the assumption that we call [register]
only at the top level, which is currently true. *)letlangs=Table.create(moduleString)32letregistersyntaxdata=letname=Syntax.namesyntaxinifTable.memlangsnamethenCode_error.raise"Versioned_file.Lang.register: already registered"[("name",Dyn.Encoder.stringname)];Table.add_exnlangsname{syntax;data}letparsefirst_line:Instance.t=let{First_line.lang=name_loc,name;version=ver_loc,ver}=first_lineinletdune_lang_ver=Decoder.parseSyntax.Version.decodeUniv_map.empty(Atom(ver_loc,Atom.of_stringver))inmatchTable.findlangsnamewith|None->User_error.raise~loc:name_loc[Pp.textf"Unknown language %S."name]~hints:(User_message.did_you_meanname~candidates:(Table.keyslangs))|Somet->Syntax.check_supported~dune_lang_vert.syntax(ver_loc,dune_lang_ver);{syntax=t.syntax;data=t.data;version=dune_lang_ver}(* TODO get_exn is only called with "dune" so far, but
greatest_supported_version may return None for extensions which are not
supported under the specified dune_lang version *)letget_exnname:Instance.t=lett=Table.find_exnlangsnamein{syntax=t.syntax;data=t.data;version=Option.value_exn(Syntax.greatest_supported_versiont.syntax)}endletparse_lang_exnlb=letfirst_line=First_line.lexlbinletlang=Lang.parsefirst_linein(lang,Parser.parselb~mode:Many_as_one)letparse_ast((lang:Lang.Instance.t),ast)~f=letparsing_context=Univ_map.singleton(Syntax.keylang.syntax)lang.versioninDecoder.parse(Decoder.enter(flang))parsing_contextastletparse_contentslb~f=letast=parse_lang_exnlbinparse_astast~fletloadfn~f=Io.with_lexbuf_from_filefn~f:(funlb->Result.try_with(fun()->parse_contentslb~f))letload_exnfn~f=Result.ok_exn(loadfn~f)endletno_more_lang=letopenDecoderinlet+(_:_list)=multi_field"lang"(let+loc=locand+_=repeatrawinUser_error.raise~loc[Pp.text"The (lang ..) line cannot appear more than once."])in()