webidltopas.pp 105 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604
  1. {
  2. This file is part of the Free Component Library
  3. WEBIDL to pascal code converter
  4. Copyright (c) 2021 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit webidltopas;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode objfpc}{$H+}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. System.Classes, System.SysUtils, System.Contnrs, WebIdl.Parser, WebIdl.Scanner, WebIdl.Defs, Pascal.CodeGenerator;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. Classes, SysUtils, contnrs, WebIDLParser, WebIDLScanner, WebIDLDefs, pascodegen;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. Const
  24. SDefaultGetterName = 'GetDefault';
  25. SDefaultSetterName = 'SetDefault';
  26. Type
  27. TPascalNativeType = (
  28. ntUnknown, // unknown
  29. ntNone, // None -> void
  30. ntError, // Special : error condition
  31. ntBoolean,
  32. ntShortInt,
  33. ntByte,
  34. ntSmallInt,
  35. ntWord,
  36. ntLongint,
  37. ntCardinal,
  38. ntInt64,
  39. ntQWord,
  40. ntSingle,
  41. ntDouble,
  42. ntUnicodeString,
  43. ntUTF8String,
  44. ntVariant,
  45. ntObject,
  46. ntInterface,
  47. ntArray,
  48. ntMethod);
  49. TPascalNativeTypes = Set of TPascalNativeType;
  50. { TPasData }
  51. TPasData = Class(TObject)
  52. private
  53. FPasName: String;
  54. Public
  55. IDL: TIDLBaseObject;
  56. Line, Column: integer;
  57. SrcFile: string;
  58. Resolved: TIDLTypeDefinition;
  59. NativeType : TPascalNativeType;
  60. NameChecked : Boolean;
  61. ChromeChecked : Boolean;
  62. FullMemberList : TIDLDefinitionList;
  63. ParentsMemberList : TIDLDefinitionList;
  64. Used : Boolean;
  65. Constructor Create(APasName: String; D: TIDLBaseObject);
  66. Destructor Destroy; override;
  67. Property PasName: String read FPasName write FPasName;
  68. function ToString : RTLString; override;
  69. end;
  70. TPasDataClass = class of TPasData;
  71. TBaseConversionOption = (
  72. coAddOptionsToHeader,
  73. coExpandUnionTypeArgs,
  74. coDictionaryAsClass,
  75. coChromeWindow,
  76. coOnlyUsed,
  77. coPrivateMethods
  78. );
  79. TBaseConversionOptions = Set of TBaseConversionOption;
  80. const
  81. BaseConversionOptionName: array[TBaseConversionOption] of string = (
  82. 'AddOptionsToHeader',
  83. 'ExpandUnionTypeArgs',
  84. 'DictionaryAsClass',
  85. 'ChromeWindow',
  86. 'OnlyUsed',
  87. 'PrivateMethods'
  88. );
  89. NativeTypeNames : Array [TPascalNativeType] of String = (
  90. '',
  91. '',
  92. '', // Special : error condition
  93. 'Boolean',
  94. 'ShortInt',
  95. 'Byte',
  96. 'SmallInt',
  97. 'Word',
  98. 'LongInt',
  99. 'Cardinal',
  100. 'Int64',
  101. 'QWord',
  102. 'Single',
  103. 'Double',
  104. 'UnicodeString',
  105. 'UTF8String',
  106. 'Variant',
  107. 'Object',
  108. 'Interface',
  109. 'Array',
  110. 'Method');
  111. type
  112. { TBaseWebIDLToPas }
  113. TBaseWebIDLToPas = Class(TPascalCodeGenerator)
  114. private
  115. FArrayPrefix: String;
  116. FArraySuffix: String;
  117. FAutoTypes: TStrings;
  118. FBaseOptions: TBaseConversionOptions;
  119. FClassPrefix: String;
  120. FClassSuffix: String;
  121. FContext: TWebIDLContext;
  122. FDictionaryClassParent: String;
  123. FFieldPrefix: String;
  124. FGeneratingImplementation: Boolean;
  125. FGlobalVars: TStrings;
  126. FInputStream: TStream;
  127. FOutputStream: TStream;
  128. FTypePrefix: String;
  129. FGetterPrefix: String;
  130. FIncludeImplementationCode: TStrings;
  131. FIncludeInterfaceCode: TStrings;
  132. FInputFileName: String;
  133. FUsedDefs,
  134. FGlobalDefs: TFPObjectHashTable;
  135. FOutputFileName: String;
  136. FPasDataClass: TPasDataClass;
  137. FPasNameList: TFPObjectList; // list TPasData
  138. FSetterPrefix: String;
  139. FTypeAliases: TStrings; // user defined type maping name to name
  140. FVerbose: Boolean;
  141. FWebIDLVersion: TWebIDLVersion;
  142. function CreateCallBackFromInterface(aDef: TIDLInterfaceDefinition): TIDLCallBackDefinition;
  143. function GetUsed(D: TIDLDefinition): Boolean;
  144. function InUsedList(D: TIDLDefinition): Boolean;
  145. procedure ResolveCallbackInterfaces;
  146. procedure SetGlobalVars(const AValue: TStrings);
  147. procedure SetIncludeImplementationCode(AValue: TStrings);
  148. procedure SetIncludeInterfaceCode(AValue: TStrings);
  149. procedure SetOutputFileName(const AValue: String);
  150. procedure SetTypeAliases(AValue: TStrings);
  151. Protected
  152. function CheckExistingSequence(ST: TIDLSequenceTypeDefDefinition; out TN: TIDLString): Boolean;
  153. function CheckExistingUnion(UT: TIDLUnionTypeDefDefinition; out TN: TIDLString): Boolean;
  154. function GetAliasPascalType(aNativeTypeName: String; out PascalTypeName: string): TPascalNativeType;
  155. procedure TrimList(List: TStrings); virtual;
  156. procedure AddOptionsToHeader;
  157. Procedure Parse; virtual;
  158. Procedure WritePascal; virtual;
  159. function CreateParser(aContext: TWebIDLContext; S: TWebIDLScanner): TWebIDLParser; virtual;
  160. function CreateScanner(S: TStream): TWebIDLScanner; virtual;
  161. Function CreateContext: TWebIDLContext; virtual;
  162. // Auxiliary routines
  163. function CheckChromeOnly(D: TIDLDefinition): Boolean;
  164. function MarkUsed(D: TIDLDefinition; ParentIsUsed: Boolean): Boolean;
  165. procedure MarkUsedDefinitions(aList: TIDLDefinitionList; ParentIsUsed: Boolean);
  166. procedure PropagateChromeOnly(aList: TIDLDefinitionList);
  167. procedure AddFullMemberList(aParent: TIDLStructuredDefinition; AddToList: TIDLDefinitionList);
  168. function GetFullMemberList(aParent: TIDLStructuredDefinition): TIDLDefinitionList;
  169. function GetParentsMemberList(aParent: TIDLStructuredDefinition): TIDLDefinitionList;
  170. procedure GetOptions(L: TStrings; Full: boolean); virtual;
  171. procedure ProcessDefinitions; virtual;
  172. function CreatePasData(aName: String; aNativetype : TPascalNativeType; D: TIDLBaseObject; Escape: boolean): TPasData; virtual;
  173. function ClonePasData(Data: TPasData; OwnerDef: TIDLBaseObject): TPasData; virtual;
  174. procedure AddGlobalJSIdentifier(D: TIDLDefinition); virtual;
  175. procedure ResolveParentInterfaces(aList: TIDLDefinitionList); virtual;
  176. procedure ResolveParentInterface(Intf: TIDLInterfaceDefinition); virtual;
  177. procedure ResolveParentInterface(Intf: TIDLDictionaryDefinition); virtual;
  178. procedure ResolveTypeDefs(aList: TIDLDefinitionList); virtual;
  179. procedure ResolveTypeDef(D: TIDLDefinition); virtual;
  180. procedure RemoveInterfaceForwards(aList: TIDLDefinitionList); virtual;
  181. Function ConvertDef(D : TIDLDefinition) : Boolean;
  182. function FindGlobalDef(const aName: UTF8String): TIDLDefinition; virtual;
  183. function GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean = false): string; virtual;
  184. function GetPasDataPos(D: TPasData; WithoutFile: boolean = false): string; virtual;
  185. // Pascal Name allocation/retrieval
  186. function AddSequenceDef(ST: TIDLSequenceTypeDefDefinition): Boolean; virtual;
  187. function AddUnionDef(UT: TIDLUnionTypeDefDefinition): Boolean; virtual;
  188. procedure EnsureUniqueNames(aParent : TIDLStructuredDefinition; ML: TIDLDefinitionList; const aParentName: String); virtual;
  189. procedure EnsureUniqueArgNames(Intf: TIDLStructuredDefinition); virtual;
  190. procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String=''); virtual;
  191. function AllocatePasName(D: TIDLDefinition; ParentName: String; Recurse : Boolean): TPasData; virtual;
  192. function GetAliasPascalType(D: TIDLDefinition; out PascalTypeName : string): TPascalNativeType; virtual;
  193. function AllocateArgumentPasName(D: TIDLArgumentDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  194. function AllocateAttributePasName(aParent : TIDLStructuredDefinition; D: TIDLAttributeDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  195. function AllocateCallbackPasName(D: TIDLCallBackDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  196. function AllocateDefaultPasName(D: TIDLDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  197. function AllocateDictionaryMemberPasName(D: TIDLDictionaryMemberDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  198. function AllocateDictionaryPasName(D: TIDLDictionaryDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  199. function AllocateFunctionPasName(D: TIDLFunctionDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  200. function AllocateInterfacePasName(D: TIDLInterfaceDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  201. function AllocateNamespacePasName(D: TIDLNameSpaceDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  202. function AllocateSequencePasName(D: TIDLSequenceTypeDefDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  203. function AllocatePromisePasName(D: TIDLPromiseTypeDefDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  204. function AllocateUnionPasName(D: TIDLUnionTypeDefDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  205. function AllocateMapLikePasName(D: TIDLMapLikeDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  206. function AllocateEnumeratedPasName(D: TIDLEnumDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  207. function AllocateConstPasName(D: TIDLConstDefinition; ParentName: String; Recurse: Boolean): TPasData; virtual;
  208. function GetPasName(ADef: TIDLDefinition): String; virtual;
  209. function GetPasNativeType(ADef: TIDLDefinition): TPascalNativeType; virtual;
  210. function GetPasNativeTypeAndName(ADef: TIDLDefinition; out aPascalName : String): TPascalNativeType; virtual;
  211. function GetPasClassName(const aName: string): string; overload; virtual;
  212. function IDLToPascalNativeType(const aTypeName: String): TPascalNativetype; virtual;
  213. function GetPascalTypeAndName(Const aTypeName: String; Out aPascalName : String): TPascalNativeType; overload; virtual;
  214. function GetPascalTypeName(Const aTypeName: String; ForTypeDef: Boolean=False): String; overload; virtual;
  215. function GetPascalTypeName(aTypeDef: TIDLTypeDefDefinition; ForTypeDef: Boolean=False): String;
  216. function GetJSTypeName(aTypeDef: TIDLTypeDefDefinition): String; overload; virtual;
  217. function GetResolvedType(aDef: TIDLTypeDefDefinition; out PascalNativeType: TPascalNativeType; out aTypeName, aResolvedTypename: string): TIDLTypeDefinition; overload; virtual;
  218. function ConstructSequenceTypeName(Seq: TIDLSequenceTypeDefDefinition; ForTypeDef: Boolean=False): string; virtual;
  219. function GetInterfaceDefHead(Intf: TIDLInterfaceDefinition): String; virtual;
  220. function GetNamespaceDefHead(Intf: TIDLNamespaceDefinition): String; virtual;
  221. function GetDictionaryDefHead(const CurClassName: string; Dict: TIDLDictionaryDefinition): String; virtual;
  222. function CheckUnionTypeDefinition(D: TIDLDefinition): TIDLUnionTypeDefDefinition; virtual;
  223. Function CloneArgument(Arg: TIDLArgumentDefinition): TIDLArgumentDefinition; virtual;
  224. procedure AddArgumentToOverloads(aList: TFPObjectlist; aName, aPasName, aTypeName: String; PosEl: TIDLBaseObject); overload; virtual;
  225. procedure AddArgumentToOverloads(aList: TFPObjectlist; aDef: TIDLArgumentDefinition); overload; virtual;
  226. procedure AddUnionOverloads(aList: TFPObjectlist; aName, aPasName: String; UT: TIDLUnionTypeDefDefinition); virtual;
  227. procedure AddOverloads(aList: TFPObjectlist; aDef: TIDLFunctionDefinition; aIdx: Integer); virtual;
  228. function CloneNonPartialArgumentList(aList: TFPObjectlist; ADest: TFPObjectlist= Nil; AsPartial: Boolean=True): integer; virtual;
  229. function GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist; virtual;
  230. function GetArguments(aList: TIDLDefinitionList; ForceBrackets: Boolean): String; virtual;
  231. function HaveConsts(aList: TIDLDefinitionList): Boolean; virtual;
  232. // Code generation routines. Return the number of actually written defs.
  233. function WriteImplicitAutoType(aType: TIDLDefinition): Integer;
  234. function WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer; virtual;
  235. function WriteAttributeImplicitTypes(aList: TIDLDefinitionList): Integer; virtual;
  236. function WriteDictionaryImplicitTypes(aList: TIDLDefinitionList): Integer; virtual;
  237. function WriteOtherImplicitTypes(Intf: TIDLStructuredDefinition; aMemberList: TIDLDefinitionList): Integer; virtual;
  238. function WriteDictionaryMemberImplicitTypes(aDict: TIDLDictionaryDefinition; aList: TIDLDefinitionList): Integer; virtual;
  239. function WriteDictionaryDefs(aList: TIDLDefinitionList): Integer; virtual;
  240. function WriteForwardClassDefs(aList: TIDLDefinitionList): Integer; virtual;
  241. function WriteInterfaceDefs(aList: TIDLDefinitionList): Integer; virtual;
  242. function WriteNamespaceDefs(aList: TIDLDefinitionList): Integer; virtual;
  243. function WriteMethodDefs(aParent: TIDLStructuredDefinition; aList: TIDLDefinitionList): Integer; virtual;
  244. function WriteUtilityMethods(Intf: TIDLStructuredDefinition): Integer; virtual;
  245. function WriteTypeDefsAndCallbacks(aList: TIDLDefinitionList): Integer; virtual;
  246. function WriteEnumDefs(aList: TIDLDefinitionList): Integer; virtual;
  247. function WriteConsts(aParent: TIDLDefinition; aList: TIDLDefinitionList): Integer; virtual;
  248. function WriteProperties(aParent: TIDLDefinition; aList: TIDLDefinitionList): Integer; virtual;
  249. function WritePlainFields(aParent: TIDLDefinition; aList: TIDLDefinitionList): Integer; virtual;
  250. function WriteDictionaryFields(aDict: TIDLDictionaryDefinition; aList: TIDLDefinitionList): Integer; virtual;
  251. function WritePrivateReadOnlyFields(aParent: TIDLDefinition; aList: TIDLDefinitionList): Integer; virtual;
  252. function WriteGetters(aParent: TIDLStructuredDefinition; aList: TIDLDefinitionList): Integer; virtual;
  253. function WriteSetters(aParent: TIDLStructuredDefinition; aList: TIDLDefinitionList): Integer; virtual;
  254. // Maplike-specific methods
  255. function WriteMapLikePrivateReadOnlyFields(aParent: TIDLDefinition; aMap: TIDLMapLikeDefinition): Integer; virtual;
  256. function WriteMapLikeMethodDefinitions(aParent: TIDLStructuredDefinition; aMap: TIDLMapLikeDefinition): integer; virtual;
  257. function WriteMapLikeProperties(aParent: TIDLDefinition; aMap: TIDLMapLikeDefinition): Integer; virtual;
  258. function WriteMapLikeGetters(aParent: TIDLStructuredDefinition; aMap: TIDLMapLikeDefinition): Integer; virtual;
  259. // Implementations. For webidl2pas, these are empty
  260. procedure WriteDefinitionImplementation(D: TIDLDefinition); virtual;
  261. procedure WriteTypeDefsAndCallbackImplementations(aList: TIDLDefinitionList); virtual;
  262. // Definitions. Return true if a definition was written.
  263. function WriteForwardClassDef(D: TIDLStructuredDefinition): Boolean; virtual;
  264. function WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition; aName: String = ''): Boolean; virtual;
  265. function WriteFunctionDefinition(aParent: TIDLStructuredDefinition; aDef: TIDLFunctionDefinition): Boolean; virtual;
  266. function WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean; virtual;
  267. function WriteRecordDef(aDef: TIDLRecordDefinition): Boolean; virtual;
  268. function WriteEnumDef(aDef: TIDLEnumDefinition): Boolean; virtual;
  269. function WriteDictionaryField(aDict: TIDLDictionaryDefinition; aField: TIDLDictionaryMemberDefinition): Boolean; virtual;
  270. function WriteField(aAttr: TIDLAttributeDefinition): Boolean; virtual;
  271. function WriteConst(aConst: TIDLConstDefinition): Boolean ; virtual;
  272. function WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean; virtual;
  273. function WriteNamespaceDef(aNamespace: TIDLNamespaceDefinition): Boolean; virtual;
  274. function WriteDictionaryDef(aDict: TIDLDictionaryDefinition): Boolean; virtual;
  275. // Additional
  276. procedure WriteAliasTypeDef(aDef: TIDLTypeDefDefinition); virtual;
  277. procedure WritePromiseDef(aDef: TIDLPromiseTypeDefDefinition); virtual;
  278. procedure WriteSequenceDef(aDef: TIDLSequenceTypeDefDefinition); virtual;
  279. procedure WriteUnionDef(aDef: TIDLUnionTypeDefDefinition); virtual;
  280. // Extra interface/Implementation code.
  281. procedure WriteGlobalVar(aDef: String); virtual;
  282. procedure WriteNamespaceVars; virtual;
  283. procedure WriteGlobalVars;
  284. procedure WriteImplementation; virtual;
  285. procedure WriteIncludeInterfaceCode; virtual;
  286. Property Context: TWebIDLContext Read FContext;
  287. Public
  288. constructor Create(TheOwner: TComponent); override;
  289. destructor Destroy; override;
  290. procedure Execute; virtual;
  291. procedure WriteOptions; virtual;
  292. procedure SetUsedList(aList : TStrings);
  293. function IsKeyWord(const S: String): Boolean; override;
  294. Property GeneratingImplementation : Boolean Read FGeneratingImplementation;
  295. Public
  296. Property InputFileName: String Read FInputFileName Write FInputFileName;
  297. Property InputStream: TStream Read FInputStream Write FInputStream;
  298. Property OutputFileName: String Read FOutputFileName Write SetOutputFileName;
  299. Property OutputStream: TStream Read FOutputStream Write FOutputStream;
  300. Property Verbose: Boolean Read FVerbose Write FVerbose;
  301. Property FieldPrefix: String Read FFieldPrefix Write FFieldPrefix;
  302. Property ClassPrefix: String Read FClassPrefix Write FClassPrefix;
  303. Property ClassSuffix: String Read FClassSuffix Write FClassSuffix;
  304. Property ArrayPrefix: String Read FArrayPrefix Write FArrayPrefix;
  305. Property ArraySuffix: String Read FArraySuffix Write FArraySuffix;
  306. Property GetterPrefix: String read FGetterPrefix write FGetterPrefix;
  307. Property SetterPrefix: String read FSetterPrefix write FSetterPrefix;
  308. Property TypePrefix: String read FTypePrefix write FTypePrefix;
  309. Property WebIDLVersion: TWebIDLVersion Read FWebIDLVersion Write FWebIDLVersion;
  310. Property TypeAliases: TStrings Read FTypeAliases Write SetTypeAliases;
  311. Property GlobalVars: TStrings Read FGlobalVars Write SetGlobalVars;
  312. Property IncludeInterfaceCode: TStrings Read FIncludeInterfaceCode Write SetIncludeInterfaceCode;
  313. Property IncludeImplementationCode: TStrings Read FIncludeImplementationCode Write SetIncludeImplementationCode;
  314. Property DictionaryClassParent: String Read FDictionaryClassParent Write FDictionaryClassParent;
  315. Property BaseOptions: TBaseConversionOptions read FBaseOptions write FBaseOptions;
  316. Property PasDataClass: TPasDataClass read FPasDataClass write FPasDataClass;
  317. end;
  318. function BaseConversionOptionsToStr(Opts: TBaseConversionOptions): string;
  319. Resourcestring
  320. SErrBeforeException = ' before an exception occurred';
  321. implementation
  322. {$IFDEF FPC_DOTTEDUNITS}
  323. uses System.TypInfo;
  324. {$ELSE FPC_DOTTEDUNITS}
  325. uses typinfo;
  326. {$ENDIF FPC_DOTTEDUNITS}
  327. function BaseConversionOptionsToStr(Opts: TBaseConversionOptions): string;
  328. var
  329. o: TBaseConversionOption;
  330. begin
  331. Result:='';
  332. for o in Opts do
  333. begin
  334. if Result<>'' then Result:=Result+',';
  335. Result:=Result+BaseConversionOptionName[o];
  336. end;
  337. Result:='['+Result+']';
  338. end;
  339. { TPasData }
  340. constructor TPasData.Create(APasName: String; D: TIDLBaseObject);
  341. begin
  342. FPasName:=APasName;
  343. IDL:=D;
  344. SrcFile:=D.SrcFile;
  345. Line:=D.Line;
  346. Column:=D.Column;
  347. end;
  348. destructor TPasData.Destroy;
  349. begin
  350. FreeAndNil(FullmemberList);
  351. FreeAndNil(ParentsMemberList);
  352. inherited Destroy;
  353. end;
  354. function TPasData.ToString: RTLString;
  355. var
  356. S : String;
  357. begin
  358. Result:=inherited ToString;
  359. WriteStr(S,NativeType);
  360. Result:=Result+Format(': NativeType: %s, Name: %s, location: [%s: %d:%d], used: %b',[S,PasName,SrcFile,Line,Column,Used]);
  361. end;
  362. { TBaseWebIDLToPas }
  363. function TBaseWebIDLToPas.CreateContext: TWebIDLContext;
  364. begin
  365. Result:=TWebIDLContext.Create(True);
  366. end;
  367. function TBaseWebIDLToPas.CreateScanner(S: TStream): TWebIDLScanner;
  368. begin
  369. Result:=TWebIDLScanner.Create(S);
  370. end;
  371. function TBaseWebIDLToPas.CreateParser(aContext: TWebIDLContext;S: TWebIDLScanner): TWebIDLParser;
  372. begin
  373. Result:=TWebIDLParser.Create(aContext,S);
  374. Result.Version:=FWebIDLVersion;
  375. end;
  376. procedure TBaseWebIDLToPas.Parse;
  377. Var
  378. ms: TMemoryStream;
  379. S: TWebIDLScanner;
  380. P: TWebIDLParser;
  381. begin
  382. P:=Nil;
  383. S:=Nil;
  384. ms:=TMemoryStream.Create;
  385. try
  386. if InputStream<>nil then
  387. ms.CopyFrom(InputStream,InputStream.Size-InputStream.Position)
  388. else
  389. ms.LoadFromFile(InputFileName);
  390. ms.Position:=0;
  391. S:=CreateScanner(ms);
  392. S.CurFile:=InputFileName;
  393. P:=CreateParser(Context,S);
  394. P.Parse;
  395. finally
  396. P.Free;
  397. S.Free;
  398. ms.Free;
  399. end;
  400. end;
  401. function TBaseWebIDLToPas.GetPasName(ADef: TIDLDefinition): String;
  402. begin
  403. GetPasNativeTypeAndName(aDef,Result);
  404. end;
  405. function TBaseWebIDLToPas.GetPasNativeType(ADef: TIDLDefinition): TPascalNativeType;
  406. var
  407. Dummy : String;
  408. begin
  409. Result:=GetPasNativeTypeAndName(aDef,Dummy);
  410. end;
  411. function TBaseWebIDLToPas.GetPasNativeTypeAndName(ADef: TIDLDefinition; out aPascalName: String): TPascalNativeType;
  412. begin
  413. aPascalName:='';
  414. Result:=ntUnknown;
  415. If Not Assigned(ADef) then
  416. raise EConvertError.CreateFmt('Attempt to get pascal name for empty definition',[Adef.GetNamePath]);
  417. if (ADef.Data is TPasData) then
  418. begin
  419. aPascalName:=TPasData(ADef.Data).PasName;
  420. Result:=TPasData(ADef.Data).NativeType;
  421. end
  422. else
  423. raise EConvertError.CreateFmt('No pascal data allocated for %s',[Adef.GetNamePath]);
  424. end;
  425. function TBaseWebIDLToPas.GetPasClassName(const aName: string): string;
  426. begin
  427. if aName='' then
  428. raise EConvertError.Create('[20220725184209] empty name');
  429. Result:=ClassPrefix+aName+ClassSuffix;
  430. end;
  431. function TBaseWebIDLToPas.HaveConsts(aList: TIDLDefinitionList): Boolean;
  432. Var
  433. D: TIDLDefinition;
  434. begin
  435. Result:=False;
  436. For D in aList do
  437. if D is TIDLConstDefinition then
  438. if ConvertDef(D) then
  439. Exit(True);
  440. end;
  441. function TBaseWebIDLToPas.WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer;
  442. procedure DoFunction(FD : TIDLFunctionDefinition);
  443. var
  444. D2,D3: TIDLDefinition;
  445. DA: TIDLArgumentDefinition absolute D2;
  446. UT: TIDLUnionTypeDefDefinition;
  447. begin
  448. if assigned(FD.ReturnType) then
  449. Result:=Result+WriteImplicitAutoType(FD.ReturnType);
  450. For D2 in FD.Arguments do
  451. begin
  452. WriteImplicitAutoType(DA.ArgumentType);
  453. UT:=CheckUnionTypeDefinition(DA.ArgumentType);
  454. if Assigned(UT) then
  455. For D3 in UT.Union do
  456. if (D3 is TIDLSequenceTypeDefDefinition) then
  457. if AddSequenceDef(D3 as TIDLSequenceTypeDefDefinition) then
  458. Inc(Result);
  459. end;
  460. end;
  461. Var
  462. D : TIDLDefinition;
  463. begin
  464. Result:=0;
  465. for D in aList do
  466. if ConvertDef(D) then
  467. if D is TIDLFunctionDefinition then
  468. DoFunction(TIDLFunctionDefinition(D))
  469. else if D is TIDLCallBackDefinition then
  470. DoFunction(TIDLCallBackDefinition(D).FunctionDef);
  471. if Result>0 then
  472. AddLn('');
  473. end;
  474. function TBaseWebIDLToPas.WriteImplicitAutoType(aType : TIDLDefinition) : Integer;
  475. begin
  476. Result:=0;
  477. if (aType is TIDLSequenceTypeDefDefinition) then
  478. begin
  479. if AddSequenceDef(aType as TIDLSequenceTypeDefDefinition) then
  480. Inc(Result)
  481. end
  482. else if (aType is TIDLUnionTypeDefDefinition) then
  483. begin
  484. if AddUnionDef(aType as TIDLUnionTypeDefDefinition) then
  485. Inc(Result);
  486. end
  487. end;
  488. function TBaseWebIDLToPas.WriteAttributeImplicitTypes(aList: TIDLDefinitionList): Integer;
  489. Var
  490. D: TIDLDefinition;
  491. FA: TIDLAttributeDefinition absolute D;
  492. begin
  493. Result:=0;
  494. for D in aList do
  495. if D is TIDLAttributeDefinition then
  496. if ConvertDef(D) then
  497. Result:=Result+WriteImplicitAutoType(FA.AttributeType);
  498. end;
  499. function TBaseWebIDLToPas.WriteDictionaryImplicitTypes(aList: TIDLDefinitionList): Integer;
  500. Var
  501. D: TIDLDefinition;
  502. MD : TIDLDictionaryMemberDefinition absolute D;
  503. begin
  504. Result:=0;
  505. for D in aList do
  506. if D is TIDLDictionaryDefinition then
  507. if ConvertDef(D) then
  508. Result:=Result+WriteImplicitAutoType(MD.MemberType);
  509. end;
  510. function TBaseWebIDLToPas.WriteOtherImplicitTypes(
  511. Intf: TIDLStructuredDefinition; aMemberList: TIDLDefinitionList): Integer;
  512. begin
  513. Result:=0;
  514. if Intf=nil then ;
  515. if aMemberList=nil then ;
  516. end;
  517. function TBaseWebIDLToPas.WriteDictionaryMemberImplicitTypes(
  518. aDict: TIDLDictionaryDefinition; aList: TIDLDefinitionList): Integer;
  519. Var
  520. D: TIDLDefinition;
  521. FD: TIDLDictionaryMemberDefinition absolute D;
  522. begin
  523. Result:=0;
  524. if aDict=nil then ;
  525. for D in aList do
  526. if D is TIDLDictionaryMemberDefinition then
  527. if ConvertDef(D) then
  528. Result:=Result+WriteImplicitAutoType(FD.MemberType);
  529. end;
  530. function TBaseWebIDLToPas.WritePrivateReadOnlyFields(aParent: TIDLDefinition;
  531. aList: TIDLDefinitionList): Integer;
  532. var
  533. D : TIDLDefinition;
  534. MD : TIDLMapLikeDefinition absolute D;
  535. begin
  536. Result:=0;
  537. if aParent=nil then ;
  538. if aList=nil then ;
  539. for D in aList do
  540. if D is TIDLMapLikeDefinition then
  541. if ConvertDef(D) then
  542. Result:=Result+WriteMapLikePrivateReadOnlyFields(aParent,MD);
  543. end;
  544. function TBaseWebIDLToPas.WriteGetters(
  545. aParent: TIDLStructuredDefinition; aList: TIDLDefinitionList): Integer;
  546. var
  547. D : TIDLDefinition;
  548. MD : TIDLMapLikeDefinition absolute D;
  549. begin
  550. Result:=0;
  551. if aParent=nil then ;
  552. if aList=nil then ;
  553. for D in aList do
  554. if D is TIDLMapLikeDefinition then
  555. if ConvertDef(D) then
  556. Result:=Result+WriteMapLikeGetters(aParent,MD);
  557. end;
  558. function TBaseWebIDLToPas.WriteSetters(
  559. aParent: TIDLStructuredDefinition; aList: TIDLDefinitionList): Integer;
  560. begin
  561. Result:=0;
  562. if aParent=nil then ;
  563. if aList=nil then ;
  564. end;
  565. function TBaseWebIDLToPas.WriteMapLikePrivateReadOnlyFields(aParent: TIDLDefinition; aMap: TIDLMapLikeDefinition): Integer;
  566. begin
  567. if (aParent=Nil) and (aMap=Nil) then ; // Silence compiler warning
  568. Result:=1;
  569. AddLn('fsize : NativeInt; external name ''size'';');
  570. end;
  571. function TBaseWebIDLToPas.WriteProperties(aParent: TIDLDefinition;
  572. aList: TIDLDefinitionList): Integer;
  573. var
  574. D : TIDLDefinition;
  575. MD : TIDLMapLikeDefinition absolute D;
  576. begin
  577. Result:=0;
  578. if aParent=nil then ;
  579. if aList=nil then ;
  580. for D in aList do
  581. if D is TIDLMapLikeDefinition then
  582. if ConvertDef(D) then
  583. Result:=Result+WriteMapLikeProperties(aParent,MD);
  584. end;
  585. function TBaseWebIDLToPas.WriteMapLikeProperties(aParent: TIDLDefinition; aMap: TIDLMapLikeDefinition): Integer;
  586. begin
  587. if (aParent=Nil) and (aMap=nil) then ; // Silence compiler warning
  588. AddLn('property size : NativeInt read fsize;');
  589. Result:=1;
  590. end;
  591. function TBaseWebIDLToPas.WriteMapLikeGetters(aParent: TIDLStructuredDefinition; aMap: TIDLMapLikeDefinition): Integer;
  592. begin
  593. if (aParent<>Nil) and (aMap<>Nil) then;
  594. Result:=0;
  595. // AddLn('function _Getsize: NativeInt;');
  596. // Result:=1;
  597. end;
  598. function TBaseWebIDLToPas.WriteConst(aConst: TIDLConstDefinition): Boolean;
  599. var
  600. S: UTF8String;
  601. begin
  602. Result:=true;
  603. S:=aConst.Value;
  604. if aConst.ConstType=ctInteger then
  605. S:=StringReplace(S,'0x','$',[]);
  606. Addln('%s = %s;',[GetPasName(aConst),S])
  607. end;
  608. function TBaseWebIDLToPas.WriteConsts(aParent: TIDLDefinition;
  609. aList: TIDLDefinitionList): Integer;
  610. Var
  611. D: TIDLDefinition;
  612. begin
  613. if aParent=nil then ;
  614. EnsureSection(csConst);
  615. Indent;
  616. Result:=0;
  617. For D in aList do
  618. if D is TIDLConstDefinition then
  619. if ConvertDef(D) then
  620. if WriteConst(D as TIDLConstDefinition) then
  621. Inc(Result);
  622. Undent;
  623. end;
  624. function TBaseWebIDLToPas.WritePlainFields(aParent: TIDLDefinition;
  625. aList: TIDLDefinitionList): Integer;
  626. Var
  627. D: TIDLDefinition;
  628. A: TIDLAttributeDefinition absolute D;
  629. begin
  630. if aParent=nil then ;
  631. EnsureSection(csDeclaration);
  632. Result:=0;
  633. For D in aList do
  634. if D is TIDLAttributeDefinition then
  635. if ConvertDef(D) then
  636. if Not (aoReadOnly in A.Options) then
  637. if WriteField(A) then
  638. Inc(Result);
  639. end;
  640. function TBaseWebIDLToPas.WriteDictionaryField(aDict: TIDLDictionaryDefinition;
  641. aField: TIDLDictionaryMemberDefinition): Boolean;
  642. Var
  643. Def,N,TN: String;
  644. begin
  645. Result:=True;
  646. if aDict=nil then ;
  647. N:=GetPasName(aField);
  648. TN:=GetPasName(aField.MemberType);
  649. if TN='record' then
  650. TN:='TJSObject';
  651. if SameText(N,TN) then
  652. N:='_'+N;
  653. Def:=Format('%s: %s;',[N,TN]);
  654. if (N<>aField.Name) then
  655. Def:=Def+Format('external name ''%s'';',[aField.Name]);
  656. AddLn(Def);
  657. end;
  658. function TBaseWebIDLToPas.WriteDictionaryFields(
  659. aDict: TIDLDictionaryDefinition; aList: TIDLDefinitionList): Integer;
  660. Var
  661. D: TIDLDefinition;
  662. M: TIDLDictionaryMemberDefinition absolute D;
  663. begin
  664. Indent;
  665. Result:=0;
  666. For D in aList do
  667. if D is TIDLDictionaryMemberDefinition then
  668. if ConvertDef(D) then
  669. if WriteDictionaryField(aDict,M) then
  670. Inc(Result);
  671. Undent;
  672. end;
  673. function TBaseWebIDLToPas.WriteMethodDefs(aParent: TIDLStructuredDefinition;
  674. aList: TIDLDefinitionList): Integer;
  675. Var
  676. D: TIDLDefinition;
  677. FD: TIDLFunctionDefinition absolute D;
  678. MD: TIDLMapLikeDefinition absolute D;
  679. begin
  680. Result:=0;
  681. for D in aList do
  682. if ConvertDef(D) then
  683. if D is TIDLFunctionDefinition then
  684. begin
  685. if Not (foCallBack in FD.Options) then
  686. if WriteFunctionDefinition(aParent,FD) then
  687. Inc(Result);
  688. end
  689. else if D is TIDLMaplikeDefinition then
  690. Result:=Result+WriteMapLikeMethodDefinitions(aParent,MD);
  691. end;
  692. function TBaseWebIDLToPas.GetParentsMemberList(aParent: TIDLStructuredDefinition) : TIDLDefinitionList;
  693. var
  694. D : TPasData;
  695. begin
  696. D:=TPasData(aParent.Data);
  697. if Not Assigned(D) then
  698. Raise EWebIDLError.CreateFmt('%s does not have data assigned to it',[aParent]);
  699. if Not Assigned(D.ParentsMemberList) then
  700. begin
  701. D.ParentsMemberList:=TIDLDefinitionList.Create(aParent,False);
  702. While aParent<>Nil do
  703. begin
  704. AddFullMemberList(aParent,D.ParentsmemberList);
  705. if aParent is TIDLInterfaceDefinition then
  706. aParent:=TIDLInterfaceDefinition(aParent).ParentInterface
  707. else if aParent is TIDLDictionaryDefinition then
  708. aParent:=TIDLDictionaryDefinition(aParent).ParentDictionary
  709. else
  710. aParent:=Nil;
  711. end;
  712. end;
  713. Result:=D.ParentsmemberList;
  714. end;
  715. procedure TBaseWebIDLToPas.AddFullMemberList(aParent: TIDLStructuredDefinition; AddToList : TIDLDefinitionList);
  716. Var
  717. List : TIDLDefinitionList;
  718. D : TIDLDefinition;
  719. begin
  720. List:=GetFullMemberList(AParent);
  721. For D in List do
  722. addToList.Add(D);
  723. end;
  724. function TBaseWebIDLToPas.GetFullMemberList(aParent: TIDLStructuredDefinition) : TIDLDefinitionList;
  725. var
  726. D : TPasData;
  727. begin
  728. D:=TPasData(aParent.Data);
  729. if Not Assigned(D) then
  730. Raise EWebIDLError.CreateFmt('%s does not have data assigned to it',[aParent]);
  731. if Not Assigned(D.FullmemberList) then
  732. begin
  733. D.FullmemberList:=TIDLDefinitionList.Create(aParent,False);
  734. aParent.GetFullMemberList(D.FullmemberList);
  735. end;
  736. Result:=D.FullmemberList;
  737. end;
  738. function TBaseWebIDLToPas.WriteMapLikeMethodDefinitions(aParent: TIDLStructuredDefinition; aMap: TIDLMapLikeDefinition): integer;
  739. var
  740. D1,KeyType,ValueType : String;
  741. lReadOnly : Boolean;
  742. L : TIDLDefinitionList;
  743. KNT,VNT : TPascalNativeType;
  744. begin
  745. Result:=0;
  746. GetResolvedType(aMap.KeyType,KNT,D1,KeyType);
  747. GetResolvedType(aMap.ValueType,VNT,D1,ValueType);
  748. // KeyType:=GetResolName();
  749. // ValueType:=GetName(aMap.ValueType);
  750. lReadOnly:=aMap.IsReadonly;
  751. L:=GetFullMemberList(aParent);
  752. if Not L.HasName('get') then
  753. AddLn('function get(key: %s) : %s;',[KeyType,ValueType]);
  754. if Not L.HasName('has') then
  755. AddLn('function has(key: %s) : Boolean;',[KeyType]);
  756. if Not L.HasName('entries') then
  757. AddLn('function entries : IJSIterator;');
  758. if Not L.HasName('keys') then
  759. AddLn('function keys : IJSIterator;');
  760. if Not L.HasName('values') then
  761. AddLn('function values : IJSIterator;');
  762. Inc(Result,5);
  763. if not lReadOnly then
  764. begin
  765. if Not L.HasName('set') then
  766. AddLn('procedure set_(key: %s; value : %s);',[KeyType,ValueType]);
  767. if Not L.HasName('clear') then
  768. AddLn('procedure clear;');
  769. if Not L.HasName('delete') then
  770. AddLn('procedure delete(key: %s);',[KeyType]);
  771. Inc(Result,3);
  772. end;
  773. end;
  774. function TBaseWebIDLToPas.WriteUtilityMethods(Intf: TIDLStructuredDefinition
  775. ): Integer;
  776. begin
  777. Result:=0;
  778. if Intf=nil then ;
  779. end;
  780. function TBaseWebIDLToPas.CheckExistingSequence(ST: TIDLSequenceTypeDefDefinition; out TN: TIDLString): Boolean;
  781. var
  782. ArgTypeName,ArgResolvedTypeName : String;
  783. NT : TPascalNativeType;
  784. begin
  785. GetResolvedType(ST,NT,ArgTypeName,ArgResolvedTypeName);
  786. TN:=ArgTypeName;
  787. Result:=FAutoTypes.IndexOf(TN)<>-1;
  788. end;
  789. function TBaseWebIDLToPas.CheckExistingUnion(UT: TIDLUnionTypeDefDefinition; out TN: TIDLString): Boolean;
  790. var
  791. ArgTypeName,ArgResolvedTypeName : String;
  792. NT : TPascalNativeType;
  793. begin
  794. GetResolvedType(UT,NT,ArgTypeName,ArgResolvedTypeName);
  795. TN:=ArgTypeName;
  796. Result:=FAutoTypes.IndexOf(TN)<>-1;
  797. end;
  798. function TBaseWebIDLToPas.AddSequenceDef(ST: TIDLSequenceTypeDefDefinition
  799. ): Boolean;
  800. var
  801. TN : TIDLString;
  802. begin
  803. Result:=Not CheckExistingSequence(ST,TN);
  804. if Result then
  805. begin
  806. FAutoTypes.Add(TN);
  807. if Verbose then
  808. DoLog('Automatically adding %s sequence definition for %s.',[TN,GetDefPos(ST)]);
  809. WriteSequenceDef(ST);
  810. end;
  811. end;
  812. function TBaseWebIDLToPas.AddUnionDef(UT: TIDLUnionTypeDefDefinition): Boolean;
  813. var
  814. TN : TIDLString;
  815. begin
  816. Result:=Not CheckExistingUnion(UT,TN);
  817. if Result then
  818. begin
  819. FAutoTypes.Add(TN);
  820. if Verbose then
  821. DoLog('Automatically adding %s sequence definition for %s.',[TN,GetDefPos(UT)]);
  822. WriteUnionDef(UT);
  823. end;
  824. end;
  825. procedure TBaseWebIDLToPas.EnsureUniqueNames(aParent : TIDLStructuredDefinition;ML: TIDLDefinitionList;const aParentName : String);
  826. Var
  827. L: TFPObjectHashTable;
  828. Function CanRename(Def: TIDLDefinition) : Boolean;
  829. var
  830. isStringifier : Boolean;
  831. IsIterable : Boolean;
  832. begin
  833. IsStringifier:=(Def.Name='') and (Def is TIDLAttributeDefinition) and (aoStringifier in TIDLAttributeDefinition(Def).Options);
  834. isIterable:=(Def is TIDLIterableDefinition);
  835. Result:=not (IsStringifier or isIterable);
  836. end;
  837. Procedure CheckRename(Def: TIDLDefinition);
  838. var
  839. I: integer;
  840. OrigType : TPascalNativeType;
  841. OrigName,BaseName,NewName: String;
  842. IsOverload: Boolean;
  843. CurDef , ConflictDef: TIDLDefinition;
  844. begin
  845. OrigType:=GetPasNativeTypeAndName(Def,OrigName);
  846. BaseName:=LowerCase(OrigName);
  847. NewName:=BaseName;
  848. I:=0;
  849. IsOverload:=False;
  850. ConflictDef:=nil;
  851. Repeat
  852. CurDef:=TIDLDefinition(L.Items[NewName]);
  853. if (CurDef<>Nil) then
  854. // Overloads
  855. begin
  856. IsOverload:=((CurDef is TIDLFunctionDefinition) and (Def is TIDLFunctionDefinition));
  857. if IsOverload then
  858. CurDef:=Nil
  859. else
  860. begin
  861. ConflictDef:=CurDef;
  862. inc(I);
  863. if I>1 then
  864. raise EConvertError.CreateFmt('[20220725172221] Duplicate identifier %s at (%s) and (%s)',[BaseName,GetDefPos(Def),GetDefPos(CurDef)]);
  865. NewName:=KeywordPrefix+BaseName+KeywordSuffix;
  866. OrigName:=KeywordPrefix+OrigName+KeywordSuffix;
  867. end;
  868. end;
  869. Until (CurDef=Nil);
  870. if (BaseName<>NewName) then
  871. begin
  872. BaseName:=GetPasName(Def);
  873. if Verbose then
  874. DoLog('Renaming duplicate identifier (%s) %s at %s to %s, other at %s',[Def.ClassName,BaseName,GetDefPos(Def),OrigName,GetDefPos(ConflictDef)]);
  875. // Original TPasName is in list, will be freed automatically
  876. Def.Data:=CreatePasData(OrigName,OrigType,Def,False);
  877. end;
  878. if not IsOverload then
  879. L.Add(NewName,Def);
  880. end;
  881. var
  882. D: TIDLDefinition;
  883. begin
  884. if (aParent=Nil) and (aParentname='') then ; // Silence compiler warning
  885. L:=TFPObjectHashTable.Create(False);
  886. try
  887. For D in ML Do
  888. if ConvertDef(D) then
  889. if CanRename(D) and not (D is TIDLConstDefinition) then
  890. CheckRename(D);
  891. For D in ML Do
  892. if ConvertDef(D) then
  893. if CanRename(D) and (D is TIDLConstDefinition) then
  894. CheckRename(D);
  895. finally
  896. L.Free;
  897. end;
  898. end;
  899. procedure TBaseWebIDLToPas.EnsureUniqueArgNames(Intf: TIDLStructuredDefinition);
  900. var
  901. Names: TFPObjectHashTable;
  902. procedure CheckRenameArgs(Func: TIDLFunctionDefinition);
  903. var
  904. i: Integer;
  905. Arg: TIDLArgumentDefinition;
  906. ArgName: String;
  907. ConflictDef: TIDLDefinition;
  908. D : TPasData;
  909. begin
  910. for i:=0 to Func.Arguments.Count-1 do
  911. begin
  912. Arg:=Func.Argument[i];
  913. D:=TPasData(Arg.Data);
  914. if D=Nil then
  915. Raise EWebIDLError.CreateFmt('Function %s argument %s does not have pascal data assigned',[Func.Name,Arg.Name]);
  916. if not D.NameChecked then
  917. begin
  918. ArgName:=GetPasName(Arg);
  919. ArgName:='a'+Uppercase(ArgName[1])+copy(ArgName,2,length(ArgName));
  920. repeat
  921. ConflictDef:=TIDLDefinition(Names.Items[LowerCase(ArgName)]);
  922. if (ConflictDef=Nil) then break;
  923. // name conflict -> rename
  924. ArgName:='_'+ArgName;
  925. until false;
  926. D.PasName:=ArgName;
  927. D.NameChecked:=True;
  928. end;
  929. end;
  930. end;
  931. var
  932. Members, MembersWithParents: TIDLDefinitionList;
  933. D: TIDLDefinition;
  934. CurName: String;
  935. begin
  936. Members:=GetFullMemberList(Intf);
  937. MembersWithParents:=GetParentsMemberList(Intf);
  938. Names:=TFPObjectHashTable.Create(False);
  939. try
  940. For D in MembersWithParents Do
  941. if ConvertDef(D) then
  942. begin
  943. CurName:=LowerCase(GetPasName(D));
  944. if Names.Items[CurName]=nil then
  945. Names.Add(CurName,D);
  946. end;
  947. For D in Members Do
  948. if D is TIDLFunctionDefinition then
  949. if ConvertDef(D) then
  950. CheckRenameArgs(TIDLFunctionDefinition(D));
  951. finally
  952. Names.Free;
  953. end;
  954. end;
  955. function TBaseWebIDLToPas.WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean;
  956. Var
  957. aClassName: String;
  958. Decl: String;
  959. ML: TIDLDefinitionList;
  960. begin
  961. Result:=True;
  962. ML:=GetFullMemberList(Intf);
  963. EnsureUniqueNames(Intf,ML,Intf.Name);
  964. EnsureUniqueArgNames(Intf);
  965. aClassName:=GetPasName(Intf);
  966. // class comment
  967. ClassComment(aClassName);
  968. // sub types
  969. WriteFunctionImplicitTypes(ML);
  970. WriteAttributeImplicitTypes(ML);
  971. WriteOtherImplicitTypes(Intf,ML);
  972. // class and ancestor
  973. Decl:=aClassName+' = '+GetInterfaceDefHead(Intf);
  974. AddLn(Decl);
  975. PushSection(csUnknown);
  976. // private section
  977. AddLn('Private');
  978. Indent;
  979. WritePrivateReadOnlyFields(Intf,ML);
  980. if Not (coPrivateMethods in BaseOptions) then
  981. begin
  982. Undent;
  983. AddLn('Protected');
  984. Indent;
  985. end;
  986. WriteGetters(Intf,ML);
  987. WriteSetters(Intf,ML);
  988. Undent;
  989. // write public section
  990. AddLn('Public');
  991. if HaveConsts(ML) then
  992. begin
  993. Indent;
  994. WriteConsts(Intf,ML);
  995. Undent;
  996. AddLn('Public');
  997. end;
  998. Indent;
  999. WritePlainFields(Intf,ML);
  1000. WriteMethodDefs(Intf,ML);
  1001. WriteUtilityMethods(Intf);
  1002. WriteProperties(Intf,ML);
  1003. PopSection;
  1004. Undent;
  1005. AddLn('end;');
  1006. end;
  1007. function TBaseWebIDLToPas.WriteNamespaceDef(aNamespace: TIDLNamespaceDefinition): Boolean;
  1008. Var
  1009. aClassName: String;
  1010. Decl: String;
  1011. ML: TIDLDefinitionList;
  1012. begin
  1013. Result:=True;
  1014. ML:=GetFullMemberList(aNamespace);
  1015. EnsureUniqueNames(aNameSpace,ML,aNameSpace.name);
  1016. EnsureUniqueArgNames(aNamespace);
  1017. aClassName:=GetPasName(aNamespace);
  1018. // class comment
  1019. ClassComment(aClassName);
  1020. // sub types
  1021. WriteFunctionImplicitTypes(ML);
  1022. WriteAttributeImplicitTypes(ML);
  1023. WriteOtherImplicitTypes(aNameSpace,ML);
  1024. // class and ancestor
  1025. Decl:=aClassName+' = '+GetNamespaceDefHead(aNamespace);
  1026. AddLn(Decl);
  1027. // private section
  1028. AddLn('Private');
  1029. Indent;
  1030. WritePrivateReadOnlyFields(aNamespace,ML);
  1031. if not (coPrivateMethods in BaseOptions) then
  1032. begin
  1033. Undent;
  1034. AddLn('Protected');
  1035. Indent;
  1036. end;
  1037. WriteGetters(aNamespace,ML);
  1038. WriteSetters(aNamespace,ML);
  1039. Undent;
  1040. // write public section
  1041. AddLn('Public');
  1042. if HaveConsts(ML) then
  1043. begin
  1044. Indent;
  1045. PushSection(csUnknown);
  1046. WriteConsts(aNamespace,ML);
  1047. PopSection;
  1048. Undent;
  1049. AddLn('Public');
  1050. end;
  1051. Indent;
  1052. WriteMethodDefs(aNamespace,ML);
  1053. WriteUtilityMethods(aNamespace);
  1054. WriteProperties(aNamespace,ML);
  1055. Undent;
  1056. AddLn('end;');
  1057. end;
  1058. function TBaseWebIDLToPas.WriteDictionaryDef(aDict: TIDLDictionaryDefinition): Boolean;
  1059. Var
  1060. CurClassName, Decl: String;
  1061. DefList: TIDLDefinitionList;
  1062. begin
  1063. Result:=True;
  1064. DefList:=GetParentsMemberList(aDict);
  1065. CurClassName:=GetPasName(aDict);
  1066. ClassComment(CurClassName);
  1067. WriteDictionaryMemberImplicitTypes(aDict, DefList);
  1068. // class and ancestor
  1069. Decl:=GetDictionaryDefHead(CurClassName,aDict);
  1070. AddLn(Decl);
  1071. WriteDictionaryFields(aDict,DefList);
  1072. AddLn('end;');
  1073. end;
  1074. constructor TBaseWebIDLToPas.Create(TheOwner: TComponent);
  1075. begin
  1076. inherited Create(TheOwner);
  1077. WebIDLVersion:=v2;
  1078. FieldPrefix:='F';
  1079. ClassPrefix:='T';
  1080. ClassSuffix:='';
  1081. ArrayPrefix:='T';
  1082. ArraySuffix:='DynArray';
  1083. GetterPrefix:='Get';
  1084. SetterPrefix:='Set';
  1085. TypePrefix:='T';
  1086. FTypeAliases:=TStringList.Create;
  1087. FGlobalVars:=TStringList.Create;
  1088. FPasNameList:=TFPObjectList.Create(True);
  1089. FPasDataClass:=TPasData;
  1090. FAutoTypes:=TStringList.Create;
  1091. FIncludeInterfaceCode:=TStringList.Create;
  1092. FIncludeImplementationCode:=TStringList.Create;
  1093. FGlobalDefs:=TFPObjectHashTable.Create(False);
  1094. end;
  1095. destructor TBaseWebIDLToPas.Destroy;
  1096. begin
  1097. FreeAndNil(FUsedDefs);
  1098. FreeAndNil(FGlobalDefs);
  1099. FreeAndNil(FIncludeInterfaceCode);
  1100. FreeAndNil(FIncludeImplementationCode);
  1101. FreeAndNil(FAutoTypes);
  1102. FreeAndNil(FGlobalVars);
  1103. FreeAndNil(FTypeAliases);
  1104. FreeAndNil(FPasNameList);
  1105. inherited Destroy;
  1106. end;
  1107. procedure TBaseWebIDLToPas.WriteTypeDefsAndCallbackImplementations(aList : TIDLDefinitionList);
  1108. begin
  1109. if aList<>Nil then;
  1110. // Do nothing
  1111. end;
  1112. procedure TBaseWebIDLToPas.WriteImplementation;
  1113. Var
  1114. S: String;
  1115. D : TIDLDefinition;
  1116. Cnt : Integer;
  1117. OK : Boolean;
  1118. Msg : String;
  1119. begin
  1120. FGeneratingImplementation:=True;
  1121. Msg:='';
  1122. if Verbose then
  1123. DoLog('Writing implementation section');
  1124. Addln('');
  1125. For S in FIncludeImplementationCode do
  1126. Addln(S);
  1127. Addln('');
  1128. WriteTypeDefsAndCallbackImplementations(Context.Definitions);
  1129. OK:=False;
  1130. Cnt:=0;
  1131. try
  1132. For D in Context.Definitions do
  1133. begin
  1134. inc(Cnt);
  1135. if ConvertDef(D) then
  1136. if not ((D is TIDLStructuredDefinition) and (TIDLStructuredDefinition(D).IsPartial)) then
  1137. WriteDefinitionImplementation(D);
  1138. end;
  1139. OK:=True;
  1140. finally
  1141. if not OK then
  1142. Msg:=SErrBeforeException;
  1143. if Verbose then
  1144. DoLog('Wrote %d of %d definitions%s',[Cnt,Context.Definitions.Count,Msg]);
  1145. end;
  1146. FGeneratingImplementation:=False;
  1147. end;
  1148. procedure TBaseWebIDLToPas.WriteDefinitionImplementation(D: TIDLDefinition);
  1149. begin
  1150. if Assigned(D) then;
  1151. end;
  1152. function TBaseWebIDLToPas.GetJSTypeName(aTypeDef: TIDLTypeDefDefinition): String;
  1153. begin
  1154. if assigned(aTypeDef) then
  1155. Result:=aTypeDef.GetJSTypeName
  1156. else
  1157. Result:='';
  1158. end;
  1159. function TBaseWebIDLToPas.GetPascalTypeName(aTypeDef: TIDLTypeDefDefinition; ForTypeDef: Boolean = False): String;
  1160. begin
  1161. Result:=GetPascalTypeName(GetJSTypeName(aTypeDef),ForTypeDef)
  1162. end;
  1163. function TBaseWebIDLToPas.GetResolvedType(aDef: TIDLTypeDefDefinition; out PascalNativeType : TPascalNativeType; out aTypeName, aResolvedTypename: string): TIDLTypeDefinition;
  1164. begin
  1165. Result:=nil;
  1166. aTypeName:='';
  1167. aResolvedTypename:='';
  1168. if aDef=nil then
  1169. exit;
  1170. PascalNativeType:=GetPasNativeTypeAndName(aDef,aTypeName);
  1171. //writeln('TBaseWebIDLToPas.GetResolvedType START aDef=',aDef.Name,':',aDef.ClassName,' ',aDef.TypeName,' ',GetDefPos(aDef),' Resolved=',(aDef.Data is TPasData) and (TPasData(aDef.Data).Resolved<>nil));
  1172. Result:=aDef;
  1173. while (aDef.Data is TPasData) and (TPasData(aDef.Data).Resolved<>nil) do
  1174. begin
  1175. Result:=TPasData(aDef.Data).Resolved;
  1176. //writeln('TBaseWebIDLToPas.GetResolvedType RESOLVED Result=',Result.Name,' ',GetDefPos(Result));
  1177. if not (Result is TIDLTypeDefDefinition) then
  1178. break;
  1179. if Result=aDef then
  1180. break;
  1181. aDef:=TIDLTypeDefDefinition(Result);
  1182. end;
  1183. if Result is TIDLTypeDefDefinition then
  1184. aResolvedTypename:=GetPascalTypeName(TIDLTypeDefDefinition(Result))
  1185. else
  1186. aResolvedTypename:=GetPasName(Result);
  1187. end;
  1188. function TBaseWebIDLToPas.ConstructSequenceTypeName(
  1189. Seq: TIDLSequenceTypeDefDefinition; ForTypeDef: Boolean): string;
  1190. begin
  1191. Result:=GetPasName(Seq.ElementType);
  1192. if Result='' then
  1193. Result:=GetPascalTypeName(Seq.ElementType,ForTypeDef);
  1194. if (Result='') then
  1195. begin
  1196. if ForTypeDef then
  1197. raise EConvertError.Create('[20220725172227] sequence without name at '+GetDefPos(Seq));
  1198. Result:=GetPasName(Seq);
  1199. end;
  1200. if LeftStr(Result,length(ArrayPrefix))<>ArrayPrefix then
  1201. Result:=ArrayPrefix+Result;
  1202. Result:=Result+ArraySuffix;
  1203. end;
  1204. function TBaseWebIDLToPas.GetInterfaceDefHead(Intf: TIDLInterfaceDefinition
  1205. ): String;
  1206. begin
  1207. Result:='class';
  1208. if Intf=nil then ;
  1209. end;
  1210. function TBaseWebIDLToPas.GetNamespaceDefHead(Intf: TIDLNamespaceDefinition): String;
  1211. begin
  1212. Result:='class';
  1213. if Intf=nil then ;
  1214. end;
  1215. function TBaseWebIDLToPas.GetDictionaryDefHead(const CurClassName: string; Dict: TIDLDictionaryDefinition): String;
  1216. var
  1217. CurParent: String;
  1218. begin
  1219. if Dict=nil then ;
  1220. if (coDictionaryAsClass in BaseOptions) then
  1221. begin
  1222. CurParent:=DictionaryClassParent;
  1223. if CurParent='' then
  1224. CurParent:='TJSObject';
  1225. Result:='class('+CurParent+')'
  1226. end
  1227. else
  1228. Result:='record';
  1229. Result:=CurClassName+' = '+Result;
  1230. end;
  1231. function TBaseWebIDLToPas.IDLToPascalNativeType(const aTypeName: String) : TPascalNativetype;
  1232. begin
  1233. Case aTypeName of
  1234. 'boolean': Result:=ntBoolean;
  1235. 'byte': Result:=ntShortInt;
  1236. 'octet': Result:=ntByte;
  1237. 'short': Result:=ntSmallInt;
  1238. 'unsigned short': Result:=ntWord;
  1239. 'long': Result:=ntLongint;
  1240. 'unsigned long': Result:=ntCardinal;
  1241. 'long long': Result:=ntInt64;
  1242. 'unsigned long long': Result:=ntQWord;
  1243. 'float',
  1244. 'unrestricted float': Result:=ntSingle;
  1245. 'double',
  1246. 'unrestricted double' : Result:=ntDouble;
  1247. 'union',
  1248. 'any': Result:=ntVariant;
  1249. 'DOMString',
  1250. 'USVString',
  1251. 'ByteString': Result:=ntUnicodeString;
  1252. 'UTF8String' : Result:=ntUtf8String;
  1253. 'record',
  1254. 'object': result:=ntObject; // Result:=GetPasClassName('Object');
  1255. 'Error',
  1256. 'DOMException': result:=ntError; // Result:=GetPasClassName('Error');
  1257. 'Int8Array',
  1258. 'Int16Array',
  1259. 'Int32Array',
  1260. 'Uint8Array',
  1261. 'Uint16Array',
  1262. 'Uint32Array',
  1263. 'Uint8ClampedArray',
  1264. 'Float32Array',
  1265. 'Float64Array' : Result:=ntArray;
  1266. 'ArrayBuffer',
  1267. 'ArrayBufferView',
  1268. 'DataView',
  1269. 'Document',
  1270. 'DocumentFragment',
  1271. 'Node': Result:=ntObject; // Result:=GetPasClassName(aTypeName);
  1272. 'undefined',
  1273. 'void': Result:=ntNone; // Result:=aTypeName;
  1274. else
  1275. Result:=ntUnknown;
  1276. end;
  1277. end;
  1278. function TBaseWebIDLToPas.GetPascalTypeAndName(const aTypeName: String; out aPascalName: String): TPascalNativeType;
  1279. Var
  1280. A: UTF8String;
  1281. D: TIDLDefinition;
  1282. P: Integer;
  1283. begin
  1284. Result:=IDLToPascalNativeType(aTypeName);
  1285. Case Result of
  1286. ntObject:
  1287. begin
  1288. Case aTypeName of
  1289. 'ArrayBuffer',
  1290. 'ArrayBufferView',
  1291. 'DataView',
  1292. 'Document',
  1293. 'DocumentFragment',
  1294. 'Node': aPascalName:=GetPasClassName(aTypeName);
  1295. else
  1296. aPascalName:=GetPasClassName('Object')
  1297. end;
  1298. end;
  1299. ntArray:
  1300. begin
  1301. Case aTypeName of
  1302. 'DataView',
  1303. 'Int8Array',
  1304. 'Int16Array',
  1305. 'Int32Array',
  1306. 'Uint8Array',
  1307. 'Uint16Array',
  1308. 'Uint32Array',
  1309. 'Uint8ClampedArray',
  1310. 'Float32Array',
  1311. 'Float64Array' : aPascalName:=GetPasClassName(aTypeName);
  1312. end;
  1313. end;
  1314. ntError:
  1315. aPascalName:=GetPasClassName('Error');
  1316. ntUnknown:
  1317. begin
  1318. a:=aTypeName;
  1319. D:=FindGlobalDef(aTypeName);
  1320. if D=Nil then
  1321. D:=FContext.FindDefinition(aTypeName);
  1322. if (D<>Nil) and (D.Data<>Nil) then
  1323. Result:=GetPasNativeTypeAndName(D,aPascalName)
  1324. else
  1325. begin
  1326. A:=FTypeAliases.Values[aTypeName];
  1327. If (A<>'') then
  1328. begin
  1329. aPascalName:=A;
  1330. P:=Pos(',',A);
  1331. if P>0 then
  1332. SetLength(aPascalName,P-1);
  1333. Result:=GetAliasPascalType(aTypeName,aPascalName);
  1334. end;
  1335. end;
  1336. end;
  1337. else
  1338. aPascalName:=NativeTypeNames[Result];
  1339. end;
  1340. end;
  1341. function TBaseWebIDLToPas.GetPascalTypeName(const aTypeName: String; ForTypeDef: Boolean): String;
  1342. begin
  1343. if ForTypeDef then; // Silence compiler warning
  1344. GetPascalTypeAndName(aTypeName,Result);
  1345. end;
  1346. function TBaseWebIDLToPas.WriteField(aAttr: TIDLAttributeDefinition): Boolean;
  1347. begin
  1348. Result:=false;
  1349. if aAttr=nil then ;
  1350. end;
  1351. function TBaseWebIDLToPas.WriteForwardClassDef(D: TIDLStructuredDefinition): Boolean;
  1352. begin
  1353. Result:=not D.IsPartial;
  1354. if Result then
  1355. AddLn('%s = class;',[GetPasName(D)]);
  1356. end;
  1357. function TBaseWebIDLToPas.WriteForwardClassDefs(aList: TIDLDefinitionList): Integer;
  1358. Var
  1359. D: TIDLDefinition;
  1360. begin
  1361. Result:=0;
  1362. Comment('Forward class definitions');
  1363. For D in aList do
  1364. if (D is TIDLInterfaceDefinition) or (D is TIDLNamespaceDefinition) then
  1365. if ConvertDef(D) then
  1366. begin
  1367. if WriteForwardClassDef(D as TIDLStructuredDefinition) then
  1368. Inc(Result);
  1369. end;
  1370. if coDictionaryAsClass in BaseOptions then
  1371. For D in aList do
  1372. if D is TIDLDictionaryDefinition then
  1373. if ConvertDef(D) then
  1374. if WriteForwardClassDef(D as TIDLDictionaryDefinition) then
  1375. Inc(Result);
  1376. end;
  1377. procedure TBaseWebIDLToPas.WriteSequenceDef(aDef: TIDLSequenceTypeDefDefinition);
  1378. begin
  1379. Addln('%s = array of %s;',[GetPasName(aDef),GetPascalTypeName(aDef.ElementType)])
  1380. end;
  1381. procedure TBaseWebIDLToPas.WriteUnionDef(aDef: TIDLUnionTypeDefDefinition);
  1382. Var
  1383. aLine,S: UTF8String;
  1384. D: TIDLDefinition;
  1385. begin
  1386. S:='';
  1387. For D in adef.Union do
  1388. begin
  1389. if (S<>'') then
  1390. S:=S+', ';
  1391. S:=S+(D as TIDLTypeDefDefinition).TypeName;
  1392. end;
  1393. Comment('Union of '+S);
  1394. aLine:=GetPasName(aDef)+' = '+GetPascalTypeName('any')+';';
  1395. AddLn(aLine);
  1396. end;
  1397. procedure TBaseWebIDLToPas.WriteGlobalVar(aDef : String);
  1398. var
  1399. P : Integer;
  1400. VarName, VarType: String;
  1401. begin
  1402. P:=Pos('=',aDef);
  1403. VarName:=Trim(Copy(aDef,1,P-1));
  1404. VarType:=Trim(Copy(aDef,P+1));
  1405. AddLn(VarName+': '+VarType+';');
  1406. end;
  1407. procedure TBaseWebIDLToPas.WriteGlobalVars;
  1408. var
  1409. i: Integer;
  1410. begin
  1411. if (GlobalVars.Count=0) and Not Context.HaveNamespaces then
  1412. exit;
  1413. AddLn('var');
  1414. Indent;
  1415. for i:=0 to GlobalVars.Count-1 do
  1416. begin
  1417. WriteGlobalvar(GlobalVars[i]);
  1418. end;
  1419. WriteNamespaceVars;
  1420. Undent;
  1421. end;
  1422. procedure TBaseWebIDLToPas.WriteNamespaceVars;
  1423. var
  1424. i: Integer;
  1425. VarName, VarType: String;
  1426. begin
  1427. for I:=0 to Context.Definitions.Count-1 do
  1428. if Context.Definitions[i] is TIDLNamespaceDefinition then
  1429. begin
  1430. VarName:=Context.Definitions[i].Name;
  1431. VarType:=GetPasName(Context.Definitions[i]);
  1432. AddLn(VarName+': '+VarType+';');
  1433. end;
  1434. end;
  1435. procedure TBaseWebIDLToPas.WritePromiseDef(aDef: TIDLPromiseTypeDefDefinition);
  1436. begin
  1437. if aDef<>Nil then;
  1438. // AddLn(GetName(aDef)+' = '+ClassPrefix+'Promise'+ClassSuffix+';');
  1439. end;
  1440. procedure TBaseWebIDLToPas.WriteAliasTypeDef(aDef: TIDLTypeDefDefinition);
  1441. Var
  1442. TN: String;
  1443. begin
  1444. TN:=GetPascalTypeName(aDef,True);
  1445. AddLn('%s = %s;',[GetPasName(aDef),TN]);
  1446. end;
  1447. function TBaseWebIDLToPas.WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean;
  1448. var
  1449. TN : TIDLString;
  1450. begin
  1451. Result:=(TypeAliases.IndexOfName(aDef.Name)=-1);
  1452. if not Result then
  1453. exit;
  1454. if ADef is TIDLSequenceTypeDefDefinition then
  1455. begin
  1456. if not CheckExistingSequence(aDef as TIDLSequenceTypeDefDefinition,TN) then
  1457. begin
  1458. FAutoTypes.Add(TN);
  1459. WriteSequenceDef(aDef as TIDLSequenceTypeDefDefinition);
  1460. end;
  1461. end
  1462. else if ADef is TIDLUnionTypeDefDefinition then
  1463. WriteUnionDef(aDef as TIDLUnionTypeDefDefinition)
  1464. else if ADef is TIDLPromiseTypeDefDefinition then
  1465. WritePromiseDef(aDef as TIDLPromiseTypeDefDefinition)
  1466. else if ADef is TIDLRecordDefinition then
  1467. WriteRecordDef(aDef as TIDLRecordDefinition)
  1468. else
  1469. WriteAliasTypeDef(aDef);
  1470. end;
  1471. function TBaseWebIDLToPas.WriteRecordDef(aDef: TIDLRecordDefinition): Boolean;
  1472. Var
  1473. KT,VT: String;
  1474. begin
  1475. Result:=True;
  1476. KT:=GetPascalTypeName(aDef.KeyType);
  1477. VT:=GetPascalTypeName(aDef.ValueType);
  1478. AddLn('%s = Class(TJSObject)',[GetPasName(aDef)]);
  1479. AddLn('private');
  1480. Indent;
  1481. AddLn('function GetValue(aKey: %s): %s; external name ''[]'';',[KT,VT]);
  1482. AddLn('procedure SetValue(aKey: %s; const AValue: %s); external name ''[]'';',[KT,VT]);
  1483. Undent;
  1484. AddLn('public');
  1485. Indent;
  1486. AddLn('property Values[Name: %s]: %s read GetProperties write SetProperties; default;',[KT,VT]);
  1487. Undent;
  1488. AddLn('end;');
  1489. end;
  1490. function TBaseWebIDLToPas.WriteTypeDefsAndCallbacks(aList: TIDLDefinitionList): Integer;
  1491. const
  1492. SimpleTypes = [ntError, ntBoolean, ntShortInt, ntByte, ntSmallInt, ntWord, ntLongint, ntCardinal,
  1493. ntInt64, ntQWord, ntSingle, ntDouble, ntUnicodeString, ntUTF8String, ntVariant];
  1494. Var
  1495. D: TIDLDefinition;
  1496. TD: TIDLTypeDefDefinition absolute D;
  1497. CD: TIDLCallbackDefinition absolute D;
  1498. begin
  1499. Result:=0;
  1500. EnsureSection(csType);
  1501. // Better would be to sort the definitions on dependency.
  1502. // Simple typedefs
  1503. for D in aList do
  1504. if D is TIDLTypeDefDefinition then
  1505. begin
  1506. if ConvertDef(D) then
  1507. if GetPasNativeType(TD) in SimpleTypes then
  1508. if WriteTypeDef(TD) then
  1509. Inc(Result);
  1510. end;
  1511. // Complex typedefs and callbacks (which can reference typedefs);
  1512. for D in aList do
  1513. if D is TIDLTypeDefDefinition then
  1514. begin
  1515. if ConvertDef(D) then
  1516. if Not (GetPasNativeType(TD) in SimpleTypes) then
  1517. if WriteTypeDef(TD) then
  1518. Inc(Result);
  1519. end
  1520. else if D is TIDLCallbackDefinition then
  1521. begin
  1522. if ConvertDef(D) then
  1523. if WriteFunctionTypeDefinition(CD.FunctionDef,GetPasName(CD)) then
  1524. Inc(Result);
  1525. end;
  1526. end;
  1527. function TBaseWebIDLToPas.WriteEnumDef(aDef: TIDLEnumDefinition): Boolean;
  1528. begin
  1529. Result:=True;
  1530. AddLn('%s = String;',[GetPasName(aDef)]);
  1531. end;
  1532. function TBaseWebIDLToPas.WriteEnumDefs(aList: TIDLDefinitionList): Integer;
  1533. Var
  1534. D: TIDLDefinition;
  1535. ED: TIDLEnumDefinition absolute D;
  1536. begin
  1537. Result:=0;
  1538. EnsureSection(csType);
  1539. for D in aList do
  1540. if D is TIDLEnumDefinition then
  1541. if ConvertDef(D) then
  1542. if WriteEnumDef(ED) then
  1543. Inc(Result);
  1544. end;
  1545. function TBaseWebIDLToPas.GetArguments(aList: TIDLDefinitionList; ForceBrackets: Boolean): String;
  1546. Var
  1547. I, ArgType: TIDLDefinition;
  1548. Arg: TIDLArgumentDefinition absolute I;
  1549. NT : TPascalNativeType;
  1550. ArgName, ArgTypeName, ArgResolvedTypeName: string;
  1551. begin
  1552. Result:='';
  1553. For I in aList do
  1554. begin
  1555. ArgName:=GetPasName(Arg);
  1556. if IsKeyWord(ArgName) then
  1557. ArgName:=ArgName+'_';
  1558. ArgType:=GetResolvedType(Arg.ArgumentType,NT,ArgTypeName,ArgResolvedTypeName);
  1559. ArgName:=ArgName+': '+ArgTypeName;
  1560. //writeln('TBaseWebIDLToPas.GetArguments Arg="',ArgName,'" A.ArgumentType.TypeName=',Arg.ArgumentType.TypeName,' ',Def<>nil);
  1561. if (ArgType is TIDLFunctionDefinition)
  1562. or (ArgType is TIDLCallBackDefinition)
  1563. or (ArgType is TIDLDictionaryDefinition)
  1564. or (ArgType is TIDLSequenceTypeDefDefinition)
  1565. or (ArgResolvedTypeName='Variant')
  1566. or (ArgResolvedTypeName='UnicodeString')
  1567. or (ArgResolvedTypeName='UTF8String') then
  1568. ArgName:='const '+ArgName;
  1569. if Result<>'' then
  1570. Result:=Result+'; ';
  1571. Result:=Result+ArgName;
  1572. end;
  1573. if (Result<>'') or ForceBrackets then
  1574. Result:='('+Result+')';
  1575. end;
  1576. Type
  1577. // A partial argument list is a list which has been generated for a optional argument.
  1578. // Additional arguments can never be added to a partial list...
  1579. TIDLPartialDefinitionList = Class(TIDLDefinitionList);
  1580. function TBaseWebIDLToPas.CloneNonPartialArgumentList(aList: TFPObjectlist;
  1581. ADest: TFPObjectlist; AsPartial: Boolean): integer;
  1582. Var
  1583. I,J: Integer;
  1584. CD: TIDLDefinition;
  1585. DL,CL: TIDLDefinitionList;
  1586. begin
  1587. Result:=0;
  1588. if ADest=Nil then
  1589. ADest:=aList;
  1590. I:=aList.Count-1;
  1591. While (I>=0) do
  1592. begin
  1593. DL:=TIDLDefinitionList(alist[i]);
  1594. if Not (DL is TIDLPartialDefinitionList) then
  1595. begin
  1596. Inc(Result);
  1597. if AsPartial then
  1598. CL:=TIDLPartialDefinitionList.Create(Nil,True)
  1599. else
  1600. CL:=TIDLDefinitionList.Create(Nil,True);
  1601. aDest.Add(CL);
  1602. For J:=0 to DL.Count-1 do
  1603. begin
  1604. CD:=CloneArgument(DL.Definitions[J] as TIDLArgumentDefinition);
  1605. CL.Add(CD);
  1606. end;
  1607. end;
  1608. Dec(I);
  1609. end;
  1610. end;
  1611. procedure TBaseWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; aName,
  1612. aPasName, aTypeName: String; PosEl: TIDLBaseObject);
  1613. Var
  1614. I: Integer;
  1615. CD: TIDLArgumentDefinition;
  1616. DL: TIDLDefinitionList;
  1617. ODef : TIDLDefinition absolute posEl;
  1618. aType : TPascalNativeType;
  1619. begin
  1620. For I:=0 to aList.Count-1 do
  1621. begin
  1622. DL:=TIDLDefinitionList(alist[i]);
  1623. if Not (DL is TIDLPartialDefinitionList) then
  1624. begin
  1625. CD:=TIDLArgumentDefinition.Create(Nil,aName,PosEl.SrcFile,PosEl.Line,PosEl.Column);
  1626. if PosEl is TIDLTypeDefDefinition then
  1627. CD.ArgumentType:=TIDLTypeDefDefinition(PosEl).Clone(CD)
  1628. else
  1629. CD.ArgumentType:=TIDLTypeDefDefinition.Create(CD,'',PosEl.SrcFile,PosEl.Line,PosEl.Column);
  1630. CD.ArgumentType.TypeName:=aTypeName;
  1631. if (PosEl is TIDLDefinition) and (ODef.Data is TPasData) then
  1632. begin
  1633. CD.ArgumentType.Data:=ClonePasData(ODef.Data as TPasData,CD.ArgumentType);
  1634. aType:=TPasData(CD.ArgumentType.Data).NativeType;
  1635. end
  1636. else
  1637. begin
  1638. if verbose then
  1639. DoLog('Unknown native type for overload %s (%s -> %s)',[aName,aTypeName,aPasName]);
  1640. end;
  1641. DL.Add(CD);
  1642. CD.Data:=CreatePasData(aPasName,aType,CD,false);
  1643. ResolveTypeDef(CD.ArgumentType);
  1644. end;
  1645. end;
  1646. end;
  1647. procedure TBaseWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; aDef: TIDLArgumentDefinition);
  1648. Var
  1649. I: Integer;
  1650. CD: TIDLDefinition;
  1651. DL: TIDLDefinitionList;
  1652. begin
  1653. For I:=0 to aList.Count-1 do
  1654. begin
  1655. DL:=TIDLDefinitionList(aList[i]);
  1656. if Not (DL is TIDLPartialDefinitionList) then
  1657. begin
  1658. CD:=CloneArgument(aDef);
  1659. DL.Add(CD);
  1660. end;
  1661. end;
  1662. end;
  1663. procedure TBaseWebIDLToPas.AddUnionOverloads(aList: TFPObjectlist; aName,
  1664. aPasName: String; UT: TIDLUnionTypeDefDefinition);
  1665. Var
  1666. L,L2: TFPObjectList;
  1667. I,J: Integer;
  1668. D: TIDLDefinitionList;
  1669. Dups: TStringList;
  1670. CurTypeDef: TIDLTypeDefDefinition;
  1671. begin
  1672. //writeln('TBaseWebIDLToPas.AddUnionOverloads Name=',aName,' PasName=',aPasName);
  1673. L2:=Nil;
  1674. Dups:=TStringList.Create;
  1675. Dups.Sorted:=True;
  1676. Dups.Duplicates:=dupIgnore;
  1677. L:=TFPObjectList.Create(False);
  1678. try
  1679. L2:=TFPObjectList.Create(False);
  1680. // Collect non partial argument lists
  1681. for I:=0 to aList.Count-1 do
  1682. begin
  1683. D:=TIDLDefinitionList(aList[i]);
  1684. if Not (D is TIDLPartialDefinitionList) then
  1685. L.Add(D);
  1686. end;
  1687. // Collect unique pascal types. Note that this can reduce the list to 1 element...
  1688. For I:=0 to UT.Union.Count-1 do
  1689. begin
  1690. CurTypeDef:=UT.Union[I] as TIDLTypeDefDefinition;
  1691. //writeln('TBaseWebIDLToPas.AddUnionOverloads Union[',I,']='+GetTypeName(CurTypeDef));
  1692. Dups.AddObject(CurTypeDef.TypeName,CurTypeDef);
  1693. end;
  1694. // First, clone list and add argument to cloned lists
  1695. For I:=1 to Dups.Count-1 do
  1696. begin
  1697. // Clone list
  1698. CloneNonPartialArgumentList(L,L2,False);
  1699. // Add argument to cloned list
  1700. CurTypeDef:=TIDLTypeDefDefinition(Dups.Objects[I]);
  1701. //writeln('TBaseWebIDLToPas.AddUnionOverloads Dups[',i,']=',Dups[i]);
  1702. AddArgumentToOverloads(L2,aName,aPasName,Dups[i],CurTypeDef);
  1703. // Add overloads to original list
  1704. For J:=0 to L2.Count-1 do
  1705. aList.Add(L2[J]);
  1706. L2.Clear;
  1707. end;
  1708. // Add first Union to original list
  1709. CurTypeDef:=TIDLTypeDefDefinition(Dups.Objects[0]);
  1710. //writeln('TBaseWebIDLToPas.AddUnionOverloads Dups[',0,']=',Dups[0]);
  1711. AddArgumentToOverloads(L,aName,aPasName,Dups[0],CurTypeDef);
  1712. finally
  1713. Dups.Free;
  1714. L2.Free;
  1715. L.Free;
  1716. end;
  1717. end;
  1718. function TBaseWebIDLToPas.CheckUnionTypeDefinition(D: TIDLDefinition
  1719. ): TIDLUnionTypeDefDefinition;
  1720. begin
  1721. Result:=Nil;
  1722. If (D is TIDLUnionTypeDefDefinition) then
  1723. Result:=D as TIDLUnionTypeDefDefinition
  1724. else
  1725. begin
  1726. D:=Context.FindDefinition((D as TIDLTypeDefDefinition).TypeName);
  1727. if (D is TIDLUnionTypeDefDefinition) then
  1728. Result:=D as TIDLUnionTypeDefDefinition
  1729. end
  1730. end;
  1731. function TBaseWebIDLToPas.CloneArgument(Arg: TIDLArgumentDefinition
  1732. ): TIDLArgumentDefinition;
  1733. begin
  1734. Result:=Arg.Clone(nil);
  1735. if Arg.Data<>nil then
  1736. Result.Data:=ClonePasData(TPasData(Arg.Data),Result)
  1737. else if verbose then
  1738. DoLog('Warning : cloning argument "%s" without associated data',[Arg.GetNamePath]);
  1739. Result.ArgumentType:=Arg.ArgumentType.Clone(Result);
  1740. if Arg.ArgumentType.Data<>nil then
  1741. Result.ArgumentType.Data:=ClonePasData(TPasData(Arg.ArgumentType.Data),Result)
  1742. else if verbose then
  1743. DoLog('Warning : cloning argument "%s" type "%s" without associated data',[Arg.GetNamePath,Arg.ArgumentType.GetNamePath]);
  1744. // if Assigned(Result.ArgumentType)
  1745. end;
  1746. procedure TBaseWebIDLToPas.AddOverloads(aList: TFPObjectlist;
  1747. aDef: TIDLFunctionDefinition; aIdx: Integer);
  1748. Var
  1749. Arg: TIDLArgumentDefinition;
  1750. ArgType: TIDLDefinition;
  1751. UT: TIDLUnionTypeDefDefinition;
  1752. begin
  1753. if aIdx>=aDef.Arguments.Count then
  1754. exit;
  1755. Arg:=aDef.Argument[aIdx];
  1756. //writeln('TBaseWebIDLToPas.AddOverloads ',aDef.Name,'[',aIdx,']=',Arg.Name,':',Arg.ArgumentType.ClassName,' at ',GetDefPos(Arg),' Arg.IsOptional=',Arg.IsOptional);
  1757. if Arg.IsOptional then
  1758. CloneNonPartialArgumentList(aList);
  1759. // Add current to list.
  1760. ArgType:=Arg.ArgumentType;
  1761. UT:=Nil;
  1762. if coExpandUnionTypeArgs in BaseOptions then
  1763. UT:=CheckUnionTypeDefinition(ArgType);
  1764. if UT=Nil then
  1765. AddArgumentToOverloads(aList,Arg)
  1766. else
  1767. AddUnionOverLoads(aList,Arg.Name,GetPasName(Arg),UT);
  1768. AddOverloads(aList,aDef,aIdx+1);
  1769. end;
  1770. function TBaseWebIDLToPas.GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist;
  1771. begin
  1772. Result:=TFPObjectList.Create;
  1773. try
  1774. Result.Add(TIDLDefinitionList.Create(Nil,True));
  1775. AddOverloads(Result,aDef,0);
  1776. except
  1777. Result.Free;
  1778. Raise;
  1779. end;
  1780. end;
  1781. function TBaseWebIDLToPas.WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition; aName: String = ''): Boolean;
  1782. Var
  1783. FN,RT,Args: String;
  1784. begin
  1785. Result:=True;
  1786. FN:=aName;
  1787. if FN='' then
  1788. FN:=GetPasName(aDef);
  1789. RT:=GetJSTypeName(aDef.ReturnType);
  1790. if (RT='void') then
  1791. RT:='';
  1792. Args:=GetArguments(aDef.Arguments,False);
  1793. if (RT='') then
  1794. AddLn('%s = procedure %s;',[FN,Args])
  1795. else
  1796. AddLn('%s = function %s: %s;',[FN,Args,RT])
  1797. end;
  1798. function TBaseWebIDLToPas.WriteFunctionDefinition(
  1799. aParent: TIDLStructuredDefinition; aDef: TIDLFunctionDefinition): Boolean;
  1800. begin
  1801. Result:=true;
  1802. if aDef=nil then exit;
  1803. if aParent=nil then ;
  1804. end;
  1805. function TBaseWebIDLToPas.WriteDictionaryDefs(aList: TIDLDefinitionList): Integer;
  1806. Var
  1807. D: TIDLDefinition;
  1808. DD: TIDLDictionaryDefinition absolute D;
  1809. begin
  1810. Result:=0;
  1811. EnsureSection(csType);
  1812. for D in aList do
  1813. if D is TIDLDictionaryDefinition then
  1814. if not TIDLDictionaryDefinition(D).IsPartial then
  1815. if ConvertDef(D) then
  1816. if WriteDictionaryDef(DD) then
  1817. Inc(Result);
  1818. end;
  1819. function TBaseWebIDLToPas.WriteInterfaceDefs(aList: TIDLDefinitionList): Integer;
  1820. Var
  1821. D: TIDLDefinition;
  1822. ID: TIDLInterfaceDefinition absolute D;
  1823. total : integer;
  1824. ok : Boolean;
  1825. Msg : string;
  1826. begin
  1827. Result:=0;
  1828. Msg:='';
  1829. Total:=0;
  1830. OK:=False;
  1831. EnsureSection(csType);
  1832. for D in aList do
  1833. if D is TIDLInterfaceDefinition then
  1834. if not ID.IsPartial then
  1835. if ConvertDef(D) then
  1836. Inc(total);
  1837. try
  1838. for D in aList do
  1839. if D is TIDLInterfaceDefinition then
  1840. if not ID.IsPartial then
  1841. if ConvertDef(D) then
  1842. if WriteInterfaceDef(ID) then
  1843. Inc(Result);
  1844. OK:=True;
  1845. finally
  1846. if not OK then
  1847. Msg:=SErrBeforeException;
  1848. if verbose then
  1849. DoLog('Wrote %d out of %d interface definitions%s.',[Result,Total,Msg]);
  1850. end;
  1851. end;
  1852. function TBaseWebIDLToPas.WriteNamespaceDefs(aList: TIDLDefinitionList): Integer;
  1853. Var
  1854. D: TIDLDefinition;
  1855. ND: TIDLNamespaceDefinition absolute D;
  1856. begin
  1857. Result:=0;
  1858. EnsureSection(csType);
  1859. for D in aList do
  1860. if D is TIDLNamespaceDefinition then
  1861. if not ND.IsPartial then
  1862. if ConvertDef(D) then
  1863. if WriteNamespaceDef(ND) then
  1864. Inc(Result);
  1865. end;
  1866. procedure TBaseWebIDLToPas.GetOptions(L: TStrings; Full: boolean);
  1867. function CountLines(const s: string): integer;
  1868. var
  1869. p: Integer;
  1870. begin
  1871. Result:=1;
  1872. p:=1;
  1873. while p<=length(s) do
  1874. case s[p] of
  1875. #10:
  1876. begin
  1877. inc(p);
  1878. inc(Result);
  1879. end;
  1880. #13:
  1881. begin
  1882. inc(p);
  1883. inc(Result);
  1884. if (p<=length(s)) and (s[p]=#10) then inc(p);
  1885. end;
  1886. else
  1887. inc(p);
  1888. end;
  1889. end;
  1890. function CodeInfo(Src: TStrings): string;
  1891. var
  1892. LineCount, i: Integer;
  1893. begin
  1894. Result:='';
  1895. if Src.Count=0 then
  1896. exit;
  1897. LineCount:=0;
  1898. for i:=0 to Src.Count-1 do
  1899. inc(LineCount,CountLines(Src[i]));
  1900. Result:=Result+IntToStr(Src.Count)+' chunks in '+IntToStr(LineCount)+' lines';
  1901. end;
  1902. Var
  1903. S: String;
  1904. I: Integer;
  1905. begin
  1906. L.Add('Used command-line options: ');
  1907. For I:=1 to ParamCount do
  1908. L.Add(ParamStr(i));
  1909. L.Add('');
  1910. L.Add('Command-line options translated to: ');
  1911. L.Add('');
  1912. if Full then
  1913. begin
  1914. L.Add('Verbose: '+BoolToStr(Verbose,true));
  1915. L.Add('Converter: '+ClassName);
  1916. L.Add('InputFileName: '+InputFileName);
  1917. L.Add('OutputFileName: '+OutputFileName);
  1918. end;
  1919. L.Add('Keyword prefix: '+KeywordPrefix);
  1920. L.Add('Keyword suffix: '+KeywordSuffix);
  1921. L.Add('Class prefix: '+ClassPrefix);
  1922. L.Add('Class suffix: '+ClassSuffix);
  1923. L.Add('Field prefix: '+FieldPrefix);
  1924. L.Add('Getter prefix: '+GetterPrefix);
  1925. L.Add('Setter prefix: '+SetterPrefix);
  1926. Str(WebIDLVersion,S);
  1927. L.Add('WebIDL version: '+S);
  1928. if TypeAliases.Count>0 then
  1929. begin
  1930. L.Add('Type aliases:');
  1931. L.AddStrings(Self.TypeAliases);
  1932. end;
  1933. L.Add('Dictionary class parent: '+DictionaryClassParent);
  1934. if Full then
  1935. begin
  1936. L.Add('Include interface code: '+CodeInfo(IncludeInterfaceCode));
  1937. L.Add('Include implementation code: '+CodeInfo(IncludeImplementationCode));
  1938. end;
  1939. L.Add('Base Options: '+BaseConversionOptionsToStr(BaseOptions));
  1940. end;
  1941. procedure TBaseWebIDLToPas.AddOptionsToHeader;
  1942. Var
  1943. L: TStrings;
  1944. begin
  1945. L:=TStringList.Create;
  1946. try
  1947. L.Add('Automatically generated file by '+ClassName+' on '+FormatDateTime('yyyy-mm-dd hh:nn:ss',Now));
  1948. L.Add('');
  1949. GetOptions(L,false);
  1950. Comment(L);
  1951. finally
  1952. L.Free;
  1953. end;
  1954. end;
  1955. procedure TBaseWebIDLToPas.WriteIncludeInterfaceCode;
  1956. Var
  1957. S: String;
  1958. begin
  1959. For S in IncludeInterfaceCode do
  1960. Addln(S);
  1961. end;
  1962. procedure TBaseWebIDLToPas.WritePascal;
  1963. var
  1964. i: Integer;
  1965. Line: String;
  1966. aList : TIDLDefinitionList;
  1967. begin
  1968. CreateUnitClause;
  1969. CreateHeader;
  1970. if coAddOptionsToHeader in BaseOptions then
  1971. AddOptionsToHeader;
  1972. EnsureSection(csType);
  1973. Indent;
  1974. DoLog('Writing interface section.');
  1975. DoLog('Generating forward class/interface definitions');
  1976. WriteForwardClassDefs(Context.Definitions);
  1977. DoLog('Generating enumerated definitions');
  1978. WriteEnumDefs(Context.Definitions);
  1979. // Callbacks
  1980. DoLog('Generating types definitions');
  1981. WriteFunctionImplicitTypes(Context.Definitions);
  1982. DoLog('Generating typedefs and callback definitions');
  1983. WriteTypeDefsAndCallbacks(Context.Definitions);
  1984. DoLog('Generating dictionary definitions');
  1985. aList:=Context.GetDictionariesTopologically;
  1986. try
  1987. WriteDictionaryDefs(aList);
  1988. finally
  1989. aList.Free;
  1990. end;
  1991. DoLog('Generating interface definitions');
  1992. aList:=Context.GetInterfacesTopologically;
  1993. try
  1994. WriteInterfaceDefs(aList);
  1995. finally
  1996. aList.Free;
  1997. end;
  1998. DoLog('Generating namespace definitions');
  1999. WriteNamespaceDefs(Context.Definitions);
  2000. Undent;
  2001. WriteGlobalVars;
  2002. WriteIncludeInterfaceCode;
  2003. Addln('');
  2004. AddLn('implementation');
  2005. WriteImplementation;
  2006. AddLn('end.');
  2007. if OutputStream<>nil then
  2008. begin
  2009. for i:=0 to Source.Count-1 do
  2010. begin
  2011. Line:=Source[i]+sLineBreak;
  2012. OutputStream.Write(Line[1],length(Line));
  2013. end;
  2014. end
  2015. else
  2016. Source.SaveToFile(OutputFileName);
  2017. end;
  2018. function TBaseWebIDLToPas.CreatePasData(aName: String; aNativetype: TPascalNativeType; D: TIDLBaseObject; Escape: boolean
  2019. ): TPasData;
  2020. begin
  2021. if Escape then
  2022. aName:=EscapeKeyWord(aName);
  2023. Result:=PasDataClass.Create(aName,D);
  2024. Result.NativeType:=aNativeType;
  2025. FPasNameList.Add(Result);
  2026. end;
  2027. function TBaseWebIDLToPas.ClonePasData(Data: TPasData; OwnerDef: TIDLBaseObject
  2028. ): TPasData;
  2029. begin
  2030. Result:=PasDataClass.Create(Data.PasName,OwnerDef);
  2031. Result.Resolved:=Data.Resolved;
  2032. Result.NativeType:=Data.NativeType;
  2033. Result.Used:=Data.Used;
  2034. FPasNameList.Add(Result);
  2035. end;
  2036. function TBaseWebIDLToPas.AllocateInterfacePasName(D: TIDLInterfaceDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2037. var
  2038. CN : String;
  2039. begin
  2040. if (ParentName='') then ; // Silence compiler warning
  2041. CN:=D.Name;
  2042. if CN='' then
  2043. raise EConvertError.Create('[20220725184324] at '+GetDefPos(D));
  2044. CN:=ClassPrefix+CN+ClassSuffix;
  2045. if D.Data=Nil then
  2046. D.Data:=CreatePasData(CN,ntObject,D,true);
  2047. if Recurse then
  2048. AllocatePasNames(D.Members,D.Name);
  2049. Result:=TPasData(D.Data);
  2050. end;
  2051. function TBaseWebIDLToPas.AllocateNamespacePasName(D: TIDLNameSpaceDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2052. var
  2053. CN : String;
  2054. begin
  2055. if (ParentName='') then ; // Silence compiler warning
  2056. CN:=D.Name;
  2057. if CN='' then
  2058. raise EConvertError.Create('[20220725184324] at '+GetDefPos(D));
  2059. CN:=ClassPrefix+CN+ClassSuffix;
  2060. if D.Data=Nil then
  2061. D.Data:=CreatePasData(CN,ntObject,D,true);
  2062. if Recurse then
  2063. AllocatePasNames(D.Members,D.Name);
  2064. Result:=TPasData(D.Data);
  2065. end;
  2066. function TBaseWebIDLToPas.AllocateDictionaryPasName(D: TIDLDictionaryDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2067. var
  2068. CN : String;
  2069. begin
  2070. if (ParentName='') then ; // Silence compiler warning
  2071. CN:=D.Name;
  2072. if CN='' then
  2073. raise EConvertError.Create('[20220725184410] at '+GetDefPos(D));
  2074. if coDictionaryAsClass in BaseOptions then
  2075. CN:=ClassPrefix+CN+ClassSuffix;
  2076. if D.Data=nil then
  2077. D.Data:=CreatePasData(EscapeKeyWord(CN),ntObject,D,true);
  2078. if Recurse then
  2079. AllocatePasNames(D.Members,D.Name);
  2080. Result:=TPasData(D.Data);
  2081. end;
  2082. Function ConcatNames(const ParentName,CN : string) : string;
  2083. begin
  2084. Result:=CN;
  2085. if (Result<>'') and (ParentName<>'') then
  2086. Result:='_'+Result;
  2087. Result:=ParentName+Result;
  2088. end;
  2089. function TBaseWebIDLToPas.AllocateSequencePasName(D: TIDLSequenceTypeDefDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2090. var
  2091. CN : String;
  2092. sDef : TIDLDefinition;
  2093. begin
  2094. Result:=Nil;
  2095. CN:=D.Name;
  2096. if Recurse then
  2097. begin
  2098. // Should be passed in first
  2099. AllocatePasName(D.ElementType,ConcatNames(ParentName,CN),True);
  2100. if CN='' then
  2101. CN:=ConstructSequenceTypeName(TIDLSequenceTypeDefDefinition(D),False)
  2102. else
  2103. CN:=ArrayPrefix+CN+ArraySuffix;
  2104. if D.Data=Nil then
  2105. begin
  2106. sDef:=FindGlobalDef(CN);
  2107. if (SDef=Nil) or (sDef.Data=Nil) then
  2108. D.Data:=CreatePasData(EscapeKeyWord(CN),ntArray,D,true)
  2109. else
  2110. D.Data:=ClonePasData(TPasData(sDef.Data),D);
  2111. end;
  2112. end;
  2113. Result:=TPasData(D.Data);
  2114. end;
  2115. function TBaseWebIDLToPas.AllocatePromisePasName(D: TIDLPromiseTypeDefDefinition; ParentName: String; Recurse: Boolean): TPasData;
  2116. var
  2117. CN : String;
  2118. sDef : TIDLDefinition;
  2119. begin
  2120. Result:=Nil;
  2121. CN:=D.Name;
  2122. if CN='' then
  2123. CN:='IJSPromise';
  2124. if D.Data=Nil then
  2125. begin
  2126. sDef:=FindGlobalDef(CN);
  2127. if (SDef=Nil) or (sDef.Data=Nil) then
  2128. D.Data:=CreatePasData(EscapeKeyWord(CN),ntArray,D,true)
  2129. else
  2130. D.Data:=ClonePasData(TPasData(sDef.Data),D);
  2131. end;
  2132. if Recurse then
  2133. AllocatePasName(D.ReturnType,ConcatNames(ParentName,CN+'Result'),True);
  2134. Result:=TPasData(D.Data);
  2135. end;
  2136. function TBaseWebIDLToPas.AllocateDictionaryMemberPasName(D: TIDLDictionaryMemberDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2137. Var
  2138. CN: String;
  2139. begin
  2140. Result:=Nil;
  2141. CN:=D.Name;
  2142. CN:=StringReplace(CN,'-','_',[rfReplaceAll]);
  2143. if (D.Data=Nil) then
  2144. D.Data:=CreatePasData(EscapeKeyWord(CN),ntNone,D,true);
  2145. Result:=TPasData(D.Data);
  2146. if Recurse then
  2147. AllocatePasName(D.MemberType,ConcatNames(ParentName,D.Name),True);
  2148. end;
  2149. function TBaseWebIDLToPas.AllocateArgumentPasName(D: TIDLArgumentDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2150. Var
  2151. CN: String;
  2152. begin
  2153. CN:=D.Name;
  2154. if D.Data=Nil then
  2155. D.Data:=CreatePasData(CN,ntNone,D,true);
  2156. if Recurse then
  2157. begin
  2158. AllocatePasName(D.ArgumentType,ConcatNames(ParentName,D.Name),True);
  2159. end;
  2160. Result:=TPasData(D.Data);
  2161. end;
  2162. function TBaseWebIDLToPas.AllocateUnionPasName(D: TIDLUnionTypeDefDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2163. var
  2164. CN: String;
  2165. sDef : TIDLDefinition;
  2166. begin
  2167. CN:=D.Name;
  2168. // This happens when there is an inline type declaration in a function definition.
  2169. if CN='' then
  2170. CN:=TypePrefix+ParentName+'_Type'
  2171. else
  2172. CN:=TypePrefix+CN;
  2173. sDef:=FindGlobalDef(CN);
  2174. if (SDef=Nil) or (sDef.Data=Nil) then
  2175. Result:=CreatePasData(EscapeKeyWord(CN),ntVariant,D,true)
  2176. else
  2177. Result:=ClonePasData(TPasData(sDef.Data),D);
  2178. D.Data:=Result;
  2179. If Recurse then
  2180. AllocatePasNames((D as TIDLUnionTypeDefDefinition).Union,CN)
  2181. end;
  2182. function TBaseWebIDLToPas.AllocateMapLikePasName(D: TIDLMapLikeDefinition; ParentName: String; Recurse: Boolean): TPasData;
  2183. Var
  2184. CN: String;
  2185. begin
  2186. CN:=D.Name;
  2187. if CN='' then
  2188. CN:=ParentName+'Type';
  2189. CN:=TypePrefix+CN;
  2190. if D.Data=Nil then
  2191. D.Data:=CreatePasData(CN,ntNone,D,true);
  2192. Result:=TPasData(D.Data);
  2193. if Recurse then
  2194. begin
  2195. if assigned(D.KeyType) then
  2196. AllocatePasName(D.KeyType,ConcatNames(ParentName,D.Name),True);
  2197. if assigned(D.ValueType) then
  2198. AllocatePasName(D.ValueType,ConcatNames(ParentName,D.Name),True);
  2199. end;
  2200. end;
  2201. function TBaseWebIDLToPas.AllocateEnumeratedPasName(D: TIDLEnumDefinition; ParentName: String; Recurse: Boolean): TPasData;
  2202. var
  2203. CN : String;
  2204. begin
  2205. if (ParentName='') and Recurse then ; // Silence compiler warning
  2206. CN:=D.Name;
  2207. Result:=TPasData(D.Data);
  2208. if Result=Nil then
  2209. begin
  2210. CN:=TypePrefix+CN;
  2211. Result:=CreatePasData(CN,ntUnicodeString,D,true);
  2212. D.Data:=Result;
  2213. end;
  2214. end;
  2215. function TBaseWebIDLToPas.AllocateCallbackPasName(D: TIDLCallBackDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2216. Var
  2217. CN: String;
  2218. begin
  2219. CN:=D.Name;
  2220. if CN='' then
  2221. CN:=ParentName+'Type';
  2222. CN:=TypePrefix+CN;
  2223. if D.Data=nil then
  2224. D.Data:=CreatePasData(CN,ntMethod,D,true);
  2225. Result:=TPasData(D.Data);
  2226. if Recurse then
  2227. AllocatePasName(D.FunctionDef,'',True)
  2228. end;
  2229. function TBaseWebIDLToPas.AllocateAttributePasName(aParent: TIDLStructuredDefinition; D: TIDLAttributeDefinition;
  2230. ParentName: String; Recurse: Boolean): TPasData;
  2231. Var
  2232. CN: String;
  2233. begin
  2234. if (aParent=Nil) then ; // Silence compiler warning
  2235. CN:=D.Name;
  2236. if CN='' then
  2237. CN:=ParentName+'Type';
  2238. //CN:=TypePrefix+CN;
  2239. if D.Data=Nil then
  2240. D.Data:=CreatePasData(CN,ntNone,D,true);
  2241. Result:=TPasData(D.Data);
  2242. if Recurse and assigned(D.AttributeType) then
  2243. AllocatePasName(D.AttributeType,Concatnames(ParentName,D.Name),True);
  2244. end;
  2245. function TBaseWebIDLToPas.AllocateFunctionPasName(D: TIDLFunctionDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2246. Var
  2247. CN : String;
  2248. begin
  2249. CN:=D.name;
  2250. if CN='' then
  2251. begin
  2252. if foGetter in D.options then
  2253. CN:=SDefaultGetterName
  2254. else if foSetter in D.options then
  2255. CN:=SDefaultSetterName
  2256. else
  2257. CN:=ParentName+'Type';
  2258. end;
  2259. if (D.Data=Nil) then
  2260. D.Data:=CreatePasData(CN,ntNone,D,true);
  2261. Result:=TPasData(D.Data);
  2262. if Recurse then
  2263. begin
  2264. AllocatePasNames(D.Arguments,ConcatNames(ParentName,D.Name));
  2265. if Assigned(D.ReturnType) then
  2266. AllocatePasName(D.ReturnType,ConcatNames(ParentName,D.Name),True);
  2267. end;
  2268. end;
  2269. function TBaseWebIDLToPas.GetAliasPascalType(D: TIDLDefinition; out PascalTypeName: string): TPascalNativeType;
  2270. var
  2271. NativeName: TIDLString;
  2272. begin
  2273. NativeName:=D.Name;
  2274. if (NativeName='') and (D is TIDLTypeDefinition) then
  2275. NativeName:=TIDLTypeDefinition(D).GetJSTypeName;
  2276. Result:=GetAliasPascalType(NativeName,PascalTypeName);
  2277. end;
  2278. function TBaseWebIDLToPas.GetAliasPascalType(aNativeTypeName : String; out PascalTypeName: string): TPascalNativeType;
  2279. var
  2280. NT,S : String;
  2281. P,I : Integer;
  2282. begin
  2283. result:=ntunknown;
  2284. S:=TypeAliases.Values[aNativeTypeName];
  2285. if S='' then
  2286. exit;
  2287. Result:=ntObject;
  2288. P:=Pos(',',S);
  2289. if P>0 then
  2290. begin
  2291. NT:=Copy(S,P+1);
  2292. if LowerCase(copy(nt,1,2))<>'nt' then
  2293. nt:='nt'+nt;
  2294. I:=GetEnumValue(TypeInfo(TPascalNativeType),nt);
  2295. if (I<>-1) then
  2296. Result:=TPascalNativeType(I)
  2297. else
  2298. begin
  2299. if Verbose then
  2300. DoLog('Warning: unknown native type in alias %s: %s',[S,NT]);
  2301. SetLength(S,P-1);
  2302. end;
  2303. end;
  2304. PascalTypeName:=S;
  2305. end;
  2306. function TBaseWebIDLToPas.AllocateConstPasName(D: TIDLConstDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2307. var
  2308. PN,CN,TN : String;
  2309. aNativeType : TPascalNativeType;
  2310. begin
  2311. if (ParentName='') and Recurse then ; // Silence compiler warning
  2312. CN:=D.Name;
  2313. TN:=D.TypeName;
  2314. aNativeType:=GetPascalTypeAndName(TN,PN);
  2315. if aNativeType=ntUnknown then
  2316. aNativeType:=GetAliasPascalType(D,PN);
  2317. if D.Data=Nil then
  2318. D.Data:=CreatePasData(CN,aNativeType,D,true);
  2319. Result:=TPasData(D.Data);
  2320. end;
  2321. function TBaseWebIDLToPas.AllocateDefaultPasName(D: TIDLDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2322. var
  2323. TN,CN,PN : String;
  2324. aNativeType : TPascalNativeType;
  2325. IsTypeDef,IsNamedTypeDef : Boolean;
  2326. gDef : TIDLDefinition;
  2327. begin
  2328. if (ParentName='') and Recurse then ; // Silence compiler warning
  2329. {
  2330. We are actually doing 2 things. We allocate a pascal name for an identifier,
  2331. and we determine the native pascal type of the identifier, if possible.
  2332. }
  2333. isTypeDef:=(D is TIDLTypeDefDefinition);
  2334. isNamedTypeDef:=IsTypedef and (TIDLTypeDefDefinition(D).IsTypeDef);
  2335. if isNamedTypeDef then
  2336. CN:=D.Name
  2337. else
  2338. CN:='';
  2339. if IsTypeDef then
  2340. TN:=TIDLTypeDefDefinition(D).TypeName
  2341. else
  2342. TN:=CN;
  2343. aNativeType:=GetPascalTypeAndName(TN,PN);
  2344. if aNativeType=ntUnknown then
  2345. aNativeType:=GetAliasPascalType(D,PN);
  2346. // We have a name
  2347. if CN<>'' then
  2348. CN:=TypePrefix+CN
  2349. else if (aNativeType<>ntUnknown) then
  2350. // Reuse native name
  2351. CN:=PN
  2352. else
  2353. // Not native, not known:
  2354. // If it is a globally defined type, reuse the name
  2355. begin
  2356. gDef:=FindGlobalDef(TN);
  2357. if (gDef<>nil) then
  2358. begin
  2359. if Not assigned(gDef.Data) then
  2360. AllocatePasName(gDef,'',True);
  2361. // It should have the type prefix...
  2362. CN:=GetPasName(gDef)
  2363. end
  2364. else
  2365. begin
  2366. // if we have a type alias, use that.
  2367. CN:=TypeAliases.Values[TN];
  2368. if CN='' then
  2369. begin
  2370. CN:=ParentName+'Type';
  2371. CN:=TypePrefix+CN;
  2372. end;
  2373. end;
  2374. end;
  2375. if (CN='') and not (aNativeType in [ntUnknown,ntNone, ntError]) then
  2376. Raise Exception.CreateFmt('No name for %s (TN: %s, Parent : %s)',[D.Name,TN,ParentName]);
  2377. if D.Data=Nil then
  2378. D.Data:=CreatePasData(CN,aNativeType,D,true);
  2379. Result:=TPasData(D.Data);
  2380. end;
  2381. function TBaseWebIDLToPas.AllocatePasName(D: TIDLDefinition; ParentName: String; Recurse : Boolean): TPasData;
  2382. {
  2383. Here we make sure every definition for which code will be generated has a pascal (type) name.
  2384. }
  2385. Var
  2386. CN: String;
  2387. begin
  2388. Result:=Nil;
  2389. //writeln('TBaseWebIDLToPas.AllocatePasName ',ParentName,'.',D.Name,':',D.ClassName);
  2390. if D Is TIDLInterfaceDefinition then
  2391. Result:=AllocateInterfacePasName(TIDLInterfaceDefinition(D),ParentName,Recurse)
  2392. else if D Is TIDLNamespaceDefinition then
  2393. Result:=AllocateNameSpacePasName(TIDLNamespaceDefinition(D),ParentName,Recurse)
  2394. else if D Is TIDLDictionaryDefinition then
  2395. Result:=AllocateDictionaryPasName(TIDLDictionaryDefinition(D),ParentName,Recurse)
  2396. else if D Is TIDLDictionaryMemberDefinition then
  2397. Result:=AllocateDictionaryMemberPasName(TIDLDictionaryMemberDefinition(D),ParentName,Recurse)
  2398. else if (D Is TIDLSequenceTypeDefDefinition) then
  2399. Result:=AllocateSequencePasName(TIDLSequenceTypeDefDefinition(D),ParentName,Recurse)
  2400. else if (D Is TIDLPromiseTypeDefDefinition) then
  2401. Result:=AllocatePromisePasName(TIDLPromiseTypeDefDefinition(D),ParentName,Recurse)
  2402. else if D Is TIDLArgumentDefinition then
  2403. Result:=AllocateArgumentPasName(TIDLArgumentDefinition(D),ParentName,Recurse)
  2404. else if D Is TIDLUnionTypeDefDefinition then
  2405. Result:=AllocateUnionPasName(TIDLUnionTypeDefDefinition(D),ParentName,Recurse)
  2406. else if D Is TIDLMapLikeDefinition then
  2407. Result:=AllocateMapLikePasName(TIDLMapLikeDefinition(D),ParentName,Recurse)
  2408. else if D Is TIDLCallBackDefinition then
  2409. Result:=AllocateCallBackPasName(TIDLCallBackDefinition(D),ParentName,Recurse)
  2410. else if D is TIDLAttributeDefinition then
  2411. Result:=AllocateAttributePasName(D.Parent as TIDLStructuredDefinition,TIDLAttributeDefinition(D),ParentName,Recurse)
  2412. else if D is TIDLFunctionDefinition then
  2413. Result:=AllocateFunctionPasName(TIDLFunctionDefinition(D),ParentName,Recurse)
  2414. else if D is TIDLEnumDefinition then
  2415. Result:=AllocateEnumeratedPasName(TIDLEnumDefinition(D),ParentName,Recurse)
  2416. else if D is TIDLConstDefinition then
  2417. Result:=AllocateConstPasName(TIDLConstDefinition(D),ParentName,Recurse)
  2418. else
  2419. Result:=AllocateDefaultPasName(D,ParentName,Recurse);
  2420. if Verbose and Assigned(Result) and (Result.PasName<>D.Name) then
  2421. begin
  2422. CN:=D.Name;
  2423. if CN='' then
  2424. CN:='<anonymous>';
  2425. if (ParentName<>'') then
  2426. CN:=ParentName+'.'+CN;
  2427. if Verbose then
  2428. DoLog('Renamed %s to %s at %s',[CN,Result.PasName,GetPasDataPos(Result)]);
  2429. end;
  2430. end;
  2431. procedure TBaseWebIDLToPas.AddGlobalJSIdentifier(D: TIDLDefinition);
  2432. function IsPartial : Boolean; inline;
  2433. begin
  2434. Result:=(D is TIDLStructuredDefinition) and (TIDLStructuredDefinition(D).IsPartial);
  2435. end;
  2436. function IsInclude : Boolean; inline;
  2437. begin
  2438. Result:=(D is TIDLIncludesDefinition);
  2439. end;
  2440. var
  2441. Old: TIDLDefinition;
  2442. begin
  2443. if (not (IsPartial or IsInclude)) then
  2444. begin
  2445. Old:=FindGlobalDef(D.Name);
  2446. if (Old<>nil) then
  2447. raise EWebIDLParser.Create('Duplicate identifier '+D.Name+' at '+GetDefPos(D)+' and '+GetDefPos(Old)+' (20220718185400)');
  2448. // AllocatePasName(D,'',False);
  2449. FGlobalDefs.Add(D.Name,D);
  2450. end
  2451. end;
  2452. procedure TBaseWebIDLToPas.ResolveParentInterfaces(aList: TIDLDefinitionList);
  2453. var
  2454. D: TIDLDefinition;
  2455. begin
  2456. For D in aList do
  2457. if D is TIDLInterfaceDefinition then
  2458. ResolveParentInterface(TIDLInterfaceDefinition(D))
  2459. else if D is TIDLDictionaryDefinition then
  2460. ResolveParentInterface(TIDLDictionaryDefinition(D));
  2461. end;
  2462. procedure TBaseWebIDLToPas.ResolveParentInterface(Intf: TIDLInterfaceDefinition
  2463. );
  2464. var
  2465. aDef: TIDLDefinition;
  2466. begin
  2467. if Intf.ParentInterface<>nil then exit;
  2468. if Intf.ParentName='' then exit;
  2469. aDef:=FindGlobalDef(Intf.ParentName);
  2470. if aDef is TIDLInterfaceDefinition then
  2471. Intf.ParentInterface:=TIDLInterfaceDefinition(aDef);
  2472. end;
  2473. procedure TBaseWebIDLToPas.ResolveParentInterface(Intf: TIDLDictionaryDefinition
  2474. );
  2475. var
  2476. aDef: TIDLDefinition;
  2477. begin
  2478. if Intf.ParentDictionary<>nil then exit;
  2479. if Intf.ParentName='' then exit;
  2480. aDef:=FindGlobalDef(Intf.ParentName);
  2481. if aDef is TIDLDictionaryDefinition then
  2482. Intf.ParentDictionary:=TIDLDictionaryDefinition(aDef);
  2483. end;
  2484. procedure TBaseWebIDLToPas.ResolveTypeDefs(aList: TIDLDefinitionList);
  2485. var
  2486. D: TIDLDefinition;
  2487. begin
  2488. For D in aList do
  2489. ResolveTypeDef(D);
  2490. end;
  2491. procedure TBaseWebIDLToPas.ResolveTypeDef(D: TIDLDefinition);
  2492. {
  2493. Here we make sure every type name is resolved to
  2494. - Either a Javascript base type
  2495. - a TIDLTypeDefinition instance.
  2496. In the latter case the resulting resolved TIDLTypeDefinition instance is stored in the Resolved field of a TPasData() element.
  2497. Conceivably, we can create type defs for all base types, so every type results in a TIDLTypeDefinition,
  2498. regardless of whether it is a base type or not.
  2499. }
  2500. procedure ResolveTypeName(const aTypeName: string);
  2501. var
  2502. Def: TIDLDefinition;
  2503. Data: TPasData;
  2504. begin
  2505. if (D.Data is TPasData) and (TPasData(D.Data).Resolved<>nil) then
  2506. exit;
  2507. Def:=FindGlobalDef(aTypeName);
  2508. if Def=nil then
  2509. begin
  2510. if (NameToWebIDLBaseType(aTypeName)=wibtNone)
  2511. and (TypeAliases.Values[aTypeName]='') then
  2512. raise EConvertError.Create('[20220725172231] type "'+aTypeName+'" of "'+D.Name+'" not found at '+GetDefPos(D));
  2513. end
  2514. else if not (Def is TIDLTypeDefinition) then
  2515. begin
  2516. raise EConvertError.Create('[20220725172231] type "'+D.ClassName+'" of "'+D.Name+'" is not a type at '+GetDefPos(D));
  2517. end
  2518. else
  2519. begin
  2520. if (D.Data=nil) then
  2521. begin
  2522. if not (Def.Data is TPasData) then
  2523. raise EConvertError.Create('[20240417092301] type "'+D.ClassName+'" of "'+D.Name+'" does not have pascal data associated at'+GetDefPos(D));
  2524. D.Data:=ClonePasData(TPasData(Def.Data),D);;
  2525. end;
  2526. Data:=TPasData(D.Data);
  2527. if Def<>D then
  2528. Data.Resolved:=Def as TIDLTypeDefinition;
  2529. //writeln('ResolveTypeName Resolved D=',D.Name,':',D.ClassName,' at ',GetDefPos(D),' Data.Resolved=',Def.Name,':',Def.ClassName,' at ',GetDefPos(Def));
  2530. end;
  2531. end;
  2532. var
  2533. DMD: TIDLDictionaryMemberDefinition;
  2534. IT: TIDLIterableDefinition;
  2535. SerializerD: TIDLSerializerDefinition;
  2536. FD: TIDLFunctionDefinition;
  2537. begin
  2538. if D=nil then exit;
  2539. if not ConvertDef(D) then
  2540. exit;
  2541. // writeln('TBaseWebIDLToPas.ResolveTypeDef START ',D.Name,':',D.ClassName,' at ',GetDefPos(D),' D=',hexstr(ptruint(D),sizeof(ptruint)*2));
  2542. if D Is TIDLInterfaceDefinition then
  2543. ResolveTypeDefs(TIDLInterfaceDefinition(D).Members)
  2544. else if D Is TIDLNamespaceDefinition then
  2545. ResolveTypeDefs(TIDLNamespaceDefinition(D).Members)
  2546. else if D Is TIDLDictionaryDefinition then
  2547. ResolveTypeDefs(TIDLDictionaryDefinition(D).Members)
  2548. else if D is TIDLIncludesDefinition then
  2549. //
  2550. else if D Is TIDLFunctionDefinition then
  2551. begin
  2552. FD:=TIDLFunctionDefinition(D);
  2553. ResolveTypeDefs(FD.Arguments);
  2554. ResolveTypeDef(FD.ReturnType);
  2555. end
  2556. else if D is TIDLAttributeDefinition then
  2557. ResolveTypeDef(TIDLAttributeDefinition(D).AttributeType)
  2558. else if D is TIDLArgumentDefinition then
  2559. ResolveTypeDef(TIDLArgumentDefinition(D).ArgumentType)
  2560. else if D is TIDLSequenceTypeDefDefinition then
  2561. ResolveTypeDef(TIDLSequenceTypeDefDefinition(D).ElementType)
  2562. else if D is TIDLPromiseTypeDefDefinition then
  2563. ResolveTypeDef(TIDLPromiseTypeDefDefinition(D).ReturnType)
  2564. else if D is TIDLMapLikeDefinition then
  2565. begin
  2566. ResolveTypeDef(TIDLMapLikeDefinition(D).KeyType);
  2567. ResolveTypeDef(TIDLMapLikeDefinition(D).ValueType);
  2568. end
  2569. else if D is TIDLTypeDefDefinition then
  2570. begin
  2571. ResolveTypeName(TIDLTypeDefDefinition(D).TypeName)
  2572. end
  2573. else if D is TIDLConstDefinition then
  2574. begin
  2575. if TIDLConstDefinition(D).TypeName<>'' then
  2576. ResolveTypeName(TIDLConstDefinition(D).TypeName);
  2577. end
  2578. else if D is TIDLSerializerDefinition then
  2579. begin
  2580. SerializerD:=TIDLSerializerDefinition(D);
  2581. ResolveTypeDef(SerializerD.SerializerFunction);
  2582. end
  2583. else if D is TIDLDictionaryMemberDefinition then
  2584. begin
  2585. DMD:=TIDLDictionaryMemberDefinition(D);
  2586. ResolveTypeDef(DMD.MemberType);
  2587. ResolveTypeDef(DMD.DefaultValue);
  2588. end
  2589. else if D is TIDLEnumDefinition then
  2590. //
  2591. else if D is TIDLCallBackDefinition then
  2592. ResolveTypeDef(TIDLCallBackDefinition(D).FunctionDef)
  2593. else if D is TIDLSetlikeDefinition then
  2594. ResolveTypeDef(TIDLSetlikeDefinition(D).ElementType)
  2595. else if D is TIDLImplementsOrIncludesDefinition then
  2596. //
  2597. else if D is TIDLIterableDefinition then
  2598. begin
  2599. IT:=TIDLIterableDefinition(D);
  2600. ResolveTypeDef(IT.ValueType);
  2601. ResolveTypeDef(IT.KeyType);
  2602. end
  2603. else {if Verbose then}
  2604. raise EConvertError.Create('[20220725172214] TBaseWebIDLToPas.ResolveTypeDef unknown '+D.Name+':'+D.ClassName+' at '+GetDefPos(D));
  2605. end;
  2606. procedure TBaseWebIDLToPas.RemoveInterfaceForwards(aList: TIDLDefinitionList);
  2607. Var
  2608. L: TFPObjectHashTable;
  2609. Procedure DeleteIntf(Def: TIDLInterfaceDefinition);
  2610. begin
  2611. if Verbose then
  2612. DoLog('removing interface '+Def.Name+' at '+GetDefPos(Def));
  2613. aList.Delete(Def);
  2614. end;
  2615. Procedure CheckDuplicateInterfaceDef(Def: TIDLInterfaceDefinition);
  2616. var
  2617. aName: UTF8String;
  2618. OldDef: TIDLInterfaceDefinition;
  2619. begin
  2620. if Def.IsPartial then exit;
  2621. aName:=Def.Name;
  2622. OldDef:=TIDLInterfaceDefinition(L.Items[aName]);
  2623. if OldDef=nil then
  2624. L.add(aName,Def)
  2625. else
  2626. begin
  2627. if OldDef.IsForward then
  2628. begin
  2629. L.Delete(OldDef.Name);
  2630. DeleteIntf(OldDef);
  2631. L.Add(aName,Def);
  2632. end
  2633. else if Def.IsForward then
  2634. DeleteIntf(Def)
  2635. else
  2636. raise EConvertError.Create('[20220725172236] Duplicate interface '+GetDefPos(Def)+' and '+GetDefPos(OldDef)+' (20220718184717)');
  2637. end;
  2638. end;
  2639. var
  2640. i: Integer;
  2641. begin
  2642. L:=TFPObjectHashTable.Create(False);
  2643. try
  2644. For i:=aList.Count-1 downto 0 do
  2645. if (aList[i] is TIDLInterfaceDefinition) then
  2646. CheckDuplicateInterfaceDef(TIDLInterfaceDefinition(aList[i]));
  2647. finally
  2648. L.Free;
  2649. end;
  2650. end;
  2651. function TBaseWebIDLToPas.ConvertDef(D: TIDLDefinition): Boolean;
  2652. var
  2653. AD : TIDLAttributeDefinition absolute D;
  2654. FD : TIDLFunctionDefinition;
  2655. A,RT : TIDLDefinition;
  2656. FAD : TIDLArgumentDefinition absolute A;
  2657. RN,N : String;
  2658. ANT : TPascalNativeType;
  2659. isChrome : Boolean;
  2660. begin
  2661. isChrome:=False;
  2662. Result:=(coChromeWindow in BaseOptions) or Not D.HasSimpleAttribute('ChromeOnly');
  2663. if not Result then
  2664. exit;
  2665. if Result and (coOnlyUsed in BaseOptions) then
  2666. if (D.Data is TPasData) and not TPasData(D.Data).Used then
  2667. exit(False);
  2668. end;
  2669. function TBaseWebIDLToPas.FindGlobalDef(const aName: UTF8String
  2670. ): TIDLDefinition;
  2671. begin
  2672. Result:=TIDLDefinition(FGlobalDefs.Items[aName]);
  2673. end;
  2674. function TBaseWebIDLToPas.GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean
  2675. ): string;
  2676. begin
  2677. Result:='('+IntToStr(Def.Line)+','+IntToStr(Def.Column)+')';
  2678. if not WithoutFile then
  2679. Result:=Def.SrcFile+Result;
  2680. end;
  2681. function TBaseWebIDLToPas.GetPasDataPos(D: TPasData; WithoutFile: boolean
  2682. ): string;
  2683. begin
  2684. Result:='('+IntToStr(D.Line)+','+IntToStr(D.Column)+')';
  2685. if not WithoutFile then
  2686. Result:=D.SrcFile+Result;
  2687. end;
  2688. procedure TBaseWebIDLToPas.SetTypeAliases(AValue: TStrings);
  2689. begin
  2690. if FTypeAliases.Equals(AValue) then Exit;
  2691. FTypeAliases.Assign(AValue);
  2692. TrimList(FTypeAliases);
  2693. end;
  2694. procedure TBaseWebIDLToPas.TrimList(List: TStrings);
  2695. var
  2696. i: Integer;
  2697. begin
  2698. for i:=List.Count-1 downto 0 do
  2699. if Trim(List[i])='' then
  2700. List.Delete(i);
  2701. end;
  2702. procedure TBaseWebIDLToPas.SetIncludeInterfaceCode(AValue: TStrings);
  2703. begin
  2704. if FIncludeInterfaceCode=AValue then Exit;
  2705. FIncludeInterfaceCode.Assign(AValue);
  2706. end;
  2707. procedure TBaseWebIDLToPas.SetOutputFileName(const AValue: String);
  2708. var
  2709. aName, Ext: String;
  2710. begin
  2711. if FOutputFileName=AValue then Exit;
  2712. FOutputFileName:=AValue;
  2713. if OutputUnitName='' then
  2714. begin
  2715. aName:=ExtractFileName(AValue);
  2716. Ext:=ExtractFileExt(AName);
  2717. if Ext<>'' then
  2718. aName:=LeftStr(aName,length(aName)-length(Ext));
  2719. OutputUnitName:=aName;
  2720. end;
  2721. end;
  2722. procedure TBaseWebIDLToPas.SetIncludeImplementationCode(AValue: TStrings);
  2723. begin
  2724. if FIncludeImplementationCode=AValue then Exit;
  2725. FIncludeImplementationCode.Assign(AValue);
  2726. end;
  2727. procedure TBaseWebIDLToPas.SetGlobalVars(const AValue: TStrings);
  2728. begin
  2729. if FGlobalVars.Equals(AValue) then Exit;
  2730. FGlobalVars.Assign(AValue);
  2731. TrimList(FGlobalVars);
  2732. end;
  2733. procedure TBaseWebIDLToPas.AllocatePasNames(aList: TIDLDefinitionList; ParentName: String = '');
  2734. var
  2735. D: TIDLDefinition;
  2736. begin
  2737. For D in aList do
  2738. AllocatePasName(D,ParentName,False);
  2739. For D in aList do
  2740. AllocatePasName(D,ParentName,True);
  2741. end;
  2742. function TBaseWebIDLToPas.CreateCallBackFromInterface(aDef: TIDLInterfaceDefinition): TIDLCallBackDefinition;
  2743. var
  2744. I,Idx,Count : Integer;
  2745. begin
  2746. if Verbose then
  2747. DoLog('Converting callback interface %s to callback',[aDef.Name]);
  2748. Count:=0;
  2749. For I:=0 to aDef.Members.Count-1 do
  2750. if (aDef.Member[I] is TIDLFunctionDefinition) then
  2751. begin
  2752. Idx:=I;
  2753. Inc(Count);
  2754. end;
  2755. if (Count<>1) then
  2756. Raise EWebIDLParser.CreateFmt('Callback Interface %s has wrong function member count',[aDef.Name]);
  2757. if not (aDef.Member[Idx] is TIDLFunctionDefinition) then
  2758. Raise EWebIDLParser.CreateFmt('Callback Interface %s member %s is not a function',[aDef.Name,aDef.Members[Idx].Name]);
  2759. Result:=TIDLCallBackDefinition(FContext.Add(TIDLCallBackDefinition,aDef.Name,aDef.SrcFile,aDef.Line,aDef.Column));
  2760. Result.FunctionDef:=TIDLFunctionDefinition(aDef.Members.Extract(aDef.Member[Idx]));
  2761. Result.FunctionDef.Name:=Result.Name;
  2762. Result.FunctionDef.Parent:=Result;
  2763. end;
  2764. procedure TBaseWebIDLToPas.ResolveCallbackInterfaces;
  2765. var
  2766. D : TIDLDefinition;
  2767. DI : TIDLInterfaceDefinition absolute D;
  2768. begin
  2769. For D In FContext.Definitions do
  2770. if (D is TIDLInterfaceDefinition) and DI.IsCallBack then
  2771. begin
  2772. CreateCallBackFromInterface(DI);
  2773. FContext.Definitions.Delete(D);
  2774. end;
  2775. end;
  2776. function TBaseWebIDLToPas.GetUsed(D: TIDLDefinition) : Boolean;
  2777. begin
  2778. Result:=False;
  2779. Result:=(not (D.Data is TPasData)) or TPasData(D.Data).Used;
  2780. end;
  2781. function TBaseWebIDLToPas.InUsedList(D: TIDLDefinition) : Boolean;
  2782. begin
  2783. Result:=FUsedDefs.Items[D.Name]<>Nil;
  2784. end;
  2785. function TBaseWebIDLToPas.MarkUsed(D: TIDLDefinition; ParentIsUsed : Boolean) : Boolean;
  2786. // Return true if the definition 'used' status was change to true
  2787. function DoMark : Boolean;
  2788. begin
  2789. Result:=False;
  2790. if (D.Data=nil) and not (D is TIDLTypeDefDefinition) then
  2791. begin
  2792. if Verbose then
  2793. DoLog('[202406021006] type "'+D.ClassName+'" of "'+D.Name+'" has no pascal name assigned, cannot check used');
  2794. Exit;
  2795. end;
  2796. if GetUsed(D) then
  2797. exit;
  2798. if ParentIsUsed or InUsedList(D) then
  2799. begin
  2800. // Writeln('Marking ',D.GetNamePath,' as used');
  2801. TPasData(D.Data).Used:=True;
  2802. Result:=True;
  2803. end;
  2804. end;
  2805. function MarkAlias(const aTypeName: string) : Boolean;
  2806. var
  2807. lDef: TIDLDefinition;
  2808. begin
  2809. lDef:=FindGlobalDef(aTypeName);
  2810. Result:=(lDef<>nil) and MarkUsed(lDef,True);
  2811. end;
  2812. var
  2813. DMD: TIDLDictionaryMemberDefinition;
  2814. IT: TIDLIterableDefinition;
  2815. SerializerD: TIDLSerializerDefinition;
  2816. FD: TIDLFunctionDefinition;
  2817. P : TIDLInterfaceDefinition;
  2818. I : Integer;
  2819. begin
  2820. Result:=False;
  2821. if D=nil then exit;
  2822. // Writeln('Checking ',D.GetNamePath,' for used');
  2823. if not DoMark then
  2824. exit;
  2825. // Mark sub-classes as used
  2826. if D Is TIDLInterfaceDefinition then
  2827. begin
  2828. MarkUsedDefinitions(TIDLInterfaceDefinition(D).Members,True);
  2829. P:=TIDLInterfaceDefinition(D).ParentInterface;
  2830. While Assigned(P) do
  2831. begin
  2832. MarkUsed(P,True);
  2833. P:=P.ParentInterface;
  2834. end;
  2835. P:=TIDLInterfaceDefinition(D);
  2836. For I:=0 to P.Partials.Count-1 do
  2837. MarkUsed(P.Partial[i],True);
  2838. end
  2839. else if D Is TIDLNamespaceDefinition then
  2840. begin
  2841. MarkUsedDefinitions(TIDLNamespaceDefinition(D).Members,True);
  2842. end
  2843. else if D Is TIDLDictionaryDefinition then
  2844. begin
  2845. MarkUsedDefinitions(TIDLDictionaryDefinition(D).Members,True);
  2846. MarkUsed(TIDLDictionaryDefinition(D).ParentDictionary,True);
  2847. end
  2848. else if D is TIDLIncludesDefinition then
  2849. begin
  2850. //
  2851. end
  2852. else if D Is TIDLFunctionDefinition then
  2853. begin
  2854. FD:=TIDLFunctionDefinition(D);
  2855. MarkUsedDefinitions(FD.Arguments,True);
  2856. MarkUsed(FD.ReturnType,True);
  2857. end
  2858. else if D Is TIDLUnionTypeDefDefinition then
  2859. MarkUsedDefinitions(TIDLUnionTypeDefDefinition(D).Union,True)
  2860. else if D is TIDLAttributeDefinition then
  2861. MarkUsed(TIDLAttributeDefinition(D).AttributeType,True)
  2862. else if D is TIDLArgumentDefinition then
  2863. MarkUsed(TIDLArgumentDefinition(D).ArgumentType,True)
  2864. else if D is TIDLSequenceTypeDefDefinition then
  2865. MarkUsed(TIDLSequenceTypeDefDefinition(D).ElementType,True)
  2866. else if D is TIDLPromiseTypeDefDefinition then
  2867. MarkUsed(TIDLPromiseTypeDefDefinition(D).ReturnType,True)
  2868. else if D is TIDLMapLikeDefinition then
  2869. begin
  2870. MarkUsed(TIDLMapLikeDefinition(D).KeyType,True);
  2871. MarkUsed(TIDLMapLikeDefinition(D).ValueType,True);
  2872. end
  2873. else if D is TIDLTypeDefDefinition then
  2874. begin
  2875. MarkAlias(TIDLTypeDefDefinition(D).TypeName)
  2876. end
  2877. else if D is TIDLConstDefinition then
  2878. begin
  2879. if TIDLConstDefinition(D).TypeName<>'' then
  2880. MarkAlias(TIDLConstDefinition(D).TypeName);
  2881. end
  2882. else if D is TIDLSerializerDefinition then
  2883. begin
  2884. SerializerD:=TIDLSerializerDefinition(D);
  2885. MarkUsed(SerializerD.SerializerFunction,True);
  2886. end
  2887. else if D is TIDLDictionaryMemberDefinition then
  2888. begin
  2889. DMD:=TIDLDictionaryMemberDefinition(D);
  2890. MarkUsed(DMD.MemberType,True);
  2891. // MarkUsed(DMD.DefaultValue,True);
  2892. end
  2893. else if D is TIDLEnumDefinition then
  2894. //
  2895. else if D is TIDLCallBackDefinition then
  2896. MarkUsed(TIDLCallBackDefinition(D).FunctionDef,True)
  2897. else if D is TIDLSetlikeDefinition then
  2898. MarkUsed(TIDLSetlikeDefinition(D).ElementType,True)
  2899. else if D is TIDLImplementsOrIncludesDefinition then
  2900. //
  2901. else if D is TIDLIterableDefinition then
  2902. begin
  2903. IT:=TIDLIterableDefinition(D);
  2904. MarkUsed(IT.ValueType,True);
  2905. MarkUsed(IT.KeyType,True);
  2906. end
  2907. else {if Verbose then}
  2908. raise EConvertError.Create('[20220725172214] TBaseWebIDLToPas.ResolveTypeDef unknown '+D.Name+':'+D.ClassName+' at '+GetDefPos(D));
  2909. end;
  2910. procedure TBaseWebIDLToPas.MarkUsedDefinitions(aList : TIDLDefinitionList; ParentIsUsed : Boolean);
  2911. var
  2912. D : TIDLDefinition;
  2913. begin
  2914. For D In aList do
  2915. begin
  2916. MarkUsed(D,ParentIsUsed);
  2917. end;
  2918. end;
  2919. Function TBaseWebIDLToPas.CheckChromeOnly(D : TIDLDefinition) : Boolean;
  2920. Function IsChromeOnly(D : TIDLDefinition) : boolean; inline;
  2921. begin
  2922. Result:=Assigned(D) and D.HasSimpleAttribute('ChromeOnly');
  2923. end;
  2924. function CheckAlias(const aTypeName: string) : Boolean;
  2925. var
  2926. lDef: TIDLDefinition;
  2927. begin
  2928. lDef:=FindGlobalDef(aTypeName);
  2929. Result:=(lDef<>nil) and CheckChromeOnly(lDef);
  2930. end;
  2931. var
  2932. AD : TIDLAttributeDefinition absolute D;
  2933. FD : TIDLFunctionDefinition;
  2934. A,RT : TIDLDefinition;
  2935. FAD : TIDLArgumentDefinition absolute A;
  2936. RN,N : String;
  2937. ANT : TPascalNativeType;
  2938. isChrome : Boolean;
  2939. SerializerD: TIDLSerializerDefinition;
  2940. DMD: TIDLDictionaryMemberDefinition;
  2941. IT : TIDLIterableDefinition;
  2942. begin
  2943. Result:=False;
  2944. isChrome:=False;
  2945. if (D=Nil) then
  2946. exit;
  2947. Result:=IsChromeOnly(D);
  2948. if Result then
  2949. exit;
  2950. if (D.Data is TPasData) then
  2951. begin
  2952. if TPasData(D.Data).ChromeChecked then exit;
  2953. TPasData(D.Data).ChromeChecked:=True;
  2954. end;
  2955. // Check sub definitions
  2956. if D Is TIDLInterfaceDefinition then
  2957. PropagateChromeOnly(TIDLInterfaceDefinition(D).Members)
  2958. else if D Is TIDLNamespaceDefinition then
  2959. PropagateChromeOnly(TIDLNamespaceDefinition(D).Members)
  2960. else if D Is TIDLDictionaryDefinition then
  2961. PropagateChromeOnly(TIDLDictionaryDefinition(D).Members)
  2962. else if D is TIDLIncludesDefinition then
  2963. //
  2964. else if D is TIDLArgumentDefinition then
  2965. begin
  2966. IsChrome:=CheckChromeOnly(TIDLArgumentDefinition(D).ArgumentType);
  2967. if IsChrome and Verbose then
  2968. DoLog('Marking argument %s as "ChromeOnly" because the argument type is marked "ChromeOnly"',[D.Name]);
  2969. end
  2970. else if D is TIDLSequenceTypeDefDefinition then
  2971. begin
  2972. IsChrome:=CheckChromeOnly(TIDLSequenceTypeDefDefinition(D).ElementType);
  2973. if IsChrome and Verbose then
  2974. DoLog('Marking sequence %s as "ChromeOnly" because the element type is marked "ChromeOnly"',[D.Name]);
  2975. end
  2976. else if D is TIDLPromiseTypeDefDefinition then
  2977. begin
  2978. IsChrome:=CheckChromeOnly(TIDLPromiseTypeDefDefinition(D).ReturnType);
  2979. if IsChrome and Verbose then
  2980. DoLog('Marking map %s as "ChromeOnly" because the promise result type is marked "ChromeOnly"',[D.Name]);
  2981. end
  2982. else if D is TIDLMapLikeDefinition then
  2983. begin
  2984. isChrome:=CheckChromeOnly(TIDLMapLikeDefinition(D).KeyType);
  2985. isChrome:=CheckChromeOnly(TIDLMapLikeDefinition(D).ValueType) or IsChrome;
  2986. if IsChrome and Verbose then
  2987. DoLog('Marking map %s as "ChromeOnly" because the map key or value type is marked "ChromeOnly"',[D.Name]);
  2988. end
  2989. else if D is TIDLTypeDefDefinition then
  2990. begin
  2991. CheckAlias(TIDLTypeDefDefinition(D).TypeName)
  2992. end
  2993. else if D is TIDLConstDefinition then
  2994. begin
  2995. if TIDLConstDefinition(D).TypeName<>'' then
  2996. IsChrome:=CheckAlias(TIDLConstDefinition(D).TypeName);
  2997. if IsChrome and Verbose then
  2998. DoLog('Marking const %s as "ChromeOnly" because the const type is marked "ChromeOnly"',[D.Name]);
  2999. end
  3000. else if D is TIDLSerializerDefinition then
  3001. begin
  3002. SerializerD:=TIDLSerializerDefinition(D);
  3003. IsChrome:=CheckChromeOnly(SerializerD.SerializerFunction);
  3004. if IsChrome and Verbose then
  3005. DoLog('Marking serializer %s as "ChromeOnly" because the function type is marked "ChromeOnly"',[D.Name]);
  3006. end
  3007. else if D is TIDLDictionaryMemberDefinition then
  3008. begin
  3009. DMD:=TIDLDictionaryMemberDefinition(D);
  3010. IsChrome:=CheckChromeOnly(DMD.MemberType);
  3011. IsChrome:=CheckChromeOnly(DMD.DefaultValue) or IsChrome;
  3012. if IsChrome and Verbose then
  3013. DoLog('Marking dictionary member %s as "ChromeOnly" because the member type or the default value is marked "ChromeOnly"',[D.Name]);
  3014. end
  3015. else if D is TIDLEnumDefinition then
  3016. //
  3017. else if D is TIDLCallBackDefinition then
  3018. begin
  3019. IsChrome:=CheckChromeOnly(TIDLCallBackDefinition(D).FunctionDef);
  3020. if IsChrome and Verbose then
  3021. DoLog('Marking callback definition %s as "ChromeOnly" because the function type is marked "ChromeOnly"',[D.Name]);
  3022. end
  3023. else if D is TIDLSetlikeDefinition then
  3024. begin
  3025. IsChrome:=CheckChromeOnly(TIDLSetlikeDefinition(D).ElementType);
  3026. if IsChrome and Verbose then
  3027. DoLog('Marking set %s as "ChromeOnly" because the member type is marked "ChromeOnly"',[D.Name]);
  3028. end
  3029. else if D is TIDLImplementsOrIncludesDefinition then
  3030. //
  3031. else if D is TIDLIterableDefinition then
  3032. begin
  3033. IT:=TIDLIterableDefinition(D);
  3034. IsChrome:=CheckChromeOnly(IT.ValueType);
  3035. IsChrome:=CheckChromeOnly(IT.KeyType) or IsChrome;
  3036. if IsChrome and Verbose then
  3037. DoLog('Marking iterable %s as "ChromeOnly" because the key or value type is marked "ChromeOnly"',[D.Name]);
  3038. end
  3039. else if (D is TIDLAttributeDefinition) and Assigned(AD.AttributeType) then
  3040. begin
  3041. ResolveTypeDef(AD.AttributeType);
  3042. RT:=GetResolvedType(AD.AttributeType,ANT,N,RN);
  3043. isChrome:=CheckChromeOnly(RT);
  3044. if isChrome and Verbose then
  3045. DoLog('Marking attribute %s as "ChromeOnly" because attribute type "%s" is marked "ChromeOnly"',[D.Name,N{AD.AttributeType.Name}]);
  3046. end
  3047. else if (D is TIDLFunctionDefinition) then
  3048. begin
  3049. FD:=TIDLFunctionDefinition(D);
  3050. RT:=GetResolvedType(FD.ReturnType,ANT,N,RN);
  3051. isChrome:=CheckChromeOnly(RT);
  3052. if isChrome and Verbose then
  3053. DoLog('Marking function %s as "ChromeOnly" because return type %s is marked "ChromeOnly"',[D.Name, RT.Name]);
  3054. For A in FD.Arguments do
  3055. begin
  3056. ResolveTypeDef(FAD.ArgumentType);
  3057. RT:=GetResolvedType(FAD.ArgumentType,ANT,N,RN);
  3058. if CheckChromeOnly(RT) then
  3059. begin
  3060. IsChrome:=True;
  3061. if Verbose then
  3062. DoLog('Marking function "%s" as "ChromeOnly" because argument "%s" (type "%s") is marked "ChromeOnly"',[D.Name,A.Name, RT.Name]);
  3063. end;
  3064. end;
  3065. end
  3066. else if (D is TIDLCallbackDefinition) then
  3067. begin
  3068. FD:=TIDLCallbackDefinition(D).FunctionDef;
  3069. RT:=GetResolvedType(FD.ReturnType,ANT,N,RN);
  3070. isChrome:=CheckChromeOnly(RT);
  3071. if isChrome and Verbose then
  3072. DoLog('Marking callback function %s as "ChromeOnly" because return type %s is marked "ChromeOnly"',[D.Name, RT.Name]);
  3073. For A in FD.Arguments do
  3074. begin
  3075. ResolveTypeDef(FAD.ArgumentType);
  3076. RT:=GetResolvedType(FAD.ArgumentType,Ant,N,RN);
  3077. if CheckChromeOnly(RT) then
  3078. begin
  3079. IsChrome:=True;
  3080. if Verbose then
  3081. DoLog('Marking callback function %s as "ChromeOnly" because argument "%s" (type "%s") is marked "ChromeOnly"',[D.Name,A.Name, RT.Name]);
  3082. end;
  3083. end;
  3084. end;
  3085. if IsChrome then
  3086. begin
  3087. D.Attributes.Add('ChromeOnly');
  3088. Result:=True;
  3089. end;
  3090. end;
  3091. procedure TBaseWebIDLToPas.PropagateChromeOnly(aList : TIDLDefinitionList);
  3092. var
  3093. D : TIDLDefinition;
  3094. begin
  3095. For D in aList do
  3096. CheckChromeOnly(D);
  3097. end;
  3098. procedure TBaseWebIDLToPas.ProcessDefinitions;
  3099. var
  3100. D : TIDLDefinition;
  3101. begin
  3102. DoLog('Resolving callback interfaces.');
  3103. ResolveCallbackInterfaces;
  3104. DoLog('Removing interface forwards.');
  3105. RemoveInterfaceForwards(FContext.Definitions);
  3106. DoLog('Appending partials to interfaces.');
  3107. FContext.AppendPartials;
  3108. DoLog('Appending includes to interfaces.');
  3109. FContext.AppendIncludes;
  3110. DoLog('Adding global identifiers.');
  3111. For D in FContext.Definitions do
  3112. if D.Name<>'' then
  3113. AddGlobalJSIdentifier(D);
  3114. DoLog('Allocating pascal names.');
  3115. AllocatePasNames(FContext.Definitions);
  3116. DoLog('Resolving parent interfaces.');
  3117. ResolveParentInterfaces(FContext.Definitions);
  3118. // We need to do this before ResolveTypeDefs, because ResolveTypeDefs uses ConvertDef()
  3119. if (coOnlyUsed in BaseOptions) then
  3120. begin
  3121. DoLog('Marking used type definitions.');
  3122. MarkUsedDefinitions(FContext.Definitions,False);
  3123. end;
  3124. if Not (coChromeWindow in BaseOptions) then
  3125. begin
  3126. DoLog('Propagating ChromeOnly attribute.');
  3127. PropagateChromeOnly(FContext.Definitions);
  3128. end;
  3129. DoLog('Resolving type definitions.');
  3130. ResolveTypeDefs(FContext.Definitions);
  3131. DoLog('Done processing definitions.');
  3132. end;
  3133. procedure TBaseWebIDLToPas.Execute;
  3134. begin
  3135. if Verbose then
  3136. begin
  3137. WriteOptions;
  3138. DoLog('');
  3139. end;
  3140. FContext:=CreateContext;
  3141. try
  3142. FContext.Aliases:=Self.TypeAliases;
  3143. Parse;
  3144. if Verbose then
  3145. DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
  3146. ProcessDefinitions;
  3147. if Verbose then
  3148. DoLog('Processed %d definitions.',[Context.Definitions.Count]);
  3149. WritePascal;
  3150. finally
  3151. FreeAndNil(FContext);
  3152. end;
  3153. end;
  3154. procedure TBaseWebIDLToPas.WriteOptions;
  3155. var
  3156. i: Integer;
  3157. L: TStringList;
  3158. begin
  3159. L:=TStringList.Create;
  3160. try
  3161. GetOptions(L,true);
  3162. for i:=0 to L.Count-1 do
  3163. DoLog(L[i]);
  3164. finally
  3165. L.Free;
  3166. end;
  3167. end;
  3168. procedure TBaseWebIDLToPas.SetUsedList(aList: TStrings);
  3169. var
  3170. S : String;
  3171. begin
  3172. if (aList=Nil) or (aList.Count=0) then
  3173. exit;
  3174. Include(FBaseOptions,coOnlyUsed);
  3175. if not Assigned(FUsedDefs) then
  3176. FUsedDefs:=TFPObjectHashTable.Create(False)
  3177. else
  3178. FUsedDefs.Clear;
  3179. // We just need to know if a name is in the list
  3180. For S in aList do
  3181. FUsedDefs.Add(S,Self);
  3182. end;
  3183. function TBaseWebIDLToPas.IsKeyWord(const S: String): Boolean;
  3184. Const
  3185. KW=';class;classname;finalization;function;initialization;procedure;';
  3186. begin
  3187. Result:=inherited IsKeyWord(S);
  3188. if Result then exit;
  3189. Result:=Pos(';'+lowercase(S)+';',KW)<>0;
  3190. end;
  3191. end.