interp.ml 138 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545
  1. (*
  2. * Copyright (C)2005-2013 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Common
  23. open Nast
  24. open Unix
  25. open Type
  26. (* ---------------------------------------------------------------------- *)
  27. (* TYPES *)
  28. type value =
  29. | VNull
  30. | VBool of bool
  31. | VInt of int
  32. | VFloat of float
  33. | VString of string
  34. | VObject of vobject
  35. | VArray of value array
  36. | VAbstract of vabstract
  37. | VFunction of vfunction
  38. | VClosure of value list * (value list -> value list -> value)
  39. | VInt32 of int32
  40. and vobject = {
  41. mutable ofields : (int * value) array;
  42. mutable oproto : vobject option;
  43. }
  44. and vabstract =
  45. | AKind of vabstract
  46. | AHash of (value, value) Hashtbl.t
  47. | ARandom of Random.State.t ref
  48. | ABuffer of Buffer.t
  49. | APos of Ast.pos
  50. | AFRead of in_channel
  51. | AFWrite of out_channel
  52. | AReg of regexp
  53. | AZipI of zlib
  54. | AZipD of zlib
  55. | AUtf8 of UTF8.Buf.buf
  56. | ASocket of Unix.file_descr
  57. | ATExpr of texpr
  58. | ATDecl of module_type
  59. | AUnsafe of Obj.t
  60. | ALazyType of (unit -> Type.t) ref
  61. | ANekoAbstract of Extc.value
  62. | ANekoBuffer of value
  63. | ACacheRef of value
  64. | AInt32Kind
  65. and vfunction =
  66. | Fun0 of (unit -> value)
  67. | Fun1 of (value -> value)
  68. | Fun2 of (value -> value -> value)
  69. | Fun3 of (value -> value -> value -> value)
  70. | Fun4 of (value -> value -> value -> value -> value)
  71. | Fun5 of (value -> value -> value -> value -> value -> value)
  72. | FunVar of (value list -> value)
  73. and regexp = {
  74. r : Str.regexp;
  75. mutable r_string : string;
  76. mutable r_groups : (int * int) option array;
  77. }
  78. and zlib = {
  79. z : Extc.zstream;
  80. mutable z_flush : Extc.zflush;
  81. }
  82. type cmp =
  83. | CEq
  84. | CSup
  85. | CInf
  86. | CUndef
  87. type extern_api = {
  88. pos : Ast.pos;
  89. get_com : unit -> Common.context;
  90. get_type : string -> Type.t option;
  91. get_module : string -> Type.t list;
  92. on_generate : (Type.t list -> unit) -> unit;
  93. on_type_not_found : (string -> value) -> unit;
  94. parse_string : string -> Ast.pos -> bool -> Ast.expr;
  95. typeof : Ast.expr -> Type.t;
  96. get_display : string -> string;
  97. allow_package : string -> unit;
  98. type_patch : string -> string -> bool -> string option -> unit;
  99. meta_patch : string -> string -> string option -> bool -> unit;
  100. set_js_generator : (value -> unit) -> unit;
  101. get_local_type : unit -> t option;
  102. get_local_method : unit -> string;
  103. get_local_using : unit -> tclass list;
  104. get_local_vars : unit -> (string, Type.tvar) PMap.t;
  105. get_build_fields : unit -> value;
  106. get_pattern_locals : Ast.expr -> Type.t -> (string,Type.tvar) PMap.t;
  107. define_type : value -> unit;
  108. module_dependency : string -> string -> bool -> unit;
  109. current_module : unit -> module_def;
  110. delayed_macro : int -> (unit -> (unit -> value));
  111. use_cache : unit -> bool;
  112. }
  113. type callstack = {
  114. cpos : pos;
  115. cthis : value;
  116. cstack : int;
  117. cenv : value array;
  118. }
  119. type context = {
  120. gen : Genneko.context;
  121. types : (Type.path,int) Hashtbl.t;
  122. prototypes : (string list, vobject) Hashtbl.t;
  123. fields_cache : (int,string) Hashtbl.t;
  124. mutable error : bool;
  125. mutable error_proto : vobject;
  126. mutable enums : (value * string) array array;
  127. mutable do_call : value -> value -> value list -> pos -> value;
  128. mutable do_string : value -> string;
  129. mutable do_loadprim : value -> value -> value;
  130. mutable do_compare : value -> value -> cmp;
  131. mutable loader : value;
  132. mutable exports : value;
  133. (* runtime *)
  134. mutable stack : value DynArray.t;
  135. mutable callstack : callstack list;
  136. mutable callsize : int;
  137. mutable exc : pos list;
  138. mutable vthis : value;
  139. mutable venv : value array;
  140. (* context *)
  141. mutable curapi : extern_api;
  142. mutable on_reused : (unit -> bool) list;
  143. mutable is_reused : bool;
  144. (* eval *)
  145. mutable locals_map : (string, int) PMap.t;
  146. mutable locals_count : int;
  147. mutable locals_barrier : int;
  148. mutable locals_env : string DynArray.t;
  149. mutable globals : (string, value ref) PMap.t;
  150. }
  151. type access =
  152. | AccThis
  153. | AccLocal of int
  154. | AccGlobal of value ref
  155. | AccEnv of int
  156. | AccField of (unit -> value) * string
  157. | AccArray of (unit -> value) * (unit -> value)
  158. exception Runtime of value
  159. exception Builtin_error
  160. exception Error of string * Ast.pos list
  161. exception Abort
  162. exception Continue
  163. exception Break of value
  164. exception Return of value
  165. exception Invalid_expr
  166. (* ---------------------------------------------------------------------- *)
  167. (* UTILS *)
  168. let get_ctx_ref = ref (fun() -> assert false)
  169. let encode_complex_type_ref = ref (fun t -> assert false)
  170. let encode_type_ref = ref (fun t -> assert false)
  171. let decode_type_ref = ref (fun t -> assert false)
  172. let encode_expr_ref = ref (fun e -> assert false)
  173. let decode_expr_ref = ref (fun e -> assert false)
  174. let encode_clref_ref = ref (fun c -> assert false)
  175. let enc_hash_ref = ref (fun h -> assert false)
  176. let enc_array_ref = ref (fun l -> assert false)
  177. let enc_string_ref = ref (fun s -> assert false)
  178. let make_ast_ref = ref (fun _ -> assert false)
  179. let make_complex_type_ref = ref (fun _ -> assert false)
  180. let get_ctx() = (!get_ctx_ref)()
  181. let enc_array (l:value list) : value = (!enc_array_ref) l
  182. let encode_complex_type (t:Ast.complex_type) : value = (!encode_complex_type_ref) t
  183. let encode_type (t:Type.t) : value = (!encode_type_ref) t
  184. let decode_type (v:value) : Type.t = (!decode_type_ref) v
  185. let encode_expr (e:Ast.expr) : value = (!encode_expr_ref) e
  186. let decode_expr (e:value) : Ast.expr = (!decode_expr_ref) e
  187. let encode_clref (c:tclass) : value = (!encode_clref_ref) c
  188. let enc_hash (h:('a,'b) Hashtbl.t) : value = (!enc_hash_ref) h
  189. let make_ast (e:texpr) : Ast.expr = (!make_ast_ref) e
  190. let enc_string (s:string) : value = (!enc_string_ref) s
  191. let make_complex_type (t:Type.t) : Ast.complex_type = (!make_complex_type_ref) t
  192. let to_int f = Int32.of_float (mod_float f 2147483648.0)
  193. let need_32_bits i = Int32.compare (Int32.logand (Int32.add i 0x40000000l) 0x80000000l) Int32.zero <> 0
  194. let best_int i = if need_32_bits i then VInt32 i else VInt (Int32.to_int i)
  195. let make_pos p =
  196. let low = p.pline land 0xFFFFF in
  197. {
  198. Ast.pfile = p.psource;
  199. Ast.pmin = low;
  200. Ast.pmax = low + (p.pline lsr 20);
  201. }
  202. let warn ctx msg p =
  203. (ctx.curapi.get_com()).Common.warning msg (make_pos p)
  204. let rec pop ctx n =
  205. if n > 0 then begin
  206. DynArray.delete_last ctx.stack;
  207. pop ctx (n - 1);
  208. end
  209. let pop_ret ctx f n =
  210. let v = f() in
  211. pop ctx n;
  212. v
  213. let push ctx v =
  214. DynArray.add ctx.stack v
  215. let hash f =
  216. let h = ref 0 in
  217. for i = 0 to String.length f - 1 do
  218. h := !h * 223 + int_of_char (String.unsafe_get f i);
  219. done;
  220. if Sys.word_size = 64 then Int32.to_int (Int32.shift_right (Int32.shift_left (Int32.of_int !h) 1) 1) else !h
  221. let constants =
  222. let h = Hashtbl.create 0 in
  223. List.iter (fun f -> Hashtbl.add h (hash f) f)
  224. ["done";"read";"write";"min";"max";"file";"args";"loadprim";"loadmodule";"__a";"__s";"h";
  225. "tag";"index";"length";"message";"pack";"name";"params";"sub";"doc";"kind";"meta";"access";
  226. "constraints";"opt";"type";"value";"ret";"expr";"field";"values";"get";"__string";"toString";
  227. "$";"add";"remove";"has";"__t";"module";"isPrivate";"isPublic";"isExtern";"isInterface";"exclude";
  228. "constructs";"names";"superClass";"interfaces";"fields";"statics";"constructor";"init";"t";
  229. "gid";"uid";"atime";"mtime";"ctime";"dev";"ino";"nlink";"rdev";"size";"mode";"pos";"len";
  230. "binops";"unops";"from";"to";"array";"op";"isPostfix";"impl"];
  231. h
  232. let h_get = hash "__get" and h_set = hash "__set"
  233. and h_add = hash "__add" and h_radd = hash "__radd"
  234. and h_sub = hash "__sub" and h_rsub = hash "__rsub"
  235. and h_mult = hash "__mult" and h_rmult = hash "__rmult"
  236. and h_div = hash "__div" and h_rdiv = hash "__rdiv"
  237. and h_mod = hash "__mod" and h_rmod = hash "__rmod"
  238. and h_string = hash "__string" and h_compare = hash "__compare"
  239. and h_constructs = hash "__constructs__" and h_a = hash "__a" and h_s = hash "__s"
  240. and h_class = hash "__class__"
  241. let exc v =
  242. raise (Runtime v)
  243. let hash_field ctx f =
  244. let h = hash f in
  245. (try
  246. let f2 = Hashtbl.find ctx.fields_cache h in
  247. if f <> f2 then exc (VString ("Field conflict between " ^ f ^ " and " ^ f2));
  248. with Not_found ->
  249. Hashtbl.add ctx.fields_cache h f);
  250. h
  251. let field_name ctx fid =
  252. try
  253. Hashtbl.find ctx.fields_cache fid
  254. with Not_found ->
  255. "???"
  256. let obj hash fields =
  257. let fields = Array.of_list (List.map (fun (k,v) -> hash k, v) fields) in
  258. Array.sort (fun (k1,_) (k2,_) -> compare k1 k2) fields;
  259. {
  260. ofields = fields;
  261. oproto = None;
  262. }
  263. let parse_int s =
  264. let rec loop_hex i =
  265. if i = String.length s then s else
  266. match String.unsafe_get s i with
  267. | '0'..'9' | 'a'..'f' | 'A'..'F' -> loop_hex (i + 1)
  268. | _ -> String.sub s 0 i
  269. in
  270. let rec loop sp i =
  271. if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else
  272. match String.unsafe_get s i with
  273. | '0'..'9' -> loop sp (i + 1)
  274. | ' ' when sp = i -> loop (sp + 1) (i + 1)
  275. | '-' when i = 0 -> loop sp (i + 1)
  276. | ('x' | 'X') when i = 1 && String.get s 0 = '0' -> loop_hex (i + 1)
  277. | _ -> String.sub s sp (i - sp)
  278. in
  279. best_int (Int32.of_string (loop 0 0))
  280. let parse_float s =
  281. let rec loop sp i =
  282. if i = String.length s then (if sp = 0 then s else String.sub s sp (i - sp)) else
  283. match String.unsafe_get s i with
  284. | ' ' when sp = i -> loop (sp + 1) (i + 1)
  285. | '0'..'9' | '-' | 'e' | 'E' | '.' -> loop sp (i + 1)
  286. | _ -> String.sub s sp (i - sp)
  287. in
  288. float_of_string (loop 0 0)
  289. let find_sub str sub start =
  290. let sublen = String.length sub in
  291. if sublen = 0 then
  292. 0
  293. else
  294. let found = ref 0 in
  295. let len = String.length str in
  296. try
  297. for i = start to len - sublen do
  298. let j = ref 0 in
  299. while String.unsafe_get str (i + !j) = String.unsafe_get sub !j do
  300. incr j;
  301. if !j = sublen then begin found := i; raise Exit; end;
  302. done;
  303. done;
  304. raise Not_found
  305. with
  306. Exit -> !found
  307. let nargs = function
  308. | Fun0 _ -> 0
  309. | Fun1 _ -> 1
  310. | Fun2 _ -> 2
  311. | Fun3 _ -> 3
  312. | Fun4 _ -> 4
  313. | Fun5 _ -> 5
  314. | FunVar _ -> -1
  315. let rec get_field o fid =
  316. let rec loop min max =
  317. if min < max then begin
  318. let mid = (min + max) lsr 1 in
  319. let cid, v = Array.unsafe_get o.ofields mid in
  320. if cid < fid then
  321. loop (mid + 1) max
  322. else if cid > fid then
  323. loop min mid
  324. else
  325. v
  326. end else
  327. match o.oproto with
  328. | None -> VNull
  329. | Some p -> get_field p fid
  330. in
  331. loop 0 (Array.length o.ofields)
  332. let set_field o fid v =
  333. let rec loop min max =
  334. let mid = (min + max) lsr 1 in
  335. if min < max then begin
  336. let cid, _ = Array.unsafe_get o.ofields mid in
  337. if cid < fid then
  338. loop (mid + 1) max
  339. else if cid > fid then
  340. loop min mid
  341. else
  342. Array.unsafe_set o.ofields mid (cid,v)
  343. end else
  344. let fields = Array.make (Array.length o.ofields + 1) (fid,v) in
  345. Array.blit o.ofields 0 fields 0 mid;
  346. Array.blit o.ofields mid fields (mid + 1) (Array.length o.ofields - mid);
  347. o.ofields <- fields
  348. in
  349. loop 0 (Array.length o.ofields)
  350. let rec remove_field o fid =
  351. let rec loop min max =
  352. let mid = (min + max) lsr 1 in
  353. if min < max then begin
  354. let cid, v = Array.unsafe_get o.ofields mid in
  355. if cid < fid then
  356. loop (mid + 1) max
  357. else if cid > fid then
  358. loop min mid
  359. else begin
  360. let fields = Array.make (Array.length o.ofields - 1) (fid,VNull) in
  361. Array.blit o.ofields 0 fields 0 mid;
  362. Array.blit o.ofields (mid + 1) fields mid (Array.length o.ofields - mid - 1);
  363. o.ofields <- fields;
  364. true
  365. end
  366. end else
  367. false
  368. in
  369. loop 0 (Array.length o.ofields)
  370. let rec get_field_opt o fid =
  371. let rec loop min max =
  372. if min < max then begin
  373. let mid = (min + max) lsr 1 in
  374. let cid, v = Array.unsafe_get o.ofields mid in
  375. if cid < fid then
  376. loop (mid + 1) max
  377. else if cid > fid then
  378. loop min mid
  379. else
  380. Some v
  381. end else
  382. match o.oproto with
  383. | None -> None
  384. | Some p -> get_field_opt p fid
  385. in
  386. loop 0 (Array.length o.ofields)
  387. let catch_errors ctx ?(final=(fun() -> ())) f =
  388. let n = DynArray.length ctx.stack in
  389. try
  390. let v = f() in
  391. final();
  392. Some v
  393. with Runtime v ->
  394. pop ctx (DynArray.length ctx.stack - n);
  395. final();
  396. let rec loop o =
  397. if o == ctx.error_proto then true else match o.oproto with None -> false | Some p -> loop p
  398. in
  399. (match v with
  400. | VObject o when loop o ->
  401. (match get_field o (hash "message"), get_field o (hash "pos") with
  402. | VObject msg, VAbstract (APos pos) ->
  403. (match get_field msg h_s with
  404. | VString msg -> raise (Typecore.Error (Typecore.Custom msg,pos))
  405. | _ -> ());
  406. | _ -> ());
  407. | _ -> ());
  408. raise (Error (ctx.do_string v,List.map (fun s -> make_pos s.cpos) ctx.callstack))
  409. | Abort ->
  410. pop ctx (DynArray.length ctx.stack - n);
  411. final();
  412. None
  413. let make_library fl =
  414. let h = Hashtbl.create 0 in
  415. List.iter (fun (n,f) -> Hashtbl.add h n f) fl;
  416. h
  417. (* ---------------------------------------------------------------------- *)
  418. (* NEKO INTEROP *)
  419. type primitive = (string * Extc.value * int)
  420. type neko_context = {
  421. load : string -> int -> primitive;
  422. call : primitive -> value list -> value;
  423. }
  424. let neko =
  425. let is_win = Sys.os_type = "Win32" || Sys.os_type = "Cygwin" in
  426. let neko = Extc.dlopen (if is_win then "neko.dll" else "libneko.so") in
  427. let null = Extc.dlint 0 in
  428. let neko = if Obj.magic neko == null && not is_win then Extc.dlopen "libneko.dylib" else neko in
  429. if Obj.magic neko == null then
  430. None
  431. else
  432. let load v =
  433. let s = Extc.dlsym neko v in
  434. if (Obj.magic s) == null then failwith ("Could not load neko." ^ v);
  435. s
  436. in
  437. ignore(Extc.dlcall0 (load "neko_global_init"));
  438. let vm = Extc.dlcall1 (load "neko_vm_alloc") null in
  439. ignore(Extc.dlcall1 (load "neko_vm_select") vm);
  440. let loader = Extc.dlcall2 (load "neko_default_loader") null null in
  441. let loadprim = Extc.dlcall2 (load "neko_val_field") loader (Extc.dlcall1 (load "neko_val_id") (Extc.dlstring "loadprim")) in
  442. let callN = load "neko_val_callN" in
  443. let callEx = load "neko_val_callEx" in
  444. let copy_string = load "neko_copy_string" in
  445. let alloc_root = load "neko_alloc_root" in
  446. let free_root = load "neko_free_root" in
  447. let alloc_root v =
  448. let r = Extc.dlcall1 alloc_root (Extc.dlint 1) in
  449. Extc.dlsetptr r v;
  450. r
  451. in
  452. let free_root r =
  453. ignore(Extc.dlcall1 free_root r)
  454. in
  455. ignore(alloc_root vm);
  456. ignore(alloc_root loader);
  457. ignore(alloc_root loadprim);
  458. let alloc_string s =
  459. Extc.dlcall2 copy_string (Extc.dlstring s) (Extc.dlint (String.length s))
  460. in
  461. let alloc_int (i:int) : Extc.value =
  462. Obj.magic i
  463. in
  464. let loadprim n args =
  465. let exc = ref null in
  466. let vargs = [|alloc_string n;alloc_int args|] in
  467. let p = Extc.dlcall5 callEx loader loadprim (Obj.magic vargs) (Extc.dlint 2) (Obj.magic exc) in
  468. if !exc != null then failwith ("Failed to load " ^ n ^ ":" ^ string_of_int args);
  469. ignore(alloc_root p);
  470. (n,p,args)
  471. in
  472. let call_raw_prim (_,p,nargs) (args:Extc.value array) =
  473. Extc.dlcall3 callN p (Obj.magic args) (Extc.dlint nargs)
  474. in
  475. (* a bit tricky since load "val_true" does not work as expected on Windows *)
  476. let unser = try loadprim "std@unserialize" 2 with _ -> ("",null,0) in
  477. (* did we fail to load std.ndll ? *)
  478. if (match unser with ("",_,_) -> true | _ -> false) then None else
  479. let val_true = call_raw_prim unser [|alloc_string "T";loader|] in
  480. let val_false = call_raw_prim unser [|alloc_string "F";loader|] in
  481. let val_null = call_raw_prim unser [|alloc_string "N";loader|] in
  482. let is_64 = call_raw_prim (loadprim "std@sys_is64" 0) [||] == val_true in
  483. let alloc_i32, is_v2 = (try load "neko_alloc_int32", true with _ -> Obj.magic 0, false) in
  484. let alloc_i32 = if is_v2 then
  485. (fun i -> Extc.dlcall1 alloc_i32 (Extc.dlint32 i))
  486. else
  487. (fun i -> alloc_int (Int32.to_int (if Int32.compare i Int32.zero < 0 then Int32.logand i 0x7FFFFFFFl else Int32.logor i 0x80000000l)))
  488. in
  489. let tag_bits = if is_v2 then 4 else 3 in
  490. let tag_mask = (1 lsl tag_bits) - 1 in
  491. let ptr_size = if is_64 then 8 else 4 in
  492. let val_field v i = Extc.dladdr v ((i + 1) * ptr_size) in
  493. let val_str v = Extc.dladdr v 4 in
  494. let val_fun_env v = Extc.dladdr v (8 + ptr_size) in
  495. (* alloc support *)
  496. let alloc_function = load "neko_alloc_function" in
  497. let alloc_array = load "neko_alloc_array" in
  498. let alloc_float = load "neko_alloc_float" in
  499. let alloc_object = load "neko_alloc_object" in
  500. let alloc_field = load "neko_alloc_field" in
  501. let alloc_abstract = load "neko_alloc_abstract" in
  502. let val_gc = load "neko_val_gc" in
  503. let val_field_name = load "neko_val_field_name" in
  504. let val_iter_fields = load "neko_val_iter_fields" in
  505. let gen_callback = Extc.dlcaml_callback 2 in
  506. (* roots *)
  507. let on_abstract_gc = Extc.dlcaml_callback 1 in
  508. let root_index = ref 0 in
  509. let roots = Hashtbl.create 0 in
  510. Callback.register "dlcallb1" (fun a ->
  511. let index : int = Obj.magic (Extc.dlptr (val_field a 1)) in
  512. Hashtbl.remove roots index;
  513. null
  514. );
  515. (* wrapping *)
  516. let copy_string v =
  517. let head = Extc.dltoint (Extc.dlptr v) in
  518. let size = head asr tag_bits in
  519. let s = String.create size in
  520. Extc.dlmemcpy (Extc.dlstring s) (val_str v) size;
  521. s
  522. in
  523. let buffers = ref [] in
  524. let rec value_neko ?(obj=VNull) = function
  525. | VNull -> val_null
  526. | VBool b -> if b then val_true else val_false
  527. | VInt i -> alloc_int i
  528. | VAbstract (ANekoAbstract a) -> a
  529. | VAbstract (ANekoBuffer (VString buf)) ->
  530. let v = value_neko (VString buf) in
  531. buffers := (buf,v) :: !buffers;
  532. v
  533. | VString s ->
  534. let v = alloc_string s in (* make a copy *)
  535. ignore(copy_string v);
  536. v
  537. | VObject o as obj ->
  538. let vo = Extc.dlcall1 alloc_object null in
  539. Array.iter (fun (id,v) ->
  540. ignore(Extc.dlcall3 alloc_field vo (Extc.dlint id) (value_neko ~obj v))
  541. ) o.ofields;
  542. vo
  543. | VClosure _ ->
  544. failwith "Closure not supported"
  545. | VFunction f ->
  546. let callb = Extc.dlcall3 alloc_function gen_callback (Extc.dlint (-1)) (Obj.magic "<callback>") in
  547. let index = !root_index in
  548. incr root_index;
  549. Hashtbl.add roots index (f,obj);
  550. let a = Extc.dlcall2 alloc_abstract null (Obj.magic index) in
  551. if Extc.dlptr (val_field a 1) != Obj.magic index then assert false;
  552. ignore(Extc.dlcall2 val_gc a on_abstract_gc);
  553. Extc.dlsetptr (val_fun_env callb) a;
  554. callb
  555. | VArray a ->
  556. let va = Extc.dlcall1 alloc_array (Extc.dlint (Array.length a)) in
  557. Array.iteri (fun i v ->
  558. Extc.dlsetptr (val_field va i) (value_neko v)
  559. ) a;
  560. va
  561. | VFloat f ->
  562. Extc.dlcall1 alloc_float (Obj.magic f)
  563. | VAbstract _ ->
  564. failwith "Abstract not supported"
  565. | VInt32 i ->
  566. alloc_i32 i
  567. in
  568. let obj_r = ref [] in
  569. let obj_fun = (fun v id -> obj_r := (v,id) :: !obj_r; val_null) in
  570. let rec neko_value (v:Extc.value) =
  571. if Obj.is_int (Obj.magic v) then
  572. VInt (Obj.magic v)
  573. else
  574. let head = Extc.dltoint (Extc.dlptr v) in
  575. match head land tag_mask with
  576. | 0 -> VNull
  577. | 2 -> VBool (v == val_true)
  578. | 3 -> VString (copy_string v)
  579. | 4 ->
  580. ignore(Extc.dlcall3 val_iter_fields v (Extc.dlcallback 2) (Obj.magic obj_fun));
  581. let r = !obj_r in
  582. obj_r := [];
  583. let ctx = get_ctx() in
  584. let fields = List.rev_map (fun (v,id) ->
  585. let iid = Extc.dltoint id in
  586. if not (Hashtbl.mem ctx.fields_cache iid) then begin
  587. let name = copy_string (Extc.dlcall1 val_field_name id) in
  588. ignore(hash_field ctx name);
  589. end;
  590. iid, neko_value v
  591. ) r in
  592. VObject { ofields = Array.of_list fields; oproto = None }
  593. | 5 ->
  594. VArray (Array.init (head asr tag_bits) (fun i -> neko_value (Extc.dlptr (val_field v i))))
  595. | 7 ->
  596. let r = alloc_root v in
  597. let a = ANekoAbstract v in
  598. Gc.finalise (fun _ -> free_root r) a;
  599. VAbstract a
  600. | t ->
  601. failwith ("Unsupported Neko value tag " ^ string_of_int t)
  602. in
  603. Callback.register "dlcallb2" (fun args nargs ->
  604. (* get back the VM env, which was set in value_neko *)
  605. let env = Extc.dlptr (Extc.dladdr vm (2 * ptr_size)) in
  606. (* extract the index stored in abstract data *)
  607. let index : int = Obj.magic (Extc.dlptr (val_field env 1)) in
  608. let f, obj = (try Hashtbl.find roots index with Not_found -> assert false) in
  609. let nargs = Extc.dltoint nargs in
  610. let rec loop i =
  611. if i = nargs then [] else neko_value (Extc.dlptr (Extc.dladdr args (i * ptr_size))) :: loop (i + 1)
  612. in
  613. let v = (get_ctx()).do_call obj (VFunction f) (loop 0) { psource = "<callback>"; pline = 0; } in
  614. value_neko v
  615. );
  616. let callprim (n,p,nargs) args =
  617. let arr = Array.of_list (List.map value_neko args) in
  618. let exc = ref null in
  619. if Array.length arr <> nargs then failwith n;
  620. let ret = Extc.dlcall5 callEx val_null p (Obj.magic arr) (Extc.dlint nargs) (Obj.magic exc) in
  621. if !exc != null then raise (Runtime (neko_value !exc));
  622. (match !buffers with
  623. | [] -> ()
  624. | l ->
  625. buffers := [];
  626. (* copy back data *)
  627. List.iter (fun (buf,v) ->
  628. Extc.dlmemcpy (Extc.dlstring buf) (val_str v) (String.length buf);
  629. ) l);
  630. neko_value ret
  631. in
  632. Some {
  633. load = loadprim;
  634. call = callprim;
  635. }
  636. (* ---------------------------------------------------------------------- *)
  637. (* BUILTINS *)
  638. let builtins =
  639. let p = { psource = "<builtin>"; pline = 0 } in
  640. let error() =
  641. raise Builtin_error
  642. in
  643. let vint = function
  644. | VInt n -> n
  645. | _ -> error()
  646. in
  647. let varray = function
  648. | VArray a -> a
  649. | _ -> error()
  650. in
  651. let vstring = function
  652. | VString s -> s
  653. | _ -> error()
  654. in
  655. let vobj = function
  656. | VObject o -> o
  657. | _ -> error()
  658. in
  659. let vfun = function
  660. | VFunction f -> f
  661. | VClosure (cl,f) -> FunVar (f cl)
  662. | _ -> error()
  663. in
  664. let vhash = function
  665. | VAbstract (AHash h) -> h
  666. | _ -> error()
  667. in
  668. let build_stack sl =
  669. let make p =
  670. let p = make_pos p in
  671. VArray [|VString p.Ast.pfile;VInt (Lexer.get_error_line p)|]
  672. in
  673. VArray (Array.of_list (List.map make sl))
  674. in
  675. let do_closure args args2 =
  676. match args with
  677. | f :: obj :: args ->
  678. (get_ctx()).do_call obj f (args @ args2) p
  679. | _ ->
  680. assert false
  681. in
  682. let funcs = [
  683. (* array *)
  684. "array", FunVar (fun vl -> VArray (Array.of_list vl));
  685. "amake", Fun1 (fun v -> VArray (Array.create (vint v) VNull));
  686. "acopy", Fun1 (fun a -> VArray (Array.copy (varray a)));
  687. "asize", Fun1 (fun a -> VInt (Array.length (varray a)));
  688. "asub", Fun3 (fun a p l -> VArray (Array.sub (varray a) (vint p) (vint l)));
  689. "ablit", Fun5 (fun dst dstp src p l ->
  690. Array.blit (varray src) (vint p) (varray dst) (vint dstp) (vint l);
  691. VNull
  692. );
  693. "aconcat", Fun1 (fun arr ->
  694. let arr = Array.map varray (varray arr) in
  695. VArray (Array.concat (Array.to_list arr))
  696. );
  697. (* string *)
  698. "string", Fun1 (fun v -> VString ((get_ctx()).do_string v));
  699. "smake", Fun1 (fun l -> VString (String.make (vint l) '\000'));
  700. "ssize", Fun1 (fun s -> VInt (String.length (vstring s)));
  701. "scopy", Fun1 (fun s -> VString (String.copy (vstring s)));
  702. "ssub", Fun3 (fun s p l -> VString (String.sub (vstring s) (vint p) (vint l)));
  703. "sget", Fun2 (fun s p ->
  704. try VInt (int_of_char (String.get (vstring s) (vint p))) with Invalid_argument _ -> VNull
  705. );
  706. "sset", Fun3 (fun s p c ->
  707. let c = char_of_int ((vint c) land 0xFF) in
  708. try
  709. String.set (vstring s) (vint p) c;
  710. VInt (int_of_char c)
  711. with Invalid_argument _ -> VNull);
  712. "sblit", Fun5 (fun dst dstp src p l ->
  713. String.blit (vstring src) (vint p) (vstring dst) (vint dstp) (vint l);
  714. VNull
  715. );
  716. "sfind", Fun3 (fun src pos pat ->
  717. try VInt (find_sub (vstring src) (vstring pat) (vint pos)) with Not_found -> VNull
  718. );
  719. (* object *)
  720. "new", Fun1 (fun o ->
  721. match o with
  722. | VNull -> VObject { ofields = [||]; oproto = None }
  723. | VObject o -> VObject { ofields = Array.copy o.ofields; oproto = o.oproto }
  724. | _ -> error()
  725. );
  726. "objget", Fun2 (fun o f ->
  727. match o with
  728. | VObject o -> get_field o (vint f)
  729. | _ -> VNull
  730. );
  731. "objset", Fun3 (fun o f v ->
  732. match o with
  733. | VObject o -> set_field o (vint f) v; v
  734. | _ -> VNull
  735. );
  736. "objcall", Fun3 (fun o f pl ->
  737. match o with
  738. | VObject oo ->
  739. (get_ctx()).do_call o (get_field oo (vint f)) (Array.to_list (varray pl)) p
  740. | _ -> VNull
  741. );
  742. "objfield", Fun2 (fun o f ->
  743. match o with
  744. | VObject o ->
  745. let p = o.oproto in
  746. o.oproto <- None;
  747. let v = get_field_opt o (vint f) in
  748. o.oproto <- p;
  749. VBool (v <> None)
  750. | _ -> VBool false
  751. );
  752. "objremove", Fun2 (fun o f ->
  753. VBool (remove_field (vobj o) (vint f))
  754. );
  755. "objfields", Fun1 (fun o ->
  756. VArray (Array.map (fun (fid,_) -> VInt fid) (vobj o).ofields)
  757. );
  758. "hash", Fun1 (fun v -> VInt (hash_field (get_ctx()) (vstring v)));
  759. "fasthash", Fun1 (fun v -> VInt (hash (vstring v)));
  760. "field", Fun1 (fun v ->
  761. try VString (Hashtbl.find (get_ctx()).fields_cache (vint v)) with Not_found -> VNull
  762. );
  763. "objsetproto", Fun2 (fun o p ->
  764. let o = vobj o in
  765. (match p with
  766. | VNull -> o.oproto <- None
  767. | VObject p -> o.oproto <- Some p
  768. | _ -> error());
  769. VNull;
  770. );
  771. "objgetproto", Fun1 (fun o ->
  772. match (vobj o).oproto with
  773. | None -> VNull
  774. | Some p -> VObject p
  775. );
  776. (* function *)
  777. "nargs", Fun1 (fun f ->
  778. VInt (nargs (vfun f))
  779. );
  780. "call", Fun3 (fun f o args ->
  781. (get_ctx()).do_call o f (Array.to_list (varray args)) p
  782. );
  783. "closure", FunVar (fun vl ->
  784. match vl with
  785. | VFunction f :: _ :: _ ->
  786. VClosure (vl, do_closure)
  787. | _ -> exc (VString "Can't create closure : value is not a function")
  788. );
  789. "apply", FunVar (fun vl ->
  790. match vl with
  791. | f :: args ->
  792. let f = vfun f in
  793. VFunction (FunVar (fun args2 -> (get_ctx()).do_call VNull (VFunction f) (args @ args2) p))
  794. | _ -> exc (VString "Invalid closure arguments number")
  795. );
  796. "varargs", Fun1 (fun f ->
  797. match f with
  798. | VFunction (FunVar _) | VFunction (Fun1 _) | VClosure _ ->
  799. VFunction (FunVar (fun vl -> (get_ctx()).do_call VNull f [VArray (Array.of_list vl)] p))
  800. | _ ->
  801. error()
  802. );
  803. (* numbers *)
  804. (* skip iadd, isub, idiv, imult *)
  805. "isnan", Fun1 (fun f ->
  806. match f with
  807. | VFloat f -> VBool (f <> f)
  808. | _ -> VBool false
  809. );
  810. "isinfinite", Fun1 (fun f ->
  811. match f with
  812. | VFloat f -> VBool (f = infinity || f = neg_infinity)
  813. | _ -> VBool false
  814. );
  815. "int", Fun1 (fun v ->
  816. match v with
  817. | VInt _ | VInt32 _ -> v
  818. | VFloat f -> best_int (to_int f)
  819. | VString s -> (try parse_int s with _ -> VNull)
  820. | _ -> VNull
  821. );
  822. "float", Fun1 (fun v ->
  823. match v with
  824. | VInt i -> VFloat (float_of_int i)
  825. | VInt32 i -> VFloat (Int32.to_float i)
  826. | VFloat _ -> v
  827. | VString s -> (try VFloat (parse_float s) with _ -> VNull)
  828. | _ -> VNull
  829. );
  830. (* abstract *)
  831. "getkind", Fun1 (fun v ->
  832. match v with
  833. | VAbstract a -> VAbstract (AKind a)
  834. | VInt32 _ -> VAbstract (AKind AInt32Kind)
  835. | _ -> error()
  836. );
  837. "iskind", Fun2 (fun v k ->
  838. match v, k with
  839. | VAbstract a, VAbstract (AKind k) -> VBool (Obj.tag (Obj.repr a) = Obj.tag (Obj.repr k))
  840. | VInt32 _, VAbstract (AKind AInt32Kind) -> VBool true
  841. | _, VAbstract (AKind _) -> VBool false
  842. | _ -> error()
  843. );
  844. (* hash *)
  845. "hkey", Fun1 (fun v -> VInt (Hashtbl.hash v));
  846. "hnew", Fun1 (fun v ->
  847. VAbstract (AHash (match v with
  848. | VNull -> Hashtbl.create 0
  849. | VInt n -> Hashtbl.create n
  850. | _ -> error()))
  851. );
  852. "hresize", Fun1 (fun v -> VNull);
  853. "hget", Fun3 (fun h k cmp ->
  854. if cmp <> VNull then assert false;
  855. (try Hashtbl.find (vhash h) k with Not_found -> VNull)
  856. );
  857. "hmem", Fun3 (fun h k cmp ->
  858. if cmp <> VNull then assert false;
  859. VBool (Hashtbl.mem (vhash h) k)
  860. );
  861. "hremove", Fun3 (fun h k cmp ->
  862. if cmp <> VNull then assert false;
  863. let h = vhash h in
  864. let old = Hashtbl.mem h k in
  865. if old then Hashtbl.remove h k;
  866. VBool old
  867. );
  868. "hset", Fun4 (fun h k v cmp ->
  869. if cmp <> VNull then assert false;
  870. let h = vhash h in
  871. let old = Hashtbl.mem h k in
  872. Hashtbl.replace h k v;
  873. VBool (not old);
  874. );
  875. "hadd", Fun4 (fun h k v cmp ->
  876. if cmp <> VNull then assert false;
  877. let h = vhash h in
  878. let old = Hashtbl.mem h k in
  879. Hashtbl.add h k v;
  880. VBool (not old);
  881. );
  882. "hiter", Fun2 (fun h f -> Hashtbl.iter (fun k v -> ignore ((get_ctx()).do_call VNull f [k;v] p)) (vhash h); VNull);
  883. "hcount", Fun1 (fun h -> VInt (Hashtbl.length (vhash h)));
  884. "hsize", Fun1 (fun h -> VInt (Hashtbl.length (vhash h)));
  885. (* misc *)
  886. "print", FunVar (fun vl -> List.iter (fun v ->
  887. let ctx = get_ctx() in
  888. let com = ctx.curapi.get_com() in
  889. com.print (ctx.do_string v)
  890. ) vl; VNull);
  891. "throw", Fun1 (fun v -> exc v);
  892. "rethrow", Fun1 (fun v ->
  893. let ctx = get_ctx() in
  894. ctx.callstack <- List.rev (List.map (fun p -> { cpos = p; cthis = ctx.vthis; cstack = DynArray.length ctx.stack; cenv = ctx.venv }) ctx.exc) @ ctx.callstack;
  895. exc v
  896. );
  897. "istrue", Fun1 (fun v ->
  898. match v with
  899. | VNull | VInt 0 | VBool false | VInt32 0l -> VBool false
  900. | _ -> VBool true
  901. );
  902. "not", Fun1 (fun v ->
  903. match v with
  904. | VNull | VInt 0 | VBool false | VInt32 0l -> VBool true
  905. | _ -> VBool false
  906. );
  907. "typeof", Fun1 (fun v ->
  908. VInt (match v with
  909. | VNull -> 0
  910. | VInt _ | VInt32 _ -> 1
  911. | VFloat _ -> 2
  912. | VBool _ -> 3
  913. | VString _ -> 4
  914. | VObject _ -> 5
  915. | VArray _ -> 6
  916. | VFunction _ | VClosure _ -> 7
  917. | VAbstract _ -> 8)
  918. );
  919. "compare", Fun2 (fun a b ->
  920. match (get_ctx()).do_compare a b with
  921. | CUndef -> VNull
  922. | CEq -> VInt 0
  923. | CSup -> VInt 1
  924. | CInf -> VInt (-1)
  925. );
  926. "pcompare", Fun2 (fun a b ->
  927. assert false
  928. );
  929. "excstack", Fun0 (fun() ->
  930. build_stack (get_ctx()).exc
  931. );
  932. "callstack", Fun0 (fun() ->
  933. build_stack (List.map (fun s -> s.cpos) (get_ctx()).callstack)
  934. );
  935. "version", Fun0 (fun() ->
  936. VInt 200
  937. );
  938. (* extra *)
  939. "use_neko_dll", Fun0 (fun() ->
  940. VBool (neko <> None)
  941. );
  942. ] in
  943. let vals = [
  944. "tnull", VInt 0;
  945. "tint", VInt 1;
  946. "tfloat", VInt 2;
  947. "tbool", VInt 3;
  948. "tstring", VInt 4;
  949. "tobject", VInt 5;
  950. "tarray", VInt 6;
  951. "tfunction", VInt 7;
  952. "tabstract", VInt 8;
  953. ] in
  954. let h = Hashtbl.create 0 in
  955. List.iter (fun (n,f) -> Hashtbl.add h n (VFunction f)) funcs;
  956. List.iter (fun (n,v) -> Hashtbl.add h n v) vals;
  957. h
  958. (* ---------------------------------------------------------------------- *)
  959. (* STD LIBRARY *)
  960. let std_lib =
  961. let p = { psource = "<stdlib>"; pline = 0 } in
  962. let error() =
  963. raise Builtin_error
  964. in
  965. let make_list l =
  966. let rec loop acc = function
  967. | [] -> acc
  968. | x :: l -> loop (VArray [|x;acc|]) l
  969. in
  970. loop VNull (List.rev l)
  971. in
  972. let num = function
  973. | VInt i -> float_of_int i
  974. | VInt32 i -> Int32.to_float i
  975. | VFloat f -> f
  976. | _ -> error()
  977. in
  978. let make_date f =
  979. VInt32 (Int32.of_float f)
  980. in
  981. let date = function
  982. | VInt32 i -> Int32.to_float i
  983. | VInt i -> float_of_int i
  984. | _ -> error()
  985. in
  986. let make_i32 i =
  987. VInt32 i
  988. in
  989. let int32 = function
  990. | VInt i -> Int32.of_int i
  991. | VInt32 i -> i
  992. | _ -> error()
  993. in
  994. let vint = function
  995. | VInt n -> n
  996. | _ -> error()
  997. in
  998. let vstring = function
  999. | VString s -> s
  1000. | _ -> error()
  1001. in
  1002. let int32_addr h =
  1003. let base = Int32.to_int (Int32.logand h 0xFFFFFFl) in
  1004. let str = Printf.sprintf "%ld.%d.%d.%d" (Int32.shift_right_logical h 24) (base lsr 16) ((base lsr 8) land 0xFF) (base land 0xFF) in
  1005. Unix.inet_addr_of_string str
  1006. in
  1007. let int32_op op = Fun2 (fun a b -> make_i32 (op (int32 a) (int32 b))) in
  1008. make_library ([
  1009. (* math *)
  1010. "math_atan2", Fun2 (fun a b -> VFloat (atan2 (num a) (num b)));
  1011. "math_pow", Fun2 (fun a b -> VFloat ((num a) ** (num b)));
  1012. "math_abs", Fun1 (fun v ->
  1013. match v with
  1014. | VInt i -> VInt (abs i)
  1015. | VInt32 i -> VInt32 (Int32.abs i)
  1016. | VFloat f -> VFloat (abs_float f)
  1017. | _ -> error()
  1018. );
  1019. "math_ceil", Fun1 (fun v -> match v with VInt _ | VInt32 _ -> v | _ -> best_int (to_int (ceil (num v))));
  1020. "math_floor", Fun1 (fun v -> match v with VInt _ | VInt32 _ -> v | _ -> best_int (to_int (floor (num v))));
  1021. "math_round", Fun1 (fun v -> match v with VInt _ | VInt32 _ -> v | _ -> best_int (to_int (floor (num v +. 0.5))));
  1022. "math_pi", Fun0 (fun() -> VFloat (4.0 *. atan 1.0));
  1023. "math_sqrt", Fun1 (fun v -> VFloat (sqrt (num v)));
  1024. "math_atan", Fun1 (fun v -> VFloat (atan (num v)));
  1025. "math_cos", Fun1 (fun v -> VFloat (cos (num v)));
  1026. "math_sin", Fun1 (fun v -> VFloat (sin (num v)));
  1027. "math_tan", Fun1 (fun v -> VFloat (tan (num v)));
  1028. "math_log", Fun1 (fun v -> VFloat (Pervasives.log (num v)));
  1029. "math_exp", Fun1 (fun v -> VFloat (exp (num v)));
  1030. "math_acos", Fun1 (fun v -> VFloat (acos (num v)));
  1031. "math_asin", Fun1 (fun v -> VFloat (asin (num v)));
  1032. "math_fceil", Fun1 (fun v -> VFloat (ceil (num v)));
  1033. "math_ffloor", Fun1 (fun v -> VFloat (floor (num v)));
  1034. "math_fround", Fun1 (fun v -> VFloat (floor (num v +. 0.5)));
  1035. "math_int", Fun1 (fun v ->
  1036. match v with
  1037. | VInt _ | VInt32 _ -> v
  1038. | VFloat f -> best_int (to_int (if f < 0. then ceil f else floor f))
  1039. | _ -> error()
  1040. );
  1041. (* buffer *)
  1042. "buffer_new", Fun0 (fun() ->
  1043. VAbstract (ABuffer (Buffer.create 0))
  1044. );
  1045. "buffer_add", Fun2 (fun b v ->
  1046. match b with
  1047. | VAbstract (ABuffer b) -> Buffer.add_string b ((get_ctx()).do_string v); VNull
  1048. | _ -> error()
  1049. );
  1050. "buffer_add_char", Fun2 (fun b v ->
  1051. match b, v with
  1052. | VAbstract (ABuffer b), VInt n when n >= 0 && n < 256 -> Buffer.add_char b (char_of_int n); VNull
  1053. | _ -> error()
  1054. );
  1055. "buffer_add_sub", Fun4 (fun b s p l ->
  1056. match b, s, p, l with
  1057. | VAbstract (ABuffer b), VString s, VInt p, VInt l -> (try Buffer.add_substring b s p l; VNull with _ -> error())
  1058. | _ -> error()
  1059. );
  1060. "buffer_string", Fun1 (fun b ->
  1061. match b with
  1062. | VAbstract (ABuffer b) -> VString (Buffer.contents b)
  1063. | _ -> error()
  1064. );
  1065. "buffer_reset", Fun1 (fun b ->
  1066. match b with
  1067. | VAbstract (ABuffer b) -> Buffer.reset b; VNull;
  1068. | _ -> error()
  1069. );
  1070. (* date *)
  1071. "date_now", Fun0 (fun () ->
  1072. make_date (Unix.time())
  1073. );
  1074. "date_new", Fun1 (fun v ->
  1075. make_date (match v with
  1076. | VNull -> Unix.time()
  1077. | VString s ->
  1078. (match String.length s with
  1079. | 19 ->
  1080. let r = Str.regexp "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\) \\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" in
  1081. if not (Str.string_match r s 0) then exc (VString ("Invalid date format : " ^ s));
  1082. let t = Unix.localtime (Unix.time()) in
  1083. let t = { t with
  1084. tm_year = int_of_string (Str.matched_group 1 s) - 1900;
  1085. tm_mon = int_of_string (Str.matched_group 2 s) - 1;
  1086. tm_mday = int_of_string (Str.matched_group 3 s);
  1087. tm_hour = int_of_string (Str.matched_group 4 s);
  1088. tm_min = int_of_string (Str.matched_group 5 s);
  1089. tm_sec = int_of_string (Str.matched_group 6 s);
  1090. } in
  1091. fst (Unix.mktime t)
  1092. | 10 ->
  1093. assert false
  1094. | 8 ->
  1095. assert false
  1096. | _ ->
  1097. exc (VString ("Invalid date format : " ^ s)));
  1098. | _ -> error())
  1099. );
  1100. "date_set_hour", Fun4 (fun d h m s ->
  1101. let d = date d in
  1102. let t = Unix.localtime d in
  1103. make_date (fst (Unix.mktime { t with tm_hour = vint h; tm_min = vint m; tm_sec = vint s }))
  1104. );
  1105. "date_set_day", Fun4 (fun d y m da ->
  1106. let d = date d in
  1107. let t = Unix.localtime d in
  1108. make_date (fst (Unix.mktime { t with tm_year = vint y - 1900; tm_mon = vint m - 1; tm_mday = vint da }))
  1109. );
  1110. "date_format", Fun2 (fun d fmt ->
  1111. match fmt with
  1112. | VNull ->
  1113. let t = Unix.localtime (date d) in
  1114. VString (Printf.sprintf "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec)
  1115. | VString "%w" ->
  1116. (* week day *)
  1117. let t = Unix.localtime (date d) in
  1118. VString (string_of_int t.tm_wday)
  1119. | VString _ ->
  1120. exc (VString "Custom date format is not supported") (* use native Haxe implementation *)
  1121. | _ ->
  1122. error()
  1123. );
  1124. "date_get_hour", Fun1 (fun d ->
  1125. let t = Unix.localtime (date d) in
  1126. let o = obj (hash_field (get_ctx())) [
  1127. "h", VInt t.tm_hour;
  1128. "m", VInt t.tm_min;
  1129. "s", VInt t.tm_sec;
  1130. ] in
  1131. VObject o
  1132. );
  1133. "date_get_day", Fun1 (fun d ->
  1134. let t = Unix.localtime (date d) in
  1135. let o = obj (hash_field (get_ctx())) [
  1136. "d", VInt t.tm_mday;
  1137. "m", VInt (t.tm_mon + 1);
  1138. "y", VInt (t.tm_year + 1900);
  1139. ] in
  1140. VObject o
  1141. );
  1142. (* string *)
  1143. "string_split", Fun2 (fun s d ->
  1144. make_list (match s, d with
  1145. | VString "", VString _ -> [VString ""]
  1146. | VString s, VString "" -> Array.to_list (Array.init (String.length s) (fun i -> VString (String.make 1 (String.get s i))))
  1147. | VString s, VString d -> List.map (fun s -> VString s) (ExtString.String.nsplit s d)
  1148. | _ -> error())
  1149. );
  1150. "url_encode", Fun1 (fun s ->
  1151. let s = vstring s in
  1152. let b = Buffer.create 0 in
  1153. let hex = "0123456789ABCDEF" in
  1154. for i = 0 to String.length s - 1 do
  1155. let c = String.unsafe_get s i in
  1156. match c with
  1157. | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' ->
  1158. Buffer.add_char b c
  1159. | _ ->
  1160. Buffer.add_char b '%';
  1161. Buffer.add_char b (String.unsafe_get hex (int_of_char c lsr 4));
  1162. Buffer.add_char b (String.unsafe_get hex (int_of_char c land 0xF));
  1163. done;
  1164. VString (Buffer.contents b)
  1165. );
  1166. "url_decode", Fun1 (fun s ->
  1167. let s = vstring s in
  1168. let b = Buffer.create 0 in
  1169. let len = String.length s in
  1170. let decode c =
  1171. match c with
  1172. | '0'..'9' -> Some (int_of_char c - int_of_char '0')
  1173. | 'a'..'f' -> Some (int_of_char c - int_of_char 'a' + 10)
  1174. | 'A'..'F' -> Some (int_of_char c - int_of_char 'A' + 10)
  1175. | _ -> None
  1176. in
  1177. let rec loop i =
  1178. if i = len then () else
  1179. let c = String.unsafe_get s i in
  1180. match c with
  1181. | '%' ->
  1182. let p1 = (try decode (String.get s (i + 1)) with _ -> None) in
  1183. let p2 = (try decode (String.get s (i + 2)) with _ -> None) in
  1184. (match p1, p2 with
  1185. | Some c1, Some c2 ->
  1186. Buffer.add_char b (char_of_int ((c1 lsl 4) lor c2));
  1187. loop (i + 3)
  1188. | _ ->
  1189. loop (i + 1));
  1190. | '+' ->
  1191. Buffer.add_char b ' ';
  1192. loop (i + 1)
  1193. | c ->
  1194. Buffer.add_char b c;
  1195. loop (i + 1)
  1196. in
  1197. loop 0;
  1198. VString (Buffer.contents b)
  1199. );
  1200. "base_encode", Fun2 (fun s b ->
  1201. match s, b with
  1202. | VString s, VString "0123456789abcdef" when String.length s = 16 ->
  1203. VString (Digest.to_hex s)
  1204. | VString s, VString b ->
  1205. if String.length b <> 64 then assert false;
  1206. let tbl = Array.init 64 (String.unsafe_get b) in
  1207. VString (Base64.str_encode ~tbl s)
  1208. | _ -> error()
  1209. );
  1210. "base_decode", Fun2 (fun s b ->
  1211. let s = vstring s in
  1212. let b = vstring b in
  1213. if String.length b <> 64 then assert false;
  1214. let tbl = Array.init 64 (String.unsafe_get b) in
  1215. VString (Base64.str_decode ~tbl:(Base64.make_decoding_table tbl) s)
  1216. );
  1217. "make_md5", Fun1 (fun s ->
  1218. VString (Digest.string (vstring s))
  1219. );
  1220. (* sprintf *)
  1221. (* int32 *)
  1222. "int32_new", Fun1 (fun v ->
  1223. match v with
  1224. | VInt32 _ -> v
  1225. | VInt i -> make_i32 (Int32.of_int i)
  1226. | VFloat f -> make_i32 (Int32.of_float f)
  1227. | _ -> error()
  1228. );
  1229. "int32_to_int", Fun1 (fun v ->
  1230. let v = int32 v in
  1231. let i = Int32.to_int v in
  1232. if Int32.compare (Int32.of_int i) v <> 0 then error();
  1233. VInt i
  1234. );
  1235. "int32_to_float", Fun1 (fun v ->
  1236. VFloat (Int32.to_float (int32 v))
  1237. );
  1238. "int32_compare", Fun2 (fun a b ->
  1239. VInt (Int32.compare (int32 a) (int32 b))
  1240. );
  1241. "int32_add", int32_op Int32.add;
  1242. "int32_sub", int32_op Int32.sub;
  1243. "int32_mul", int32_op Int32.mul;
  1244. "int32_div", int32_op Int32.div;
  1245. "int32_shl", int32_op (fun a b -> Int32.shift_left a (Int32.to_int b));
  1246. "int32_shr", int32_op (fun a b -> Int32.shift_right a (Int32.to_int b));
  1247. "int32_ushr", int32_op (fun a b -> Int32.shift_right_logical a (Int32.to_int b));
  1248. "int32_mod", int32_op Int32.rem;
  1249. "int32_or", int32_op Int32.logor;
  1250. "int32_and", int32_op Int32.logand;
  1251. "int32_xor", int32_op Int32.logxor;
  1252. "int32_neg", Fun1 (fun v -> make_i32 (Int32.neg (int32 v)));
  1253. "int32_complement", Fun1 (fun v -> make_i32 (Int32.lognot (int32 v)));
  1254. (* misc *)
  1255. "same_closure", Fun2 (fun a b ->
  1256. VBool (match a, b with
  1257. | VClosure (la,fa), VClosure (lb,fb) ->
  1258. fa == fb && List.length la = List.length lb && List.for_all2 (fun a b -> (get_ctx()).do_compare a b = CEq) la lb
  1259. | VFunction a, VFunction b -> a == b
  1260. | _ -> false)
  1261. );
  1262. "double_bytes", Fun2 (fun f big ->
  1263. let f = (match f with VFloat f -> f | VInt i -> float_of_int i | _ -> error()) in
  1264. match big with
  1265. | VBool big ->
  1266. let ch = IO.output_string() in
  1267. if big then IO.BigEndian.write_double ch f else IO.write_double ch f;
  1268. VString (IO.close_out ch)
  1269. | _ ->
  1270. error()
  1271. );
  1272. "float_bytes", Fun2 (fun f big ->
  1273. let f = (match f with VFloat f -> f | VInt i -> float_of_int i | _ -> error()) in
  1274. match big with
  1275. | VBool big ->
  1276. let ch = IO.output_string() in
  1277. let i = Int32.bits_of_float f in
  1278. if big then IO.BigEndian.write_real_i32 ch i else IO.write_real_i32 ch i;
  1279. VString (IO.close_out ch)
  1280. | _ ->
  1281. error()
  1282. );
  1283. "double_of_bytes", Fun2 (fun s big ->
  1284. match s, big with
  1285. | VString s, VBool big when String.length s = 8 ->
  1286. let ch = IO.input_string s in
  1287. VFloat (if big then IO.BigEndian.read_double ch else IO.read_double ch)
  1288. | _ ->
  1289. error()
  1290. );
  1291. "float_of_bytes", Fun2 (fun s big ->
  1292. match s, big with
  1293. | VString s, VBool big when String.length s = 4 ->
  1294. let ch = IO.input_string s in
  1295. VFloat (Int32.float_of_bits (if big then IO.BigEndian.read_real_i32 ch else IO.read_real_i32 ch))
  1296. | _ ->
  1297. error()
  1298. );
  1299. (* random *)
  1300. "random_new", Fun0 (fun() -> VAbstract (ARandom (ref (Random.State.make_self_init()))));
  1301. "random_set_seed", Fun2 (fun r s ->
  1302. match r, s with
  1303. | VAbstract (ARandom r), VInt seed -> r := Random.State.make [|seed|]; VNull
  1304. | VAbstract (ARandom r), VInt32 seed -> r := Random.State.make [|Int32.to_int seed|]; VNull
  1305. | _ -> error()
  1306. );
  1307. "random_int", Fun2 (fun r s ->
  1308. match r, s with
  1309. | VAbstract (ARandom r), VInt max -> VInt (Random.State.int (!r) (if max <= 0 then 1 else max))
  1310. | _ -> error()
  1311. );
  1312. "random_float", Fun1 (fun r ->
  1313. match r with
  1314. | VAbstract (ARandom r) -> VFloat (Random.State.float (!r) 1.0)
  1315. | _ -> error()
  1316. );
  1317. (* file *)
  1318. "file_open", Fun2 (fun f r ->
  1319. match f, r with
  1320. | VString f, VString r ->
  1321. let perms = 0o666 in
  1322. VAbstract (match r with
  1323. | "r" -> AFRead (open_in_gen [Open_rdonly] 0 f)
  1324. | "rb" -> AFRead (open_in_gen [Open_rdonly;Open_binary] 0 f)
  1325. | "w" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc] perms f)
  1326. | "wb" -> AFWrite (open_out_gen [Open_wronly;Open_creat;Open_trunc;Open_binary] perms f)
  1327. | "a" -> AFWrite (open_out_gen [Open_append] perms f)
  1328. | "ab" -> AFWrite (open_out_gen [Open_append;Open_binary] perms f)
  1329. | _ -> error())
  1330. | _ -> error()
  1331. );
  1332. "file_close", Fun1 (fun f ->
  1333. (match f with
  1334. | VAbstract (AFRead f) -> close_in f
  1335. | VAbstract (AFWrite f) -> close_out f
  1336. | _ -> error());
  1337. VNull
  1338. );
  1339. (* file_name *)
  1340. "file_write", Fun4 (fun f s p l ->
  1341. match f, s, p, l with
  1342. | VAbstract (AFWrite f), VString s, VInt p, VInt l -> output f s p l; VInt l
  1343. | _ -> error()
  1344. );
  1345. "file_read", Fun4 (fun f s p l ->
  1346. match f, s, p, l with
  1347. | VAbstract (AFRead f), VString s, VInt p, VInt l ->
  1348. let n = input f s p l in
  1349. if n = 0 then exc (VArray [|VString "file_read"|]);
  1350. VInt n
  1351. | _ -> error()
  1352. );
  1353. "file_write_char", Fun2 (fun f c ->
  1354. match f, c with
  1355. | VAbstract (AFWrite f), VInt c -> output_char f (char_of_int c); VNull
  1356. | _ -> error()
  1357. );
  1358. "file_read_char", Fun1 (fun f ->
  1359. match f with
  1360. | VAbstract (AFRead f) -> VInt (int_of_char (try input_char f with _ -> exc (VArray [|VString "file_read_char"|])))
  1361. | _ -> error()
  1362. );
  1363. "file_seek", Fun3 (fun f pos mode ->
  1364. match f, pos, mode with
  1365. | VAbstract (AFRead f), VInt pos, VInt mode ->
  1366. seek_in f (match mode with 0 -> pos | 1 -> pos_in f + pos | 2 -> in_channel_length f - pos | _ -> error());
  1367. VNull;
  1368. | VAbstract (AFWrite f), VInt pos, VInt mode ->
  1369. seek_out f (match mode with 0 -> pos | 1 -> pos_out f + pos | 2 -> out_channel_length f - pos | _ -> error());
  1370. VNull;
  1371. | _ -> error()
  1372. );
  1373. "file_tell", Fun1 (fun f ->
  1374. match f with
  1375. | VAbstract (AFRead f) -> VInt (pos_in f)
  1376. | VAbstract (AFWrite f) -> VInt (pos_out f)
  1377. | _ -> error()
  1378. );
  1379. "file_eof", Fun1 (fun f ->
  1380. match f with
  1381. | VAbstract (AFRead f) ->
  1382. VBool (try
  1383. ignore(input_char f);
  1384. seek_in f (pos_in f - 1);
  1385. false
  1386. with End_of_file ->
  1387. true)
  1388. | _ -> error()
  1389. );
  1390. "file_flush", Fun1 (fun f ->
  1391. (match f with
  1392. | VAbstract (AFWrite f) -> flush f
  1393. | _ -> error());
  1394. VNull
  1395. );
  1396. "file_contents", Fun1 (fun f ->
  1397. match f with
  1398. | VString f -> VString (Std.input_file ~bin:true f)
  1399. | _ -> error()
  1400. );
  1401. "file_stdin", Fun0 (fun() -> VAbstract (AFRead Pervasives.stdin));
  1402. "file_stdout", Fun0 (fun() -> VAbstract (AFWrite Pervasives.stdout));
  1403. "file_stderr", Fun0 (fun() -> VAbstract (AFWrite Pervasives.stderr));
  1404. (* serialize *)
  1405. (* TODO *)
  1406. (* socket *)
  1407. "socket_init", Fun0 (fun() -> VNull);
  1408. "socket_new", Fun1 (fun v ->
  1409. match v with
  1410. | VBool b -> VAbstract (ASocket (Unix.socket PF_INET (if b then SOCK_DGRAM else SOCK_STREAM) 0));
  1411. | _ -> error()
  1412. );
  1413. "socket_close", Fun1 (fun s ->
  1414. match s with
  1415. | VAbstract (ASocket s) -> Unix.close s; VNull
  1416. | _ -> error()
  1417. );
  1418. "socket_send_char", Fun2 (fun s c ->
  1419. match s, c with
  1420. | VAbstract (ASocket s), VInt c when c >= 0 && c <= 255 ->
  1421. ignore(Unix.send s (String.make 1 (char_of_int c)) 0 1 []);
  1422. VNull
  1423. | _ -> error()
  1424. );
  1425. "socket_send", Fun4 (fun s buf pos len ->
  1426. match s, buf, pos, len with
  1427. | VAbstract (ASocket s), VString buf, VInt pos, VInt len -> VInt (Unix.send s buf pos len [])
  1428. | _ -> error()
  1429. );
  1430. "socket_recv", Fun4 (fun s buf pos len ->
  1431. match s, buf, pos, len with
  1432. | VAbstract (ASocket s), VString buf, VInt pos, VInt len -> VInt (Unix.recv s buf pos len [])
  1433. | _ -> error()
  1434. );
  1435. "socket_recv_char", Fun1 (fun s ->
  1436. match s with
  1437. | VAbstract (ASocket s) ->
  1438. let buf = String.make 1 '\000' in
  1439. ignore(Unix.recv s buf 0 1 []);
  1440. VInt (int_of_char (String.unsafe_get buf 0))
  1441. | _ -> error()
  1442. );
  1443. "socket_write", Fun2 (fun s str ->
  1444. match s, str with
  1445. | VAbstract (ASocket s), VString str ->
  1446. let pos = ref 0 in
  1447. let len = ref (String.length str) in
  1448. while !len > 0 do
  1449. let k = Unix.send s str (!pos) (!len) [] in
  1450. pos := !pos + k;
  1451. len := !len - k;
  1452. done;
  1453. VNull
  1454. | _ -> error()
  1455. );
  1456. "socket_read", Fun1 (fun s ->
  1457. match s with
  1458. | VAbstract (ASocket s) ->
  1459. let tmp = String.make 1024 '\000' in
  1460. let buf = Buffer.create 0 in
  1461. let rec loop() =
  1462. let k = (try Unix.recv s tmp 0 1024 [] with Unix_error _ -> 0) in
  1463. if k > 0 then begin
  1464. Buffer.add_substring buf tmp 0 k;
  1465. loop();
  1466. end
  1467. in
  1468. loop();
  1469. VString (Buffer.contents buf)
  1470. | _ -> error()
  1471. );
  1472. "host_resolve", Fun1 (fun s ->
  1473. let h = (try Unix.gethostbyname (vstring s) with Not_found -> error()) in
  1474. let addr = Unix.string_of_inet_addr h.h_addr_list.(0) in
  1475. let a, b, c, d = Scanf.sscanf addr "%d.%d.%d.%d" (fun a b c d -> a,b,c,d) in
  1476. VInt32 (Int32.logor (Int32.shift_left (Int32.of_int a) 24) (Int32.of_int (d lor (c lsl 8) lor (b lsl 16))))
  1477. );
  1478. "host_to_string", Fun1 (fun h ->
  1479. match h with
  1480. | VInt32 h -> VString (Unix.string_of_inet_addr (int32_addr h));
  1481. | _ -> error()
  1482. );
  1483. "host_reverse", Fun1 (fun h ->
  1484. match h with
  1485. | VInt32 h -> VString (gethostbyaddr (int32_addr h)).h_name
  1486. | _ -> error()
  1487. );
  1488. "host_local", Fun0 (fun() ->
  1489. VString (Unix.gethostname())
  1490. );
  1491. "socket_connect", Fun3 (fun s h p ->
  1492. match s, h, p with
  1493. | VAbstract (ASocket s), VInt32 h, VInt p ->
  1494. Unix.connect s (ADDR_INET (int32_addr h,p));
  1495. VNull
  1496. | _ -> error()
  1497. );
  1498. "socket_listen", Fun2 (fun s l ->
  1499. match s, l with
  1500. | VAbstract (ASocket s), VInt l ->
  1501. Unix.listen s l;
  1502. VNull
  1503. | _ -> error()
  1504. );
  1505. "socket_set_timeout", Fun2 (fun s t ->
  1506. match s with
  1507. | VAbstract (ASocket s) ->
  1508. let t = (match t with VNull -> 0. | VInt t -> float_of_int t | VFloat f -> f | _ -> error()) in
  1509. Unix.setsockopt_float s SO_RCVTIMEO t;
  1510. Unix.setsockopt_float s SO_SNDTIMEO t;
  1511. VNull
  1512. | _ -> error()
  1513. );
  1514. "socket_shutdown", Fun3 (fun s r w ->
  1515. match s, r, w with
  1516. | VAbstract (ASocket s), VBool r, VBool w ->
  1517. Unix.shutdown s (match r, w with true, true -> SHUTDOWN_ALL | true, false -> SHUTDOWN_RECEIVE | false, true -> SHUTDOWN_SEND | _ -> error());
  1518. VNull
  1519. | _ -> error()
  1520. );
  1521. (* TODO : select, bind, accept, peer, host *)
  1522. (* poll_alloc, poll : not planned *)
  1523. (* system *)
  1524. "get_env", Fun1 (fun v ->
  1525. try VString (Unix.getenv (vstring v)) with _ -> VNull
  1526. );
  1527. "put_env", Fun2 (fun e v ->
  1528. Unix.putenv (vstring e) (vstring v);
  1529. VNull
  1530. );
  1531. "sys_sleep", Fun1 (fun f ->
  1532. match f with
  1533. | VFloat f -> ignore(Unix.select [] [] [] f); VNull
  1534. | _ -> error()
  1535. );
  1536. "set_time_locale", Fun1 (fun l ->
  1537. match l with
  1538. | VString s -> VBool false (* always fail *)
  1539. | _ -> error()
  1540. );
  1541. "get_cwd", Fun0 (fun() ->
  1542. let dir = Unix.getcwd() in
  1543. let l = String.length dir in
  1544. VString (if l = 0 then "./" else match dir.[l - 1] with '/' | '\\' -> dir | _ -> dir ^ "/")
  1545. );
  1546. "set_cwd", Fun1 (fun s ->
  1547. Unix.chdir (vstring s);
  1548. VNull;
  1549. );
  1550. "sys_string", Fun0 (fun() ->
  1551. VString (match Sys.os_type with
  1552. | "Unix" -> "Linux"
  1553. | "Win32" | "Cygwin" -> "Windows"
  1554. | s -> s)
  1555. );
  1556. "sys_is64", Fun0 (fun() ->
  1557. VBool (Sys.word_size = 64)
  1558. );
  1559. "sys_command", Fun1 (fun cmd ->
  1560. VInt (((get_ctx()).curapi.get_com()).run_command (vstring cmd))
  1561. );
  1562. "sys_exit", Fun1 (fun code ->
  1563. if (get_ctx()).curapi.use_cache() then raise Typecore.Fatal_error;
  1564. exit (vint code);
  1565. );
  1566. "sys_exists", Fun1 (fun file ->
  1567. VBool (Sys.file_exists (vstring file))
  1568. );
  1569. "file_delete", Fun1 (fun file ->
  1570. Sys.remove (vstring file);
  1571. VNull;
  1572. );
  1573. "sys_rename", Fun2 (fun file target ->
  1574. Sys.rename (vstring file) (vstring target);
  1575. VNull;
  1576. );
  1577. "sys_stat", Fun1 (fun file ->
  1578. let s = Unix.stat (vstring file) in
  1579. VObject (obj (hash_field (get_ctx())) [
  1580. "gid", VInt s.st_gid;
  1581. "uid", VInt s.st_uid;
  1582. "atime", VInt32 (Int32.of_float s.st_atime);
  1583. "mtime", VInt32 (Int32.of_float s.st_mtime);
  1584. "ctime", VInt32 (Int32.of_float s.st_ctime);
  1585. "dev", VInt s.st_dev;
  1586. "ino", VInt s.st_ino;
  1587. "nlink", VInt s.st_nlink;
  1588. "rdev", VInt s.st_rdev;
  1589. "size", VInt s.st_size;
  1590. "mode", VInt s.st_perm;
  1591. ])
  1592. );
  1593. "sys_file_type", Fun1 (fun file ->
  1594. VString (match (Unix.stat (vstring file)).st_kind with
  1595. | S_REG -> "file"
  1596. | S_DIR -> "dir"
  1597. | S_CHR -> "char"
  1598. | S_BLK -> "block"
  1599. | S_LNK -> "symlink"
  1600. | S_FIFO -> "fifo"
  1601. | S_SOCK -> "sock")
  1602. );
  1603. "sys_create_dir", Fun2 (fun dir mode ->
  1604. Unix.mkdir (vstring dir) (vint mode);
  1605. VNull
  1606. );
  1607. "sys_remove_dir", Fun1 (fun dir ->
  1608. Unix.rmdir (vstring dir);
  1609. VNull;
  1610. );
  1611. "sys_time", Fun0 (fun() ->
  1612. VFloat (Unix.gettimeofday())
  1613. );
  1614. "sys_cpu_time", Fun0 (fun() ->
  1615. VFloat (Sys.time())
  1616. );
  1617. "sys_read_dir", Fun1 (fun dir ->
  1618. let d = Sys.readdir (vstring dir) in
  1619. let rec loop acc i =
  1620. if i < 0 then
  1621. acc
  1622. else
  1623. loop (VArray [|VString d.(i);acc|]) (i - 1)
  1624. in
  1625. loop VNull (Array.length d - 1)
  1626. );
  1627. "file_full_path", Fun1 (fun file ->
  1628. VString (try Extc.get_full_path (vstring file) with _ -> error())
  1629. );
  1630. "sys_exe_path", Fun0 (fun() ->
  1631. VString (Extc.executable_path())
  1632. );
  1633. "sys_env", Fun0 (fun() ->
  1634. let env = Unix.environment() in
  1635. let rec loop acc i =
  1636. if i < 0 then
  1637. acc
  1638. else
  1639. let e, v = ExtString.String.split "=" env.(i) in
  1640. loop (VArray [|VString e;VString v;acc|]) (i - 1)
  1641. in
  1642. loop VNull (Array.length env - 1)
  1643. );
  1644. "sys_getch", Fun1 (fun echo ->
  1645. match echo with
  1646. | VBool b -> VInt (Extc.getch b)
  1647. | _ -> error()
  1648. );
  1649. "sys_get_pid", Fun0 (fun() ->
  1650. VInt (Unix.getpid())
  1651. );
  1652. (* utf8 *)
  1653. "utf8_buf_alloc", Fun1 (fun v ->
  1654. VAbstract (AUtf8 (UTF8.Buf.create (vint v)))
  1655. );
  1656. "utf8_buf_add", Fun2 (fun b c ->
  1657. match b with
  1658. | VAbstract (AUtf8 buf) -> UTF8.Buf.add_char buf (UChar.chr_of_uint (vint c)); VNull
  1659. | _ -> error()
  1660. );
  1661. "utf8_buf_content", Fun1 (fun b ->
  1662. match b with
  1663. | VAbstract (AUtf8 buf) -> VString (UTF8.Buf.contents buf);
  1664. | _ -> error()
  1665. );
  1666. "utf8_buf_length", Fun1 (fun b ->
  1667. match b with
  1668. | VAbstract (AUtf8 buf) -> VInt (UTF8.length (UTF8.Buf.contents buf));
  1669. | _ -> error()
  1670. );
  1671. "utf8_buf_size", Fun1 (fun b ->
  1672. match b with
  1673. | VAbstract (AUtf8 buf) -> VInt (String.length (UTF8.Buf.contents buf));
  1674. | _ -> error()
  1675. );
  1676. "utf8_validate", Fun1 (fun s ->
  1677. VBool (try UTF8.validate (vstring s); true with UTF8.Malformed_code -> false)
  1678. );
  1679. "utf8_length", Fun1 (fun s ->
  1680. VInt (UTF8.length (vstring s))
  1681. );
  1682. "utf8_sub", Fun3 (fun s p l ->
  1683. let buf = UTF8.Buf.create 0 in
  1684. let pos = ref (-1) in
  1685. let p = vint p and l = vint l in
  1686. UTF8.iter (fun c ->
  1687. incr pos;
  1688. if !pos >= p && !pos < p + l then UTF8.Buf.add_char buf c;
  1689. ) (vstring s);
  1690. if !pos < p + l then error();
  1691. VString (UTF8.Buf.contents buf)
  1692. );
  1693. "utf8_get", Fun2 (fun s p ->
  1694. VInt (UChar.uint_code (try UTF8.look (vstring s) (vint p) with _ -> error()))
  1695. );
  1696. "utf8_iter", Fun2 (fun s f ->
  1697. let ctx = get_ctx() in
  1698. UTF8.iter (fun c ->
  1699. ignore(ctx.do_call VNull f [VInt (UChar.uint_code c)] p);
  1700. ) (vstring s);
  1701. VNull;
  1702. );
  1703. "utf8_compare", Fun2 (fun s1 s2 ->
  1704. VInt (UTF8.compare (vstring s1) (vstring s2))
  1705. );
  1706. (* xml *)
  1707. "parse_xml", (match neko with
  1708. | None -> Fun2 (fun str o ->
  1709. match str, o with
  1710. | VString str, VObject events ->
  1711. let ctx = get_ctx() in
  1712. let p = { psource = "parse_xml"; pline = 0 } in
  1713. let xml = get_field events (hash "xml") in
  1714. let don = get_field events (hash "done") in
  1715. let pcdata = get_field events (hash "pcdata") in
  1716. (*
  1717. Since we use the Xml parser, we don't have support for
  1718. - CDATA
  1719. - comments, prolog, doctype (allowed but skipped)
  1720. let cdata = get_field events (hash "cdata") in
  1721. let comment = get_field events (hash "comment") in
  1722. *)
  1723. let rec loop = function
  1724. | Xml.Element (node, attribs, children) ->
  1725. ignore(ctx.do_call o xml [VString node;VObject (obj (hash_field ctx) (List.map (fun (a,v) -> a, VString v) attribs))] p);
  1726. List.iter loop children;
  1727. ignore(ctx.do_call o don [] p);
  1728. | Xml.PCData s ->
  1729. ignore(ctx.do_call o pcdata [VString s] p);
  1730. in
  1731. let x = XmlParser.make() in
  1732. XmlParser.check_eof x false;
  1733. loop (try
  1734. XmlParser.parse x (XmlParser.SString str)
  1735. with Xml.Error e -> failwith ("Parser failure (" ^ Xml.error e ^ ")")
  1736. | e -> failwith ("Parser failure (" ^ Printexc.to_string e ^ ")"));
  1737. VNull
  1738. | _ -> error())
  1739. | Some neko ->
  1740. let parse_xml = neko.load "std@parse_xml" 2 in
  1741. Fun2 (fun str o -> neko.call parse_xml [str;o])
  1742. );
  1743. (* memory, module, thread : not planned *)
  1744. ]
  1745. (* process *)
  1746. @ (match neko with
  1747. | None -> []
  1748. | Some neko ->
  1749. let p_run = neko.load "std@process_run" 2 in
  1750. let p_stdout_read = neko.load "std@process_stdout_read" 4 in
  1751. let p_stderr_read = neko.load "std@process_stderr_read" 4 in
  1752. let p_stdin_write = neko.load "std@process_stdin_write" 4 in
  1753. let p_stdin_close = neko.load "std@process_stdin_close" 1 in
  1754. let p_exit = neko.load "std@process_exit" 1 in
  1755. let p_pid = neko.load "std@process_pid" 1 in
  1756. let p_close = neko.load "std@process_close" 1 in
  1757. let win_ec = (try Some (neko.load "std@win_env_changed" 0) with _ -> None) in
  1758. [
  1759. "process_run", (Fun2 (fun a b -> neko.call p_run [a;b]));
  1760. "process_stdout_read", (Fun4 (fun a b c d -> neko.call p_stdout_read [a;VAbstract (ANekoBuffer b);c;d]));
  1761. "process_stderr_read", (Fun4 (fun a b c d -> neko.call p_stderr_read [a;VAbstract (ANekoBuffer b);c;d]));
  1762. "process_stdin_write", (Fun4 (fun a b c d -> neko.call p_stdin_write [a;b;c;d]));
  1763. "process_stdin_close", (Fun1 (fun p -> neko.call p_stdin_close [p]));
  1764. "process_exit", (Fun1 (fun p -> neko.call p_exit [p]));
  1765. "process_pid", (Fun1 (fun p -> neko.call p_pid [p]));
  1766. "process_close", (Fun1 (fun p -> neko.call p_close [p]));
  1767. "win_env_changed", (Fun0 (fun() -> match win_ec with None -> error() | Some f -> neko.call f []));
  1768. ]))
  1769. (* ---------------------------------------------------------------------- *)
  1770. (* REGEXP LIBRARY *)
  1771. let reg_lib =
  1772. let error() =
  1773. raise Builtin_error
  1774. in
  1775. (* try to load regexp first : we might fail if pcre is not installed *)
  1776. let neko = (match neko with
  1777. | None -> None
  1778. | Some neko ->
  1779. (try ignore(neko.load "regexp@regexp_new_options" 2); Some neko with _ -> None)
  1780. ) in
  1781. match neko with
  1782. | None ->
  1783. make_library [
  1784. (* regexp_new : deprecated *)
  1785. "regexp_new_options", Fun2 (fun str opt ->
  1786. match str, opt with
  1787. | VString str, VString opt ->
  1788. let case_sensitive = ref true in
  1789. List.iter (function
  1790. | 'm' -> () (* always ON ? *)
  1791. | 'i' -> case_sensitive := false
  1792. | c -> failwith ("Unsupported regexp option '" ^ String.make 1 c ^ "'")
  1793. ) (ExtString.String.explode opt);
  1794. let buf = Buffer.create 0 in
  1795. let rec loop prev esc = function
  1796. | [] -> ()
  1797. | c :: l when esc ->
  1798. (match c with
  1799. | 'n' -> Buffer.add_char buf '\n'
  1800. | 'r' -> Buffer.add_char buf '\r'
  1801. | 't' -> Buffer.add_char buf '\t'
  1802. | 'd' -> Buffer.add_string buf "[0-9]"
  1803. | '\\' -> Buffer.add_string buf "\\\\"
  1804. | '(' | ')' -> Buffer.add_char buf c
  1805. | '1'..'9' | '+' | '$' | '^' | '*' | '?' | '.' | '[' | ']' ->
  1806. Buffer.add_char buf '\\';
  1807. Buffer.add_char buf c;
  1808. | _ -> failwith ("Unsupported escaped char '" ^ String.make 1 c ^ "'"));
  1809. loop c false l
  1810. | c :: l ->
  1811. match c with
  1812. | '\\' -> loop prev true l
  1813. | '(' | '|' | ')' ->
  1814. Buffer.add_char buf '\\';
  1815. Buffer.add_char buf c;
  1816. loop c false l
  1817. | '?' when prev = '(' && (match l with ':' :: _ -> true | _ -> false) ->
  1818. failwith "Non capturing groups '(?:' are not supported in macros"
  1819. | '?' when prev = '*' ->
  1820. failwith "Ungreedy *? are not supported in macros"
  1821. | _ ->
  1822. Buffer.add_char buf c;
  1823. loop c false l
  1824. in
  1825. loop '\000' false (ExtString.String.explode str);
  1826. let str = Buffer.contents buf in
  1827. let r = {
  1828. r = if !case_sensitive then Str.regexp str else Str.regexp_case_fold str;
  1829. r_string = "";
  1830. r_groups = [||];
  1831. } in
  1832. VAbstract (AReg r)
  1833. | _ -> error()
  1834. );
  1835. "regexp_match", Fun4 (fun r str pos len ->
  1836. match r, str, pos, len with
  1837. | VAbstract (AReg r), VString str, VInt pos, VInt len ->
  1838. let nstr, npos, delta = (if len = String.length str - pos then str, pos, 0 else String.sub str pos len, 0, pos) in
  1839. (try
  1840. ignore(Str.search_forward r.r nstr npos);
  1841. let rec loop n =
  1842. if n = 9 then
  1843. []
  1844. else try
  1845. (Some (Str.group_beginning n + delta, Str.group_end n + delta)) :: loop (n + 1)
  1846. with Not_found ->
  1847. None :: loop (n + 1)
  1848. | Invalid_argument _ ->
  1849. []
  1850. in
  1851. r.r_string <- str;
  1852. r.r_groups <- Array.of_list (loop 0);
  1853. VBool true;
  1854. with Not_found ->
  1855. VBool false)
  1856. | _ -> error()
  1857. );
  1858. "regexp_matched", Fun2 (fun r n ->
  1859. match r, n with
  1860. | VAbstract (AReg r), VInt n ->
  1861. (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with
  1862. | None -> VNull
  1863. | Some (pos,pend) -> VString (String.sub r.r_string pos (pend - pos)))
  1864. | _ -> error()
  1865. );
  1866. "regexp_matched_pos", Fun2 (fun r n ->
  1867. match r, n with
  1868. | VAbstract (AReg r), VInt n ->
  1869. (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with
  1870. | None -> VNull
  1871. | Some (pos,pend) -> VObject (obj (hash_field (get_ctx())) ["pos",VInt pos;"len",VInt (pend - pos)]))
  1872. | _ -> error()
  1873. );
  1874. (* regexp_replace : not used by Haxe *)
  1875. (* regexp_replace_all : not used by Haxe *)
  1876. (* regexp_replace_fun : not used by Haxe *)
  1877. ]
  1878. | Some neko ->
  1879. let regexp_new_options = neko.load "regexp@regexp_new_options" 2 in
  1880. let regexp_match = neko.load "regexp@regexp_match" 4 in
  1881. let regexp_matched = neko.load "regexp@regexp_matched" 2 in
  1882. let regexp_matched_pos = neko.load "regexp@regexp_matched_pos" 2 in
  1883. make_library [
  1884. "regexp_new_options", Fun2 (fun str opt -> neko.call regexp_new_options [str;opt]);
  1885. "regexp_match", Fun4 (fun r str pos len -> neko.call regexp_match [r;str;pos;len]);
  1886. "regexp_matched", Fun2 (fun r n -> neko.call regexp_matched [r;n]);
  1887. "regexp_matched_pos", Fun2 (fun r n -> neko.call regexp_matched_pos [r;n]);
  1888. ]
  1889. (* ---------------------------------------------------------------------- *)
  1890. (* ZLIB LIBRARY *)
  1891. let z_lib =
  1892. let error() =
  1893. raise Builtin_error
  1894. in
  1895. make_library [
  1896. "inflate_init", Fun1 (fun f ->
  1897. let z = Extc.zlib_inflate_init2 (match f with VNull -> 15 | VInt i -> i | _ -> error()) in
  1898. VAbstract (AZipI { z = z; z_flush = Extc.Z_NO_FLUSH })
  1899. );
  1900. "deflate_init", Fun1 (fun f ->
  1901. let z = Extc.zlib_deflate_init (match f with VInt i -> i | _ -> error()) in
  1902. VAbstract (AZipD { z = z; z_flush = Extc.Z_NO_FLUSH })
  1903. );
  1904. "deflate_end", Fun1 (fun z ->
  1905. match z with
  1906. | VAbstract (AZipD z) -> Extc.zlib_deflate_end z.z; VNull;
  1907. | _ -> error()
  1908. );
  1909. "inflate_end", Fun1 (fun z ->
  1910. match z with
  1911. | VAbstract (AZipI z) -> Extc.zlib_inflate_end z.z; VNull;
  1912. | _ -> error()
  1913. );
  1914. "set_flush_mode", Fun2 (fun z f ->
  1915. match z, f with
  1916. | VAbstract (AZipI z | AZipD z), VString s ->
  1917. z.z_flush <- (match s with
  1918. | "NO" -> Extc.Z_NO_FLUSH
  1919. | "SYNC" -> Extc.Z_SYNC_FLUSH
  1920. | "FULL" -> Extc.Z_FULL_FLUSH
  1921. | "FINISH" -> Extc.Z_FINISH
  1922. | "BLOCK" -> Extc.Z_PARTIAL_FLUSH
  1923. | _ -> error());
  1924. VNull;
  1925. | _ -> error()
  1926. );
  1927. "inflate_buffer", Fun5 (fun z src pos dst dpos ->
  1928. match z, src, pos, dst, dpos with
  1929. | VAbstract (AZipI z), VString src, VInt pos, VString dst, VInt dpos ->
  1930. let r = Extc.zlib_inflate z.z src pos (String.length src - pos) dst dpos (String.length dst - dpos) z.z_flush in
  1931. VObject (obj (hash_field (get_ctx())) [
  1932. "done", VBool r.Extc.z_finish;
  1933. "read", VInt r.Extc.z_read;
  1934. "write", VInt r.Extc.z_wrote;
  1935. ])
  1936. | _ -> error()
  1937. );
  1938. "deflate_buffer", Fun5 (fun z src pos dst dpos ->
  1939. match z, src, pos, dst, dpos with
  1940. | VAbstract (AZipD z), VString src, VInt pos, VString dst, VInt dpos ->
  1941. let r = Extc.zlib_deflate z.z src pos (String.length src - pos) dst dpos (String.length dst - dpos) z.z_flush in
  1942. VObject (obj (hash_field (get_ctx())) [
  1943. "done", VBool r.Extc.z_finish;
  1944. "read", VInt r.Extc.z_read;
  1945. "write", VInt r.Extc.z_wrote;
  1946. ])
  1947. | _ -> error()
  1948. );
  1949. "deflate_bound", Fun2 (fun z size ->
  1950. match z, size with
  1951. | VAbstract (AZipD z), VInt size -> VInt (size + 1024)
  1952. | _ -> error()
  1953. );
  1954. ]
  1955. (* ---------------------------------------------------------------------- *)
  1956. (* MACRO LIBRARY *)
  1957. let macro_lib =
  1958. let error() =
  1959. raise Builtin_error
  1960. in
  1961. let ccom() =
  1962. (get_ctx()).curapi.get_com()
  1963. in
  1964. make_library [
  1965. "curpos", Fun0 (fun() -> VAbstract (APos (get_ctx()).curapi.pos));
  1966. "error", Fun2 (fun msg p ->
  1967. match msg, p with
  1968. | VString s, VAbstract (APos p) ->
  1969. (ccom()).Common.error s p;
  1970. raise Abort
  1971. | _ -> error()
  1972. );
  1973. "warning", Fun2 (fun msg p ->
  1974. match msg, p with
  1975. | VString s, VAbstract (APos p) ->
  1976. (ccom()).warning s p;
  1977. VNull;
  1978. | _ -> error()
  1979. );
  1980. "class_path", Fun0 (fun() ->
  1981. VArray (Array.of_list (List.map (fun s -> VString s) (ccom()).class_path));
  1982. );
  1983. "resolve", Fun1 (fun file ->
  1984. match file with
  1985. | VString s -> VString (try Common.find_file (ccom()) s with Not_found -> failwith ("File not found '" ^ s ^ "'"))
  1986. | _ -> error();
  1987. );
  1988. "define", Fun1 (fun s ->
  1989. match s with
  1990. | VString s -> Common.raw_define (ccom()) s; VNull
  1991. | _ -> error();
  1992. );
  1993. "defined", Fun1 (fun s ->
  1994. match s with
  1995. | VString s -> VBool (Common.raw_defined (ccom()) s)
  1996. | _ -> error();
  1997. );
  1998. "defined_value", Fun1 (fun s ->
  1999. match s with
  2000. | VString s -> (try VString (Common.raw_defined_value (ccom()) s) with Not_found -> VNull)
  2001. | _ -> error();
  2002. );
  2003. "get_type", Fun1 (fun s ->
  2004. match s with
  2005. | VString s ->
  2006. (match (get_ctx()).curapi.get_type s with
  2007. | None -> failwith ("Type not found '" ^ s ^ "'")
  2008. | Some t -> encode_type t)
  2009. | _ -> error()
  2010. );
  2011. "get_module", Fun1 (fun s ->
  2012. match s with
  2013. | VString s ->
  2014. enc_array (List.map encode_type ((get_ctx()).curapi.get_module s))
  2015. | _ -> error()
  2016. );
  2017. "on_generate", Fun1 (fun f ->
  2018. match f with
  2019. | VFunction (Fun1 _) ->
  2020. let ctx = get_ctx() in
  2021. ctx.curapi.on_generate (fun tl ->
  2022. ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [enc_array (List.map encode_type tl)] null_pos));
  2023. );
  2024. VNull
  2025. | _ -> error()
  2026. );
  2027. "on_type_not_found", Fun1 (fun f ->
  2028. match f with
  2029. | VFunction (Fun1 _) ->
  2030. let ctx = get_ctx() in
  2031. ctx.curapi.on_type_not_found (fun path ->
  2032. ctx.do_call VNull f [enc_string path] null_pos
  2033. );
  2034. VNull
  2035. | _ -> error()
  2036. );
  2037. "parse", Fun3 (fun s p b ->
  2038. match s, p, b with
  2039. | VString s, VAbstract (APos p), VBool b -> encode_expr ((get_ctx()).curapi.parse_string s p b)
  2040. | _ -> error()
  2041. );
  2042. "make_expr", Fun2 (fun v p ->
  2043. match p with
  2044. | VAbstract (APos p) ->
  2045. let h_enum = hash "__enum__" and h_et = hash "__et__" and h_ct = hash "__ct__" in
  2046. let h_tag = hash "tag" and h_args = hash "args" in
  2047. let h_length = hash "length" in
  2048. let ctx = get_ctx() in
  2049. let error v = failwith ("Unsupported value " ^ ctx.do_string v) in
  2050. let make_path t =
  2051. let rec loop = function
  2052. | [] -> assert false
  2053. | [name] -> (Ast.EConst (Ast.Ident name),p)
  2054. | name :: l -> (Ast.EField (loop l,name),p)
  2055. in
  2056. let t = t_infos t in
  2057. loop (List.rev (if t.mt_module.m_path = t.mt_path then fst t.mt_path @ [snd t.mt_path] else fst t.mt_module.m_path @ [snd t.mt_module.m_path;snd t.mt_path]))
  2058. in
  2059. let rec loop = function
  2060. | VNull -> (Ast.EConst (Ast.Ident "null"),p)
  2061. | VBool b -> (Ast.EConst (Ast.Ident (if b then "true" else "false")),p)
  2062. | VInt i -> (Ast.EConst (Ast.Int (string_of_int i)),p)
  2063. | VInt32 i -> (Ast.EConst (Ast.Int (Int32.to_string i)),p)
  2064. | VFloat f -> (Ast.EConst (Ast.Float (string_of_float f)),p)
  2065. | VAbstract (APos p) ->
  2066. (Ast.EObjectDecl (
  2067. ("fileName" , (Ast.EConst (Ast.String p.Ast.pfile) , p)) ::
  2068. ("lineNumber" , (Ast.EConst (Ast.Int (string_of_int (Lexer.get_error_line p))),p)) ::
  2069. ("className" , (Ast.EConst (Ast.String ("")),p)) ::
  2070. []
  2071. ), p)
  2072. | VString _ | VArray _ | VAbstract _ | VFunction _ | VClosure _ as v -> error v
  2073. | VObject o as v ->
  2074. match o.oproto with
  2075. | None ->
  2076. (match get_field_opt o h_ct with
  2077. | Some (VAbstract (ATDecl t)) ->
  2078. make_path t
  2079. | _ ->
  2080. let fields = List.fold_left (fun acc (fid,v) -> (field_name ctx fid, loop v) :: acc) [] (Array.to_list o.ofields) in
  2081. (Ast.EObjectDecl fields, p))
  2082. | Some proto ->
  2083. match get_field_opt proto h_enum, get_field_opt o h_a, get_field_opt o h_s, get_field_opt o h_length with
  2084. | _, Some (VArray a), _, Some (VInt len) ->
  2085. (Ast.EArrayDecl (List.map loop (Array.to_list (Array.sub a 0 len))),p)
  2086. | _, _, Some (VString s), _ ->
  2087. (Ast.EConst (Ast.String s),p)
  2088. | Some (VObject en), _, _, _ ->
  2089. (match get_field en h_et, get_field o h_tag with
  2090. | VAbstract (ATDecl t), VString tag ->
  2091. let e = (Ast.EField (make_path t,tag),p) in
  2092. (match get_field_opt o h_args with
  2093. | Some (VArray args) ->
  2094. let args = List.map loop (Array.to_list args) in
  2095. (Ast.ECall (e,args),p)
  2096. | _ -> e)
  2097. | _ ->
  2098. error v)
  2099. | _ ->
  2100. error v
  2101. in
  2102. encode_expr (loop v)
  2103. | _ -> error()
  2104. );
  2105. "signature", Fun1 (fun v ->
  2106. let cache = ref [] in
  2107. let cache_count = ref 0 in
  2108. let hfiles = Hashtbl.create 0 in
  2109. let get_file f =
  2110. try
  2111. Hashtbl.find hfiles f
  2112. with Not_found ->
  2113. let ff = Common.unique_full_path f in
  2114. Hashtbl.add hfiles f ff;
  2115. ff
  2116. in
  2117. let do_cache (v:value) (v2:value) =
  2118. (*
  2119. tricky : we need to have a quick not-linear cache based on objects address
  2120. but we can't use address since the GC might be triggered here.
  2121. Instead let's mutate the object temporary.
  2122. *)
  2123. let vt = Obj.repr v in
  2124. let old = Obj.tag vt in
  2125. let old_val = Obj.field vt 0 in
  2126. let abstract_tag = 7 in
  2127. Obj.set_tag vt abstract_tag;
  2128. Obj.set_field vt 0 (Obj.repr (ACacheRef v2));
  2129. cache := (vt,old,old_val) :: !cache;
  2130. incr cache_count
  2131. in
  2132. let rec loop v =
  2133. match v with
  2134. | VNull | VBool _ | VInt _ | VFloat _ | VString _ | VInt32 _ -> v
  2135. | VObject o ->
  2136. let o2 = { ofields = [||]; oproto = None } in
  2137. let v2 = VObject o2 in
  2138. do_cache v v2;
  2139. Array.iter (fun (f,v) -> if f <> h_class then set_field o2 f (loop v)) o.ofields;
  2140. (match o.oproto with
  2141. | None -> ()
  2142. | Some p -> (match loop (VObject p) with VObject p2 -> o2.oproto <- Some p2 | _ -> assert false));
  2143. v2
  2144. | VArray a ->
  2145. let a2 = Array.create (Array.length a) VNull in
  2146. let v2 = VArray a2 in
  2147. do_cache v v2;
  2148. for i = 0 to Array.length a - 1 do
  2149. a2.(i) <- loop a.(i);
  2150. done;
  2151. v2
  2152. | VFunction f ->
  2153. let v2 = VFunction (Obj.magic !cache_count) in
  2154. do_cache v v2;
  2155. v2
  2156. | VClosure (vl,f) ->
  2157. let rl = ref [] in
  2158. let v2 = VClosure (Obj.magic rl, Obj.magic !cache_count) in
  2159. do_cache v v2;
  2160. rl := List.map loop vl;
  2161. v2
  2162. | VAbstract (APos p) -> VAbstract (APos { p with Ast.pfile = get_file p.Ast.pfile })
  2163. | VAbstract (ACacheRef v) -> v
  2164. | VAbstract (AHash h) ->
  2165. let h2 = Hashtbl.create 0 in
  2166. let v2 = VAbstract (AHash h2) in
  2167. do_cache v v2;
  2168. Hashtbl.iter (fun k v -> Hashtbl.add h2 k (loop v)) h2;
  2169. v2
  2170. | VAbstract _ ->
  2171. let v2 = VAbstract (Obj.magic !cache_count) in
  2172. do_cache v v2;
  2173. v2
  2174. in
  2175. let v = loop v in
  2176. (* restore *)
  2177. List.iter (fun (vt,tag,field) ->
  2178. Obj.set_tag vt tag;
  2179. Obj.set_field vt 0 field;
  2180. ) !cache;
  2181. VString (Digest.to_hex (Digest.string (Marshal.to_string v [Marshal.Closures])))
  2182. );
  2183. "to_complex", Fun1 (fun v ->
  2184. try encode_complex_type (make_complex_type (decode_type v))
  2185. with Exit -> VNull
  2186. );
  2187. "unify", Fun2 (fun t1 t2 ->
  2188. try Type.unify (decode_type t1) (decode_type t2); VBool true
  2189. with Unify_error _ -> VBool false
  2190. );
  2191. "typeof", Fun1 (fun v ->
  2192. encode_type ((get_ctx()).curapi.typeof (decode_expr v))
  2193. );
  2194. "s_type", Fun1 (fun v ->
  2195. VString (Type.s_type (print_context()) (decode_type v))
  2196. );
  2197. "display", Fun1 (fun v ->
  2198. match v with
  2199. | VString s ->
  2200. VString ((get_ctx()).curapi.get_display s)
  2201. | _ ->
  2202. error()
  2203. );
  2204. "allow_package", Fun1 (fun v ->
  2205. match v with
  2206. | VString s ->
  2207. (get_ctx()).curapi.allow_package s;
  2208. VNull
  2209. | _ -> error());
  2210. "type_patch", Fun4 (fun t f s v ->
  2211. let p = (get_ctx()).curapi.type_patch in
  2212. (match t, f, s, v with
  2213. | VString t, VString f, VBool s, VString v -> p t f s (Some v)
  2214. | VString t, VString f, VBool s, VNull -> p t f s None
  2215. | _ -> error());
  2216. VNull
  2217. );
  2218. "meta_patch", Fun4 (fun m t f s ->
  2219. let p = (get_ctx()).curapi.meta_patch in
  2220. (match m, t, f, s with
  2221. | VString m, VString t, VString f, VBool s -> p m t (Some f) s
  2222. | VString m, VString t, VNull, VBool s -> p m t None s
  2223. | _ -> error());
  2224. VNull
  2225. );
  2226. "custom_js", Fun1 (fun f ->
  2227. match f with
  2228. | VFunction (Fun1 _) ->
  2229. let ctx = get_ctx() in
  2230. ctx.curapi.set_js_generator (fun api ->
  2231. ignore(catch_errors ctx (fun() -> ctx.do_call VNull f [api] null_pos));
  2232. );
  2233. VNull
  2234. | _ -> error()
  2235. );
  2236. "get_pos_infos", Fun1 (fun p ->
  2237. match p with
  2238. | VAbstract (APos p) -> VObject (obj (hash_field (get_ctx())) ["min",VInt p.Ast.pmin;"max",VInt p.Ast.pmax;"file",VString p.Ast.pfile])
  2239. | _ -> error()
  2240. );
  2241. "make_pos", Fun3 (fun min max file ->
  2242. match min, max, file with
  2243. | VInt min, VInt max, VString file -> VAbstract (APos { Ast.pmin = min; Ast.pmax = max; Ast.pfile = file })
  2244. | _ -> error()
  2245. );
  2246. "add_resource", Fun2 (fun name data ->
  2247. match name, data with
  2248. | VString name, VString data ->
  2249. Hashtbl.replace (ccom()).resources name data;
  2250. let m = (get_ctx()).curapi.current_module() in
  2251. m.m_extra.m_binded_res <- PMap.add name data m.m_extra.m_binded_res;
  2252. VNull
  2253. | _ -> error()
  2254. );
  2255. "local_type", Fun0 (fun() ->
  2256. match (get_ctx()).curapi.get_local_type() with
  2257. | None -> VNull
  2258. | Some t -> encode_type t
  2259. );
  2260. "local_method", Fun0 (fun() ->
  2261. VString ((get_ctx()).curapi.get_local_method())
  2262. );
  2263. "local_using", Fun0 (fun() ->
  2264. enc_array (List.map encode_clref ((get_ctx()).curapi.get_local_using()))
  2265. );
  2266. "local_vars", Fun0 (fun() ->
  2267. let vars = (get_ctx()).curapi.get_local_vars() in
  2268. let h = Hashtbl.create 0 in
  2269. PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) vars;
  2270. enc_hash h
  2271. );
  2272. "follow", Fun2 (fun v once ->
  2273. let t = decode_type v in
  2274. let follow_once t =
  2275. match t with
  2276. | TMono r ->
  2277. (match !r with
  2278. | None -> t
  2279. | Some t -> t)
  2280. | TAbstract _ | TEnum _ | TInst _ | TFun _ | TAnon _ | TDynamic _ ->
  2281. t
  2282. | TType (t,tl) ->
  2283. apply_params t.t_types tl t.t_type
  2284. | TLazy f ->
  2285. (!f)()
  2286. in
  2287. encode_type (match once with VNull | VBool false -> follow t | VBool true -> follow_once t | _ -> error())
  2288. );
  2289. "build_fields", Fun0 (fun() ->
  2290. (get_ctx()).curapi.get_build_fields()
  2291. );
  2292. "define_type", Fun1 (fun v ->
  2293. (get_ctx()).curapi.define_type v;
  2294. VNull
  2295. );
  2296. "add_class_path", Fun1 (fun v ->
  2297. match v with
  2298. | VString cp ->
  2299. let com = ccom() in
  2300. com.class_path <- (Common.normalize_path cp) :: com.class_path;
  2301. VNull
  2302. | _ ->
  2303. error()
  2304. );
  2305. "add_native_lib", Fun1 (fun v ->
  2306. match v with
  2307. | VString file ->
  2308. let com = ccom() in
  2309. (match com.platform with
  2310. | Flash -> Genswf.add_swf_lib com file false
  2311. | _ -> failwith "Unsupported platform");
  2312. VNull
  2313. | _ ->
  2314. error()
  2315. );
  2316. "module_dependency", Fun2 (fun m file ->
  2317. match m, file with
  2318. | VString m, VString file ->
  2319. (get_ctx()).curapi.module_dependency m file false;
  2320. VNull
  2321. | _ -> error()
  2322. );
  2323. "module_reuse_call", Fun2 (fun m mcall ->
  2324. match m, mcall with
  2325. | VString m, VString mcall ->
  2326. (get_ctx()).curapi.module_dependency m mcall true;
  2327. VNull
  2328. | _ -> error()
  2329. );
  2330. "get_typed_expr", Fun1 (fun e ->
  2331. match e with
  2332. | VAbstract (ATExpr e) ->
  2333. encode_expr (make_ast e)
  2334. | _ -> error()
  2335. );
  2336. "get_output", Fun0 (fun() ->
  2337. VString (ccom()).file
  2338. );
  2339. "set_output", Fun1 (fun s ->
  2340. match s with
  2341. | VString s -> (ccom()).file <- s; VNull
  2342. | _ -> error()
  2343. );
  2344. "get_display_pos", Fun0 (fun() ->
  2345. let p = !Parser.resume_display in
  2346. if p = Ast.null_pos then
  2347. VNull
  2348. else
  2349. VObject (obj (hash_field (get_ctx())) ["file",VString p.Ast.pfile;"pos",VInt p.Ast.pmin])
  2350. );
  2351. "pattern_locals", Fun2 (fun e t ->
  2352. let loc = (get_ctx()).curapi.get_pattern_locals (decode_expr e) (decode_type t) in
  2353. let h = Hashtbl.create 0 in
  2354. PMap.iter (fun n v -> Hashtbl.replace h (VString n) (encode_type v.v_type)) loc;
  2355. enc_hash h
  2356. );
  2357. "macro_context_reused", Fun1 (fun c ->
  2358. match c with
  2359. | VFunction (Fun0 _) ->
  2360. let ctx = get_ctx() in
  2361. ctx.on_reused <- (fun() -> catch_errors ctx (fun() -> ctx.do_call VNull c [] null_pos) = Some (VBool true)) :: ctx.on_reused;
  2362. VNull
  2363. | _ -> error()
  2364. );
  2365. ]
  2366. (* ---------------------------------------------------------------------- *)
  2367. (* EVAL *)
  2368. let throw ctx p msg =
  2369. ctx.callstack <- { cpos = p; cthis = ctx.vthis; cstack = DynArray.length ctx.stack; cenv = ctx.venv } :: ctx.callstack;
  2370. exc (VString msg)
  2371. let declare ctx var =
  2372. ctx.locals_map <- PMap.add var ctx.locals_count ctx.locals_map;
  2373. ctx.locals_count <- ctx.locals_count + 1
  2374. let save_locals ctx =
  2375. let old, oldcount = ctx.locals_map, ctx.locals_count in
  2376. (fun() ->
  2377. let n = ctx.locals_count - oldcount in
  2378. ctx.locals_count <- oldcount;
  2379. ctx.locals_map <- old;
  2380. n;
  2381. )
  2382. let get_ident ctx s =
  2383. try
  2384. let index = PMap.find s ctx.locals_map in
  2385. if index >= ctx.locals_barrier then
  2386. AccLocal (ctx.locals_count - index)
  2387. else (try
  2388. AccEnv (DynArray.index_of (fun s2 -> s = s2) ctx.locals_env)
  2389. with Not_found ->
  2390. let index = DynArray.length ctx.locals_env in
  2391. DynArray.add ctx.locals_env s;
  2392. AccEnv index
  2393. )
  2394. with Not_found -> try
  2395. AccGlobal (PMap.find s ctx.globals)
  2396. with Not_found ->
  2397. let g = ref VNull in
  2398. ctx.globals <- PMap.add s g ctx.globals;
  2399. AccGlobal g
  2400. let no_env = [||]
  2401. let rec eval ctx (e,p) =
  2402. match e with
  2403. | EConst c ->
  2404. (match c with
  2405. | True -> (fun() -> VBool true)
  2406. | False -> (fun() -> VBool false)
  2407. | Null -> (fun() -> VNull)
  2408. | This -> (fun() -> ctx.vthis)
  2409. | Int i -> (fun() -> VInt i)
  2410. | Int32 i -> (fun() -> VInt32 i)
  2411. | Float f ->
  2412. let f = float_of_string f in
  2413. (fun() -> VFloat f)
  2414. | String s -> (fun() -> VString s)
  2415. | Builtin "loader" ->
  2416. (fun() -> ctx.loader)
  2417. | Builtin "exports" ->
  2418. (fun() -> ctx.exports)
  2419. | Builtin s ->
  2420. let b = (try Hashtbl.find builtins s with Not_found -> throw ctx p ("Builtin not found '" ^ s ^ "'")) in
  2421. (fun() -> b)
  2422. | Ident s ->
  2423. acc_get ctx p (get_ident ctx s))
  2424. | EBlock el ->
  2425. let old = save_locals ctx in
  2426. let el = List.map (eval ctx) el in
  2427. let n = old() in
  2428. let rec loop = function
  2429. | [] -> VNull
  2430. | [e] -> e()
  2431. | e :: l ->
  2432. ignore(e());
  2433. loop l
  2434. in
  2435. (fun() ->
  2436. let v = loop el in
  2437. pop ctx n;
  2438. v)
  2439. | EParenthesis e ->
  2440. eval ctx e
  2441. | EField (e,f) ->
  2442. let e = eval ctx e in
  2443. let h = hash_field ctx f in
  2444. (fun() ->
  2445. match e() with
  2446. | VObject o -> get_field o h
  2447. | _ -> throw ctx p ("Invalid field access : " ^ f)
  2448. )
  2449. | ECall ((EConst (Builtin "mk_pos"),_),[(ECall (_,[EConst (String file),_]),_);(EConst (Int min),_);(EConst (Int max),_)]) ->
  2450. let pos = VAbstract (APos { Ast.pfile = file; Ast.pmin = min; Ast.pmax = max }) in
  2451. (fun() -> pos)
  2452. | ECall ((EConst (Builtin "typewrap"),_),[t]) ->
  2453. (fun() -> VAbstract (ATDecl (Obj.magic t)))
  2454. | ECall ((EConst (Builtin "delay_call"),_),[EConst (Int index),_]) ->
  2455. let f = ctx.curapi.delayed_macro index in
  2456. let fbuild = ref None in
  2457. let old = { ctx with gen = ctx.gen } in
  2458. let compile_delayed_call() =
  2459. let oldl, oldc, oldb, olde = ctx.locals_map, ctx.locals_count, ctx.locals_barrier, ctx.locals_env in
  2460. ctx.locals_map <- old.locals_map;
  2461. ctx.locals_count <- old.locals_count;
  2462. ctx.locals_barrier <- old.locals_barrier;
  2463. ctx.locals_env <- DynArray.copy old.locals_env;
  2464. let save = save_locals ctx in
  2465. let e = f() in
  2466. let n = save() in
  2467. let e = if DynArray.length ctx.locals_env = DynArray.length old.locals_env then
  2468. e
  2469. else
  2470. let n = DynArray.get ctx.locals_env (DynArray.length ctx.locals_env - 1) in
  2471. (fun() -> exc (VString ("Macro-in-macro call can't access to closure variable '" ^ n ^ "'")))
  2472. in
  2473. ctx.locals_map <- oldl;
  2474. ctx.locals_count <- oldc;
  2475. ctx.locals_barrier <- oldb;
  2476. ctx.locals_env <- olde;
  2477. (fun() ->
  2478. let v = e() in
  2479. pop ctx n;
  2480. v
  2481. )
  2482. in
  2483. (fun() ->
  2484. let e = (match !fbuild with
  2485. | Some e -> e
  2486. | None ->
  2487. let e = compile_delayed_call() in
  2488. fbuild := Some e;
  2489. e
  2490. ) in
  2491. e())
  2492. | ECall (e,el) ->
  2493. let el = List.map (eval ctx) el in
  2494. (match fst e with
  2495. | EField (e,f) ->
  2496. let e = eval ctx e in
  2497. let h = hash_field ctx f in
  2498. (fun() ->
  2499. let pl = List.map (fun f -> f()) el in
  2500. let o = e() in
  2501. let f = (match o with
  2502. | VObject o -> get_field o h
  2503. | _ -> throw ctx p ("Invalid field access : " ^ f)
  2504. ) in
  2505. call ctx o f pl p
  2506. )
  2507. | _ ->
  2508. let e = eval ctx e in
  2509. (fun() ->
  2510. let pl = List.map (fun f -> f()) el in
  2511. call ctx ctx.vthis (e()) pl p
  2512. ))
  2513. | EArray (e1,e2) ->
  2514. let e1 = eval ctx e1 in
  2515. let e2 = eval ctx e2 in
  2516. let acc = AccArray (e1,e2) in
  2517. acc_get ctx p acc
  2518. | EVars vl ->
  2519. let vl = List.map (fun (v,eo) ->
  2520. let eo = (match eo with None -> (fun() -> VNull) | Some e -> eval ctx e) in
  2521. declare ctx v;
  2522. eo
  2523. ) vl in
  2524. (fun() ->
  2525. List.iter (fun e -> push ctx (e())) vl;
  2526. VNull
  2527. )
  2528. | EWhile (econd,e,NormalWhile) ->
  2529. let econd = eval ctx econd in
  2530. let e = eval ctx e in
  2531. let rec loop st =
  2532. match econd() with
  2533. | VBool true ->
  2534. let v = (try
  2535. ignore(e()); None
  2536. with
  2537. | Continue -> pop ctx (DynArray.length ctx.stack - st); None
  2538. | Break v -> pop ctx (DynArray.length ctx.stack - st); Some v
  2539. ) in
  2540. (match v with
  2541. | None -> loop st
  2542. | Some v -> v)
  2543. | _ ->
  2544. VNull
  2545. in
  2546. (fun() -> try loop (DynArray.length ctx.stack) with Sys.Break -> throw ctx p "Ctrl+C")
  2547. | EWhile (econd,e,DoWhile) ->
  2548. let e = eval ctx e in
  2549. let econd = eval ctx econd in
  2550. let rec loop st =
  2551. let v = (try
  2552. ignore(e()); None
  2553. with
  2554. | Continue -> pop ctx (DynArray.length ctx.stack - st); None
  2555. | Break v -> pop ctx (DynArray.length ctx.stack - st); Some v
  2556. ) in
  2557. match v with
  2558. | Some v -> v
  2559. | None ->
  2560. match econd() with
  2561. | VBool true -> loop st
  2562. | _ -> VNull
  2563. in
  2564. (fun() -> loop (DynArray.length ctx.stack))
  2565. | EIf (econd,eif,eelse) ->
  2566. let econd = eval ctx econd in
  2567. let eif = eval ctx eif in
  2568. let eelse = (match eelse with None -> (fun() -> VNull) | Some e -> eval ctx e) in
  2569. (fun() ->
  2570. match econd() with
  2571. | VBool true -> eif()
  2572. | _ -> eelse()
  2573. )
  2574. | ETry (e,exc,ecatch) ->
  2575. let old = save_locals ctx in
  2576. let e = eval ctx e in
  2577. let n1 = old() in
  2578. declare ctx exc;
  2579. let ecatch = eval ctx ecatch in
  2580. let n2 = old() in
  2581. (fun() ->
  2582. let vthis = ctx.vthis in
  2583. let venv = ctx.venv in
  2584. let stack = ctx.callstack in
  2585. let csize = ctx.callsize in
  2586. let size = DynArray.length ctx.stack in
  2587. try
  2588. pop_ret ctx e n1
  2589. with Runtime v ->
  2590. let rec loop n l =
  2591. if n = 0 then List.map (fun s -> s.cpos) l else
  2592. match l with
  2593. | [] -> []
  2594. | _ :: l -> loop (n - 1) l
  2595. in
  2596. ctx.exc <- loop (List.length stack) (List.rev ctx.callstack);
  2597. ctx.callstack <- stack;
  2598. ctx.callsize <- csize;
  2599. ctx.vthis <- vthis;
  2600. ctx.venv <- venv;
  2601. pop ctx (DynArray.length ctx.stack - size);
  2602. push ctx v;
  2603. pop_ret ctx ecatch n2
  2604. )
  2605. | EFunction (pl,e) ->
  2606. let old = save_locals ctx in
  2607. let oldb, oldenv = ctx.locals_barrier, ctx.locals_env in
  2608. ctx.locals_barrier <- ctx.locals_count;
  2609. ctx.locals_env <- DynArray.create();
  2610. List.iter (declare ctx) pl;
  2611. let e = eval ctx e in
  2612. ignore(old());
  2613. let env = ctx.locals_env in
  2614. ctx.locals_barrier <- oldb;
  2615. ctx.locals_env <- oldenv;
  2616. let env = DynArray.to_array (DynArray.map (fun s ->
  2617. acc_get ctx p (get_ident ctx s)) env
  2618. ) in
  2619. let init_env = if Array.length env = 0 then
  2620. (fun() -> no_env)
  2621. else
  2622. (fun() -> Array.map (fun e -> e()) env)
  2623. in
  2624. (match pl with
  2625. | [] ->
  2626. (fun() ->
  2627. let env = init_env() in
  2628. VFunction (Fun0 (fun() ->
  2629. ctx.venv <- env;
  2630. e())))
  2631. | [a] ->
  2632. (fun() ->
  2633. let env = init_env() in
  2634. VFunction (Fun1 (fun v ->
  2635. ctx.venv <- env;
  2636. push ctx v;
  2637. e();
  2638. )))
  2639. | [a;b] ->
  2640. (fun() ->
  2641. let env = init_env() in
  2642. VFunction (Fun2 (fun va vb ->
  2643. ctx.venv <- env;
  2644. push ctx va;
  2645. push ctx vb;
  2646. e();
  2647. )))
  2648. | [a;b;c] ->
  2649. (fun() ->
  2650. let env = init_env() in
  2651. VFunction (Fun3 (fun va vb vc ->
  2652. ctx.venv <- env;
  2653. push ctx va;
  2654. push ctx vb;
  2655. push ctx vc;
  2656. e();
  2657. )))
  2658. | [a;b;c;d] ->
  2659. (fun() ->
  2660. let env = init_env() in
  2661. VFunction (Fun4 (fun va vb vc vd ->
  2662. ctx.venv <- env;
  2663. push ctx va;
  2664. push ctx vb;
  2665. push ctx vc;
  2666. push ctx vd;
  2667. e();
  2668. )))
  2669. | [a;b;c;d;pe] ->
  2670. (fun() ->
  2671. let env = init_env() in
  2672. VFunction (Fun5 (fun va vb vc vd ve ->
  2673. ctx.venv <- env;
  2674. push ctx va;
  2675. push ctx vb;
  2676. push ctx vc;
  2677. push ctx vd;
  2678. push ctx ve;
  2679. e();
  2680. )))
  2681. | _ ->
  2682. (fun() ->
  2683. let env = init_env() in
  2684. VFunction (FunVar (fun vl ->
  2685. if List.length vl != List.length pl then exc (VString "Invalid call");
  2686. ctx.venv <- env;
  2687. List.iter (push ctx) vl;
  2688. e();
  2689. )))
  2690. )
  2691. | EBinop (op,e1,e2) ->
  2692. eval_op ctx op e1 e2 p
  2693. | EReturn None ->
  2694. (fun() -> raise (Return VNull))
  2695. | EReturn (Some e) ->
  2696. let e = eval ctx e in
  2697. (fun() -> raise (Return (e())))
  2698. | EBreak None ->
  2699. (fun() -> raise (Break VNull))
  2700. | EBreak (Some e) ->
  2701. let e = eval ctx e in
  2702. (fun() -> raise (Break (e())))
  2703. | EContinue ->
  2704. (fun() -> raise Continue)
  2705. | ENext (e1,e2) ->
  2706. let e1 = eval ctx e1 in
  2707. let e2 = eval ctx e2 in
  2708. (fun() -> ignore(e1()); e2())
  2709. | EObject fl ->
  2710. let fl = List.map (fun (f,e) -> hash_field ctx f, eval ctx e) fl in
  2711. let fields = Array.of_list (List.map (fun (f,_) -> f,VNull) fl) in
  2712. Array.sort (fun (f1,_) (f2,_) -> compare f1 f2) fields;
  2713. (fun() ->
  2714. let o = {
  2715. ofields = Array.copy fields;
  2716. oproto = None;
  2717. } in
  2718. List.iter (fun (f,e) -> set_field o f (e())) fl;
  2719. VObject o
  2720. )
  2721. | ELabel l ->
  2722. assert false
  2723. | ESwitch (e1,el,eo) ->
  2724. let e1 = eval ctx e1 in
  2725. let el = List.map (fun (cond,e) -> cond, eval ctx cond, eval ctx e) el in
  2726. let eo = (match eo with None -> (fun() -> VNull) | Some e -> eval ctx e) in
  2727. let cases = (try
  2728. let max = ref (-1) in
  2729. let ints = List.map (fun (cond,_,e) ->
  2730. match fst cond with
  2731. | EConst (Int i) -> if i < 0 then raise Exit; if i > !max then max := i; i, e
  2732. | _ -> raise Exit
  2733. ) el in
  2734. let a = Array.create (!max + 1) eo in
  2735. List.iter (fun (i,e) -> a.(i) <- e) (List.rev ints);
  2736. Some a;
  2737. with
  2738. Exit -> None
  2739. ) in
  2740. let def v =
  2741. let rec loop = function
  2742. | [] -> eo()
  2743. | (_,c,e) :: l ->
  2744. if ctx.do_compare v (c()) = CEq then e() else loop l
  2745. in
  2746. loop el
  2747. in
  2748. (match cases with
  2749. | None -> (fun() -> def (e1()))
  2750. | Some t ->
  2751. (fun() ->
  2752. match e1() with
  2753. | VInt i -> if i >= 0 && i < Array.length t then t.(i)() else eo()
  2754. | v -> def v
  2755. ))
  2756. | ENeko _ ->
  2757. throw ctx p "Inline neko code unsupported"
  2758. and eval_oop ctx p o field (params:value list) =
  2759. match get_field_opt o field with
  2760. | None -> None
  2761. | Some f -> Some (call ctx (VObject o) f params p)
  2762. and eval_access ctx (e,p) =
  2763. match e with
  2764. | EField (e,f) ->
  2765. let v = eval ctx e in
  2766. AccField (v,f)
  2767. | EArray (e,eindex) ->
  2768. let v = eval ctx e in
  2769. let idx = eval ctx eindex in
  2770. AccArray (v,idx)
  2771. | EConst (Ident s) ->
  2772. get_ident ctx s
  2773. | EConst This ->
  2774. AccThis
  2775. | _ ->
  2776. throw ctx p "Invalid assign"
  2777. and eval_access_get_set ctx (e,p) =
  2778. match e with
  2779. | EField (e,f) ->
  2780. let v = eval ctx e in
  2781. let cache = ref VNull in
  2782. AccField ((fun() -> cache := v(); !cache),f), AccField((fun() -> !cache), f)
  2783. | EArray (e,eindex) ->
  2784. let v = eval ctx e in
  2785. let idx = eval ctx eindex in
  2786. let vcache = ref VNull and icache = ref VNull in
  2787. AccArray ((fun() -> vcache := v(); !vcache),(fun() -> icache := idx(); !icache)), AccArray ((fun() -> !vcache),(fun() -> !icache))
  2788. | EConst (Ident s) ->
  2789. let acc = get_ident ctx s in
  2790. acc, acc
  2791. | EConst This ->
  2792. AccThis, AccThis
  2793. | _ ->
  2794. throw ctx p "Invalid assign"
  2795. and acc_get ctx p = function
  2796. | AccField (v,f) ->
  2797. let h = hash_field ctx f in
  2798. (fun() ->
  2799. match v() with
  2800. | VObject o -> get_field o h
  2801. | _ -> throw ctx p ("Invalid field access : " ^ f))
  2802. | AccArray (e,index) ->
  2803. (fun() ->
  2804. let e = e() in
  2805. let index = index() in
  2806. (match index, e with
  2807. | VInt i, VArray a -> (try Array.get a i with _ -> VNull)
  2808. | VInt32 _, VArray _ -> VNull
  2809. | _, VObject o ->
  2810. (match eval_oop ctx p o h_get [index] with
  2811. | None -> throw ctx p "Invalid array access"
  2812. | Some v -> v)
  2813. | _ -> throw ctx p "Invalid array access"))
  2814. | AccLocal i ->
  2815. (fun() -> DynArray.get ctx.stack (DynArray.length ctx.stack - i))
  2816. | AccGlobal g ->
  2817. (fun() -> !g)
  2818. | AccThis ->
  2819. (fun() -> ctx.vthis)
  2820. | AccEnv i ->
  2821. (fun() -> ctx.venv.(i))
  2822. and acc_set ctx p acc value =
  2823. match acc with
  2824. | AccField (v,f) ->
  2825. let h = hash_field ctx f in
  2826. (fun() ->
  2827. let v = v() in
  2828. let value = value() in
  2829. match v with
  2830. | VObject o -> set_field o h value; value
  2831. | _ -> throw ctx p ("Invalid field access : " ^ f))
  2832. | AccArray (e,index) ->
  2833. (fun() ->
  2834. let e = e() in
  2835. let index = index() in
  2836. let value = value() in
  2837. (match index, e with
  2838. | VInt i, VArray a -> (try Array.set a i value; value with _ -> value)
  2839. | VInt32 _, VArray _ -> value
  2840. | _, VObject o ->
  2841. (match eval_oop ctx p o h_set [index;value] with
  2842. | None -> throw ctx p "Invalid array access"
  2843. | Some _ -> value);
  2844. | _ -> throw ctx p "Invalid array access"))
  2845. | AccLocal i ->
  2846. (fun() ->
  2847. let value = value() in
  2848. DynArray.set ctx.stack (DynArray.length ctx.stack - i) value;
  2849. value)
  2850. | AccGlobal g ->
  2851. (fun() ->
  2852. let value = value() in
  2853. g := value;
  2854. value)
  2855. | AccThis ->
  2856. (fun() ->
  2857. let value = value() in
  2858. ctx.vthis <- value;
  2859. value)
  2860. | AccEnv i ->
  2861. (fun() ->
  2862. let value = value() in
  2863. ctx.venv.(i) <- value;
  2864. value)
  2865. and number_op ctx p sop iop fop oop rop v1 v2 =
  2866. (fun() ->
  2867. let v1 = v1() in
  2868. let v2 = v2() in
  2869. exc_number_op ctx p sop iop fop oop rop v1 v2)
  2870. and exc_number_op ctx p sop iop fop oop rop v1 v2 =
  2871. match v1, v2 with
  2872. | VInt a, VInt b -> best_int (iop (Int32.of_int a) (Int32.of_int b))
  2873. | VInt32 a, VInt b -> best_int (iop a (Int32.of_int b))
  2874. | VInt a, VInt32 b -> best_int (iop (Int32.of_int a) b)
  2875. | VFloat a, VInt b -> VFloat (fop a (float_of_int b))
  2876. | VFloat a, VInt32 b -> VFloat (fop a (Int32.to_float b))
  2877. | VInt a, VFloat b -> VFloat (fop (float_of_int a) b)
  2878. | VInt32 a, VFloat b -> VFloat (fop (Int32.to_float a) b)
  2879. | VFloat a, VFloat b -> VFloat (fop a b)
  2880. | VInt32 a, VInt32 b -> best_int (iop a b)
  2881. | VObject o, _ ->
  2882. (match eval_oop ctx p o oop [v2] with
  2883. | Some v -> v
  2884. | None ->
  2885. match v2 with
  2886. | VObject o ->
  2887. (match eval_oop ctx p o rop [v1] with
  2888. | Some v -> v
  2889. | None -> throw ctx p sop)
  2890. | _ ->
  2891. throw ctx p sop)
  2892. | _ , VObject o ->
  2893. (match eval_oop ctx p o rop [v1] with
  2894. | Some v -> v
  2895. | None -> throw ctx p sop)
  2896. | _ ->
  2897. throw ctx p sop
  2898. and int_op ctx p op iop v1 v2 =
  2899. (fun() ->
  2900. let v1 = v1() in
  2901. let v2 = v2() in
  2902. match v1, v2 with
  2903. | VInt a, VInt b -> best_int (iop (Int32.of_int a) (Int32.of_int b))
  2904. | VInt32 a, VInt b -> best_int (iop a (Int32.of_int b))
  2905. | VInt a, VInt32 b -> best_int (iop (Int32.of_int a) b)
  2906. | VInt32 a, VInt32 b -> best_int (iop a b)
  2907. | _ -> throw ctx p op)
  2908. and base_op ctx op v1 v2 p =
  2909. match op with
  2910. | "+" ->
  2911. (fun() ->
  2912. let v1 = v1() in
  2913. let v2 = v2() in
  2914. match v1, v2 with
  2915. | (VInt _ | VInt32 _), (VInt _ | VInt32 _) | (VInt _ | VInt32 _), VFloat _ | VFloat _ , (VInt _ | VInt32 _) | VFloat _ , VFloat _ | VObject _ , _ | _ , VObject _ -> exc_number_op ctx p op Int32.add (+.) h_add h_radd v1 v2
  2916. | VString a, _ -> VString (a ^ ctx.do_string v2)
  2917. | _, VString b -> VString (ctx.do_string v1 ^ b)
  2918. | _ -> throw ctx p op)
  2919. | "-" ->
  2920. number_op ctx p op Int32.sub (-.) h_sub h_rsub v1 v2
  2921. | "*" ->
  2922. number_op ctx p op Int32.mul ( *. ) h_mult h_rmult v1 v2
  2923. | "/" ->
  2924. (fun() ->
  2925. let v1 = v1() in
  2926. let v2 = v2() in
  2927. match v1, v2 with
  2928. | VInt i, VInt j -> VFloat ((float_of_int i) /. (float_of_int j))
  2929. | VInt i, VInt32 j -> VFloat ((float_of_int i) /. (Int32.to_float j))
  2930. | VInt32 i, VInt j -> VFloat ((Int32.to_float i) /. (float_of_int j))
  2931. | VInt32 i, VInt32 j -> VFloat ((Int32.to_float i) /. (Int32.to_float j))
  2932. | _ -> exc_number_op ctx p op Int32.div (/.) h_div h_rdiv v1 v2)
  2933. | "%" ->
  2934. number_op ctx p op (fun x y -> if y = 0l then throw ctx p op; Int32.rem x y) mod_float h_mod h_rmod v1 v2
  2935. | "&" ->
  2936. int_op ctx p op Int32.logand v1 v2
  2937. | "|" ->
  2938. int_op ctx p op Int32.logor v1 v2
  2939. | "^" ->
  2940. int_op ctx p op Int32.logxor v1 v2
  2941. | "<<" ->
  2942. int_op ctx p op (fun x y -> Int32.shift_left x (Int32.to_int y)) v1 v2
  2943. | ">>" ->
  2944. int_op ctx p op (fun x y -> Int32.shift_right x (Int32.to_int y)) v1 v2
  2945. | ">>>" ->
  2946. int_op ctx p op (fun x y -> Int32.shift_right_logical x (Int32.to_int y)) v1 v2
  2947. | _ ->
  2948. throw ctx p op
  2949. and eval_op ctx op e1 e2 p =
  2950. match op with
  2951. | "=" ->
  2952. let acc = eval_access ctx e1 in
  2953. let v = eval ctx e2 in
  2954. acc_set ctx p acc v
  2955. | "==" ->
  2956. let v1 = eval ctx e1 in
  2957. let v2 = eval ctx e2 in
  2958. (fun() ->
  2959. let v1 = v1() in
  2960. let v2 = v2() in
  2961. match ctx.do_compare v1 v2 with
  2962. | CEq -> VBool true
  2963. | _ -> VBool false)
  2964. | "!=" ->
  2965. let v1 = eval ctx e1 in
  2966. let v2 = eval ctx e2 in
  2967. (fun() ->
  2968. let v1 = v1() in
  2969. let v2 = v2() in
  2970. match ctx.do_compare v1 v2 with
  2971. | CEq -> VBool false
  2972. | _ -> VBool true)
  2973. | ">" ->
  2974. let v1 = eval ctx e1 in
  2975. let v2 = eval ctx e2 in
  2976. (fun() ->
  2977. let v1 = v1() in
  2978. let v2 = v2() in
  2979. match ctx.do_compare v1 v2 with
  2980. | CSup -> VBool true
  2981. | _ -> VBool false)
  2982. | ">=" ->
  2983. let v1 = eval ctx e1 in
  2984. let v2 = eval ctx e2 in
  2985. (fun() ->
  2986. let v1 = v1() in
  2987. let v2 = v2() in
  2988. match ctx.do_compare v1 v2 with
  2989. | CSup | CEq -> VBool true
  2990. | _ -> VBool false)
  2991. | "<" ->
  2992. let v1 = eval ctx e1 in
  2993. let v2 = eval ctx e2 in
  2994. (fun() ->
  2995. let v1 = v1() in
  2996. let v2 = v2() in
  2997. match ctx.do_compare v1 v2 with
  2998. | CInf -> VBool true
  2999. | _ -> VBool false)
  3000. | "<=" ->
  3001. let v1 = eval ctx e1 in
  3002. let v2 = eval ctx e2 in
  3003. (fun() ->
  3004. let v1 = v1() in
  3005. let v2 = v2() in
  3006. match ctx.do_compare v1 v2 with
  3007. | CInf | CEq -> VBool true
  3008. | _ -> VBool false)
  3009. | "+" | "-" | "*" | "/" | "%" | "|" | "&" | "^" | "<<" | ">>" | ">>>" ->
  3010. let v1 = eval ctx e1 in
  3011. let v2 = eval ctx e2 in
  3012. base_op ctx op v1 v2 p
  3013. | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>=" | ">>>=" | "|=" | "&=" | "^=" ->
  3014. let aset, aget = eval_access_get_set ctx e1 in
  3015. let v1 = acc_get ctx p aget in
  3016. let v2 = eval ctx e2 in
  3017. let v = base_op ctx (String.sub op 0 (String.length op - 1)) v1 v2 p in
  3018. acc_set ctx p aset v
  3019. | "&&" ->
  3020. let e1 = eval ctx e1 in
  3021. let e2 = eval ctx e2 in
  3022. (fun() ->
  3023. match e1() with
  3024. | VBool false as v -> v
  3025. | _ -> e2())
  3026. | "||" ->
  3027. let e1 = eval ctx e1 in
  3028. let e2 = eval ctx e2 in
  3029. (fun() ->
  3030. match e1() with
  3031. | VBool true as v -> v
  3032. | _ -> e2())
  3033. | "++=" | "--=" ->
  3034. let aset, aget = eval_access_get_set ctx e1 in
  3035. let v1 = acc_get ctx p aget in
  3036. let v2 = eval ctx e2 in
  3037. let vcache = ref VNull in
  3038. let v = base_op ctx (String.sub op 0 1) (fun() -> vcache := v1(); !vcache) v2 p in
  3039. let set = acc_set ctx p aset v in
  3040. (fun() -> ignore(set()); !vcache)
  3041. | _ ->
  3042. throw ctx p ("Unsupported " ^ op)
  3043. and call ctx vthis vfun pl p =
  3044. let oldthis = ctx.vthis in
  3045. let stackpos = DynArray.length ctx.stack in
  3046. let oldstack = ctx.callstack in
  3047. let oldsize = ctx.callsize in
  3048. let oldenv = ctx.venv in
  3049. ctx.vthis <- vthis;
  3050. ctx.callstack <- { cpos = p; cthis = oldthis; cstack = stackpos; cenv = oldenv } :: ctx.callstack;
  3051. ctx.callsize <- oldsize + 1;
  3052. if oldsize > 200 then exc (VString "Stack overflow");
  3053. let ret = (try
  3054. (match vfun with
  3055. | VClosure (vl,f) ->
  3056. f vl pl
  3057. | VFunction f ->
  3058. (match pl, f with
  3059. | [], Fun0 f -> f()
  3060. | [a], Fun1 f -> f a
  3061. | [a;b], Fun2 f -> f a b
  3062. | [a;b;c], Fun3 f -> f a b c
  3063. | [a;b;c;d], Fun4 f -> f a b c d
  3064. | [a;b;c;d;e], Fun5 f -> f a b c d e
  3065. | _, FunVar f -> f pl
  3066. | _ -> exc (VString (Printf.sprintf "Invalid call (%d args instead of %d)" (List.length pl) (nargs f))))
  3067. | VAbstract (ALazyType f) ->
  3068. encode_type ((!f)())
  3069. | _ ->
  3070. exc (VString "Invalid call"))
  3071. with Return v -> v
  3072. | Stack_overflow -> exc (VString "Compiler Stack overflow")
  3073. | Sys_error msg | Failure msg -> exc (VString msg)
  3074. | Unix.Unix_error (_,cmd,msg) -> exc (VString ("Error " ^ cmd ^ " " ^ msg))
  3075. | Invalid_expr -> exc (VString "Invalid input value")
  3076. | Builtin_error | Invalid_argument _ -> exc (VString "Invalid call")) in
  3077. ctx.vthis <- oldthis;
  3078. ctx.venv <- oldenv;
  3079. ctx.callstack <- oldstack;
  3080. ctx.callsize <- oldsize;
  3081. pop ctx (DynArray.length ctx.stack - stackpos);
  3082. ret
  3083. (* ---------------------------------------------------------------------- *)
  3084. (* OTHERS *)
  3085. let rec to_string ctx n v =
  3086. if n > 5 then
  3087. "<...>"
  3088. else let n = n + 1 in
  3089. match v with
  3090. | VNull -> "null"
  3091. | VBool true -> "true"
  3092. | VBool false -> "false"
  3093. | VInt i -> string_of_int i
  3094. | VInt32 i -> Int32.to_string i
  3095. | VFloat f ->
  3096. let s = string_of_float f in
  3097. let len = String.length s in
  3098. if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s
  3099. | VString s -> s
  3100. | VArray vl -> "[" ^ String.concat "," (Array.to_list (Array.map (to_string ctx n) vl)) ^ "]"
  3101. | VAbstract a ->
  3102. (match a with
  3103. | APos p -> "#pos(" ^ Lexer.get_error_pos (Printf.sprintf "%s:%d:") p ^ ")"
  3104. | _ -> "#abstract")
  3105. | VFunction f -> "#function:" ^ string_of_int (nargs f)
  3106. | VClosure _ -> "#function:-1"
  3107. | VObject o ->
  3108. match eval_oop ctx null_pos o h_string [] with
  3109. | Some (VString s) -> s
  3110. | _ ->
  3111. let b = Buffer.create 0 in
  3112. let first = ref true in
  3113. Buffer.add_char b '{';
  3114. Array.iter (fun (f,v) ->
  3115. if !first then begin
  3116. Buffer.add_char b ' ';
  3117. first := false;
  3118. end else
  3119. Buffer.add_string b ", ";
  3120. Buffer.add_string b (field_name ctx f);
  3121. Buffer.add_string b " => ";
  3122. Buffer.add_string b (to_string ctx n v);
  3123. ) o.ofields;
  3124. Buffer.add_string b (if !first then "}" else " }");
  3125. Buffer.contents b
  3126. let rec compare ctx a b =
  3127. let fcmp (a:float) b = if a = b then CEq else if a < b then CInf else CSup in
  3128. let scmp (a:string) b = if a = b then CEq else if a < b then CInf else CSup in
  3129. let icmp (a:int32) b = let l = Int32.compare a b in if l = 0 then CEq else if l < 0 then CInf else CSup in
  3130. match a, b with
  3131. | VNull, VNull -> CEq
  3132. | VInt a, VInt b -> if a = b then CEq else if a < b then CInf else CSup
  3133. | VInt32 a, VInt32 b -> icmp a b
  3134. | VInt a, VInt32 b -> icmp (Int32.of_int a) b
  3135. | VInt32 a, VInt b -> icmp a (Int32.of_int b)
  3136. | VFloat a, VFloat b -> fcmp a b
  3137. | VFloat a, VInt b -> fcmp a (float_of_int b)
  3138. | VFloat a, VInt32 b -> fcmp a (Int32.to_float b)
  3139. | VInt a, VFloat b -> fcmp (float_of_int a) b
  3140. | VInt32 a, VFloat b -> fcmp (Int32.to_float a) b
  3141. | VBool a, VBool b -> if a = b then CEq else if a then CSup else CInf
  3142. | VString a, VString b -> scmp a b
  3143. | VInt _ , VString s
  3144. | VInt32 _, VString s
  3145. | VFloat _ , VString s
  3146. | VBool _ , VString s -> scmp (to_string ctx 0 a) s
  3147. | VString s, VInt _
  3148. | VString s, VInt32 _
  3149. | VString s, VFloat _
  3150. | VString s, VBool _ -> scmp s (to_string ctx 0 b)
  3151. | VObject oa, VObject ob ->
  3152. if oa == ob then CEq else
  3153. (match eval_oop ctx null_pos oa h_compare [b] with
  3154. | Some (VInt i) -> if i = 0 then CEq else if i < 0 then CInf else CSup
  3155. | _ -> CUndef)
  3156. | VAbstract a, VAbstract b ->
  3157. if a == b then CEq else CUndef
  3158. | VArray a, VArray b ->
  3159. if a == b then CEq else CUndef
  3160. | VFunction a, VFunction b ->
  3161. if a == b then CEq else CUndef
  3162. | VClosure (la,fa), VClosure (lb,fb) ->
  3163. if la == lb && fa == fb then CEq else CUndef
  3164. | _ ->
  3165. CUndef
  3166. let select ctx =
  3167. get_ctx_ref := (fun() -> ctx)
  3168. let load_prim ctx f n =
  3169. match f, n with
  3170. | VString f, VInt n ->
  3171. let lib, fname = (try ExtString.String.split f "@" with _ -> "", f) in
  3172. (try
  3173. let f = (match lib with
  3174. | "std" -> Hashtbl.find std_lib fname
  3175. | "macro" -> Hashtbl.find macro_lib fname
  3176. | "regexp" -> Hashtbl.find reg_lib fname
  3177. | "zlib" -> Hashtbl.find z_lib fname
  3178. | _ -> failwith ("You cannot use the library '" ^ lib ^ "' inside a macro");
  3179. ) in
  3180. if nargs f <> n then raise Not_found;
  3181. VFunction f
  3182. with Not_found ->
  3183. VFunction (FunVar (fun _ -> exc (VString ("Primitive not found " ^ f ^ ":" ^ string_of_int n)))))
  3184. | _ ->
  3185. exc (VString "Invalid call")
  3186. let create com api =
  3187. let loader = obj hash [
  3188. "args",VArray (Array.of_list (List.map (fun s -> VString s) com.sys_args));
  3189. "loadprim",VFunction (Fun2 (fun a b -> (get_ctx()).do_loadprim a b));
  3190. "loadmodule",VFunction (Fun2 (fun a b -> assert false));
  3191. ] in
  3192. let ctx = {
  3193. gen = Genneko.new_context com 2 true;
  3194. types = Hashtbl.create 0;
  3195. error = false;
  3196. error_proto = { ofields = [||]; oproto = None };
  3197. prototypes = Hashtbl.create 0;
  3198. enums = [||];
  3199. (* eval *)
  3200. locals_map = PMap.empty;
  3201. locals_count = 0;
  3202. locals_barrier = 0;
  3203. locals_env = DynArray.create();
  3204. globals = PMap.empty;
  3205. (* runtime *)
  3206. callstack = [];
  3207. callsize = 0;
  3208. stack = DynArray.create();
  3209. exc = [];
  3210. vthis = VNull;
  3211. venv = [||];
  3212. fields_cache = Hashtbl.copy constants;
  3213. (* api *)
  3214. do_call = Obj.magic();
  3215. do_string = Obj.magic();
  3216. do_loadprim = Obj.magic();
  3217. do_compare = Obj.magic();
  3218. (* context *)
  3219. curapi = api;
  3220. loader = VObject loader;
  3221. on_reused = [];
  3222. is_reused = true;
  3223. exports = VObject { ofields = [||]; oproto = None };
  3224. } in
  3225. ctx.do_call <- call ctx;
  3226. ctx.do_string <- to_string ctx 0;
  3227. ctx.do_loadprim <- load_prim ctx;
  3228. ctx.do_compare <- compare ctx;
  3229. select ctx;
  3230. List.iter (fun e -> ignore((eval ctx e)())) (Genneko.header());
  3231. ctx
  3232. let do_reuse ctx =
  3233. ctx.is_reused <- false
  3234. let can_reuse ctx types =
  3235. let has_old_version t =
  3236. let inf = Type.t_infos t in
  3237. try
  3238. Hashtbl.find ctx.types inf.mt_path <> inf.mt_module.m_id
  3239. with Not_found ->
  3240. false
  3241. in
  3242. if List.exists has_old_version types then
  3243. false
  3244. else if ctx.is_reused then
  3245. true
  3246. else if not (List.for_all (fun f -> f()) ctx.on_reused) then
  3247. false
  3248. else begin
  3249. ctx.is_reused <- true;
  3250. true;
  3251. end
  3252. let add_types ctx types ready =
  3253. let types = List.filter (fun t ->
  3254. let path = Type.t_path t in
  3255. if Hashtbl.mem ctx.types path then false else begin
  3256. Hashtbl.add ctx.types path (Type.t_infos t).mt_module.m_id;
  3257. true;
  3258. end
  3259. ) types in
  3260. List.iter ready types;
  3261. let e = (EBlock (Genneko.build ctx.gen types), null_pos) in
  3262. ignore(catch_errors ctx (fun() -> ignore((eval ctx e)())))
  3263. let eval_expr ctx e =
  3264. let e = Genneko.gen_expr ctx.gen e in
  3265. catch_errors ctx (fun() -> (eval ctx e)())
  3266. let get_path ctx path p =
  3267. let rec loop = function
  3268. | [] -> assert false
  3269. | [x] -> (EConst (Ident x),p)
  3270. | x :: l -> (EField (loop l,x),p)
  3271. in
  3272. (eval ctx (loop (List.rev path)))()
  3273. let set_error ctx e =
  3274. ctx.error <- e
  3275. let call_path ctx path f vl api =
  3276. if ctx.error then
  3277. None
  3278. else let old = ctx.curapi in
  3279. ctx.curapi <- api;
  3280. let p = Genneko.pos ctx.gen api.pos in
  3281. catch_errors ctx ~final:(fun() -> ctx.curapi <- old) (fun() ->
  3282. match get_path ctx path p with
  3283. | VObject o ->
  3284. let f = get_field o (hash f) in
  3285. call ctx (VObject o) f vl p
  3286. | _ -> assert false
  3287. )
  3288. (* ---------------------------------------------------------------------- *)
  3289. (* EXPR ENCODING *)
  3290. type enum_index =
  3291. | IExpr
  3292. | IBinop
  3293. | IUnop
  3294. | IConst
  3295. | ITParam
  3296. | ICType
  3297. | IField
  3298. | IType
  3299. | IFieldKind
  3300. | IMethodKind
  3301. | IVarAccess
  3302. | IAccess
  3303. | IClassKind
  3304. let enum_name = function
  3305. | IExpr -> "ExprDef"
  3306. | IBinop -> "Binop"
  3307. | IUnop -> "Unop"
  3308. | IConst -> "Constant"
  3309. | ITParam -> "TypeParam"
  3310. | ICType -> "ComplexType"
  3311. | IField -> "FieldType"
  3312. | IType -> "Type"
  3313. | IFieldKind -> "FieldKind"
  3314. | IMethodKind -> "MethodKind"
  3315. | IVarAccess -> "VarAccess"
  3316. | IAccess -> "Access"
  3317. | IClassKind -> "ClassKind"
  3318. let init ctx =
  3319. let enums = [IExpr;IBinop;IUnop;IConst;ITParam;ICType;IField;IType;IFieldKind;IMethodKind;IVarAccess;IAccess;IClassKind] in
  3320. let get_enum_proto e =
  3321. match get_path ctx ["haxe";"macro";enum_name e] null_pos with
  3322. | VObject e ->
  3323. (match get_field e h_constructs with
  3324. | VObject cst ->
  3325. (match get_field cst h_a with
  3326. | VArray a ->
  3327. Array.map (fun s ->
  3328. match s with
  3329. | VObject s -> (match get_field s h_s with VString s -> get_field e (hash s),s | _ -> assert false)
  3330. | _ -> assert false
  3331. ) a
  3332. | _ -> assert false)
  3333. | _ -> assert false)
  3334. | _ -> failwith ("haxe.macro." ^ enum_name e ^ " does not exists")
  3335. in
  3336. ctx.enums <- Array.of_list (List.map get_enum_proto enums);
  3337. ctx.error_proto <- (match get_path ctx ["haxe";"macro";"Error";"prototype"] null_pos with VObject p -> p | _ -> failwith ("haxe.macro.Error does not exists"))
  3338. open Ast
  3339. let null f = function
  3340. | None -> VNull
  3341. | Some v -> f v
  3342. let encode_pos p =
  3343. VAbstract (APos p)
  3344. let enc_inst path fields =
  3345. let ctx = get_ctx() in
  3346. let p = (try Hashtbl.find ctx.prototypes path with Not_found -> try
  3347. (match get_path ctx (path@["prototype"]) Nast.null_pos with
  3348. | VObject o -> Hashtbl.add ctx.prototypes path o; o
  3349. | _ -> raise (Runtime VNull))
  3350. with Runtime _ ->
  3351. failwith ("Prototype not found " ^ String.concat "." path)
  3352. ) in
  3353. let o = obj hash fields in
  3354. o.oproto <- Some p;
  3355. VObject o
  3356. let enc_array l =
  3357. let a = Array.of_list l in
  3358. enc_inst ["Array"] [
  3359. "__a", VArray a;
  3360. "length", VInt (Array.length a);
  3361. ]
  3362. let enc_string s =
  3363. enc_inst ["String"] [
  3364. "__s", VString s;
  3365. "length", VInt (String.length s)
  3366. ]
  3367. let enc_hash h =
  3368. enc_inst ["haxe";"ds";"StringMap"] [
  3369. "h", VAbstract (AHash h);
  3370. ]
  3371. let enc_obj l = VObject (obj hash l)
  3372. let enc_enum (i:enum_index) index pl =
  3373. let eindex : int = Obj.magic i in
  3374. let edef = (get_ctx()).enums.(eindex) in
  3375. if pl = [] then
  3376. fst edef.(index)
  3377. else
  3378. enc_inst ["haxe";"macro";enum_name i] [
  3379. "tag", VString (snd edef.(index));
  3380. "index", VInt index;
  3381. "args", VArray (Array.of_list pl);
  3382. ]
  3383. let compiler_error msg pos =
  3384. exc (enc_inst ["haxe";"macro";"Error"] [("message",enc_string msg);("pos",encode_pos pos)])
  3385. let encode_const c =
  3386. let tag, pl = match c with
  3387. | Int s -> 0, [enc_string s]
  3388. | Float s -> 1, [enc_string s]
  3389. | String s -> 2, [enc_string s]
  3390. | Ident s -> 3, [enc_string s]
  3391. | Regexp (s,opt) -> 4, [enc_string s;enc_string opt]
  3392. in
  3393. enc_enum IConst tag pl
  3394. let rec encode_binop op =
  3395. let tag, pl = match op with
  3396. | OpAdd -> 0, []
  3397. | OpMult -> 1, []
  3398. | OpDiv -> 2, []
  3399. | OpSub -> 3, []
  3400. | OpAssign -> 4, []
  3401. | OpEq -> 5, []
  3402. | OpNotEq -> 6, []
  3403. | OpGt -> 7, []
  3404. | OpGte -> 8, []
  3405. | OpLt -> 9, []
  3406. | OpLte -> 10, []
  3407. | OpAnd -> 11, []
  3408. | OpOr -> 12, []
  3409. | OpXor -> 13, []
  3410. | OpBoolAnd -> 14, []
  3411. | OpBoolOr -> 15, []
  3412. | OpShl -> 16, []
  3413. | OpShr -> 17, []
  3414. | OpUShr -> 18, []
  3415. | OpMod -> 19, []
  3416. | OpAssignOp op -> 20, [encode_binop op]
  3417. | OpInterval -> 21, []
  3418. | OpArrow -> 22, []
  3419. in
  3420. enc_enum IBinop tag pl
  3421. let encode_unop op =
  3422. let tag = match op with
  3423. | Increment -> 0
  3424. | Decrement -> 1
  3425. | Not -> 2
  3426. | Neg -> 3
  3427. | NegBits -> 4
  3428. in
  3429. enc_enum IUnop tag []
  3430. let rec encode_path t =
  3431. let fields = [
  3432. "pack", enc_array (List.map enc_string t.tpackage);
  3433. "name", enc_string t.tname;
  3434. "params", enc_array (List.map encode_tparam t.tparams);
  3435. ] in
  3436. enc_obj (match t.tsub with
  3437. | None -> fields
  3438. | Some s -> ("sub", enc_string s) :: fields)
  3439. and encode_tparam = function
  3440. | TPType t -> enc_enum ITParam 0 [encode_ctype t]
  3441. | TPExpr e -> enc_enum ITParam 1 [encode_expr e]
  3442. and encode_access a =
  3443. let tag = match a with
  3444. | APublic -> 0
  3445. | APrivate -> 1
  3446. | AStatic -> 2
  3447. | AOverride -> 3
  3448. | ADynamic -> 4
  3449. | AInline -> 5
  3450. | AMacro -> 6
  3451. in
  3452. enc_enum IAccess tag []
  3453. and encode_meta_entry (m,ml,p) =
  3454. enc_obj [
  3455. "name", enc_string (fst (MetaInfo.to_string m));
  3456. "params", enc_array (List.map encode_expr ml);
  3457. "pos", encode_pos p;
  3458. ]
  3459. and encode_meta_content m =
  3460. enc_array (List.map encode_meta_entry m)
  3461. and encode_field (f:class_field) =
  3462. let tag, pl = match f.cff_kind with
  3463. | FVar (t,e) -> 0, [null encode_ctype t; null encode_expr e]
  3464. | FFun f -> 1, [encode_fun f]
  3465. | FProp (get,set, t, e) -> 2, [enc_string get; enc_string set; null encode_ctype t; null encode_expr e]
  3466. in
  3467. enc_obj [
  3468. "name",enc_string f.cff_name;
  3469. "doc", null enc_string f.cff_doc;
  3470. "pos", encode_pos f.cff_pos;
  3471. "kind", enc_enum IField tag pl;
  3472. "meta", encode_meta_content f.cff_meta;
  3473. "access", enc_array (List.map encode_access f.cff_access);
  3474. ]
  3475. and encode_ctype t =
  3476. let tag, pl = match t with
  3477. | CTPath p ->
  3478. 0, [encode_path p]
  3479. | CTFunction (pl,r) ->
  3480. 1, [enc_array (List.map encode_ctype pl);encode_ctype r]
  3481. | CTAnonymous fl ->
  3482. 2, [enc_array (List.map encode_field fl)]
  3483. | CTParent t ->
  3484. 3, [encode_ctype t]
  3485. | CTExtend (t,fields) ->
  3486. 4, [encode_path t; enc_array (List.map encode_field fields)]
  3487. | CTOptional t ->
  3488. 5, [encode_ctype t]
  3489. in
  3490. enc_enum ICType tag pl
  3491. and encode_tparam_decl tp =
  3492. enc_obj [
  3493. "name", enc_string tp.tp_name;
  3494. "params", enc_array (List.map encode_tparam_decl tp.tp_params);
  3495. "constraints", enc_array (List.map encode_ctype tp.tp_constraints);
  3496. ]
  3497. and encode_fun f =
  3498. enc_obj [
  3499. "params", enc_array (List.map encode_tparam_decl f.f_params);
  3500. "args", enc_array (List.map (fun (n,opt,t,e) ->
  3501. enc_obj [
  3502. "name", enc_string n;
  3503. "opt", VBool opt;
  3504. "type", null encode_ctype t;
  3505. "value", null encode_expr e;
  3506. ]
  3507. ) f.f_args);
  3508. "ret", null encode_ctype f.f_type;
  3509. "expr", null encode_expr f.f_expr
  3510. ]
  3511. and encode_expr e =
  3512. let rec loop (e,p) =
  3513. let tag, pl = match e with
  3514. | EConst c ->
  3515. 0, [encode_const c]
  3516. | EArray (e1,e2) ->
  3517. 1, [loop e1;loop e2]
  3518. | EBinop (op,e1,e2) ->
  3519. 2, [encode_binop op;loop e1;loop e2]
  3520. | EField (e,f) ->
  3521. 3, [loop e;enc_string f]
  3522. | EParenthesis e ->
  3523. 4, [loop e]
  3524. | EObjectDecl fl ->
  3525. 5, [enc_array (List.map (fun (f,e) -> enc_obj [
  3526. "field",enc_string f;
  3527. "expr",loop e;
  3528. ]) fl)]
  3529. | EArrayDecl el ->
  3530. 6, [enc_array (List.map loop el)]
  3531. | ECall (e,el) ->
  3532. 7, [loop e;enc_array (List.map loop el)]
  3533. | ENew (p,el) ->
  3534. 8, [encode_path p; enc_array (List.map loop el)]
  3535. | EUnop (op,flag,e) ->
  3536. 9, [encode_unop op; VBool (match flag with Prefix -> false | Postfix -> true); loop e]
  3537. | EVars vl ->
  3538. 10, [enc_array (List.map (fun (v,t,eo) ->
  3539. enc_obj [
  3540. "name",enc_string v;
  3541. "type",null encode_ctype t;
  3542. "expr",null loop eo;
  3543. ]
  3544. ) vl)]
  3545. | EFunction (name,f) ->
  3546. 11, [null enc_string name; encode_fun f]
  3547. | EBlock el ->
  3548. 12, [enc_array (List.map loop el)]
  3549. | EFor (e,eloop) ->
  3550. 13, [loop e;loop eloop]
  3551. | EIn (e1,e2) ->
  3552. 14, [loop e1;loop e2]
  3553. | EIf (econd,e,eelse) ->
  3554. 15, [loop econd;loop e;null loop eelse]
  3555. | EWhile (econd,e,flag) ->
  3556. 16, [loop econd;loop e;VBool (match flag with NormalWhile -> true | DoWhile -> false)]
  3557. | ESwitch (e,cases,eopt) ->
  3558. 17, [loop e;enc_array (List.map (fun (ecl,eg,e) ->
  3559. enc_obj [
  3560. "values",enc_array (List.map loop ecl);
  3561. "guard",null loop eg;
  3562. "expr",null loop e
  3563. ]
  3564. ) cases);null encode_null_expr eopt]
  3565. | ETry (e,catches) ->
  3566. 18, [loop e;enc_array (List.map (fun (v,t,e) ->
  3567. enc_obj [
  3568. "name",enc_string v;
  3569. "type",encode_ctype t;
  3570. "expr",loop e
  3571. ]
  3572. ) catches)]
  3573. | EReturn eo ->
  3574. 19, [null loop eo]
  3575. | EBreak ->
  3576. 20, []
  3577. | EContinue ->
  3578. 21, []
  3579. | EUntyped e ->
  3580. 22, [loop e]
  3581. | EThrow e ->
  3582. 23, [loop e]
  3583. | ECast (e,t) ->
  3584. 24, [loop e; null encode_ctype t]
  3585. | EDisplay (e,flag) ->
  3586. 25, [loop e; VBool flag]
  3587. | EDisplayNew t ->
  3588. 26, [encode_path t]
  3589. | ETernary (econd,e1,e2) ->
  3590. 27, [loop econd;loop e1;loop e2]
  3591. | ECheckType (e,t) ->
  3592. 28, [loop e; encode_ctype t]
  3593. | EMeta (m,e) ->
  3594. 29, [encode_meta_entry m;loop e]
  3595. in
  3596. enc_obj [
  3597. "pos", encode_pos p;
  3598. "expr", enc_enum IExpr tag pl;
  3599. ]
  3600. in
  3601. loop e
  3602. and encode_null_expr e =
  3603. match e with
  3604. | None ->
  3605. enc_obj ["pos", VNull;"expr",VNull]
  3606. | Some e ->
  3607. encode_expr e
  3608. (* ---------------------------------------------------------------------- *)
  3609. (* EXPR DECODING *)
  3610. let opt f v =
  3611. match v with
  3612. | VNull -> None
  3613. | _ -> Some (f v)
  3614. let opt_list f v =
  3615. match v with
  3616. | VNull -> []
  3617. | _ -> f v
  3618. let decode_pos = function
  3619. | VAbstract (APos p) -> p
  3620. | _ -> raise Invalid_expr
  3621. let field v f =
  3622. match v with
  3623. | VObject o -> get_field o (hash f)
  3624. | _ -> raise Invalid_expr
  3625. let decode_enum v =
  3626. match field v "index", field v "args" with
  3627. | VInt i, VNull -> i, []
  3628. | VInt i, VArray a -> i, Array.to_list a
  3629. | _ -> raise Invalid_expr
  3630. let dec_bool = function
  3631. | VBool b -> b
  3632. | _ -> raise Invalid_expr
  3633. let dec_string v =
  3634. match field v "__s" with
  3635. | VString s -> s
  3636. | _ -> raise Invalid_expr
  3637. let dec_array v =
  3638. match field v "__a", field v "length" with
  3639. | VArray a, VInt l -> Array.to_list (if Array.length a = l then a else Array.sub a 0 l)
  3640. | _ -> raise Invalid_expr
  3641. let decode_const c =
  3642. match decode_enum c with
  3643. | 0, [s] -> Int (dec_string s)
  3644. | 1, [s] -> Float (dec_string s)
  3645. | 2, [s] -> String (dec_string s)
  3646. | 3, [s] -> Ident (dec_string s)
  3647. | 4, [s;opt] -> Regexp (dec_string s, dec_string opt)
  3648. | 5, [s] -> Ident (dec_string s) (** deprecated CType, keep until 3.0 release **)
  3649. | _ -> raise Invalid_expr
  3650. let rec decode_op op =
  3651. match decode_enum op with
  3652. | 0, [] -> OpAdd
  3653. | 1, [] -> OpMult
  3654. | 2, [] -> OpDiv
  3655. | 3, [] -> OpSub
  3656. | 4, [] -> OpAssign
  3657. | 5, [] -> OpEq
  3658. | 6, [] -> OpNotEq
  3659. | 7, [] -> OpGt
  3660. | 8, [] -> OpGte
  3661. | 9, [] -> OpLt
  3662. | 10, [] -> OpLte
  3663. | 11, [] -> OpAnd
  3664. | 12, [] -> OpOr
  3665. | 13, [] -> OpXor
  3666. | 14, [] -> OpBoolAnd
  3667. | 15, [] -> OpBoolOr
  3668. | 16, [] -> OpShl
  3669. | 17, [] -> OpShr
  3670. | 18, [] -> OpUShr
  3671. | 19, [] -> OpMod
  3672. | 20, [op] -> OpAssignOp (decode_op op)
  3673. | 21, [] -> OpInterval
  3674. | 22,[] -> OpArrow
  3675. | _ -> raise Invalid_expr
  3676. let decode_unop op =
  3677. match decode_enum op with
  3678. | 0, [] -> Increment
  3679. | 1, [] -> Decrement
  3680. | 2, [] -> Not
  3681. | 3, [] -> Neg
  3682. | 4, [] -> NegBits
  3683. | _ -> raise Invalid_expr
  3684. let rec decode_path t =
  3685. {
  3686. tpackage = List.map dec_string (dec_array (field t "pack"));
  3687. tname = dec_string (field t "name");
  3688. tparams = List.map decode_tparam (dec_array (field t "params"));
  3689. tsub = opt dec_string (field t "sub");
  3690. }
  3691. and decode_tparam v =
  3692. match decode_enum v with
  3693. | 0,[t] -> TPType (decode_ctype t)
  3694. | 1,[e] -> TPExpr (decode_expr e)
  3695. | _ -> raise Invalid_expr
  3696. and decode_tparam_decl v =
  3697. {
  3698. tp_name = dec_string (field v "name");
  3699. tp_constraints = (match field v "constraints" with VNull -> [] | a -> List.map decode_ctype (dec_array a));
  3700. tp_params = (match field v "params" with VNull -> [] | a -> List.map decode_tparam_decl (dec_array a));
  3701. }
  3702. and decode_fun v =
  3703. {
  3704. f_params = List.map decode_tparam_decl (dec_array (field v "params"));
  3705. f_args = List.map (fun o ->
  3706. (dec_string (field o "name"),dec_bool (field o "opt"),opt decode_ctype (field o "type"),opt decode_expr (field o "value"))
  3707. ) (dec_array (field v "args"));
  3708. f_type = opt decode_ctype (field v "ret");
  3709. f_expr = opt decode_expr (field v "expr");
  3710. }
  3711. and decode_access v =
  3712. match decode_enum v with
  3713. | 0, [] -> APublic
  3714. | 1, [] -> APrivate
  3715. | 2, [] -> AStatic
  3716. | 3, [] -> AOverride
  3717. | 4, [] -> ADynamic
  3718. | 5, [] -> AInline
  3719. | 6, [] -> AMacro
  3720. | _ -> raise Invalid_expr
  3721. and decode_meta_entry v =
  3722. MetaInfo.from_string (dec_string (field v "name")), List.map decode_expr (dec_array (field v "params")), decode_pos (field v "pos")
  3723. and decode_meta_content v =
  3724. List.map decode_meta_entry (dec_array v)
  3725. and decode_field v =
  3726. let fkind = match decode_enum (field v "kind") with
  3727. | 0, [t;e] ->
  3728. FVar (opt decode_ctype t, opt decode_expr e)
  3729. | 1, [f] ->
  3730. FFun (decode_fun f)
  3731. | 2, [get;set; t; e] ->
  3732. FProp (dec_string get, dec_string set, opt decode_ctype t, opt decode_expr e)
  3733. | _ ->
  3734. raise Invalid_expr
  3735. in
  3736. {
  3737. cff_name = dec_string (field v "name");
  3738. cff_doc = opt dec_string (field v "doc");
  3739. cff_pos = decode_pos (field v "pos");
  3740. cff_kind = fkind;
  3741. cff_access = List.map decode_access (opt_list dec_array (field v "access"));
  3742. cff_meta = opt_list decode_meta_content (field v "meta");
  3743. }
  3744. and decode_ctype t =
  3745. match decode_enum t with
  3746. | 0, [p] ->
  3747. CTPath (decode_path p)
  3748. | 1, [a;r] ->
  3749. CTFunction (List.map decode_ctype (dec_array a), decode_ctype r)
  3750. | 2, [fl] ->
  3751. CTAnonymous (List.map decode_field (dec_array fl))
  3752. | 3, [t] ->
  3753. CTParent (decode_ctype t)
  3754. | 4, [t;fl] ->
  3755. CTExtend (decode_path t, List.map decode_field (dec_array fl))
  3756. | 5, [t] ->
  3757. CTOptional (decode_ctype t)
  3758. | _ ->
  3759. raise Invalid_expr
  3760. let rec decode_expr v =
  3761. let rec loop v =
  3762. (decode (field v "expr"), decode_pos (field v "pos"))
  3763. and decode e =
  3764. match decode_enum e with
  3765. | 0, [c] ->
  3766. EConst (decode_const c)
  3767. | 1, [e1;e2] ->
  3768. EArray (loop e1, loop e2)
  3769. | 2, [op;e1;e2] ->
  3770. EBinop (decode_op op, loop e1, loop e2)
  3771. | 3, [e;f] ->
  3772. EField (loop e, dec_string f)
  3773. | 4, [e] ->
  3774. EParenthesis (loop e)
  3775. | 5, [a] ->
  3776. EObjectDecl (List.map (fun o ->
  3777. (dec_string (field o "field"), loop (field o "expr"))
  3778. ) (dec_array a))
  3779. | 6, [a] ->
  3780. EArrayDecl (List.map loop (dec_array a))
  3781. | 7, [e;el] ->
  3782. ECall (loop e,List.map loop (dec_array el))
  3783. | 8, [t;el] ->
  3784. ENew (decode_path t,List.map loop (dec_array el))
  3785. | 9, [op;VBool f;e] ->
  3786. EUnop (decode_unop op,(if f then Postfix else Prefix),loop e)
  3787. | 10, [vl] ->
  3788. EVars (List.map (fun v ->
  3789. (dec_string (field v "name"),opt decode_ctype (field v "type"),opt loop (field v "expr"))
  3790. ) (dec_array vl))
  3791. | 11, [fname;f] ->
  3792. EFunction (opt dec_string fname,decode_fun f)
  3793. | 12, [el] ->
  3794. EBlock (List.map loop (dec_array el))
  3795. | 13, [e1;e2] ->
  3796. EFor (loop e1, loop e2)
  3797. | 14, [e1;e2] ->
  3798. EIn (loop e1, loop e2)
  3799. | 15, [e1;e2;e3] ->
  3800. EIf (loop e1, loop e2, opt loop e3)
  3801. | 16, [e1;e2;VBool flag] ->
  3802. EWhile (loop e1,loop e2,if flag then NormalWhile else DoWhile)
  3803. | 17, [e;cases;eo] ->
  3804. let cases = List.map (fun c ->
  3805. (List.map loop (dec_array (field c "values")),opt loop (field c "guard"),opt loop (field c "expr"))
  3806. ) (dec_array cases) in
  3807. ESwitch (loop e,cases,opt decode_null_expr eo)
  3808. | 18, [e;catches] ->
  3809. let catches = List.map (fun c ->
  3810. (dec_string (field c "name"),decode_ctype (field c "type"),loop (field c "expr"))
  3811. ) (dec_array catches) in
  3812. ETry (loop e, catches)
  3813. | 19, [e] ->
  3814. EReturn (opt loop e)
  3815. | 20, [] ->
  3816. EBreak
  3817. | 21, [] ->
  3818. EContinue
  3819. | 22, [e] ->
  3820. EUntyped (loop e)
  3821. | 23, [e] ->
  3822. EThrow (loop e)
  3823. | 24, [e;t] ->
  3824. ECast (loop e,opt decode_ctype t)
  3825. | 25, [e;f] ->
  3826. EDisplay (loop e,dec_bool f)
  3827. | 26, [t] ->
  3828. EDisplayNew (decode_path t)
  3829. | 27, [e1;e2;e3] ->
  3830. ETernary (loop e1,loop e2,loop e3)
  3831. | 28, [e;t] ->
  3832. ECheckType (loop e, decode_ctype t)
  3833. | 29, [m;e] ->
  3834. EMeta (decode_meta_entry m,loop e)
  3835. | 30, [e;f] ->
  3836. EField (loop e, dec_string f) (*** deprecated EType, keep until haxe 3 **)
  3837. | _ ->
  3838. raise Invalid_expr
  3839. in
  3840. try
  3841. loop v
  3842. with Stack_overflow ->
  3843. raise Invalid_expr
  3844. and decode_null_expr v =
  3845. match field v "expr" with
  3846. | VNull -> None
  3847. | _ -> Some (decode_expr v)
  3848. (* ---------------------------------------------------------------------- *)
  3849. (* TYPE ENCODING *)
  3850. let encode_ref v convert tostr =
  3851. enc_obj [
  3852. "get", VFunction (Fun0 (fun() -> convert v));
  3853. "__string", VFunction (Fun0 (fun() -> VString (tostr())));
  3854. "toString", VFunction (Fun0 (fun() -> enc_string (tostr())));
  3855. "$", VAbstract (AUnsafe (Obj.repr v));
  3856. ]
  3857. let decode_ref v : 'a =
  3858. match field v "$" with
  3859. | VAbstract (AUnsafe t) -> Obj.obj t
  3860. | _ -> raise Invalid_expr
  3861. let encode_pmap convert m =
  3862. let h = Hashtbl.create 0 in
  3863. PMap.iter (fun k v -> Hashtbl.add h (VString k) (convert v)) m;
  3864. enc_hash h
  3865. let encode_pmap_array convert m =
  3866. let l = ref [] in
  3867. PMap.iter (fun _ v -> l := !l @ [(convert v)]) m;
  3868. enc_array !l
  3869. let encode_array convert l =
  3870. enc_array (List.map convert l)
  3871. let encode_meta m set =
  3872. let meta = ref m in
  3873. enc_obj [
  3874. "get", VFunction (Fun0 (fun() ->
  3875. encode_meta_content (!meta)
  3876. ));
  3877. "add", VFunction (Fun3 (fun k vl p ->
  3878. (try
  3879. let el = List.map decode_expr (dec_array vl) in
  3880. meta := (MetaInfo.from_string (dec_string k), el, decode_pos p) :: !meta;
  3881. set (!meta)
  3882. with Invalid_expr ->
  3883. failwith "Invalid expression");
  3884. VNull
  3885. ));
  3886. "remove", VFunction (Fun1 (fun k ->
  3887. let k = MetaInfo.from_string (try dec_string k with Invalid_expr -> raise Builtin_error) in
  3888. meta := List.filter (fun (m,_,_) -> m <> k) (!meta);
  3889. set (!meta);
  3890. VNull
  3891. ));
  3892. "has", VFunction (Fun1 (fun k ->
  3893. let k = MetaInfo.from_string (try dec_string k with Invalid_expr -> raise Builtin_error) in
  3894. VBool (List.exists (fun (m,_,_) -> m = k) (!meta));
  3895. ));
  3896. ]
  3897. let rec encode_mtype t fields =
  3898. let i = t_infos t in
  3899. enc_obj ([
  3900. "__t", VAbstract (ATDecl t);
  3901. "pack", enc_array (List.map enc_string (fst i.mt_path));
  3902. "name", enc_string (snd i.mt_path);
  3903. "pos", encode_pos i.mt_pos;
  3904. "module", enc_string (s_type_path i.mt_module.m_path);
  3905. "isPrivate", VBool i.mt_private;
  3906. "meta", encode_meta i.mt_meta (fun m -> i.mt_meta <- m);
  3907. "doc", null enc_string i.mt_doc;
  3908. "params", encode_type_params i.mt_types;
  3909. ] @ fields)
  3910. and encode_type_params tl =
  3911. enc_array (List.map (fun (n,t) -> enc_obj ["name",enc_string n;"t",encode_type t]) tl)
  3912. and encode_tenum e =
  3913. encode_mtype (TEnumDecl e) [
  3914. "isExtern", VBool e.e_extern;
  3915. "exclude", VFunction (Fun0 (fun() -> e.e_extern <- true; VNull));
  3916. "constructs", encode_pmap encode_efield e.e_constrs;
  3917. "names", enc_array (List.map enc_string e.e_names);
  3918. ]
  3919. and encode_tabstract a =
  3920. encode_mtype (TAbstractDecl a) [
  3921. "type", encode_type a.a_this;
  3922. "impl", (match a.a_impl with None -> VNull | Some c -> encode_clref c);
  3923. "binops", enc_array (List.map (fun (op,cf) -> enc_obj [ "op",encode_binop op; "field",encode_cfield cf]) a.a_ops);
  3924. "unops", enc_array (List.map (fun (op,postfix,cf) -> enc_obj [ "op",encode_unop op; "isPostfix",VBool (match postfix with Postfix -> true | Prefix -> false); "field",encode_cfield cf]) a.a_unops);
  3925. "from", enc_array (List.map (fun (t,cfo) -> enc_obj [ "t",encode_type t; "field",match cfo with None -> VNull | Some cf -> encode_cfield cf]) a.a_from);
  3926. "to", enc_array (List.map (fun (t,cfo) -> enc_obj [ "t",encode_type t; "field",match cfo with None -> VNull | Some cf -> encode_cfield cf]) a.a_to);
  3927. "array", enc_array (List.map encode_cfield a.a_array);
  3928. ]
  3929. and encode_efield f =
  3930. enc_obj [
  3931. "name", enc_string f.ef_name;
  3932. "type", encode_type f.ef_type;
  3933. "pos", encode_pos f.ef_pos;
  3934. "index", VInt f.ef_index;
  3935. "meta", encode_meta f.ef_meta (fun m -> f.ef_meta <- m);
  3936. "doc", null enc_string f.ef_doc;
  3937. "params", encode_type_params f.ef_params;
  3938. ]
  3939. and encode_cfield f =
  3940. enc_obj [
  3941. "name", enc_string f.cf_name;
  3942. "type", (match f.cf_kind with Method _ -> encode_lazy_type f.cf_type | _ -> encode_type f.cf_type);
  3943. "isPublic", VBool f.cf_public;
  3944. "params", encode_type_params f.cf_params;
  3945. "meta", encode_meta f.cf_meta (fun m -> f.cf_meta <- m);
  3946. "expr", (VFunction (Fun0 (fun() -> ignore(follow f.cf_type); (match f.cf_expr with None -> VNull | Some e -> encode_texpr e))));
  3947. "kind", encode_field_kind f.cf_kind;
  3948. "pos", encode_pos f.cf_pos;
  3949. "doc", null enc_string f.cf_doc;
  3950. ]
  3951. and encode_field_kind k =
  3952. let tag, pl = (match k with
  3953. | Type.Var v -> 0, [encode_var_access v.v_read; encode_var_access v.v_write]
  3954. | Method m -> 1, [encode_method_kind m]
  3955. ) in
  3956. enc_enum IFieldKind tag pl
  3957. and encode_var_access a =
  3958. let tag, pl = (match a with
  3959. | AccNormal -> 0, []
  3960. | AccNo -> 1, []
  3961. | AccNever -> 2, []
  3962. | AccResolve -> 3, []
  3963. | AccCall -> 4, []
  3964. | AccInline -> 5, []
  3965. | AccRequire (s,msg) -> 6, [enc_string s; null enc_string msg]
  3966. ) in
  3967. enc_enum IVarAccess tag pl
  3968. and encode_method_kind m =
  3969. let tag, pl = (match m with
  3970. | MethNormal -> 0, []
  3971. | MethInline -> 1, []
  3972. | MethDynamic -> 2, []
  3973. | MethMacro -> 3, []
  3974. ) in
  3975. enc_enum IMethodKind tag pl
  3976. and encode_class_kind k =
  3977. let tag, pl = (match k with
  3978. | KNormal -> 0, []
  3979. | KTypeParameter pl -> 1, [encode_tparams pl]
  3980. | KExtension (cl, params) -> 2, [encode_clref cl; encode_tparams params]
  3981. | KExpr e -> 3, [encode_expr e]
  3982. | KGeneric -> 4, []
  3983. | KGenericInstance (cl, params) -> 5, [encode_clref cl; encode_tparams params]
  3984. | KMacroType -> 6, []
  3985. | KAbstractImpl a -> 7, [encode_ref a encode_tabstract (fun() -> s_type_path a.a_path)]
  3986. ) in
  3987. enc_enum IClassKind tag pl
  3988. and encode_tclass c =
  3989. c.cl_build();
  3990. encode_mtype (TClassDecl c) [
  3991. "kind", encode_class_kind c.cl_kind;
  3992. "isExtern", VBool c.cl_extern;
  3993. "exclude", VFunction (Fun0 (fun() -> c.cl_extern <- true; c.cl_init <- None; VNull));
  3994. "isInterface", VBool c.cl_interface;
  3995. "superClass", (match c.cl_super with
  3996. | None -> VNull
  3997. | Some (c,pl) -> enc_obj ["t",encode_clref c;"params",encode_tparams pl]
  3998. );
  3999. "interfaces", enc_array (List.map (fun (c,pl) -> enc_obj ["t",encode_clref c;"params",encode_tparams pl]) c.cl_implements);
  4000. "fields", encode_ref c.cl_ordered_fields (encode_array encode_cfield) (fun() -> "class fields");
  4001. "statics", encode_ref c.cl_ordered_statics (encode_array encode_cfield) (fun() -> "class fields");
  4002. "constructor", (match c.cl_constructor with None -> VNull | Some c -> encode_ref c encode_cfield (fun() -> "constructor"));
  4003. "init", (match c.cl_init with None -> VNull | Some e -> encode_texpr e);
  4004. ]
  4005. and encode_ttype t =
  4006. encode_mtype (TTypeDecl t) [
  4007. "isExtern", VBool false;
  4008. "exclude", VFunction (Fun0 (fun() -> VNull));
  4009. "type", encode_type t.t_type;
  4010. ]
  4011. and encode_tanon a =
  4012. enc_obj [
  4013. "fields", encode_pmap_array encode_cfield a.a_fields;
  4014. ]
  4015. and encode_tparams pl =
  4016. enc_array (List.map encode_type pl)
  4017. and encode_clref c =
  4018. encode_ref c encode_tclass (fun() -> s_type_path c.cl_path)
  4019. and encode_type t =
  4020. let rec loop = function
  4021. | TMono r ->
  4022. (match !r with
  4023. | None -> 0, [encode_ref r (fun r -> match !r with None -> VNull | Some t -> encode_type t) (fun() -> "<mono>")]
  4024. | Some t -> loop t)
  4025. | TEnum (e, pl) ->
  4026. 1 , [encode_ref e encode_tenum (fun() -> s_type_path e.e_path); encode_tparams pl]
  4027. | TInst (c, pl) ->
  4028. 2 , [encode_clref c; encode_tparams pl]
  4029. | TType (t,pl) ->
  4030. 3 , [encode_ref t encode_ttype (fun() -> s_type_path t.t_path); encode_tparams pl]
  4031. | TFun (pl,ret) ->
  4032. let pl = List.map (fun (n,o,t) ->
  4033. enc_obj [
  4034. "name",enc_string n;
  4035. "opt",VBool o;
  4036. "t",encode_type t
  4037. ]
  4038. ) pl in
  4039. 4 , [enc_array pl; encode_type ret]
  4040. | TAnon a ->
  4041. 5, [encode_ref a encode_tanon (fun() -> "<anonymous>")]
  4042. | TDynamic tsub as t ->
  4043. if t == t_dynamic then
  4044. 6, [VNull]
  4045. else
  4046. 6, [encode_type tsub]
  4047. | TLazy f ->
  4048. loop (!f())
  4049. | TAbstract (a, pl) ->
  4050. 8, [encode_ref a encode_tabstract (fun() -> s_type_path a.a_path); encode_tparams pl]
  4051. in
  4052. let tag, pl = loop t in
  4053. enc_enum IType tag pl
  4054. and encode_lazy_type t =
  4055. let rec loop = function
  4056. | TMono r ->
  4057. (match !r with
  4058. | Some t -> loop t
  4059. | _ -> encode_type t)
  4060. | TLazy f ->
  4061. enc_enum IType 7 [VAbstract (ALazyType f)]
  4062. | _ ->
  4063. encode_type t
  4064. in
  4065. loop t
  4066. and decode_type t =
  4067. match decode_enum t with
  4068. | 0, [r] -> TMono (decode_ref r)
  4069. | 1, [e; pl] -> TEnum (decode_ref e, List.map decode_type (dec_array pl))
  4070. | 2, [c; pl] -> TInst (decode_ref c, List.map decode_type (dec_array pl))
  4071. | 3, [t; pl] -> TType (decode_ref t, List.map decode_type (dec_array pl))
  4072. | 4, [pl; r] -> TFun (List.map (fun p -> dec_string (field p "name"), dec_bool (field p "opt"), decode_type (field p "t")) (dec_array pl), decode_type r)
  4073. | 5, [a] -> TAnon (decode_ref a)
  4074. | 6, [VNull] -> t_dynamic
  4075. | 6, [t] -> TDynamic (decode_type t)
  4076. | 7, [VAbstract (ALazyType f)] -> TLazy f
  4077. | 8, [a; pl] -> TAbstract (decode_ref a, List.map decode_type (dec_array pl))
  4078. | _ -> raise Invalid_expr
  4079. and encode_texpr e =
  4080. VAbstract (ATExpr e)
  4081. let decode_tdecl v =
  4082. match v with
  4083. | VObject o ->
  4084. (match get_field o (hash "__t") with
  4085. | VAbstract (ATDecl t) -> t
  4086. | _ -> raise Invalid_expr)
  4087. | _ -> raise Invalid_expr
  4088. (* ---------------------------------------------------------------------- *)
  4089. (* TYPE DEFINITION *)
  4090. let decode_type_def v =
  4091. let pack = List.map dec_string (dec_array (field v "pack")) in
  4092. let name = dec_string (field v "name") in
  4093. let meta = decode_meta_content (field v "meta") in
  4094. let pos = decode_pos (field v "pos") in
  4095. let isExtern = dec_bool (field v "isExtern") in
  4096. let fields = List.map decode_field (dec_array (field v "fields")) in
  4097. let mk fl dl =
  4098. {
  4099. d_name = name;
  4100. d_doc = None;
  4101. d_params = List.map decode_tparam_decl (dec_array (field v "params"));
  4102. d_meta = meta;
  4103. d_flags = fl;
  4104. d_data = dl;
  4105. }
  4106. in
  4107. let tdef = (match decode_enum (field v "kind") with
  4108. | 0, [] ->
  4109. let conv f =
  4110. let loop (n,opt,t,_) =
  4111. match t with
  4112. | None -> raise Invalid_expr
  4113. | Some t -> n, opt, t
  4114. in
  4115. let args, params, t = (match f.cff_kind with
  4116. | FVar (t,None) -> [], [], t
  4117. | FFun f -> List.map loop f.f_args, f.f_params, f.f_type
  4118. | _ -> raise Invalid_expr
  4119. ) in
  4120. {
  4121. ec_name = f.cff_name;
  4122. ec_doc = f.cff_doc;
  4123. ec_meta = f.cff_meta;
  4124. ec_pos = f.cff_pos;
  4125. ec_args = args;
  4126. ec_params = params;
  4127. ec_type = t;
  4128. }
  4129. in
  4130. EEnum (mk (if isExtern then [EExtern] else []) (List.map conv fields))
  4131. | 1, [] ->
  4132. ETypedef (mk (if isExtern then [EExtern] else []) (CTAnonymous fields))
  4133. | 2, [ext;impl;interf] ->
  4134. let flags = if isExtern then [HExtern] else [] in
  4135. let flags = (match interf with VNull | VBool false -> flags | VBool true -> HInterface :: flags | _ -> raise Invalid_expr) in
  4136. let flags = (match opt decode_path ext with None -> flags | Some t -> HExtends t :: flags) in
  4137. let flags = (match opt (fun v -> List.map decode_path (dec_array v)) impl with None -> flags | Some l -> List.map (fun t -> HImplements t) l @ flags) in
  4138. EClass (mk flags fields)
  4139. | 3, [t] ->
  4140. ETypedef (mk (if isExtern then [EExtern] else []) (decode_ctype t))
  4141. | 4, [tthis;tfrom;tto] ->
  4142. let flags = match opt dec_array tfrom with None -> [] | Some ta -> List.map (fun t -> AFromType (decode_ctype t)) ta in
  4143. let flags = match opt dec_array tto with None -> flags | Some ta -> (List.map (fun t -> AToType (decode_ctype t)) ta) @ flags in
  4144. let flags = match opt decode_ctype tthis with None -> flags | Some t -> (AIsType t) :: flags in
  4145. EAbstract(mk flags fields)
  4146. | _ ->
  4147. raise Invalid_expr
  4148. ) in
  4149. (pack, name), tdef, pos
  4150. (* ---------------------------------------------------------------------- *)
  4151. (* VALUE-TO-CONSTANT *)
  4152. let rec make_const e =
  4153. match e.eexpr with
  4154. | TConst c ->
  4155. (match c with
  4156. | TInt i -> best_int i
  4157. | TFloat s -> VFloat (float_of_string s)
  4158. | TString s -> enc_string s
  4159. | TBool b -> VBool b
  4160. | TNull -> VNull
  4161. | TThis | TSuper -> raise Exit)
  4162. | TParenthesis e ->
  4163. make_const e
  4164. | TObjectDecl el ->
  4165. VObject (obj (hash_field (get_ctx())) (List.map (fun (f,e) -> f, make_const e) el))
  4166. | TArrayDecl al ->
  4167. enc_array (List.map make_const al)
  4168. | _ ->
  4169. raise Exit
  4170. (* ---------------------------------------------------------------------- *)
  4171. (* TEXPR-TO-AST-EXPR *)
  4172. open Ast
  4173. let tpath p mp pl =
  4174. if snd mp = snd p then
  4175. CTPath {
  4176. tpackage = fst p;
  4177. tname = snd p;
  4178. tparams = List.map (fun t -> TPType t) pl;
  4179. tsub = None;
  4180. }
  4181. else CTPath {
  4182. tpackage = fst mp;
  4183. tname = snd mp;
  4184. tparams = List.map (fun t -> TPType t) pl;
  4185. tsub = Some (snd p);
  4186. }
  4187. let rec make_type = function
  4188. | TMono r ->
  4189. (match !r with
  4190. | None -> raise Exit
  4191. | Some t -> make_type t)
  4192. | TEnum (e,pl) ->
  4193. tpath e.e_path e.e_module.m_path (List.map make_type pl)
  4194. | TInst({cl_kind = KTypeParameter _} as c,pl) ->
  4195. tpath ([],snd c.cl_path) ([],snd c.cl_path) (List.map make_type pl)
  4196. | TInst (c,pl) ->
  4197. tpath c.cl_path c.cl_module.m_path (List.map make_type pl)
  4198. | TType (t,pl) as tf ->
  4199. (* recurse on type-type *)
  4200. if (snd t.t_path).[0] = '#' then make_type (follow tf) else tpath t.t_path t.t_module.m_path (List.map make_type pl)
  4201. | TAbstract (a,pl) ->
  4202. tpath a.a_path a.a_module.m_path (List.map make_type pl)
  4203. | TFun (args,ret) ->
  4204. CTFunction (List.map (fun (_,_,t) -> make_type t) args, make_type ret)
  4205. | TAnon a ->
  4206. begin match !(a.a_status) with
  4207. | Statics c -> tpath ([],"Class") ([],"Class") [tpath c.cl_path c.cl_path []]
  4208. | EnumStatics e -> tpath ([],"Enum") ([],"Enum") [tpath e.e_path e.e_path []]
  4209. | _ ->
  4210. CTAnonymous (PMap.foldi (fun _ f acc ->
  4211. {
  4212. cff_name = f.cf_name;
  4213. cff_kind = FVar (mk_ot f.cf_type,None);
  4214. cff_pos = f.cf_pos;
  4215. cff_doc = f.cf_doc;
  4216. cff_meta = f.cf_meta;
  4217. cff_access = [];
  4218. } :: acc
  4219. ) a.a_fields [])
  4220. end
  4221. | (TDynamic t2) as t ->
  4222. tpath ([],"Dynamic") ([],"Dynamic") (if t == t_dynamic then [] else [make_type t2])
  4223. | TLazy f ->
  4224. make_type ((!f)())
  4225. and mk_ot t =
  4226. match follow t with
  4227. | TMono _ -> None
  4228. | _ -> (try Some (make_type t) with Exit -> None)
  4229. let rec make_ast e =
  4230. let full_type_path t =
  4231. let mp,p = match t with
  4232. | TClassDecl c -> c.cl_module.m_path,c.cl_path
  4233. | TEnumDecl en -> en.e_module.m_path,en.e_path
  4234. | TAbstractDecl a -> a.a_module.m_path,a.a_path
  4235. | TTypeDecl t -> t.t_module.m_path,t.t_path
  4236. in
  4237. if snd mp = snd p then p else (fst mp) @ [snd mp],snd p
  4238. in
  4239. let mk_path (pack,name) p =
  4240. match List.rev pack with
  4241. | [] -> (EConst (Ident name),p)
  4242. | pl ->
  4243. let rec loop = function
  4244. | [] -> assert false
  4245. | [n] -> (EConst (Ident n),p)
  4246. | n :: l -> (EField (loop l, n),p)
  4247. in
  4248. (EField (loop pl,name),p)
  4249. in
  4250. let mk_const = function
  4251. | TInt i -> Int (Int32.to_string i)
  4252. | TFloat s -> Float s
  4253. | TString s -> String s
  4254. | TBool b -> Ident (if b then "true" else "false")
  4255. | TNull -> Ident "null"
  4256. | TThis -> Ident "this"
  4257. | TSuper -> Ident "super"
  4258. in
  4259. let mk_ident = function
  4260. | "`trace" -> Ident "trace"
  4261. | n -> Ident n
  4262. in
  4263. let eopt = function None -> None | Some e -> Some (make_ast e) in
  4264. ((match e.eexpr with
  4265. | TConst c ->
  4266. EConst (mk_const c)
  4267. | TLocal v -> EConst (mk_ident v.v_name)
  4268. | TArray (e1,e2) -> EArray (make_ast e1,make_ast e2)
  4269. | TBinop (op,e1,e2) -> EBinop (op, make_ast e1, make_ast e2)
  4270. | TField (e,f) -> EField (make_ast e, Type.field_name f)
  4271. | TTypeExpr t -> fst (mk_path (full_type_path t) e.epos)
  4272. | TParenthesis e -> EParenthesis (make_ast e)
  4273. | TObjectDecl fl -> EObjectDecl (List.map (fun (f,e) -> f, make_ast e) fl)
  4274. | TArrayDecl el -> EArrayDecl (List.map make_ast el)
  4275. | TCall (e,el) -> ECall (make_ast e,List.map make_ast el)
  4276. | TNew (c,pl,el) -> ENew ((match (try make_type (TInst (c,pl)) with Exit -> make_type (TInst (c,[]))) with CTPath p -> p | _ -> assert false),List.map make_ast el)
  4277. | TUnop (op,p,e) -> EUnop (op,p,make_ast e)
  4278. | TFunction f ->
  4279. let arg (v,c) = v.v_name, false, mk_ot v.v_type, (match c with None -> None | Some c -> Some (EConst (mk_const c),e.epos)) in
  4280. EFunction (None,{ f_params = []; f_args = List.map arg f.tf_args; f_type = mk_ot f.tf_type; f_expr = Some (make_ast f.tf_expr) })
  4281. | TVars vl ->
  4282. EVars (List.map (fun (v,e) -> v.v_name, mk_ot v.v_type, eopt e) vl)
  4283. | TBlock el -> EBlock (List.map make_ast el)
  4284. | TFor (v,it,e) ->
  4285. let ein = (EIn ((EConst (Ident v.v_name),it.epos),make_ast it),it.epos) in
  4286. EFor (ein,make_ast e)
  4287. | TIf (e,e1,e2) -> EIf (make_ast e,make_ast e1,eopt e2)
  4288. | TWhile (e1,e2,flag) -> EWhile (make_ast e1, make_ast e2, flag)
  4289. | TSwitch (e,cases,def) ->
  4290. let cases = List.map (fun (vl,e) ->
  4291. List.map make_ast vl,None,(match e.eexpr with TBlock [] -> None | _ -> Some (make_ast e))
  4292. ) cases in
  4293. let def = match eopt def with None -> None | Some (EBlock [],_) -> Some None | e -> Some e in
  4294. ESwitch (make_ast e,cases,def)
  4295. | TMatch (e,(en,_),cases,def) ->
  4296. let scases (idx,args,e) =
  4297. let p = e.epos in
  4298. let unused = (EConst (Ident "_"),p) in
  4299. let args = (match args with
  4300. | None -> None
  4301. | Some l -> Some (List.map (function None -> unused | Some v -> (EConst (Ident v.v_name),p)) l)
  4302. ) in
  4303. let mk_args n =
  4304. match args with
  4305. | None -> [unused]
  4306. | Some args ->
  4307. args @ Array.to_list (Array.make (n - List.length args) unused)
  4308. in
  4309. List.map (fun i ->
  4310. let c = (try List.nth en.e_names i with _ -> assert false) in
  4311. let cfield = (try PMap.find c en.e_constrs with Not_found -> assert false) in
  4312. let c = (EConst (Ident c),p) in
  4313. (match follow cfield.ef_type with TFun (eargs,_) -> (ECall (c,mk_args (List.length eargs)),p) | _ -> c)
  4314. ) idx, None, (match e.eexpr with TBlock [] -> None | _ -> Some (make_ast e))
  4315. in
  4316. let def = match eopt def with None -> None | Some (EBlock [],_) -> Some None | e -> Some e in
  4317. ESwitch (make_ast e,List.map scases cases,def)
  4318. | TTry (e,catches) -> ETry (make_ast e,List.map (fun (v,e) -> v.v_name, (try make_type v.v_type with Exit -> assert false), make_ast e) catches)
  4319. | TReturn e -> EReturn (eopt e)
  4320. | TBreak -> EBreak
  4321. | TContinue -> EContinue
  4322. | TThrow e -> EThrow (make_ast e)
  4323. | TCast (e,t) ->
  4324. let t = (match t with
  4325. | None -> None
  4326. | Some t ->
  4327. let t = (match t with TClassDecl c -> TInst (c,[]) | TEnumDecl e -> TEnum (e,[]) | TTypeDecl t -> TType (t,[]) | TAbstractDecl a -> TAbstract (a,[])) in
  4328. Some (try make_type t with Exit -> assert false)
  4329. ) in
  4330. ECast (make_ast e,t))
  4331. ,e.epos)
  4332. ;;
  4333. make_ast_ref := make_ast;
  4334. make_complex_type_ref := make_type;
  4335. encode_complex_type_ref := encode_ctype;
  4336. enc_array_ref := enc_array;
  4337. encode_type_ref := encode_type;
  4338. decode_type_ref := decode_type;
  4339. encode_expr_ref := encode_expr;
  4340. decode_expr_ref := decode_expr;
  4341. encode_clref_ref := encode_clref;
  4342. enc_string_ref := enc_string;
  4343. enc_hash_ref := enc_hash