mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-11 18:25:58 +02:00
pastojs: implemented typeinfo for record member:arrayf of type
git-svn-id: trunk@37147 -
This commit is contained in:
parent
68b3a79e15
commit
9a2736abcb
@ -1175,6 +1175,8 @@ type
|
|||||||
Function TransformVariableName(El: TPasElement; AContext : TConvertContext) : String; virtual;
|
Function TransformVariableName(El: TPasElement; AContext : TConvertContext) : String; virtual;
|
||||||
Function TransformModuleName(El: TPasModule; AddModulesPrefix: boolean; AContext : TConvertContext) : String; virtual;
|
Function TransformModuleName(El: TPasModule; AddModulesPrefix: boolean; AContext : TConvertContext) : String; virtual;
|
||||||
Function IsPreservedWord(const aName: string): boolean; virtual;
|
Function IsPreservedWord(const aName: string): boolean; virtual;
|
||||||
|
Function GetTypeInfoName(El: TPasType; AContext: TConvertContext;
|
||||||
|
ErrorEl: TPasElement): String; virtual;
|
||||||
// Never create an element manually, always use the below functions
|
// Never create an element manually, always use the below functions
|
||||||
Function IsElementUsed(El: TPasElement): boolean; virtual;
|
Function IsElementUsed(El: TPasElement): boolean; virtual;
|
||||||
Function IsSystemUnit(aModule: TPasModule): boolean; virtual;
|
Function IsSystemUnit(aModule: TPasModule): boolean; virtual;
|
||||||
@ -1243,6 +1245,8 @@ type
|
|||||||
Function CreateRTTIClassField(V: TPasVariable; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassField(V: TPasVariable; AContext: TConvertContext): TJSElement; virtual;
|
||||||
Function CreateRTTIClassMethod(Proc: TPasProcedure; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassMethod(Proc: TPasProcedure; AContext: TConvertContext): TJSElement; virtual;
|
||||||
Function CreateRTTIClassProperty(Prop: TPasProperty; AContext: TConvertContext): TJSElement; virtual;
|
Function CreateRTTIClassProperty(Prop: TPasProperty; AContext: TConvertContext): TJSElement; virtual;
|
||||||
|
Procedure CreateRTTIAnonymous(El: TPasType; AContext: TConvertContext;
|
||||||
|
var First, Last: TJSStatementList); virtual;
|
||||||
// Statements
|
// Statements
|
||||||
Function ConvertImplBlockElements(El: TPasImplBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
Function ConvertImplBlockElements(El: TPasImplBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
||||||
Function ConvertBeginEndStatement(El: TPasImplBeginBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
Function ConvertBeginEndStatement(El: TPasImplBeginBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
||||||
@ -9224,131 +9228,41 @@ end;
|
|||||||
function TPasToJSConverter.CreateTypeInfoRef(El: TPasType;
|
function TPasToJSConverter.CreateTypeInfoRef(El: TPasType;
|
||||||
AContext: TConvertContext; ErrorEl: TPasElement): TJSElement;
|
AContext: TConvertContext; ErrorEl: TPasElement): TJSElement;
|
||||||
var
|
var
|
||||||
C: TClass;
|
|
||||||
aName, aModName: String;
|
aName, aModName: String;
|
||||||
bt: TResolverBaseType;
|
CurEl: TPasElement;
|
||||||
jbt: TPas2jsBaseType;
|
|
||||||
Parent: TPasElement;
|
|
||||||
aModule: TPasModule;
|
aModule: TPasModule;
|
||||||
Bracket: TJSBracketMemberExpression;
|
Bracket: TJSBracketMemberExpression;
|
||||||
begin
|
begin
|
||||||
El:=AContext.Resolver.ResolveAliasType(El);
|
aName:=GetTypeInfoName(El,AContext,ErrorEl);
|
||||||
if El=nil then
|
if aName=FBuiltInNames[pbivnRTTILocal] then
|
||||||
RaiseInconsistency(20170409172756);
|
Result:=CreatePrimitiveDotExpr(aName)
|
||||||
if El=AContext.PasElement then
|
else if LeftStr(aName,length(FBuiltInNames[pbivnRTL])+1)=FBuiltInNames[pbivnRTL]+'.' then
|
||||||
|
Result:=CreatePrimitiveDotExpr(aName)
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
// refering itself
|
CurEl:=El;
|
||||||
if El is TPasClassType then
|
while CurEl<>nil do
|
||||||
begin
|
begin
|
||||||
// use this
|
if CurEl is TPasSection then
|
||||||
Result:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTTILocal]);
|
|
||||||
exit;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
RaiseNotSupported(ErrorEl,AContext,20170409195518,'cannot typeinfo itself');
|
|
||||||
end;
|
|
||||||
if El.Name='' then
|
|
||||||
DoError(20170421145257,nTypeXCannotBePublished,sTypeXCannotBePublished,
|
|
||||||
['typeinfo of anonymous '+El.ElementTypeName],ErrorEl);
|
|
||||||
|
|
||||||
C:=El.ClassType;
|
|
||||||
if C=TPasUnresolvedSymbolRef then
|
|
||||||
begin
|
|
||||||
if El.CustomData is TResElDataBaseType then
|
|
||||||
begin
|
|
||||||
bt:=TResElDataBaseType(El.CustomData).BaseType;
|
|
||||||
case bt of
|
|
||||||
btShortInt,btByte,
|
|
||||||
btSmallInt,btWord,
|
|
||||||
btLongint,btLongWord,
|
|
||||||
btIntDouble,btUIntDouble,
|
|
||||||
btString,btChar,
|
|
||||||
btDouble,
|
|
||||||
btBoolean,
|
|
||||||
btPointer:
|
|
||||||
begin
|
begin
|
||||||
// create rtl.basename
|
aModule:=CurEl.Parent as TPasModule;
|
||||||
Result:=CreateMemberExpression([FBuiltInNames[pbivnRTL],lowercase(
|
aModName:=AContext.GetLocalName(aModule);
|
||||||
AContext.Resolver.BaseTypeNames[bt])]);
|
if aModName='' then
|
||||||
|
aModName:=TransformModuleName(aModule,true,AContext);
|
||||||
|
Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El));
|
||||||
|
Bracket.MExpr:=CreateMemberExpression([aModName,FBuiltInNames[pbivnRTTI]]);
|
||||||
|
Bracket.Name:=CreateLiteralString(El,aName);
|
||||||
|
Result:=Bracket;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
btCustom:
|
CurEl:=CurEl.Parent;
|
||||||
if El.CustomData is TResElDataPas2JSBaseType then
|
|
||||||
begin
|
|
||||||
jbt:=TResElDataPas2JSBaseType(El.CustomData).JSBaseType;
|
|
||||||
case jbt of
|
|
||||||
pbtJSValue:
|
|
||||||
begin
|
|
||||||
// create rtl.basename
|
|
||||||
Result:=CreateMemberExpression([FBuiltInNames[pbivnRTL],lowercase(Pas2jsBaseTypeNames[jbt])]);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
{$IFDEF VerbosePas2JS}
|
|
||||||
writeln('TPasToJSConverter.CreateTypeInfoRef [20170409174539] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' jbt=',Pas2jsBaseTypeNames[jbt]);
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{$IFDEF VerbosePas2JS}
|
|
||||||
writeln('TPasToJSConverter.CreateTypeInfoRef [20170409174645] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' bt=',AContext.Resolver.BaseTypeNames[bt]);
|
|
||||||
{$ENDIF}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
{$IFDEF VerbosePas2JS}
|
|
||||||
writeln('TPasToJSConverter.CreateTypeInfoRef [20170409173746] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' bt=',AContext.Resolver.BaseTypeNames[bt]);
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{$IFDEF VerbosePas2JS}
|
|
||||||
writeln('TPasToJSConverter.CreateTypeInfoRef [20170409173729] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData));
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else if (C=TPasEnumType)
|
|
||||||
or (C=TPasSetType)
|
|
||||||
or (C=TPasClassType)
|
|
||||||
or (C=TPasClassOfType)
|
|
||||||
or (C=TPasArrayType)
|
|
||||||
or (C=TPasProcedureType)
|
|
||||||
or (C=TPasFunctionType)
|
|
||||||
or (C=TPasPointerType)
|
|
||||||
// ToDo or (C=TPasTypeAliasType)
|
|
||||||
or (C=TPasRecordType)
|
|
||||||
// ToDo or (C=TPasRangeType)
|
|
||||||
then
|
|
||||||
begin
|
|
||||||
// user type -> module.$rtti[typename]
|
|
||||||
aName:=TransformVariableName(El,AContext);
|
|
||||||
if aName='' then
|
|
||||||
DoError(20170411230435,nPasElementNotSupported,sPasElementNotSupported,
|
|
||||||
['typeinfo of anonymous '+El.ElementTypeName+' not supported'],ErrorEl);
|
|
||||||
Parent:=El.Parent;
|
|
||||||
while Parent.ClassType=TPasClassType do
|
|
||||||
begin
|
|
||||||
aName:=TransformVariableName(Parent,AContext)+'.'+aName;
|
|
||||||
Parent:=Parent.Parent;
|
|
||||||
end;
|
|
||||||
if Parent is TPasSection then
|
|
||||||
begin
|
|
||||||
aModule:=Parent.Parent as TPasModule;
|
|
||||||
aModName:=AContext.GetLocalName(aModule);
|
|
||||||
if aModName='' then
|
|
||||||
aModName:=TransformModuleName(aModule,true,AContext);
|
|
||||||
Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El));
|
|
||||||
Bracket.MExpr:=CreateMemberExpression([aModName,FBuiltInNames[pbivnRTTI]]);
|
|
||||||
Bracket.Name:=CreateLiteralString(El,aName);
|
|
||||||
Result:=Bracket;
|
|
||||||
exit;
|
|
||||||
end;
|
end;
|
||||||
|
// not supported
|
||||||
|
aName:=El.Name;
|
||||||
|
if aName='' then aName:=El.ClassName;
|
||||||
|
DoError(20170905152041,nTypeXCannotBePublished,sTypeXCannotBePublished,
|
||||||
|
[aName],ErrorEl);
|
||||||
end;
|
end;
|
||||||
aName:=El.Name;
|
|
||||||
if aName='' then aName:=El.ClassName;
|
|
||||||
DoError(20170409173329,nTypeXCannotBePublished,sTypeXCannotBePublished,
|
|
||||||
[aName],ErrorEl);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.CreateRTTIArgList(Parent: TPasElement;
|
function TPasToJSConverter.CreateRTTIArgList(Parent: TPasElement;
|
||||||
@ -9418,7 +9332,7 @@ end;
|
|||||||
function TPasToJSConverter.CreateRTTINewType(El: TPasType;
|
function TPasToJSConverter.CreateRTTINewType(El: TPasType;
|
||||||
const CallFuncName: string; IsForward: boolean; AContext: TConvertContext;
|
const CallFuncName: string; IsForward: boolean; AContext: TConvertContext;
|
||||||
out ObjLit: TJSObjectLiteral): TJSCallExpression;
|
out ObjLit: TJSObjectLiteral): TJSCallExpression;
|
||||||
// module.$rtti.$TiSomething("name",{})
|
// module.$rtti.$Something("name",{})
|
||||||
var
|
var
|
||||||
RttiPath, TypeName: String;
|
RttiPath, TypeName: String;
|
||||||
Call: TJSCallExpression;
|
Call: TJSCallExpression;
|
||||||
@ -9436,10 +9350,10 @@ begin
|
|||||||
|
|
||||||
Call:=CreateCallExpression(El);
|
Call:=CreateCallExpression(El);
|
||||||
try
|
try
|
||||||
// module.$rtti.$ProcVar
|
// module.$rtti.$Something
|
||||||
Call.Expr:=CreateMemberExpression([RttiPath,FBuiltInNames[pbivnRTTI],CallFuncName]);
|
Call.Expr:=CreateMemberExpression([RttiPath,FBuiltInNames[pbivnRTTI],CallFuncName]);
|
||||||
// add param "typename"
|
// add param "typename"
|
||||||
TypeName:=TransformVariableName(El,AContext);
|
TypeName:=GetTypeInfoName(El,AContext,El);
|
||||||
Call.AddArg(CreateLiteralString(El,TypeName));
|
Call.AddArg(CreateLiteralString(El,TypeName));
|
||||||
if not IsForward then
|
if not IsForward then
|
||||||
begin
|
begin
|
||||||
@ -9676,6 +9590,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPasToJSConverter.CreateRTTIAnonymous(El: TPasType;
|
||||||
|
AContext: TConvertContext; var First, Last: TJSStatementList);
|
||||||
|
// if El has any anonymous types, create the RTTI
|
||||||
|
var
|
||||||
|
C: TClass;
|
||||||
|
JS: TJSElement;
|
||||||
|
begin
|
||||||
|
if El.Name<>'' then
|
||||||
|
RaiseNotSupported(El,AContext,20170905162324,'inconsistency');
|
||||||
|
|
||||||
|
C:=El.ClassType;
|
||||||
|
if C=TPasArrayType then
|
||||||
|
begin
|
||||||
|
JS:=ConvertArrayType(TPasArrayType(El),AContext);
|
||||||
|
AddToStatementList(First,Last,JS,El);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.ConvertImplBlock(El: TPasImplBlock;
|
function TPasToJSConverter.ConvertImplBlock(El: TPasImplBlock;
|
||||||
AContext: TConvertContext): TJSElement;
|
AContext: TConvertContext): TJSElement;
|
||||||
|
|
||||||
@ -11950,19 +11882,23 @@ const
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddRTTIFields(Args: TJSArguments);
|
procedure AddRTTIFields(Args: TJSArguments; var First, Last: TJSStatementList);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
PasVar: TPasVariable;
|
PasVar: TPasVariable;
|
||||||
|
VarType: TPasType;
|
||||||
begin
|
begin
|
||||||
for i:=0 to El.Members.Count-1 do
|
for i:=0 to El.Members.Count-1 do
|
||||||
begin
|
begin
|
||||||
PasVar:=TPasVariable(El.Members[i]);
|
PasVar:=TPasVariable(El.Members[i]);
|
||||||
if not IsElementUsed(PasVar) then continue;
|
if not IsElementUsed(PasVar) then continue;
|
||||||
|
VarType:=PasVar.VarType;
|
||||||
|
if VarType.Name='' then
|
||||||
|
CreateRTTIAnonymous(VarType,AContext,First,Last);
|
||||||
// add quoted "fieldname"
|
// add quoted "fieldname"
|
||||||
Args.AddElement(CreateLiteralString(PasVar,TransformVariableName(PasVar,AContext)));
|
Args.AddElement(CreateLiteralString(PasVar,TransformVariableName(PasVar,AContext)));
|
||||||
// add typeinfo ref
|
// add typeinfo ref
|
||||||
Args.AddElement(CreateTypeInfoRef(PasVar.VarType,AContext,PasVar));
|
Args.AddElement(CreateTypeInfoRef(VarType,AContext,PasVar));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -11970,16 +11906,18 @@ var
|
|||||||
AssignSt: TJSSimpleAssignStatement;
|
AssignSt: TJSSimpleAssignStatement;
|
||||||
FDS: TJSFunctionDeclarationStatement;
|
FDS: TJSFunctionDeclarationStatement;
|
||||||
FD: TJSFuncDef;
|
FD: TJSFuncDef;
|
||||||
BodyFirst, BodyLast, List: TJSStatementList;
|
BodyFirst, BodyLast, ListFirst, ListLast: TJSStatementList;
|
||||||
FuncContext: TFunctionContext;
|
FuncContext: TFunctionContext;
|
||||||
ObjLit: TJSObjectLiteral;
|
ObjLit: TJSObjectLiteral;
|
||||||
ObjEl: TJSObjectLiteralElement;
|
ObjEl: TJSObjectLiteralElement;
|
||||||
IfSt: TJSIfStatement;
|
IfSt: TJSIfStatement;
|
||||||
Call: TJSCallExpression;
|
Call, Call2: TJSCallExpression;
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
FuncContext:=nil;
|
FuncContext:=nil;
|
||||||
|
ListFirst:=nil;
|
||||||
|
ListLast:=nil;
|
||||||
ok:=false;
|
ok:=false;
|
||||||
try
|
try
|
||||||
FDS:=CreateFunction(El);
|
FDS:=CreateFunction(El);
|
||||||
@ -12033,12 +11971,10 @@ begin
|
|||||||
if not (AContext is TFunctionContext) then
|
if not (AContext is TFunctionContext) then
|
||||||
RaiseNotSupported(El,AContext,20170412120012);
|
RaiseNotSupported(El,AContext,20170412120012);
|
||||||
|
|
||||||
List:=TJSStatementList(CreateElement(TJSStatementList,El));
|
AddToStatementList(ListFirst,ListLast,Result,El);
|
||||||
List.A:=Result;
|
Result:=nil;
|
||||||
Result:=List;
|
|
||||||
// module.$rtti.$Record("typename",{});
|
// module.$rtti.$Record("typename",{});
|
||||||
Call:=CreateRTTINewType(El,FBuiltInNames[pbifnRTTINewRecord],false,AContext,ObjLit);
|
Call:=CreateRTTINewType(El,FBuiltInNames[pbifnRTTINewRecord],false,AContext,ObjLit);
|
||||||
List.B:=Call;
|
|
||||||
if ObjLit=nil then
|
if ObjLit=nil then
|
||||||
RaiseInconsistency(20170412124804);
|
RaiseInconsistency(20170412124804);
|
||||||
if El.Members.Count>0 then
|
if El.Members.Count>0 then
|
||||||
@ -12046,17 +11982,23 @@ begin
|
|||||||
// module.$rtti.$Record("typename",{}).addFields(
|
// module.$rtti.$Record("typename",{}).addFields(
|
||||||
// "fieldname1",type1,"fieldname2",type2,...
|
// "fieldname1",type1,"fieldname2",type2,...
|
||||||
// );
|
// );
|
||||||
Call:=CreateCallExpression(El);
|
Call2:=CreateCallExpression(El);
|
||||||
Call.Expr:=CreateDotExpression(El,List.B,
|
Call2.Expr:=CreateDotExpression(El,Call,
|
||||||
CreatePrimitiveDotExpr(FBuiltInNames[pbifnRTTIAddFields]));
|
CreatePrimitiveDotExpr(FBuiltInNames[pbifnRTTIAddFields]));
|
||||||
List.B:=Call;
|
Call:=Call2;
|
||||||
AddRTTIFields(Call.Args);
|
AddRTTIFields(Call.Args,ListFirst,ListLast);
|
||||||
end;
|
end;
|
||||||
|
AddToStatementList(ListFirst,ListLast,Call,El);
|
||||||
|
Result:=ListFirst;
|
||||||
|
ListFirst:=nil;
|
||||||
|
ListLast:=nil;
|
||||||
end;
|
end;
|
||||||
ok:=true;;
|
ok:=true;
|
||||||
finally
|
finally
|
||||||
FuncContext.Free;
|
FuncContext.Free;
|
||||||
if not ok then
|
if ListFirst<>nil then
|
||||||
|
FreeAndNil(ListFirst)
|
||||||
|
else if not ok then
|
||||||
FreeAndNil(Result);
|
FreeAndNil(Result);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -12252,6 +12194,153 @@ begin
|
|||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasToJSConverter.GetTypeInfoName(El: TPasType;
|
||||||
|
AContext: TConvertContext; ErrorEl: TPasElement): String;
|
||||||
|
var
|
||||||
|
C: TClass;
|
||||||
|
bt: TResolverBaseType;
|
||||||
|
jbt: TPas2jsBaseType;
|
||||||
|
CurEl: TPasElement;
|
||||||
|
aName: String;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
El:=AContext.Resolver.ResolveAliasType(El);
|
||||||
|
if El=nil then
|
||||||
|
RaiseInconsistency(20170409172756);
|
||||||
|
if El=AContext.PasElement then
|
||||||
|
begin
|
||||||
|
// referring to itself
|
||||||
|
if El is TPasClassType then
|
||||||
|
begin
|
||||||
|
// use this
|
||||||
|
Result:=FBuiltInNames[pbivnRTTILocal];
|
||||||
|
exit;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
RaiseNotSupported(ErrorEl,AContext,20170905150746,'cannot typeinfo itself');
|
||||||
|
end;
|
||||||
|
C:=El.ClassType;
|
||||||
|
if C=TPasUnresolvedSymbolRef then
|
||||||
|
begin
|
||||||
|
if El.Name='' then
|
||||||
|
DoError(20170905150752,nTypeXCannotBePublished,sTypeXCannotBePublished,
|
||||||
|
['typeinfo of anonymous '+El.ElementTypeName],ErrorEl);
|
||||||
|
if El.CustomData is TResElDataBaseType then
|
||||||
|
begin
|
||||||
|
bt:=TResElDataBaseType(El.CustomData).BaseType;
|
||||||
|
case bt of
|
||||||
|
btShortInt,btByte,
|
||||||
|
btSmallInt,btWord,
|
||||||
|
btLongint,btLongWord,
|
||||||
|
btIntDouble,btUIntDouble,
|
||||||
|
btString,btChar,
|
||||||
|
btDouble,
|
||||||
|
btBoolean,
|
||||||
|
btPointer:
|
||||||
|
begin
|
||||||
|
// create rtl.basename
|
||||||
|
Result:=FBuiltInNames[pbivnRTL]+'.'+lowercase(AContext.Resolver.BaseTypeNames[bt]);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
btCustom:
|
||||||
|
if El.CustomData is TResElDataPas2JSBaseType then
|
||||||
|
begin
|
||||||
|
jbt:=TResElDataPas2JSBaseType(El.CustomData).JSBaseType;
|
||||||
|
case jbt of
|
||||||
|
pbtJSValue:
|
||||||
|
begin
|
||||||
|
// create rtl.basename
|
||||||
|
Result:=FBuiltInNames[pbivnRTL]+'.'+lowercase(Pas2jsBaseTypeNames[jbt]);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPasToJSConverter.CreateTypeInfoRef [20170905150833] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' jbt=',Pas2jsBaseTypeNames[jbt]);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPasToJSConverter.CreateTypeInfoRef [20170905150840] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' bt=',AContext.Resolver.BaseTypeNames[bt]);
|
||||||
|
{$ENDIF}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPasToJSConverter.CreateTypeInfoRef [20170905150842] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData),' bt=',AContext.Resolver.BaseTypeNames[bt]);
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPasToJSConverter.CreateTypeInfoRef [20170905150844] El=',GetObjName(El),' El.CustomData=',GetObjName(El.CustomData));
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if (C=TPasEnumType)
|
||||||
|
or (C=TPasSetType)
|
||||||
|
or (C=TPasClassType)
|
||||||
|
or (C=TPasClassOfType)
|
||||||
|
or (C=TPasArrayType)
|
||||||
|
or (C=TPasProcedureType)
|
||||||
|
or (C=TPasFunctionType)
|
||||||
|
or (C=TPasPointerType)
|
||||||
|
// ToDo or (C=TPasTypeAliasType)
|
||||||
|
or (C=TPasRecordType)
|
||||||
|
// ToDo or (C=TPasRangeType)
|
||||||
|
then
|
||||||
|
begin
|
||||||
|
// user type -> module.$rtti[typename]
|
||||||
|
// Notes:
|
||||||
|
// a nested type gets the parent types prepended: classnameA.ElName
|
||||||
|
// an anonymous type gets for each level '$a' prepended
|
||||||
|
// an anonymous type of a variable/argument gets the variable name prepended
|
||||||
|
CurEl:=El;
|
||||||
|
repeat
|
||||||
|
if CurEl.Name<>'' then
|
||||||
|
begin
|
||||||
|
aName:=TransformVariableName(CurEl,AContext);
|
||||||
|
if aName='' then
|
||||||
|
RaiseNotSupported(CurEl,AContext,20170905144902,'name conversion failed');
|
||||||
|
Result:=aName+Result;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// anonymous type -> prepend '$a'
|
||||||
|
// for example:
|
||||||
|
// "var AnArray: array of array of char;" becomes AnArray$a$a
|
||||||
|
Result:=FBuiltInNames[pbitnAnonymousPostfix]+Result;
|
||||||
|
end;
|
||||||
|
CurEl:=CurEl.Parent;
|
||||||
|
if CurEl=nil then
|
||||||
|
break;
|
||||||
|
C:=CurEl.ClassType;
|
||||||
|
if (C=TPasClassType)
|
||||||
|
or (C=TPasRecordType) then
|
||||||
|
// nested
|
||||||
|
Result:='.'+Result
|
||||||
|
else if C.InheritsFrom(TPasType)
|
||||||
|
or (C=TPasVariable)
|
||||||
|
or (C=TPasConst)
|
||||||
|
or (C=TPasArgument)
|
||||||
|
or (C=TPasProperty) then
|
||||||
|
begin
|
||||||
|
// for example: var a: array of longint;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
until false;
|
||||||
|
|
||||||
|
if CurEl is TPasSection then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
aName:=El.Name;
|
||||||
|
if aName='' then aName:=El.ClassName;
|
||||||
|
DoError(20170409173329,nTypeXCannotBePublished,sTypeXCannotBePublished,
|
||||||
|
[aName],ErrorEl);
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.ConvertPasElement(El: TPasElement;
|
function TPasToJSConverter.ConvertPasElement(El: TPasElement;
|
||||||
Resolver: TPas2JSResolver): TJSElement;
|
Resolver: TPas2JSResolver): TJSElement;
|
||||||
var
|
var
|
||||||
|
@ -500,6 +500,7 @@ type
|
|||||||
Procedure TestRTTI_ClassForward;
|
Procedure TestRTTI_ClassForward;
|
||||||
Procedure TestRTTI_ClassOf;
|
Procedure TestRTTI_ClassOf;
|
||||||
Procedure TestRTTI_Record;
|
Procedure TestRTTI_Record;
|
||||||
|
Procedure TestRTTI_RecordAnonymousArray;
|
||||||
Procedure TestRTTI_LocalTypes;
|
Procedure TestRTTI_LocalTypes;
|
||||||
Procedure TestRTTI_TypeInfo_BaseTypes;
|
Procedure TestRTTI_TypeInfo_BaseTypes;
|
||||||
Procedure TestRTTI_TypeInfo_LocalFail;
|
Procedure TestRTTI_TypeInfo_LocalFail;
|
||||||
@ -13381,6 +13382,48 @@ begin
|
|||||||
'']));
|
'']));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestRTTI_RecordAnonymousArray;
|
||||||
|
begin
|
||||||
|
Converter.Options:=Converter.Options-[coNoTypeInfo];
|
||||||
|
StartProgram(false);
|
||||||
|
Add('type');
|
||||||
|
Add(' TFloatRec = record');
|
||||||
|
Add(' d: array of char;');
|
||||||
|
// Add(' i: array of array of longint;');
|
||||||
|
Add(' end;');
|
||||||
|
Add('var p: pointer;');
|
||||||
|
Add(' r: tfloatrec;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' p:=typeinfo(tfloatrec);');
|
||||||
|
Add(' p:=typeinfo(r);');
|
||||||
|
Add(' p:=typeinfo(r.d);');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestRTTI_Record',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.TFloatRec = function (s) {',
|
||||||
|
' if (s) {',
|
||||||
|
' this.d = s.d;',
|
||||||
|
' } else {',
|
||||||
|
' this.d = [];',
|
||||||
|
' };',
|
||||||
|
' this.$equal = function (b) {',
|
||||||
|
' return this.d === b.d;',
|
||||||
|
' };',
|
||||||
|
'};',
|
||||||
|
'$mod.$rtti.$DynArray("TFloatRec.d$a", {',
|
||||||
|
' eltype: rtl.char',
|
||||||
|
'});',
|
||||||
|
'$mod.$rtti.$Record("TFloatRec", {}).addFields("d", $mod.$rtti["TFloatRec.d$a"]);',
|
||||||
|
'this.p = null;',
|
||||||
|
'this.r = new $mod.TFloatRec();',
|
||||||
|
'']),
|
||||||
|
LinesToStr([ // $mod.$main
|
||||||
|
'$mod.p = $mod.$rtti["TFloatRec"];',
|
||||||
|
'$mod.p = $mod.$rtti["TFloatRec"];',
|
||||||
|
'$mod.p = $mod.$rtti["TFloatRec.d$a"];',
|
||||||
|
'']));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestRTTI_LocalTypes;
|
procedure TTestModule.TestRTTI_LocalTypes;
|
||||||
begin
|
begin
|
||||||
Converter.Options:=Converter.Options-[coNoTypeInfo];
|
Converter.Options:=Converter.Options-[coNoTypeInfo];
|
||||||
|
Loading…
Reference in New Issue
Block a user