123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401 |
- {
- This file is part of the Free Component Library
- WEBIDL to pascal code converter
- Copyright (c) 2018 by Michael Van Canneyt [email protected]
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit webidltopas;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, contnrs, WebIDLParser, WebIDLScanner, WebIDLDefs, pascodegen;
- Type
- { TWebIDLToPas }
- { TPasData }
- TPasData = Class(TObject)
- private
- FPasName: String;
- Public
- Constructor Create(APasName : String);
- Property PasName : String read FPasName;
- end;
- TConversionOption = (coDictionaryAsClass,coUseNativeTypeAliases,coExternalConst,coExpandUnionTypeArgs,coaddOptionsToheader);
- TConversionOptions = Set of TConversionOption;
- TWebIDLToPas = Class(TPascalCodeGenerator)
- private
- FClassPrefix: String;
- FClassSuffix: String;
- FContext: TWebIDLContext;
- FDictionaryClassParent: String;
- FFieldPrefix: String;
- FIncludeImplementationCode: TStrings;
- FIncludeInterfaceCode: TStrings;
- FInputFileName: String;
- FOptions: TConversionOptions;
- FOutputFileName: String;
- FTypeAliases: TStrings;
- FVerbose: Boolean;
- FWebIDLVersion: TWebIDLVersion;
- FPasNameList : TFPObjectList;
- FAutoTypes : TStrings;
- procedure SetIncludeImplementationCode(AValue: TStrings);
- procedure SetIncludeInterfaceCode(AValue: TStrings);
- procedure SetTypeAliases(AValue: TStrings);
- Protected
- procedure AddOptionsToHeader;
- Procedure Parse; virtual;
- Procedure WritePascal; virtual;
- function CreateParser(aContext: TWebIDLContext; S: TWebIDLScanner): TWebIDLParser; virtual;
- function CreateScanner(S: TStream): TWebIDLScanner;virtual;
- Function CreateContext : TWebIDLContext; virtual;
- Function BaseUnits : String; override;
- // Auxiliary routines
- procedure Getoptions(L: TStrings); virtual;
- procedure ProcessDefinitions; virtual;
- function CreatePasName(aName: String): TPasData;virtual;
- procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String='');virtual;
- Function AllocatePasName(D: TIDLDefinition; ParentName: String='') : TPasData;virtual;
- procedure EnsureUniqueNames(ML: TIDLDefinitionList);virtual;
- function WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer;virtual;
- function WriteAttributeImplicitTypes(aList: TIDLDefinitionList): Integer;virtual;
- function WriteDictionaryMemberImplicitTypes(aList: TIDLDefinitionList): Integer;virtual;
- function AddSequenceDef(ST: TIDLSequenceTypeDefDefinition): Boolean; virtual;
- function GetName(ADef: TIDLDefinition): String;virtual;
- function GetTypeName(Const aTypeName: String; ForTypeDef: Boolean=False): String;virtual;
- function GetTypeName(aTypeDef: TIDLTypeDefDefinition; ForTypeDef: Boolean=False): String;virtual;
- function CheckUnionTypeDefinition(D: TIDLDefinition): TIDLUnionTypeDefDefinition;virtual;
- procedure AddArgumentToOverloads(aList: TFPObjectlist; AName, ATypeName: String);virtual;
- procedure AddUnionOverloads(aList: TFPObjectlist; AName: String; UT: TIDLUnionTypeDefDefinition);virtual;
- procedure AddArgumentToOverloads(aList: TFPObjectlist; adef: TIDLArgumentDefinition);virtual;
- procedure AddOverloads(aList: TFPObjectlist; adef: TIDLFunctionDefinition; aIdx: Integer);virtual;
- function CloneNonPartialArgumentList(aList: TFPObjectlist; ADest: TFPObjectlist= Nil; AsPartial: Boolean=True): integer;virtual;
- function GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist;virtual;
- function GetArguments(aList: TIDLDefinitionList; ForceBrackets: Boolean): String;virtual;
- function HaveConsts(aList: TIDLDefinitionList): Boolean;virtual;
- // Actual code generation routines
- // Lists. Return the number of actually written defs.
- function WriteCallBackDefs(aList: TIDLDefinitionList): Integer; virtual;
- Function WriteDictionaryDefs(aList: TIDLDefinitionList) : Integer;virtual;
- Function WriteForwardClassDefs(aList: TIDLDefinitionList) : Integer;virtual;
- Function WriteInterfaceDefs(aList: TIDLDefinitionList) : Integer;virtual;
- Function WriteMethodDefs(aList: TIDLDefinitionList) : Integer;virtual;
- Function WriteTypeDefs(aList: TIDLDefinitionList) : Integer;virtual;
- Function WriteEnumDefs(aList: TIDLDefinitionList) : Integer;virtual;
- function WriteConsts(aList: TIDLDefinitionList): Integer;virtual;
- function WriteProperties(aList: TIDLDefinitionList): Integer;
- function WritePlainFields(aList: TIDLDefinitionList): Integer;virtual;
- function WriteDictionaryFields(aList: TIDLDefinitionList): Integer;virtual;
- function WritePrivateReadOnlyFields(aList: TIDLDefinitionList): Integer;virtual;
- // Actual definitions. Return true if a definition was written.
- Function WriteForwardClassDef(D: TIDLStructuredDefinition) : Boolean;virtual;
- function WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition): Boolean;virtual;
- function WriteFunctionDefinition(aDef: TIDLFunctionDefinition): Boolean;virtual;
- function WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean; virtual;
- function WriteRecordDef(aDef: TIDLRecordDefinition): Boolean; virtual;
- function WriteEnumDef(aDef: TIDLEnumDefinition): Boolean; virtual;
- function WriteDictionaryField(aField: TIDLDictionaryMemberDefinition): Boolean;virtual;
- Function WritePrivateReadOnlyField(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
- Function WriteField(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
- Function WriteReadonlyProperty(aAttr: TIDLAttributeDefinition) : Boolean;virtual;
- Function WriteConst(aConst: TIDLConstDefinition) : Boolean ;virtual;
- function WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean; virtual;
- function WriteDictionaryDef(aDict: TIDLDictionaryDefinition): Boolean; virtual;
- // Additional
- procedure WriteAliasTypeDef(aDef: TIDLTypeDefDefinition);virtual;
- procedure WritePromiseDef(aDef: TIDLPromiseTypeDefDefinition);virtual;
- procedure WriteSequenceDef(aDef: TIDLSequenceTypeDefDefinition);virtual;
- procedure WriteUnionDef(aDef: TIDLUnionTypeDefDefinition);virtual;
- // Extra interface/Implementation code.
- procedure WriteImplementation; virtual;
- procedure WriteIncludeInterfaceCode; virtual;
- Property Context : TWebIDLContext Read FContext;
- Public
- Constructor Create(Aowner : TComponent); override;
- Destructor Destroy; override;
- Procedure Execute;
- Published
- Property InputFileName : String Read FInputFileName Write FInputFileName;
- Property OutputFileName : String Read FOutputFileName Write FOutputFileName;
- Property Verbose : Boolean Read FVerbose Write FVerbose;
- Property FieldPrefix : String Read FFieldPrefix Write FFieldPrefix;
- Property ClassPrefix : String Read FClassPrefix Write FClassPrefix;
- Property ClassSuffix : String Read FClassSuffix Write FClassSuffix;
- Property Options : TConversionOptions Read FOptions Write FOptions;
- Property WebIDLVersion : TWebIDLVersion Read FWebIDLVersion Write FWebIDLVersion;
- Property TypeAliases : TStrings Read FTypeAliases Write SetTypeAliases;
- Property IncludeInterfaceCode : TStrings Read FIncludeInterfaceCode Write SetIncludeInterfaceCode;
- Property IncludeImplementationCode : TStrings Read FIncludeImplementationCode Write SetIncludeImplementationCode;
- Property DictionaryClassParent : String Read FDictionaryClassParent Write FDictionaryClassParent;
- end;
- implementation
- uses typinfo;
- { TPasData }
- constructor TPasData.Create(APasName: String);
- begin
- FPasName:=APasName;
- end;
- { TWebIDLToPas }
- function TWebIDLToPas.CreateContext: TWebIDLContext;
- begin
- Result:=TWebIDLContext.Create(True);
- end;
- function TWebIDLToPas.CreateScanner(S : TStream) : TWebIDLScanner;
- begin
- Result:=TWebIDLScanner.Create(S);
- end;
- function TWebIDLToPas.CreateParser(aContext : TWebIDLContext;S : TWebIDLScanner) : TWebIDLParser;
- begin
- Result:=TWebIDLParser.Create(aContext,S);
- Result.Version:=FWebIDLVersion;
- end;
- procedure TWebIDLToPas.Parse;
- Var
- F : TFileStream;
- S : TWebIDLScanner;
- P : TWebIDLParser;
- begin
- P:=Nil;
- F:=TFileStream.Create(InputFileName,fmOpenRead or fmShareDenyWrite);
- try
- S:=CreateScanner(F);
- P:=CreateParser(Context,S);
- P.Parse;
- finally
- P.Free;
- S.Free;
- F.Free;
- end;
- end;
- function TWebIDLToPas.GetName(ADef: TIDLDefinition): String;
- begin
- If Assigned(ADef) and (TObject(ADef.Data) is TPasData) then
- Result:=TPasData(ADef.Data).PasName
- else
- Result:=ADef.Name;
- end;
- function TWebIDLToPas.HaveConsts(aList: TIDLDefinitionList): Boolean;
- Var
- D : TIDLDefinition;
- begin
- Result:=False;
- For D in aList do
- if D is TIDLConstDefinition then
- Exit(True);
- end;
- function TWebIDLToPas.WritePrivateReadOnlyFields(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- A : TIDLAttributeDefinition absolute D;
- begin
- Result:=0;
- For D in aList do
- if (D is TIDLAttributeDefinition) then
- if (aoReadOnly in A.Options) then
- if WritePrivateReadOnlyField(A) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteProperties(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- A : TIDLAttributeDefinition absolute D;
- begin
- Result:=0;
- For D in aList do
- if (D is TIDLAttributeDefinition) then
- if (aoReadOnly in A.Options) then
- if WriteReadOnlyProperty(A) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteConst(aConst: TIDLConstDefinition): Boolean;
- Const
- ConstTypes : Array[TConstType] of String =
- ('Double','NativeInt','Boolean','JSValue','JSValue','JSValue','JSValue','String','JSValue','JSValue');
- Var
- S : String;
- begin
- Result:=True;
- // Consts cannot be strings
- if coExternalConst in Options then
- begin
- S:=ConstTypes[aConst.ConstType];
- Addln('%s : %s;',[GetName(aConst),S])
- end
- else
- begin
- S:=aConst.Value;
- if aConst.ConstType=ctInteger then
- S:=StringReplace(S,'0x','$',[]);
- Addln('%s = %s;',[GetName(aConst),S])
- end;
- end;
- function TWebIDLToPas.WriteConsts(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- begin
- EnsureSection(csConst);
- Indent;
- Result:=0;
- For D in aList do
- if D is TIDLConstDefinition then
- if WriteConst(D as TIDLConstDefinition) then
- Inc(Result);
- Undent;
- end;
- function TWebIDLToPas.WritePlainFields(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- A : TIDLAttributeDefinition absolute D;
- begin
- EnsureSection(csDeclaration);
- Indent;
- Result:=0;
- For D in aList do
- if D is TIDLAttributeDefinition then
- if Not (aoReadOnly in A.Options) then
- if WriteField(A) then
- Inc(Result);
- Undent;
- end;
- function TWebIDLToPas.WriteDictionaryField(
- aField: TIDLDictionaryMemberDefinition): Boolean;
- Var
- Def,N,TN : String;
- begin
- Result:=True;
- N:=GetName(aField);
- TN:=GetTypeName(aField.MemberType);
- if TN='record' then
- TN:='TJSObject';
- if SameText(N,TN) then
- N:='_'+N;
- Def:=Format('%s : %s;',[N,TN]);
- if (N<>aField.Name) then
- Def:=Def+Format('external name ''%s'';',[aField.Name]);
- AddLn(Def);
- end;
- function TWebIDLToPas.WriteDictionaryFields(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- M : TIDLDictionaryMemberDefinition absolute D;
- begin
- Indent;
- Result:=0;
- For D in aList do
- if D is TIDLDictionaryMemberDefinition then
- if WriteDictionaryField(M) then
- Inc(Result);
- Undent;
- end;
- function TWebIDLToPas.WriteMethodDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- FD : TIDLFunctionDefinition absolute D;
- begin
- Result:=0;
- for D in aList do
- if D is TIDLFunctionDefinition then
- if Not (foCallBack in FD.Options) then
- if WriteFunctionDefinition(FD) then
- Inc(Result);
- end;
- function TWebIDLToPas.AddSequenceDef(ST: TIDLSequenceTypeDefDefinition
- ): Boolean;
- var
- TN : String;
- begin
- TN:=GetTypeName(ST);
- Result:=FAutoTypes.IndexOf(TN)=-1;
- if Result then
- begin
- FAutoTypes.Add(TN);
- DoLog('Automatically adding %s sequence definition.',[TN]);
- AddLn('%s = Array of %s;',[TN,GetTypeName(ST.ElementType)]);
- ST.Data:=CreatePasName(TN);
- end;
- end;
- function TWebIDLToPas.WriteFunctionImplicitTypes(aList: TIDLDefinitionList): Integer;
- Var
- D,D2,D3 : TIDLDefinition;
- FD : TIDLFunctionDefinition absolute D;
- DA : TIDLArgumentDefinition absolute D2;
- UT : TIDLUnionTypeDefDefinition;
- begin
- Result:=0;
- for D in aList do
- if D is TIDLFunctionDefinition then
- if Not (foCallBack in FD.Options) then
- begin
- if (FD.ReturnType is TIDLSequenceTypeDefDefinition) then
- if AddSequenceDef(FD.ReturnType as TIDLSequenceTypeDefDefinition) then
- Inc(Result);
- For D2 in FD.Arguments do
- if (DA.ArgumentType is TIDLSequenceTypeDefDefinition) then
- begin
- if AddSequenceDef(DA.ArgumentType as TIDLSequenceTypeDefDefinition) then
- Inc(Result);
- end
- else
- begin
- UT:=CheckUnionTypeDefinition(DA.ArgumentType);
- if Assigned(UT) then
- For D3 in UT.Union do
- if (D3 is TIDLSequenceTypeDefDefinition) then
- if AddSequenceDef(D3 as TIDLSequenceTypeDefDefinition) then
- Inc(Result);
- end;
- end;
- if Result>0 then
- AddLn('');
- end;
- function TWebIDLToPas.WriteAttributeImplicitTypes(aList: TIDLDefinitionList
- ): Integer;
- Var
- D : TIDLDefinition;
- FA : TIDLAttributeDefinition absolute D;
- begin
- Result:=0;
- for D in aList do
- if D is TIDLAttributeDefinition then
- if (FA.AttributeType is TIDLSequenceTypeDefDefinition) then
- if AddSequenceDef(FA.AttributeType as TIDLSequenceTypeDefDefinition) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteDictionaryMemberImplicitTypes(
- aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- FD : TIDLDictionaryMemberDefinition absolute D;
- begin
- Result:=0;
- for D in aList do
- if D is TIDLDictionaryMemberDefinition then
- if (FD.MemberType is TIDLSequenceTypeDefDefinition) then
- if AddSequenceDef(FD.MemberType as TIDLSequenceTypeDefDefinition) then
- Inc(Result);
- end;
- procedure TWebIDLToPas.EnsureUniqueNames(ML : TIDLDefinitionList);
- Var
- L : TFPObjectHashTable;
- Procedure CheckRename(aD : TIDLDefinition);
- var
- I : integer;
- NOrig,N,N2 : String;
- isDup : Boolean;
- D2 : TIDLDefinition;
- begin
- NOrig:=GetName(aD);
- N:=LowerCase(NOrig);
- N2:=N;
- I:=0;
- isDup:=False;
- Repeat
- D2:=TIDLDefinition(L.Items[N2]);
- if (D2<>Nil) then
- // Overloads
- begin
- isDup:=((D2 is TIDLFunctionDefinition) and (ad is TIDLFunctionDefinition));
- if IsDup then
- D2:=Nil
- else
- begin
- inc(I);
- N2:=KeywordPrefix+N+KeywordSuffix;
- Norig:=KeywordPrefix+NOrig+KeywordSuffix;
- end;
- end;
- Until (D2=Nil);
- if (N<>N2) then
- begin
- N:=GetName(aD);
- DoLog('Renaming duplicate identifier (%s) %s to %s',[aD.ClassName,N,Norig]);
- // Original TPasName is in list, will be freed automatically
- aD.Data:=CreatePasName(NOrig);
- end;
- if not IsDup then
- L.Add(N2,aD);
- end;
- var
- D : TIDLDefinition;
- begin
- L:=TFPObjectHashTable.Create(False);
- try
- For D in ML Do
- if not (D is TIDLConstDefinition) then
- CheckRename(D);
- For D in ML Do
- if (D is TIDLConstDefinition) then
- CheckRename(D);
- finally
- L.Free;
- end;
- end;
- function TWebIDLToPas.WriteInterfaceDef(Intf: TIDLInterfaceDefinition): Boolean;
- Var
- CN,PN : String;
- Decl : String;
- ML : TIDLDefinitionList;
- begin
- Result:=True;
- ML:=TIDLDefinitionList.Create(Nil,False);
- try
- Intf.GetFullMemberList(ML);
- EnsureUniqueNames(ML);
- CN:=GetName(Intf);
- ClassHeader(CN);
- WriteFunctionImplicitTypes(ML);
- WriteAttributeImplicitTypes(ML);
- Decl:=Format('%s = class external name %s ',[CN,MakePascalString(Intf.Name,True)]);
- if Assigned(Intf.ParentInterface) then
- PN:=GetName(Intf.ParentInterface)
- else
- PN:=GetTypeName(Intf.ParentName);
- if PN<>'' then
- Decl:=Decl+Format(' (%s)',[PN]);
- AddLn(Decl);
- AddLn('Private');
- Indent;
- WritePrivateReadOnlyFields(ML);
- Undent;
- AddLn('Public');
- if HaveConsts(ML) then
- begin
- Indent;
- PushSection(csUnknown);
- WriteConsts(ML);
- PopSection;
- Undent;
- AddLn('Public');
- end;
- Indent;
- WritePlainFields(ML);
- WriteMethodDefs(ML);
- WriteProperties(ML);
- Undent;
- AddLn('end;');
- finally
- ML.Free;
- end;
- end;
- function TWebIDLToPas.WriteDictionaryDef(aDict: TIDLDictionaryDefinition
- ): Boolean;
- Var
- CN,CP : String;
- ML : TIDLDefinitionList;
- PD: TIDLDictionaryDefinition;
- begin
- Result:=True;
- ML:=TIDLDefinitionList.Create(Nil,False);
- try
- PD:=aDict;
- While PD<>Nil do
- begin
- PD.GetFullMemberList(ML);
- PD:=PD.ParentDictionary;
- end;
- CN:=GetName(aDict);
- CP:=DictionaryClassParent;
- if CP='' then
- CP:='TJSObject';
- ClassHeader(CN);
- WriteDictionaryMemberImplicitTypes(ML);
- if (coDictionaryAsClass in Options) then
- Addln('%s = class(%s)',[CN,CP])
- else
- Addln('%s = record',[CN]);
- WriteDictionaryFields(ML);
- AddLn('end;');
- finally
- ML.Free;
- end;
- end;
- constructor TWebIDLToPas.Create(Aowner: TComponent);
- begin
- inherited Create(Aowner);
- WebIDLVersion:=v2;
- FieldPrefix:='F';
- ClassPrefix:='T';
- ClassSuffix:='';
- Switches.Add('modeswitch externalclass');
- FTypeAliases:=TStringList.Create;
- FPasNameList:=TFPObjectList.Create(True);
- FAutoTypes:=TStringList.Create;
- FIncludeInterfaceCode:=TStringList.Create;
- FIncludeImplementationCode:=TStringList.Create;
- end;
- destructor TWebIDLToPas.Destroy;
- begin
- FreeAndNil(FIncludeInterfaceCode);
- FreeAndNil(FIncludeImplementationCode);
- FreeAndNil(FAutoTypes);
- FreeAndNil(FTypeAliases);
- FreeAndNil(FPasNameList);
- inherited Destroy;
- end;
- procedure TWebIDLToPas.WriteImplementation;
- Var
- S : String;
- begin
- Addln('');
- For S in FIncludeImplementationCode do
- Addln(S);
- Addln('');
- end;
- function TWebIDLToPas.GetTypeName(aTypeDef : TIDLTypeDefDefinition; ForTypeDef : Boolean = False): String;
- begin
- if ATypeDef is TIDLSequenceTypeDefDefinition then
- begin
- if Assigned(aTypeDef.Data) then
- Result:=GetName(aTypeDef)
- else
- begin
- Result:=GetTypeName(TIDLSequenceTypeDefDefinition(aTypeDef).ElementType,ForTypeDef);
- Result:='T'+Result+'DynArray';
- end
- end
- else
- Result:=GetTypeName(aTypeDef.TypeName,ForTypeDef);
- end;
- function TWebIDLToPas.GetTypeName(const aTypeName: String; ForTypeDef: Boolean
- ): String;
- Function UsePascalType(Const aPascalType : string) : String;
- begin
- if (coUseNativeTypeAliases in Options) and ForTypeDef then
- Result:=StringReplace(aTypeName,' ','',[rfReplaceAll])
- else
- Result:=aPascalType;
- end;
- Var
- A,TN : UTF8String;
- D : TIDLDefinition;
- begin
- Case aTypeName of
- 'union': TN:='JSValue';
- 'short': TN:=UsePascalType('Integer');
- 'long': TN:=UsePascalType('Integer');
- 'long long': TN:=UsePascalType('NativeInt');
- 'unsigned short': TN:=UsePascalType('Cardinal');
- 'unrestricted float': TN:=UsePascalType('Double');
- 'unrestricted double': TN:=UsePascalType('Double');
- 'unsigned long': TN:=UsePascalType('NativeInt');
- 'unsigned long long': TN:=UsePascalType('NativeInt');
- 'octet': TN:=UsePascalType('Byte');
- 'any' : TN:=UsePascalType('JSValue');
- 'float' : TN:=UsePascalType('Double');
- 'double' : TN:=UsePascalType('Double');
- 'DOMString',
- 'USVString',
- 'ByteString' : TN:=UsePascalType('String');
- 'object' : TN:=UsePascalType('TJSObject');
- 'Error' : TN:=UsePascalType('TJSError');
- 'DOMException' : TN:=UsePascalType('TJSError');
- 'ArrayBuffer',
- 'DataView',
- 'Int8Array',
- 'Int16Array',
- 'Int32Array',
- 'Uint8Array',
- 'Uint16Array',
- 'Uint32Array',
- 'Uint8ClampedArray',
- 'Float32Array',
- 'Float64Array' : TN:='TJS'+aTypeName;
- else
- TN:=aTypeName;
- D:=FContext.FindDefinition(TN);
- if D<>Nil then
- TN:=GetName(D)
- else
- begin
- A:=FTypeAliases.Values[TN];
- If (A<>'') then
- TN:=A;
- end;
- end;
- Result:=TN;
- end;
- function TWebIDLToPas.WritePrivateReadOnlyField(aAttr: TIDLAttributeDefinition
- ): Boolean;
- begin
- AddLn('%s%s : %s; external name ''%s''; ',[FieldPrefix,GetName(aAttr),GetTypeName(aAttr.AttributeType),aAttr.Name]);
- end;
- function TWebIDLToPas.WriteField(aAttr: TIDLAttributeDefinition): Boolean;
- Var
- Def,TN,N : String;
- begin
- Result:=True;
- N:=GetName(aAttr);
- TN:=GetTypeName(aAttr.AttributeType);
- if TN='record' then
- TN:='TJSObject';
- if SameText(N,TN) then
- N:='_'+N;
- Def:=Format('%s : %s;',[N,TN]);
- if (N<>aAttr.Name) then
- Def:=Def+Format('external name ''%s'';',[aAttr.Name]);
- AddLn(Def);
- end;
- function TWebIDLToPas.WriteReadonlyProperty(aAttr: TIDLAttributeDefinition
- ): Boolean;
- Var
- TN,N,PN : String;
- begin
- Result:=True;
- N:=GetName(aAttr);
- PN:=N;
- TN:=GetTypeName(aAttr.AttributeType);
- if SameText(PN,TN) then
- PN:='_'+PN;
- AddLn('Property %s : %s Read %s%s; ',[PN,TN,FieldPrefix,N]);
- end;
- function TWebIDLToPas.WriteForwardClassDef(D: TIDLStructuredDefinition): Boolean;
- begin
- Result:=not D.IsPartial;
- if Result then
- AddLn('%s = Class;',[GetName(D)]);
- end;
- function TWebIDLToPas.WriteForwardClassDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- begin
- Result:=0;
- Comment('Forward class definitions');
- For D in aList do
- if D is TIDLInterfaceDefinition then
- if WriteForwardClassDef(D as TIDLInterfaceDefinition) then
- Inc(Result);
- if coDictionaryAsClass in Options then
- For D in aList do
- if D is TIDLDictionaryDefinition then
- if WriteForwardClassDef(D as TIDLDictionaryDefinition) then
- Inc(Result);
- end;
- procedure TWebIDLToPas.WriteSequenceDef(aDef : TIDLSequenceTypeDefDefinition);
- begin
- Addln('%s = array of %s;',[GetName(aDef),GetTypeName(aDef.ElementType)])
- end;
- procedure TWebIDLToPas.WriteUnionDef(aDef : TIDLUnionTypeDefDefinition);
- Var
- S : UTF8String;
- D : TIDLDefinition;
- begin
- S:='';
- For D in adef.Union do
- begin
- if (S<>'') then
- S:=S+', ';
- S:=S+(D as TIDLTypeDefDefinition).TypeName;
- end;
- Comment('Union of '+S);
- AddLn('%s = JSValue; ',[GetName(aDef)])
- end;
- procedure TWebIDLToPas.WritePromiseDef(aDef : TIDLPromiseTypeDefDefinition);
- begin
- AddLn('%s = TJSPromise;',[GetName(aDef)]);
- end;
- procedure TWebIDLToPas.WriteAliasTypeDef(aDef : TIDLTypeDefDefinition);
- Var
- TN : String;
- begin
- TN:=GetTypeName(aDef,True);
- AddLn('%s = %s;',[GetName(aDef),TN]);
- end;
- function TWebIDLToPas.WriteTypeDef(aDef: TIDLTypeDefDefinition): Boolean;
- begin
- Result:=True;
- if ADef is TIDLSequenceTypeDefDefinition then
- WriteSequenceDef(aDef as TIDLSequenceTypeDefDefinition)
- else if ADef is TIDLUnionTypeDefDefinition then
- WriteUnionDef(aDef as TIDLUnionTypeDefDefinition)
- else if ADef is TIDLPromiseTypeDefDefinition then
- WritePromiseDef(aDef as TIDLPromiseTypeDefDefinition)
- else if ADef is TIDLRecordDefinition then
- WriteRecordDef(aDef as TIDLRecordDefinition)
- else
- WriteAliasTypeDef(aDef);
- end;
- function TWebIDLToPas.WriteRecordDef(aDef: TIDLRecordDefinition): Boolean;
- Var
- KT,VT : String;
- begin
- Result:=True;
- KT:=GetTypeName(aDef.KeyType);
- VT:=GetTypeName(aDef.ValueType);
- AddLn('%s = Class(TJSObject)',[GetName(aDef)]);
- AddLn('private');
- Indent;
- AddLn('function GetValue(aKey: %s): %s; external name ''[]'';',[KT,VT]);
- AddLn('procedure SetValue(aKey: %s; const AValue: %s); external name ''[]'';',[KT,VT]);
- undent;
- AddLn('public');
- Indent;
- AddLn('property Values[Name: %s]: %s read GetProperties write SetProperties; default;',[KT,VT]);
- undent;
- AddLn('end;');
- end;
- function TWebIDLToPas.WriteTypeDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- TD : TIDLTypeDefDefinition absolute D;
- begin
- Result:=0;
- EnsureSection(csType);
- for D in aList do
- if D is TIDLTypeDefDefinition then
- if WriteTypeDef(TD) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteEnumDef(aDef: TIDLEnumDefinition): Boolean;
- begin
- Result:=True;
- AddLn('%s = String;',[GetName(aDef)]);
- end;
- function TWebIDLToPas.WriteEnumDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- ED : TIDLEnumDefinition absolute D;
- begin
- Result:=0;
- EnsureSection(csType);
- for D in aList do
- if D is TIDLEnumDefinition then
- if WriteEnumDef(ED) then
- Inc(Result);
- end;
- function TWebIDLToPas.GetArguments(aList: TIDLDefinitionList;
- ForceBrackets: Boolean): String;
- Var
- I : TIDLDefinition;
- A : TIDLArgumentDefinition absolute I;
- Arg : string;
- begin
- Result:='';
- For I in aList do
- begin
- Arg:=GetName(A);
- Arg:=Arg+' : '+GetTypeName(A.ArgumentType);
- if Result<>'' then
- Result:=Result+'; ';
- Result:=Result+Arg;
- end;
- if (Result<>'') or ForceBrackets then
- Result:='('+Result+')';
- end;
- Type
- // A partial argument list is a list which has been generated for a optional argument.
- // Additional arguments can never be added to a partial list...
- TIDLPartialDefinitionList = Class(TIDLDefinitionList);
- function TWebIDLToPas.CloneNonPartialArgumentList(aList: TFPObjectlist;
- ADest: TFPObjectlist; AsPartial: Boolean): integer;
- Var
- I,J : Integer;
- CD : TIDLDefinition;
- DL,CL : TIDLDefinitionList;
- begin
- Result:=0;
- if ADest=Nil then
- ADest:=aList;
- I:=aList.Count-1;
- While (I>=0) do
- begin
- DL:=TIDLDefinitionList(alist[i]);
- if Not (DL is TIDLPartialDefinitionList) then
- begin
- Inc(Result);
- if AsPartial then
- CL:=TIDLPartialDefinitionList.Create(Nil,True)
- else
- CL:=TIDLDefinitionList.Create(Nil,True);
- aDest.Add(CL);
- For J:=0 to DL.Count-1 do
- begin
- CD:=(DL.Definitions[J] as TIDLArgumentDefinition).Clone(Nil);
- CL.Add(CD);
- AllocatePasName(CD);
- end;
- end;
- Dec(I);
- end;
- end;
- procedure TWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; AName,ATypeName : String);
- Var
- I : Integer;
- CD : TIDLArgumentDefinition;
- DL : TIDLDefinitionList;
- begin
- For I:=0 to aList.Count-1 do
- begin
- DL:=TIDLDefinitionList(alist[i]);
- if Not (DL is TIDLPartialDefinitionList) then
- begin
- CD:=TIDLArgumentDefinition.Create(Nil,aName);
- CD.ArgumentType:=TIDLTypeDefDefinition.Create(CD,'');
- CD.ArgumentType.TypeName:=aTypeName;
- DL.Add(CD);
- AllocatePasName(cd,'');
- end;
- end;
- end;
- procedure TWebIDLToPas.AddArgumentToOverloads(aList: TFPObjectlist; adef: TIDLArgumentDefinition);
- Var
- I : Integer;
- CD : TIDLDefinition;
- DL : TIDLDefinitionList;
- begin
- For I:=0 to aList.Count-1 do
- begin
- DL:=TIDLDefinitionList(alist[i]);
- if Not (DL is TIDLPartialDefinitionList) then
- begin
- CD:=aDef.Clone(Nil);
- DL.Add(CD);
- if aDef.Data<>Nil then
- CD.Data:=CreatePasName(TPasData(aDef.Data).PasName)
- else
- AllocatePasName(cd,'');
- end;
- end;
- end;
- procedure TWebIDLToPas.AddUnionOverloads(aList: TFPObjectlist; AName : String; UT : TIDLUnionTypeDefDefinition);
- Var
- L,L2 : TFPObjectList;
- I,J : Integer;
- D : TIDLDefinitionList;
- Dups : TStringList;
- begin
- L2:=Nil;
- Dups:=TStringList.Create;
- Dups.Sorted:=True;
- Dups.Duplicates:=dupIgnore;
- L:=TFPObjectList.Create(False);
- try
- L2:=TFPObjectList.Create(False);
- // Collect non partial argument lists
- for I:=0 to AList.Count-1 do
- begin
- D:=TIDLDefinitionList(alist[i]);
- if Not (D is TIDLPartialDefinitionList) then
- L.Add(D);
- end;
- // Collect unique pascal types. Note that this can reduce the list to 1 element...
- For I:=0 to UT.Union.Count-1 do
- Dups.AddObject(GetTypeName(UT.Union[I] as TIDLTypeDefDefinition),UT.Union[I]);
- // First, clone list and add argument to cloned lists
- For I:=1 to Dups.Count-1 do
- begin
- // Clone list
- CloneNonPartialArgumentList(L,L2,False);
- // Add argument to cloned list
- AddArgumentToOverloads(L2,aName,Dups[i]);
- // Add overloads to original list
- For J:=0 to L2.Count-1 do
- aList.Add(L2[J]);
- L2.Clear;
- end;
- // Add first Union to original list
- AddArgumentToOverloads(L,aName,Dups[0]);
- finally
- Dups.Free;
- L2.Free;
- L.Free;
- end;
- end;
- function TWebIDLToPas.CheckUnionTypeDefinition(D: TIDLDefinition
- ): TIDLUnionTypeDefDefinition;
- begin
- Result:=Nil;
- If (D is TIDLUnionTypeDefDefinition) then
- Result:=D as TIDLUnionTypeDefDefinition
- else
- begin
- D:=Context.FindDefinition((D as TIDLTypeDefDefinition).TypeName);
- if (D is TIDLUnionTypeDefDefinition) then
- Result:=D as TIDLUnionTypeDefDefinition
- end
- end;
- procedure TWebIDLToPas.AddOverloads(aList: TFPObjectlist;
- adef: TIDLFunctionDefinition; aIdx: Integer);
- Var
- Arg : TIDLArgumentDefinition;
- D : TIDLDefinition;
- UT : TIDLUnionTypeDefDefinition;
- begin
- if aIdx>=ADef.Arguments.Count then
- exit;
- Arg:=ADef.Argument[aIdx];
- if Arg.IsOptional then
- CloneNonPartialArgumentList(aList);
- // Add current to list.
- D:=Arg.ArgumentType;
- UT:=Nil;
- if coExpandUnionTypeArgs in Options then
- UT:=CheckUnionTypeDefinition(D);
- if UT=Nil then
- AddArgumentToOverloads(aList,Arg)
- else
- AddUnionOverLoads(aList,Arg.Name,UT);
- AddOverloads(aList,aDef,aIdx+1);
- end;
- function TWebIDLToPas.GetOverloads(aDef: TIDLFunctionDefinition): TFPObjectlist;
- begin
- Result:=TFPObjectList.Create;
- try
- Result.Add(TIDLDefinitionList.Create(Nil,True));
- AddOverloads(Result,adef,0);
- except
- Result.Free;
- Raise;
- end;
- end;
- function TWebIDLToPas.WriteFunctionTypeDefinition(aDef: TIDLFunctionDefinition): Boolean;
- Var
- FN,RT,Args : String;
- begin
- Result:=True;
- FN:=GetName(aDef);
- RT:=GetTypeName(aDef.ReturnType,False);
- if (RT='void') then
- RT:='';
- Args:=GetArguments(aDef.Arguments,False);
- if (RT='') then
- AddLn('%s = Procedure %s;',[FN,Args])
- else
- AddLn('%s = function %s: %s;',[FN,Args,RT])
- end;
- function TWebIDLToPas.WriteFunctionDefinition(aDef: TIDLFunctionDefinition): Boolean;
- Var
- FN,RT,Suff,Args : String;
- Overloads : TFPObjectList;
- I : Integer;
- begin
- Result:=True;
- if not (foConstructor in aDef.Options) then
- begin
- FN:=GetName(aDef);
- if FN<>aDef.Name then
- Suff:=Format('; external name ''%s''',[aDef.Name]);
- RT:=GetTypeName(aDef.ReturnType,False);
- if (RT='void') then
- RT:='';
- end
- else
- FN:='New';
- Overloads:=GetOverloads(ADef);
- try
- for I:=0 to aDef.Arguments.Count-1 do
- if aDef.Argument[i].HasEllipsis then
- Suff:='; varargs';
- if Overloads.Count>1 then
- Suff:=Suff+'; overload';
- For I:=0 to Overloads.Count-1 do
- begin
- Args:=GetArguments(TIDLDefinitionList(Overloads[i]),False);
- if (RT='') then
- begin
- if not (foConstructor in aDef.Options) then
- AddLn('Procedure %s%s%s;',[FN,Args,Suff])
- else
- AddLn('constructor %s%s%s;',[FN,Args,Suff]);
- end
- else
- AddLn('function %s%s: %s%s;',[FN,Args,RT,Suff])
- end;
- finally
- Overloads.Free;
- end;
- end;
- function TWebIDLToPas.WriteCallBackDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- FD : TIDLFunctionDefinition absolute D;
- begin
- Result:=0;
- EnsureSection(csType);
- for D in aList do
- if D is TIDLFunctionDefinition then
- if (foCallBack in FD.Options) then
- if WriteFunctionTypeDefinition(FD) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteDictionaryDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- DD : TIDLDictionaryDefinition absolute D;
- begin
- Result:=0;
- EnsureSection(csType);
- for D in aList do
- if D is TIDLDictionaryDefinition then
- if not TIDLDictionaryDefinition(D).IsPartial then
- if WriteDictionaryDef(DD) then
- Inc(Result);
- end;
- function TWebIDLToPas.WriteInterfaceDefs(aList: TIDLDefinitionList): Integer;
- Var
- D : TIDLDefinition;
- ID : TIDLInterfaceDefinition absolute D;
- begin
- Result:=0;
- EnsureSection(csType);
- for D in aList do
- if D is TIDLInterfaceDefinition then
- if not TIDLInterfaceDefinition(D).IsPartial then
- if WriteInterfaceDef(ID) then
- Inc(Result);
- end;
- procedure TWebIDLToPas.Getoptions(L : TStrings);
- Var
- S : String;
- I : Integer;
- begin
- L.Add('Automatically generated file by '+ClassName+' on '+FormatDateTime('yyyy-mm-dd hh:nn:ss',Now));
- L.Add('');
- L.Add('Used command-line options : ');
- For I:=1 to ParamCount do
- L.Add(ParamStr(i));
- L.Add('');
- L.Add('Command-line options translate to: ');
- L.Add('');
- S:=SetToString(PtypeInfo(TypeInfo(TConversionOptions)),Integer(OPtions),True);
- L.Add('Options : '+S);
- L.Add('Keyword prefix : '+KeywordPrefix);
- L.Add('Keyword suffix : '+KeywordSuffix);
- L.Add('Class prefix : '+ClassPrefix);
- L.Add('Class suffix : '+ClassSuffix);
- L.Add('Field prefix : '+FieldPrefix);
- Str(WebIDLversion,S);
- L.Add('WEBIDLversion : '+S);
- if TypeAliases.Count>0 then
- begin
- L.Add('Type aliases:');
- L.AddStrings(Self.TypeAliases);
- end;
- end;
- procedure TWebIDLToPas.AddOptionsToHeader;
- Var
- L : TStrings;
- begin
- L:=TStringList.Create;
- try
- GetOptions(L);
- Comment(L);
- finally
- L.Free;
- end;
- end;
- procedure TWebIDLToPas.WriteIncludeInterfaceCode;
- Var
- S : String;
- begin
- For S in IncludeInterfaceCode do
- Addln(S);
- end;
- procedure TWebIDLToPas.WritePascal;
- begin
- CreateUnitClause;
- CreateHeader;
- if coaddOptionsToheader in Options then
- AddOptionsToHeader;
- EnsureSection(csType);
- Indent;
- WriteForwardClassDefs(Context.Definitions);
- WriteEnumDefs(Context.Definitions);
- WriteTypeDefs(Context.Definitions);
- WriteCallbackDefs(Context.Definitions);
- WriteDictionaryDefs(Context.Definitions);
- WriteInterfaceDefs(Context.Definitions);
- Undent;
- WriteIncludeInterfaceCode;
- Addln('');
- AddLn('implementation');
- WriteImplementation;
- AddLn('end.');
- Source.SaveToFile(OutputFileName);
- end;
- function TWebIDLToPas.BaseUnits: String;
- begin
- Result:='SysUtils, JS'
- end;
- function TWebIDLToPas.CreatePasName(aName: String): TPasData;
- begin
- Result:=TPasData.Create(EscapeKeyWord(aName));
- FPasNameList.Add(Result);
- end;
- function TWebIDLToPas.AllocatePasName(D: TIDLDefinition; ParentName: String): TPasData;
- Var
- CN : String;
- begin
- if D Is TIDLInterfaceDefinition then
- begin
- CN:=ClassPrefix+D.Name+ClassSuffix;
- Result:=CreatePasname(CN);
- D.Data:=Result;
- AllocatePasNames((D as TIDLInterfaceDefinition).members,D.Name);
- end
- else if D Is TIDLDictionaryDefinition then
- begin
- CN:=D.Name;
- if coDictionaryAsClass in Options then
- CN:=ClassPrefix+CN+ClassSuffix;
- Result:=CreatePasname(EscapeKeyWord(CN));
- D.Data:=Result;
- AllocatePasNames((D as TIDLDictionaryDefinition).members,D.Name);
- end
- else
- begin
- Result:=CreatePasName(D.Name);
- D.Data:=Result;
- if D Is TIDLFunctionDefinition then
- AllocatePasNames((D as TIDLFunctionDefinition).Arguments,D.Name);
- end;
- if Verbose and (TPasData(D.Data).PasName<>D.Name) then
- begin
- if (ParentName<>'') then
- ParentName:=ParentName+'.';
- DoLog('Renamed %s to %s',[ParentName+D.Name,TPasData(D.Data).PasName]);
- end;
- end;
- procedure TWebIDLToPas.SetTypeAliases(AValue: TStrings);
- begin
- if FTypeAliases=AValue then Exit;
- FTypeAliases.Assign(AValue);
- end;
- procedure TWebIDLToPas.SetIncludeInterfaceCode(AValue: TStrings);
- begin
- if FIncludeInterfaceCode=AValue then Exit;
- FIncludeInterfaceCode.Assign(AValue);
- end;
- procedure TWebIDLToPas.SetIncludeImplementationCode(AValue: TStrings);
- begin
- if FIncludeImplementationCode=AValue then Exit;
- FIncludeImplementationCode.Assign(AValue);
- end;
- procedure TWebIDLToPas.AllocatePasNames(aList : TIDLDefinitionList; ParentName: String = '');
- var
- D : TIDLDefinition;
- begin
- For D in aList do
- AllocatePasName(D,ParentName);
- end;
- procedure TWebIDLToPas.ProcessDefinitions;
- begin
- FContext.AppendPartials;
- FContext.AppendIncludes;
- AllocatePasNames(FContext.Definitions);
- end;
- procedure TWebIDLToPas.Execute;
- begin
- FContext:=CreateContext;
- try
- FContext.Aliases:=Self.TypeAliases;
- Parse;
- if Verbose then
- DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
- ProcessDefinitions;
- WritePascal;
- finally
- FreeAndNil(FContext);
- end;
- end;
- end.
|