webidl: resolving type defs

This commit is contained in:
mattias 2022-06-27 13:55:49 +02:00
parent fb5456da79
commit dd0acb6360
3 changed files with 193 additions and 15 deletions

View File

@ -22,6 +22,89 @@ uses
Classes, SysUtils, contnrs;
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 }
@ -341,8 +424,6 @@ Type
property ReturnType : TIDLTypeDefDefinition Read FReturnType Write SetReturnType;
end;
{ TIDLMapLikeDefinition }
{ TIDLKeyValueDefinition }
TIDLKeyValueDefinition = Class(TIDLTypeDefDefinition)
@ -358,6 +439,8 @@ Type
property ValueType : TIDLTypeDefDefinition Read FValueType Write SetValueType;
end;
{ TIDLMapLikeDefinition }
TIDLMapLikeDefinition = Class(TIDLKeyValueDefinition)
private
FIsReadonly: Boolean;
@ -451,9 +534,18 @@ Type
property KeyType : TIDLTypeDefDefinition Read FKeyType Write SetKeyType;
end;
function NameToWebIDLBaseType(const s: string): TWebIDLBaseType;
implementation
function NameToWebIDLBaseType(const s: string): TWebIDLBaseType;
begin
for Result in TWebIDLBaseType do
if s=WebIDLBaseTypeNames[Result] then
exit;
Result:=wibtNone;
end;
{ TIDLSetlikeDefinition }
procedure TIDLSetlikeDefinition.SetElementType(

View File

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

View File

@ -31,9 +31,11 @@ Type
private
FPasName: String;
Public
IDL: TIDLBaseObject;
Line, Column: integer;
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;
end;
TPasDataClass = class of TPasData;
@ -55,6 +57,7 @@ const
type
TBaseWebIDLToPas = Class(TPascalCodeGenerator)
private
FAutoTypes: TStrings;
FBaseOptions: TBaseConversionOptions;
FClassPrefix: String;
FClassSuffix: String;
@ -66,14 +69,14 @@ type
FIncludeImplementationCode: TStrings;
FIncludeInterfaceCode: TStrings;
FInputFileName: String;
FGlobalDefs: TFPHashList;
FOutputFileName: String;
FPasDataClass: TPasDataClass;
FPasNameList: TFPObjectList; // list TPasData
FSetterPrefix: String;
FTypeAliases: TStrings;
FTypeAliases: TStrings; // user defined type maping name to name
FVerbose: Boolean;
FWebIDLVersion: TWebIDLVersion;
FPasNameList: TFPObjectList;
FAutoTypes: TStrings;
procedure SetIncludeImplementationCode(AValue: TStrings);
procedure SetIncludeInterfaceCode(AValue: TStrings);
procedure SetTypeAliases(AValue: TStrings);
@ -90,6 +93,10 @@ type
function CreatePasName(aName: String; D: TIDLBaseObject): TPasData; virtual;
procedure AllocatePasNames(aList: TIDLDefinitionList; ParentName: String=''); 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 GetPasDataPos(D: TPasData; WithoutFile: boolean = false): string; virtual;
procedure EnsureUniqueNames(ML: TIDLDefinitionList); virtual;
@ -193,13 +200,13 @@ end;
{ TPasData }
constructor TPasData.Create(APasName: String; const aFile: string; aLine,
aCol: integer);
constructor TPasData.Create(APasName: String; D: TIDLBaseObject);
begin
FPasName:=APasName;
SrcFile:=aFile;
Line:=aLine;
Column:=aCol;
IDL:=D;
SrcFile:=D.SrcFile;
Line:=D.Line;
Column:=D.Column;
end;
{ TBaseWebIDLToPas }
@ -658,11 +665,13 @@ begin
FAutoTypes:=TStringList.Create;
FIncludeInterfaceCode:=TStringList.Create;
FIncludeImplementationCode:=TStringList.Create;
FGlobalDefs:=TFPHashList.Create;
end;
destructor TBaseWebIDLToPas.Destroy;
begin
FreeAndNil(FGlobalDefs);
FreeAndNil(FIncludeInterfaceCode);
FreeAndNil(FIncludeImplementationCode);
FreeAndNil(FAutoTypes);
@ -1345,9 +1354,8 @@ end;
function TBaseWebIDLToPas.CreatePasName(aName: String; D: TIDLBaseObject
): TPasData;
begin
Result:=PasDataClass.Create(EscapeKeyWord(aName),D.SrcFile,D.Line,D.Column);
Result:=PasDataClass.Create(EscapeKeyWord(aName),D);
FPasNameList.Add(Result);
end;
@ -1358,10 +1366,11 @@ Var
aData: TPasData;
begin
writeln('AAA1 TBaseWebIDLToPas.AllocatePasName ',D.Name,':',D.ClassName);
CN:=D.Name;
if D Is TIDLInterfaceDefinition then
begin
if not TIDLInterfaceDefinition(D).IsPartial then
AddJSIdentifier(D);
CN:=ClassPrefix+CN+ClassSuffix;
Result:=CreatePasName(CN,D);
D.Data:=Result;
@ -1369,6 +1378,8 @@ begin
end
else if D Is TIDLDictionaryDefinition then
begin
if not TIDLDictionaryDefinition(D).IsPartial then
AddJSIdentifier(D);
if coDictionaryAsClass in BaseOptions then
CN:=ClassPrefix+CN+ClassSuffix;
Result:=CreatePasName(EscapeKeyWord(CN),D);
@ -1378,7 +1389,10 @@ begin
else
begin
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);
D.Data:=Result;
if D Is TIDLFunctionDefinition then
@ -1393,6 +1407,74 @@ begin
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
): string;
begin
@ -1443,6 +1525,7 @@ begin
FContext.AppendPartials;
FContext.AppendIncludes;
AllocatePasNames(FContext.Definitions);
ResolveTypeDefs(FContext.Definitions);
end;
procedure TBaseWebIDLToPas.Execute;
@ -1461,6 +1544,8 @@ begin
if Verbose then
DoLog('Parsed %d definitions.',[Context.Definitions.Count]);
ProcessDefinitions;
if Verbose then
DoLog('Processed %d definitions.',[Context.Definitions.Count]);
WritePascal;
finally
FreeAndNil(FContext);