pastojs: library added rtl.run, moved exports behind rtl.run, fixed export unit symbols

This commit is contained in:
mattias 2022-02-06 19:16:48 +01:00
parent 568d4de77e
commit 621dcbeaf2
4 changed files with 110 additions and 27 deletions

View File

@ -1014,7 +1014,7 @@ Type
function GetNamedExports: TJSExportNameElements;
Public
Destructor Destroy; override;
Property IsDefault : Boolean Read FIsDefault Write FIsDefault;
Property IsDefault : Boolean Read FIsDefault Write FIsDefault; // write *
Property Declaration : TJSElement Read FDeclaration Write FDeclaration;
Property NameSpaceExport : TJSString Read FNameSpaceExport Write FNameSpaceExport;
Property ModuleName : TJSString Read FModuleName Write FModuleName;

View File

@ -282,6 +282,7 @@ type
procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess;
UseFull: boolean); virtual;
procedure UseResourcestring(El: TPasResString); virtual;
procedure UseExportSymbol(El: TPasExportSymbol); virtual;
procedure UseArgument(El: TPasArgument; Access: TResolvedRefAccess); virtual;
procedure UseResultElement(El: TPasResultElement; Access: TResolvedRefAccess); virtual;
// create hints for a unit, program or library
@ -1467,6 +1468,8 @@ begin
end
else if C=TPasAttributes then
// attributes are never used directly
else if C=TPasExportSymbol then
UseExportSymbol(TPasExportSymbol(Decl))
else
RaiseNotSupported(20170306165213,Decl);
end;
@ -2622,6 +2625,24 @@ begin
UseExpr(El.Expr);
end;
procedure TPasAnalyzer.UseExportSymbol(El: TPasExportSymbol);
var
Ref: TResolvedReference;
Decl: TPasElement;
begin
if not MarkElementAsUsed(El) then exit;
if El.CustomData is TResolvedReference then
begin
Ref:=TResolvedReference(El.CustomData);
Decl:=Ref.Declaration;
if Decl<>nil then
UseElement(Decl,Ref.Access,false);
end;
UseExpr(El.NameExpr);
UseExpr(El.ExportName);
UseExpr(El.ExportIndex);
end;
procedure TPasAnalyzer.UseArgument(El: TPasArgument; Access: TResolvedRefAccess
);
var

View File

@ -2097,6 +2097,7 @@ type
Function CreateImplementationSection(El: TPasModule; IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual;
Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual;
Procedure CreateExportsSection(El: TPasLibrary; Src: TJSSourceElements; AContext: TConvertContext); virtual;
Function AddLibraryRun(El: TPasLibrary; ModuleName: string; Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression; virtual;
Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual;
function AddDelayedInits(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext): boolean; virtual;
@ -8207,7 +8208,10 @@ Library:
<initialization>
};
});
export1 = pas.unit1.func1;
rtl.run('library');
var li = pas['library'];
export const func1 = pas.unit1.func1;
export const var1 = li.var1;
Unit without implementation:
rtl.module('<unitname>',
@ -8337,7 +8341,6 @@ begin
if Assigned(Lib.LibrarySection) then
AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext));
HasImplCode:=AddDelayedInits(Lib,Src,IntfContext);
CreateExportsSection(Lib,Src,IntfContext);
CreateInitSection(Lib,Src,IntfContext);
end
else
@ -8387,6 +8390,14 @@ begin
if (ModScope<>nil) and (coStoreImplJS in Options) then
StoreImplJSLocals(ModScope,IntfContext);
if El is TPasLibrary then
begin // library
Lib:=TPasLibrary(El);
AddLibraryRun(Lib,ModuleName,OuterSrc,AContext);
CreateExportsSection(Lib,OuterSrc,AContext);
end;
ok:=true;
finally
IntfContext.Free;
@ -18096,6 +18107,24 @@ begin
end;
end;
function TPasToJSConverter.AddLibraryRun(El: TPasLibrary; ModuleName: string;
Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression;
var
Call: TJSCallExpression;
begin
if AContext=nil then ;
// add rtl.run('library');
Call:=CreateCallExpression(El);
AddToSourceElements(Src,Call);
Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),'run']);
// add module name parameter
Call.AddArg(CreateLiteralString(El,ModuleName));
Result:=Call;
end;
procedure TPasToJSConverter.AddHeaderStatement(JS: TJSElement;
PosEl: TPasElement; aContext: TConvertContext);
var

View File

@ -179,6 +179,7 @@ type
function GetDottedIdentifier(El: TJSElement): string;
procedure CheckSource(Msg,Statements: String; InitStatements: string = '';
ImplStatements: string = ''); virtual;
procedure CheckFullSource(Msg,ExpectedSrc: String); virtual;
procedure CheckDiff(Msg, Expected, Actual: string); virtual;
procedure CheckUnit(Filename, ExpectedSrc: string); virtual;
procedure CheckHint(MsgType: TMessageType; MsgNumber: integer;
@ -919,9 +920,9 @@ type
Procedure TestLibrary_Export_Index_Fail;
Procedure TestLibrary_ExportVar;
Procedure TestLibrary_ExportUnitFunc;
// todo: test fail on export overloaded function
// ToDo: test delayed specialization init
// ToDo: analyzer
// ToDo: shortrefoptimization
end;
function LinesToStr(Args: array of const): string;
@ -1989,7 +1990,7 @@ var
InitFunction: TJSFunctionDeclarationStatement;
InitAssign: TJSSimpleAssignStatement;
InitName: String;
LastNode: TJSElement;
LastNode, FirstNode: TJSElement;
Arg: TJSArrayLiteralElement;
IsProg, IsLib: Boolean;
begin
@ -2020,10 +2021,12 @@ begin
{$ENDIF}
// rtl.module(...
AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count);
AssertNotNull('register module call',JSModule.Statements.Nodes[0].Node);
AssertEquals('register module call',TJSCallExpression,JSModule.Statements.Nodes[0].Node.ClassType);
FJSRegModuleCall:=JSModule.Statements.Nodes[0].Node as TJSCallExpression;
if JSModule.Statements.Count<1 then
AssertEquals('jsmodule has at least one statement - the call',1,JSModule.Statements.Count);
FirstNode:=JSModule.Statements.Nodes[0].Node;
AssertNotNull('register module call',FirstNode);
AssertEquals('register module call',TJSCallExpression,FirstNode.ClassType);
FJSRegModuleCall:=FirstNode as TJSCallExpression;
AssertNotNull('register module rtl.module expr',JSRegModuleCall.Expr);
AssertNotNull('register module rtl.module args',JSRegModuleCall.Args);
AssertEquals('rtl.module args',TJSArguments,JSRegModuleCall.Args.ClassType);
@ -2037,11 +2040,17 @@ begin
ModuleNameExpr:=Arg.Expr as TJSLiteral;
AssertEquals('module name param is string',ord(jstString),ord(ModuleNameExpr.Value.ValueType));
if IsProg then
AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString))
begin
AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString));
AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count);
end
else if IsLib then
AssertEquals('module name','library',String(ModuleNameExpr.Value.AsString))
else
begin
AssertEquals('module name',Module.Name,String(ModuleNameExpr.Value.AsString));
AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count);
end;
// main uses section
if JSModuleCallArgs.Elements.Count<2 then
@ -2187,6 +2196,14 @@ begin
CheckDiff(Msg,ExpectedSrc,ActualSrc);
end;
procedure TCustomTestModule.CheckFullSource(Msg, ExpectedSrc: String);
var
ActualSrc: String;
begin
ActualSrc:=JSToStr(JSModule);
CheckDiff(Msg,ExpectedSrc,ActualSrc);
end;
procedure TCustomTestModule.CheckDiff(Msg, Expected, Actual: string);
// search diff, ignore changes in spaces
var
@ -34134,10 +34151,14 @@ begin
Add([
'']);
ConvertLibrary;
CheckSource('TestLibrary_Empty',
CheckFullSource('TestLibrary_Empty',
LinesToStr([ // statements
'']),
LinesToStr([
'rtl.module("library", [], function () {',
' var $mod = this;',
' $mod.$main = function () {',
' };',
'});',
'rtl.run("library");',
'']));
CheckResolverUnexpectedHints();
end;
@ -34155,13 +34176,17 @@ begin
' test1.run name ''Test1Run'';',
'']);
ConvertLibrary;
CheckSource('TestLibrary_ExportFunc',
CheckFullSource('TestLibrary_ExportFunc',
LinesToStr([ // statements
'this.Run = function (w) {',
'};',
'export { this.Run as Run, this.Run as Foo, this.Run as Test1Run };',
'']),
LinesToStr([
'rtl.module("library", [], function () {',
' var $mod = this;',
' this.Run = function (w) {',
' };',
' $mod.$main = function () {',
' };',
'});',
'rtl.run("library");',
'export { pas.library.Run as Run, pas.library.Run as Foo, pas.library.Run as Test1Run };',
'']));
CheckResolverUnexpectedHints();
end;
@ -34207,12 +34232,16 @@ begin
' Wing;',
'']);
ConvertLibrary;
CheckSource('TestLibrary_ExportVar',
CheckFullSource('TestLibrary_ExportVar',
LinesToStr([ // statements
'this.Wing = 0;',
'export { this.Wing as Wing };',
'']),
LinesToStr([
'rtl.module("library", [], function () {',
' var $mod = this;',
' this.Wing = 0;',
' $mod.$main = function () {',
' };',
'});',
'rtl.run("library");',
'export { pas.library.Wing as Wing };',
'']));
CheckResolverUnexpectedHints();
end;
@ -34244,11 +34273,15 @@ begin
' TAnt.Crawl;',
'']);
ConvertLibrary;
CheckSource('TestLibrary_ExportUnitFunc',
CheckFullSource('TestLibrary_ExportUnitFunc',
LinesToStr([ // statements
'rtl.module("library", ["system", "Unit1"], function () {',
' var $mod = this;',
' $mod.$main = function () {',
' };',
'});',
'rtl.run("library");',
'export { pas.Unit1.Fly as Fly, pas.Unit1.TAnt.Crawl as Crawl };',
'']),
LinesToStr([
'']));
CheckResolverUnexpectedHints();
end;