Browse Source

webidl: resolving type defs

mattias 3 years ago
parent
commit
dd0acb6360

+ 94 - 2
packages/webidl/src/webidldefs.pp

@@ -22,6 +22,89 @@ uses
   Classes, SysUtils, contnrs;
   Classes, SysUtils, contnrs;
 
 
 Type
 Type
+  TWebIDLBaseType = (
+    wibtNone,
+    wibtVoid,
+    wibtUnion,
+    wibtAny,
+    // boolean
+    wibtBoolean,
+    // integers
+    wibtByte,
+    wibtOctet,
+    wibtShort,
+    wibtUnsignedShort,
+    wibtLong,
+    wibtUnsignedLong,
+    wibtLongLong,
+    wibtUnsignedLongLong,
+    // floats
+    wibtFloat,             // not NaN or infinity
+    wibtUnrestrictedFloat,
+    wibtDouble,            // not NaN or infinity
+    wibtUnrestrictedDouble,
+    // strings
+    wibtDOMString, // UTF-16
+    wibtUSVString, // UTF-16 without surrogates
+    wibtByteString,
+    // objects
+    wibtRecord,
+    wibtObject,
+    wibtError,
+    wibtDOMException,
+    // arrays
+    wibtArrayBuffer,
+    wibtDataView,
+    wibtInt8Array,
+    wibtInt16Array,
+    wibtInt32Array,
+    wibtUint8Array,
+    wibtUint16Array,
+    wibtUint32Array,
+    wibtUint8ClampedArray,
+    wibtFloat32Array,
+    wibtFloat64Array
+    );
+  TWebIDLBaseTypes = set of TWebIDLBaseType;
+const
+  WebIDLBaseTypeNames: array[TWebIDLBaseType] of string = (
+    '',
+    'void',
+    'union',
+    'any',
+    'boolean',
+    'byte',
+    'octet',
+    'short',
+    'unsigned short',
+    'long',
+    'unsigned long',
+    'long long',
+    'unsigned long long',
+    'float',
+    'unrestricted float',
+    'double',
+    'unrestricted double',
+    'DOMString',
+    'USVString',
+    'ByteString',
+    'record',
+    'object',
+    'Error',
+    'DOMException',
+    'ArrayBuffer',
+    'DataView',
+    'Int8Array',
+    'Int16Array',
+    'Int32Array',
+    'Uint8Array',
+    'Uint16Array',
+    'Uint32Array',
+    'Uint8ClampedArray',
+    'Float32Array',
+    'Float64Array');
+
+type
 
 
   { TExtAttributeList }
   { TExtAttributeList }
 
 
@@ -341,8 +424,6 @@ Type
     property ReturnType : TIDLTypeDefDefinition Read FReturnType Write SetReturnType;
     property ReturnType : TIDLTypeDefDefinition Read FReturnType Write SetReturnType;
   end;
   end;
 
 
-  { TIDLMapLikeDefinition }
-
   { TIDLKeyValueDefinition }
   { TIDLKeyValueDefinition }
 
 
   TIDLKeyValueDefinition = Class(TIDLTypeDefDefinition)
   TIDLKeyValueDefinition = Class(TIDLTypeDefDefinition)
@@ -358,6 +439,8 @@ Type
     property ValueType : TIDLTypeDefDefinition Read FValueType Write SetValueType;
     property ValueType : TIDLTypeDefDefinition Read FValueType Write SetValueType;
   end;
   end;
 
 
+  { TIDLMapLikeDefinition }
+
   TIDLMapLikeDefinition = Class(TIDLKeyValueDefinition)
   TIDLMapLikeDefinition = Class(TIDLKeyValueDefinition)
   private
   private
     FIsReadonly: Boolean;
     FIsReadonly: Boolean;
@@ -451,9 +534,18 @@ Type
     property KeyType : TIDLTypeDefDefinition Read FKeyType Write SetKeyType;
     property KeyType : TIDLTypeDefDefinition Read FKeyType Write SetKeyType;
   end;
   end;
 
 
+function NameToWebIDLBaseType(const s: string): TWebIDLBaseType;
 
 
 implementation
 implementation
 
 
+function NameToWebIDLBaseType(const s: string): TWebIDLBaseType;
+begin
+  for Result in TWebIDLBaseType do
+    if s=WebIDLBaseTypeNames[Result] then
+      exit;
+  Result:=wibtNone;
+end;
+
 { TIDLSetlikeDefinition }
 { TIDLSetlikeDefinition }
 
 
 procedure TIDLSetlikeDefinition.SetElementType(
 procedure TIDLSetlikeDefinition.SetElementType(

+ 1 - 0
packages/webidl/src/webidlparser.pp

@@ -25,6 +25,7 @@ Type
   EWebIDLParser = Class(Exception);
   EWebIDLParser = Class(Exception);
 
 
   { TWebIDLContext }
   { TWebIDLContext }
+
   TWebIDLVersion = webidlscanner.TWebIDLVersion;
   TWebIDLVersion = webidlscanner.TWebIDLVersion;
 
 
   TWebIDLContext = Class (TIDLBaseObject)
   TWebIDLContext = Class (TIDLBaseObject)

+ 98 - 13
packages/webidl/src/webidltopas.pp

@@ -31,9 +31,11 @@ Type
   private
   private
     FPasName: String;
     FPasName: String;
   Public
   Public
+    IDL: TIDLBaseObject;
     Line, Column: integer;
     Line, Column: integer;
     SrcFile: string;
     SrcFile: string;
-    Constructor Create(APasName: String; const aFile: string; aLine, aCol: integer);
+    Resolved: TIDLDefinition;
+    Constructor Create(APasName: String; D: TIDLBaseObject);
     Property PasName: String read FPasName;
     Property PasName: String read FPasName;
   end;
   end;
   TPasDataClass = class of TPasData;
   TPasDataClass = class of TPasData;
@@ -55,6 +57,7 @@ const
 type
 type
   TBaseWebIDLToPas = Class(TPascalCodeGenerator)
   TBaseWebIDLToPas = Class(TPascalCodeGenerator)
   private
   private
+    FAutoTypes: TStrings;
     FBaseOptions: TBaseConversionOptions;
     FBaseOptions: TBaseConversionOptions;
     FClassPrefix: String;
     FClassPrefix: String;
     FClassSuffix: String;
     FClassSuffix: String;
@@ -66,14 +69,14 @@ type
     FIncludeImplementationCode: TStrings;
     FIncludeImplementationCode: TStrings;
     FIncludeInterfaceCode: TStrings;
     FIncludeInterfaceCode: TStrings;
     FInputFileName: String;
     FInputFileName: String;
+    FGlobalDefs: TFPHashList;
     FOutputFileName: String;
     FOutputFileName: String;
     FPasDataClass: TPasDataClass;
     FPasDataClass: TPasDataClass;
+    FPasNameList: TFPObjectList; // list TPasData
     FSetterPrefix: String;
     FSetterPrefix: String;
-    FTypeAliases: TStrings;
+    FTypeAliases: TStrings; // user defined type maping name to name
     FVerbose: Boolean;
     FVerbose: Boolean;
     FWebIDLVersion: TWebIDLVersion;
     FWebIDLVersion: TWebIDLVersion;
-    FPasNameList: TFPObjectList;
-    FAutoTypes: TStrings;
     procedure SetIncludeImplementationCode(AValue: TStrings);
     procedure SetIncludeImplementationCode(AValue: TStrings);
     procedure SetIncludeInterfaceCode(AValue: TStrings);
     procedure SetIncludeInterfaceCode(AValue: TStrings);
     procedure SetTypeAliases(AValue: TStrings);
     procedure SetTypeAliases(AValue: TStrings);
@@ -90,6 +93,10 @@ type
     function CreatePasName(aName: String; D: TIDLBaseObject): TPasData; virtual;
     function CreatePasName(aName: String; D: TIDLBaseObject): TPasData; virtual;
     procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String=''); virtual;
     procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String=''); virtual;
     function AllocatePasName(D: TIDLDefinition; ParentName: String=''): TPasData; virtual;
     function AllocatePasName(D: TIDLDefinition; ParentName: String=''): TPasData; virtual;
+    procedure AddJSIdentifier(D: TIDLDefinition); virtual;
+    procedure ResolveTypeDefs(aList: TIDLDefinitionList); virtual;
+    procedure ResolveTypeDef(D: TIDLDefinition); virtual;
+    function FindGlobalDef(const aName: UTF8String): TIDLDefinition; virtual;
     function GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean = false): string; virtual;
     function GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean = false): string; virtual;
     function GetPasDataPos(D: TPasData; WithoutFile: boolean = false): string; virtual;
     function GetPasDataPos(D: TPasData; WithoutFile: boolean = false): string; virtual;
     procedure EnsureUniqueNames(ML: TIDLDefinitionList); virtual;
     procedure EnsureUniqueNames(ML: TIDLDefinitionList); virtual;
@@ -193,13 +200,13 @@ end;
 
 
 { TPasData }
 { TPasData }
 
 
-constructor TPasData.Create(APasName: String; const aFile: string; aLine,
-  aCol: integer);
+constructor TPasData.Create(APasName: String; D: TIDLBaseObject);
 begin
 begin
   FPasName:=APasName;
   FPasName:=APasName;
-  SrcFile:=aFile;
-  Line:=aLine;
-  Column:=aCol;
+  IDL:=D;
+  SrcFile:=D.SrcFile;
+  Line:=D.Line;
+  Column:=D.Column;
 end;
 end;
 
 
 { TBaseWebIDLToPas }
 { TBaseWebIDLToPas }
@@ -658,11 +665,13 @@ begin
   FAutoTypes:=TStringList.Create;
   FAutoTypes:=TStringList.Create;
   FIncludeInterfaceCode:=TStringList.Create;
   FIncludeInterfaceCode:=TStringList.Create;
   FIncludeImplementationCode:=TStringList.Create;
   FIncludeImplementationCode:=TStringList.Create;
+  FGlobalDefs:=TFPHashList.Create;
 end;
 end;
 
 
 
 
 destructor TBaseWebIDLToPas.Destroy;
 destructor TBaseWebIDLToPas.Destroy;
 begin
 begin
+  FreeAndNil(FGlobalDefs);
   FreeAndNil(FIncludeInterfaceCode);
   FreeAndNil(FIncludeInterfaceCode);
   FreeAndNil(FIncludeImplementationCode);
   FreeAndNil(FIncludeImplementationCode);
   FreeAndNil(FAutoTypes);
   FreeAndNil(FAutoTypes);
@@ -1345,9 +1354,8 @@ end;
 
 
 function TBaseWebIDLToPas.CreatePasName(aName: String; D: TIDLBaseObject
 function TBaseWebIDLToPas.CreatePasName(aName: String; D: TIDLBaseObject
   ): TPasData;
   ): TPasData;
-
 begin
 begin
-  Result:=PasDataClass.Create(EscapeKeyWord(aName),D.SrcFile,D.Line,D.Column);
+  Result:=PasDataClass.Create(EscapeKeyWord(aName),D);
   FPasNameList.Add(Result);
   FPasNameList.Add(Result);
 end;
 end;
 
 
@@ -1358,10 +1366,11 @@ Var
   aData: TPasData;
   aData: TPasData;
 
 
 begin
 begin
-  writeln('AAA1 TBaseWebIDLToPas.AllocatePasName ',D.Name,':',D.ClassName);
   CN:=D.Name;
   CN:=D.Name;
   if D Is TIDLInterfaceDefinition then
   if D Is TIDLInterfaceDefinition then
     begin
     begin
+    if not TIDLInterfaceDefinition(D).IsPartial then
+      AddJSIdentifier(D);
     CN:=ClassPrefix+CN+ClassSuffix;
     CN:=ClassPrefix+CN+ClassSuffix;
     Result:=CreatePasName(CN,D);
     Result:=CreatePasName(CN,D);
     D.Data:=Result;
     D.Data:=Result;
@@ -1369,6 +1378,8 @@ begin
     end
     end
   else if D Is TIDLDictionaryDefinition then
   else if D Is TIDLDictionaryDefinition then
     begin
     begin
+    if not TIDLDictionaryDefinition(D).IsPartial then
+      AddJSIdentifier(D);
     if coDictionaryAsClass in BaseOptions then
     if coDictionaryAsClass in BaseOptions then
       CN:=ClassPrefix+CN+ClassSuffix;
       CN:=ClassPrefix+CN+ClassSuffix;
     Result:=CreatePasName(EscapeKeyWord(CN),D);
     Result:=CreatePasName(EscapeKeyWord(CN),D);
@@ -1378,7 +1389,10 @@ begin
   else
   else
     begin
     begin
     if (D Is TIDLFunctionDefinition) and (foCallBack in TIDLFunctionDefinition(D).Options) then
     if (D Is TIDLFunctionDefinition) and (foCallBack in TIDLFunctionDefinition(D).Options) then
-      CN:=FuncTypePrefix+CN;;
+      begin
+      CN:=FuncTypePrefix+CN;
+      AddJSIdentifier(D);
+      end;
     Result:=CreatePasName(CN,D);
     Result:=CreatePasName(CN,D);
     D.Data:=Result;
     D.Data:=Result;
     if D Is TIDLFunctionDefinition then
     if D Is TIDLFunctionDefinition then
@@ -1393,6 +1407,74 @@ begin
     end;
     end;
 end;
 end;
 
 
+procedure TBaseWebIDLToPas.AddJSIdentifier(D: TIDLDefinition);
+var
+  Old: TIDLDefinition;
+begin
+  if D.Parent=nil then
+    begin
+    Old:=FindGlobalDef(D.Name);
+    if Old<>nil then
+      raise EWebIDLParser.Create('Duplicate identifier '+D.Name+' at '+GetDefPos(D)+' and '+GetDefPos(Old));
+    FGlobalDefs.Add(D.Name,D);
+    end
+  else
+    writeln('TBaseWebIDLToPas.AddJSIdentifier SubIdentifier: '+D.Name+' at '+GetDefPos(D)+' Parent=',D.Parent.Name,':',D.Parent.ClassName,' at ',GetDefPos(D.Parent));
+end;
+
+procedure TBaseWebIDLToPas.ResolveTypeDefs(aList: TIDLDefinitionList);
+var
+  D: TIDLDefinition;
+begin
+  For D in aList do
+    ResolveTypeDef(D);
+end;
+
+procedure TBaseWebIDLToPas.ResolveTypeDef(D: TIDLDefinition);
+var
+  Def: TIDLDefinition;
+  aTypeName: String;
+  Data: TPasData;
+begin
+  if D=nil then exit;
+  //writeln('TBaseWebIDLToPas.ResolveTypeDef START ',D.Name,':',D.ClassName,' at ',GetDefPos(D));
+  if D Is TIDLInterfaceDefinition then
+    ResolveTypeDefs((D as TIDLInterfaceDefinition).Members)
+  else if D Is TIDLDictionaryDefinition then
+    ResolveTypeDefs((D as TIDLDictionaryDefinition).Members)
+  else if D Is TIDLFunctionDefinition then
+    ResolveTypeDefs((D as TIDLFunctionDefinition).Arguments)
+  else if D is TIDLAttributeDefinition then
+    ResolveTypeDef(TIDLAttributeDefinition(D).AttributeType)
+  else if D is TIDLArgumentDefinition then
+    ResolveTypeDef(TIDLArgumentDefinition(D).ArgumentType)
+  else if D is TIDLTypeDefDefinition then
+    begin
+    aTypeName:=TIDLTypeDefDefinition(D).TypeName;
+    Def:=FindGlobalDef(aTypeName);
+    if Def=nil then
+      begin
+      if NameToWebIDLBaseType(aTypeName)=wibtNone then
+        writeln('Type ',aTypeName,' not found at ',GetDefPos(D));
+      end
+    else
+      begin
+      Data:=TPasData(D.Data);
+      if Data=nil then
+        Data:=CreatePasName('',D);
+      Data.Resolved:=Def;
+      end;
+    end
+  else {if Verbose then}
+    writeln('TBaseWebIDLToPas.ResolveTypeDef unknown ',D.Name,':',D.ClassName,' at ',GetDefPos(D));
+end;
+
+function TBaseWebIDLToPas.FindGlobalDef(const aName: UTF8String
+  ): TIDLDefinition;
+begin
+  Result:=TIDLDefinition(FGlobalDefs.Find(aName));
+end;
+
 function TBaseWebIDLToPas.GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean
 function TBaseWebIDLToPas.GetDefPos(Def: TIDLBaseObject; WithoutFile: boolean
   ): string;
   ): string;
 begin
 begin
@@ -1443,6 +1525,7 @@ begin
   FContext.AppendPartials;
   FContext.AppendPartials;
   FContext.AppendIncludes;
   FContext.AppendIncludes;
   AllocatePasNames(FContext.Definitions);
   AllocatePasNames(FContext.Definitions);
+  ResolveTypeDefs(FContext.Definitions);
 end;
 end;
 
 
 procedure TBaseWebIDLToPas.Execute;
 procedure TBaseWebIDLToPas.Execute;
@@ -1461,6 +1544,8 @@ begin
     if Verbose then
     if Verbose then
       DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
       DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
     ProcessDefinitions;
     ProcessDefinitions;
+    if Verbose then
+      DoLog('Processed %d definitions.',[Context.Definitions.Count]);
     WritePascal;
     WritePascal;
   finally
   finally
     FreeAndNil(FContext);
     FreeAndNil(FContext);