pastojs: implemented dotted unit reference

git-svn-id: trunk@36118 -
This commit is contained in:
Mattias Gaertner 2017-05-05 14:20:10 +00:00
parent 96f88184ef
commit 4305ffcfa3
2 changed files with 128 additions and 15 deletions

View File

@ -244,6 +244,7 @@ Works:
- ECMAScript6: - ECMAScript6:
- use 0b for binary literals - use 0b for binary literals
- use 0o for octal literals - use 0o for octal literals
- dotted unit names, namespaces
ToDos: ToDos:
- constant evaluation - constant evaluation
@ -266,7 +267,6 @@ ToDos:
- check memleaks - check memleaks
- @@ compare method in delphi mode - @@ compare method in delphi mode
- make records more lightweight - make records more lightweight
- dotted unit names, namespaces
- enumeration for..in..do - enumeration for..in..do
- pointer of record - pointer of record
- nested types in class - nested types in class
@ -10050,7 +10050,7 @@ begin
aModule:=UsesClause[i].Module as TPasModule; aModule:=UsesClause[i].Module as TPasModule;
if (not IsElementUsed(aModule)) and not IsSystemUnit(aModule) then if (not IsElementUsed(aModule)) and not IsSystemUnit(aModule) then
continue; continue;
anUnitName := TransformVariableName(aModule,AContext); anUnitName := TransformModuleName(aModule,false,AContext);
ArgEx := CreateLiteralString(UsesSection,anUnitName); ArgEx := CreateLiteralString(UsesSection,anUnitName);
ArgArray.Elements.AddElement.Expr := ArgEx; ArgArray.Elements.AddElement.Expr := ArgEx;
end; end;
@ -11805,13 +11805,35 @@ end;
function TPasToJSConverter.TransformModuleName(El: TPasModule; function TPasToJSConverter.TransformModuleName(El: TPasModule;
AddModulesPrefix: boolean; AContext: TConvertContext): String; AddModulesPrefix: boolean; AContext: TConvertContext): String;
var
p, StartP: Integer;
aName, Part: String;
begin begin
if El is TPasProgram then if El is TPasProgram then
Result:='program' Result:='program'
else else
Result:=TransformVariableName(El,AContext); begin
Result:='';
aName:=El.Name;
p:=1;
while p<=length(aName) do
begin
StartP:=p;
while (p<=length(aName)) and (aName[p]<>'.') do inc(p);
Part:=copy(aName,StartP,p-StartP);
Part:=TransformVariableName(El,Part,AContext);
if Result<>'' then Result:=Result+'.';
Result:=Result+Part;
inc(p);
end;
end;
if AddModulesPrefix then if AddModulesPrefix then
Result:=FBuiltInNames[pbivnModules]+'.'+Result; begin
if Pos('.',Result)>0 then
Result:=FBuiltInNames[pbivnModules]+'["'+Result+'"]'
else
Result:=FBuiltInNames[pbivnModules]+'.'+Result;
end;
end; end;
function TPasToJSConverter.IsPreservedWord(const aName: string): boolean; function TPasToJSConverter.IsPreservedWord(const aName: string): boolean;

View File

@ -96,6 +96,7 @@ type
function GetModuleCount: integer; function GetModuleCount: integer;
function GetModules(Index: integer): TTestEnginePasResolver; function GetModules(Index: integer): TTestEnginePasResolver;
function OnPasResolverFindUnit(const aUnitName: String): TPasModule; function OnPasResolverFindUnit(const aUnitName: String): TPasModule;
function FindUnit(const aUnitName: String): TPasModule;
protected protected
procedure SetUp; override; procedure SetUp; override;
procedure TearDown; override; procedure TearDown; override;
@ -114,9 +115,9 @@ type
procedure AddSystemUnit; virtual; procedure AddSystemUnit; virtual;
procedure StartProgram(NeedSystemUnit: boolean); virtual; procedure StartProgram(NeedSystemUnit: boolean); virtual;
procedure StartUnit(NeedSystemUnit: boolean); virtual; procedure StartUnit(NeedSystemUnit: boolean); virtual;
Procedure ConvertModule; virtual; procedure ConvertModule; virtual;
Procedure ConvertProgram; virtual; procedure ConvertProgram; virtual;
Procedure ConvertUnit; virtual; procedure ConvertUnit; virtual;
procedure CheckDottedIdentifier(Msg: string; El: TJSElement; DottedName: string); procedure CheckDottedIdentifier(Msg: string; El: TJSElement; DottedName: string);
function GetDottedIdentifier(El: TJSElement): string; function GetDottedIdentifier(El: TJSElement): string;
procedure CheckSource(Msg,Statements: String; InitStatements: string = ''; procedure CheckSource(Msg,Statements: String; InitStatements: string = '';
@ -132,6 +133,7 @@ type
procedure HandleException(E: Exception); procedure HandleException(E: Exception);
procedure RaiseException(E: Exception); procedure RaiseException(E: Exception);
procedure WriteSources(const aFilename: string; aRow, aCol: integer); procedure WriteSources(const aFilename: string; aRow, aCol: integer);
function GetDefaultNamespace: string;
property PasProgram: TPasProgram Read FPasProgram; property PasProgram: TPasProgram Read FPasProgram;
property Modules[Index: integer]: TTestEnginePasResolver read GetModules; property Modules[Index: integer]: TTestEnginePasResolver read GetModules;
property ModuleCount: integer read GetModuleCount; property ModuleCount: integer read GetModuleCount;
@ -169,6 +171,8 @@ type
Procedure TestEmptyProgramUseStrict; Procedure TestEmptyProgramUseStrict;
Procedure TestEmptyUnit; Procedure TestEmptyUnit;
Procedure TestEmptyUnitUseStrict; Procedure TestEmptyUnitUseStrict;
Procedure TestDottedUnitNames;
Procedure TestDottedUnitExpr;
// vars/const // vars/const
Procedure TestVarInt; Procedure TestVarInt;
@ -594,28 +598,48 @@ end;
function TCustomTestModule.OnPasResolverFindUnit(const aUnitName: String function TCustomTestModule.OnPasResolverFindUnit(const aUnitName: String
): TPasModule; ): TPasModule;
var
DefNamespace: String;
begin
//writeln('TTestModule.OnPasResolverFindUnit START Unit="',aUnitName,'"');
if (Pos('.',aUnitName)<1) then
begin
DefNamespace:=GetDefaultNamespace;
if DefNamespace<>'' then
begin
Result:=FindUnit(DefNamespace+'.'+aUnitName);
if Result<>nil then exit;
end;
end;
Result:=FindUnit(aUnitName);
if Result<>nil then exit;
writeln('TTestModule.OnPasResolverFindUnit missing unit "',aUnitName,'"');
Fail('can''t find unit "'+aUnitName+'"');
end;
function TCustomTestModule.FindUnit(const aUnitName: String): TPasModule;
var var
i: Integer; i: Integer;
CurEngine: TTestEnginePasResolver; CurEngine: TTestEnginePasResolver;
CurUnitName: String; CurUnitName: String;
begin begin
//writeln('TTestModule.OnPasResolverFindUnit START Unit="',aUnitName,'"'); //writeln('TTestModule.FindUnit START Unit="',aUnitName,'"');
Result:=nil; Result:=nil;
for i:=0 to ModuleCount-1 do for i:=0 to ModuleCount-1 do
begin begin
CurEngine:=Modules[i]; CurEngine:=Modules[i];
CurUnitName:=ExtractFileUnitName(CurEngine.Filename); CurUnitName:=ExtractFileUnitName(CurEngine.Filename);
//writeln('TTestModule.OnPasResolverFindUnit Checking ',i,'/',ModuleCount,' ',CurEngine.Filename,' ',CurUnitName); //writeln('TTestModule.FindUnit Checking ',i,'/',ModuleCount,' ',CurEngine.Filename,' ',CurUnitName);
if CompareText(aUnitName,CurUnitName)=0 then if CompareText(aUnitName,CurUnitName)=0 then
begin begin
Result:=CurEngine.Module; Result:=CurEngine.Module;
if Result<>nil then exit; if Result<>nil then exit;
//writeln('TTestModule.OnPasResolverFindUnit PARSING unit "',CurEngine.Filename,'"'); //writeln('TTestModule.FindUnit PARSING unit "',CurEngine.Filename,'"');
FileResolver.FindSourceFile(aUnitName); FileResolver.FindSourceFile(aUnitName);
CurEngine.Resolver:=TStreamResolver.Create; CurEngine.Resolver:=TStreamResolver.Create;
CurEngine.Resolver.OwnsStreams:=True; CurEngine.Resolver.OwnsStreams:=True;
//writeln('TTestResolver.OnPasResolverFindUnit SOURCE=',CurEngine.Source); //writeln('TTestModule.FindUnit SOURCE=',CurEngine.Source);
CurEngine.Resolver.AddStream(CurEngine.FileName,TStringStream.Create(CurEngine.Source)); CurEngine.Resolver.AddStream(CurEngine.FileName,TStringStream.Create(CurEngine.Source));
CurEngine.Scanner:=TPascalScanner.Create(CurEngine.Resolver); CurEngine.Scanner:=TPascalScanner.Create(CurEngine.Resolver);
CurEngine.Parser:=TTestPasParser.Create(CurEngine.Scanner,CurEngine.Resolver,CurEngine); CurEngine.Parser:=TTestPasParser.Create(CurEngine.Scanner,CurEngine.Resolver,CurEngine);
@ -634,13 +658,11 @@ begin
on E: Exception do on E: Exception do
HandleException(E); HandleException(E);
end; end;
//writeln('TTestModule.OnPasResolverFindUnit END ',CurUnitName); //writeln('TTestModule.FindUnit END ',CurUnitName);
Result:=CurEngine.Module; Result:=CurEngine.Module;
exit; exit;
end; end;
end; end;
writeln('TTestModule.OnPasResolverFindUnit missing unit "',aUnitName,'"');
Fail('can''t find unit "'+aUnitName+'"');
end; end;
procedure TCustomTestModule.SetUp; procedure TCustomTestModule.SetUp;
@ -844,7 +866,7 @@ begin
AddSystemUnit AddSystemUnit
else else
Parser.ImplicitUses.Clear; Parser.ImplicitUses.Clear;
Add('program test1;'); Add('program '+ExtractFileUnitName(Filename)+';');
Add(''); Add('');
end; end;
@ -1343,6 +1365,17 @@ begin
end; end;
end; end;
function TCustomTestModule.GetDefaultNamespace: string;
var
C: TClass;
begin
Result:='';
if FModule=nil then exit;
C:=FModule.ClassType;
if (C=TPasProgram) or (C=TPasLibrary) or (C=TPasPackage) then
Result:=Engine.DefaultNameSpace;
end;
{ TTestModule } { TTestModule }
procedure TTestModule.TestEmptyProgram; procedure TTestModule.TestEmptyProgram;
@ -1388,6 +1421,64 @@ begin
''); '');
end; end;
procedure TTestModule.TestDottedUnitNames;
begin
AddModuleWithIntfImplSrc('NS1.Unit2.pas',
LinesToStr([
'var iV: longint;'
]),
'');
FFilename:='ns1.test1.pp';
StartProgram(true);
Add('uses unIt2;');
Add('implementation');
Add('var');
Add(' i: longint;');
Add('begin');
Add(' i:=iv;');
Add(' i:=uNit2.iv;');
Add(' i:=Ns1.TEst1.i;');
ConvertProgram;
CheckSource('TestDottedUnitNames',
LinesToStr([
'this.i = 0;',
'']),
LinesToStr([ // this.$init
'$mod.i = pas["NS1.Unit2"].iV;',
'$mod.i = pas["NS1.Unit2"].iV;',
'$mod.i = $mod.i;',
'']) );
end;
procedure TTestModule.TestDottedUnitExpr;
begin
AddModuleWithIntfImplSrc('NS2.SubNs2.Unit2.pas',
LinesToStr([
'procedure DoIt;'
]),
'procedure DoIt; begin end;');
FFilename:='Ns1.SubNs1.Test1.pp';
StartProgram(true);
Add('uses Ns2.sUbnS2.unIt2;');
Add('implementation');
Add('var');
Add(' i: longint;');
Add('begin');
Add(' ns2.subns2.unit2.doit;');
Add(' i:=Ns1.SubNS1.TEst1.i;');
ConvertProgram;
CheckSource('TestDottedUnitExpr',
LinesToStr([
'this.i = 0;',
'']),
LinesToStr([ // this.$init
'pas["NS2.SubNs2.Unit2"].DoIt();',
'$mod.i = $mod.i;',
'']) );
end;
procedure TTestModule.TestVarInt; procedure TTestModule.TestVarInt;
begin begin
StartProgram(false); StartProgram(false);