mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 05:29:30 +02:00
pastojs: implemented funcname:=
git-svn-id: trunk@37389 -
This commit is contained in:
parent
abd8907939
commit
58454f555a
@ -43,6 +43,7 @@ Works:
|
|||||||
- modifier public to protect from removing by optimizer
|
- modifier public to protect from removing by optimizer
|
||||||
- choose overloads based on type and precision
|
- choose overloads based on type and precision
|
||||||
- fail overload on multiple with loss of precision or one used default param
|
- fail overload on multiple with loss of precision or one used default param
|
||||||
|
- FuncName:=, auto rename lower lvl Result variables
|
||||||
- assign statements
|
- assign statements
|
||||||
- char
|
- char
|
||||||
- literals
|
- literals
|
||||||
@ -110,6 +111,7 @@ Works:
|
|||||||
- const
|
- const
|
||||||
- bracket accessor, getter/setter has external name '[]'
|
- bracket accessor, getter/setter has external name '[]'
|
||||||
- TObject.Free sets variable to nil
|
- TObject.Free sets variable to nil
|
||||||
|
- property stored and index modifier
|
||||||
- dynamic arrays
|
- dynamic arrays
|
||||||
- arrays can be null
|
- arrays can be null
|
||||||
- init as "arr = []" so typeof works
|
- init as "arr = []" so typeof works
|
||||||
@ -223,7 +225,7 @@ Works:
|
|||||||
- callback: assign to jsvalue, equal, not equal
|
- callback: assign to jsvalue, equal, not equal
|
||||||
- RTTI
|
- RTTI
|
||||||
- base types
|
- base types
|
||||||
- unit $rtti
|
- $mod.$rtti
|
||||||
- enum type tkEnumeration
|
- enum type tkEnumeration
|
||||||
- set type tkSet
|
- set type tkSet
|
||||||
- procedure type tkProcVar, tkMethod
|
- procedure type tkProcVar, tkMethod
|
||||||
@ -241,7 +243,7 @@ Works:
|
|||||||
- typeinfo(class) -> class.$rtti
|
- typeinfo(class) -> class.$rtti
|
||||||
- WPO skip not used typeinfo
|
- WPO skip not used typeinfo
|
||||||
- open array param
|
- open array param
|
||||||
- property stored modifier
|
- property stored and index modifier
|
||||||
- property default value
|
- property default value
|
||||||
- pointer
|
- pointer
|
||||||
- compare with and assign nil
|
- compare with and assign nil
|
||||||
@ -251,22 +253,18 @@ Works:
|
|||||||
- dotted unit names, namespaces
|
- dotted unit names, namespaces
|
||||||
|
|
||||||
ToDos:
|
ToDos:
|
||||||
- ignore attributes
|
|
||||||
- static arrays
|
- static arrays
|
||||||
- a[][]
|
|
||||||
- a[] of record
|
- a[] of record
|
||||||
- RTTI
|
|
||||||
- property index specifier
|
|
||||||
- RTTI
|
- RTTI
|
||||||
- class property
|
- class property
|
||||||
- type alias type
|
- type alias type
|
||||||
- documentation
|
- documentation
|
||||||
- move local types to unit scope
|
- move local types to unit scope
|
||||||
- var absolute
|
- var absolute
|
||||||
- FuncName:= (instead of Result:=)
|
|
||||||
- check memleaks
|
- check memleaks
|
||||||
- make records more lightweight
|
- make records more lightweight
|
||||||
- enumeration for..in..do
|
- enumeration for..in..do
|
||||||
|
- resourcestring
|
||||||
- pointer of record
|
- pointer of record
|
||||||
- nested types in class
|
- nested types in class
|
||||||
- asm: pas() - useful for overloads and protect an identifier from optimization
|
- asm: pas() - useful for overloads and protect an identifier from optimization
|
||||||
@ -756,11 +754,20 @@ type
|
|||||||
end;
|
end;
|
||||||
TPas2JsElementDataClass = class of TPas2JsElementData;
|
TPas2JsElementDataClass = class of TPas2JsElementData;
|
||||||
|
|
||||||
|
{ TPas2JSClassScope }
|
||||||
|
|
||||||
TPas2JSClassScope = class(TPasClassScope)
|
TPas2JSClassScope = class(TPasClassScope)
|
||||||
public
|
public
|
||||||
NewInstanceFunction: TPasClassFunction;
|
NewInstanceFunction: TPasClassFunction;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPas2JSProcedureScope }
|
||||||
|
|
||||||
|
TPas2JSProcedureScope = class(TPasProcedureScope)
|
||||||
|
public
|
||||||
|
ResultVarName: string; // valid in implementation ProcScope, empty means use ResolverResultVar
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPas2JSWithExprScope }
|
{ TPas2JSWithExprScope }
|
||||||
|
|
||||||
TPas2JSWithExprScope = class(TPasWithExprScope)
|
TPas2JSWithExprScope = class(TPasWithExprScope)
|
||||||
@ -1918,6 +1925,47 @@ procedure TPas2JSResolver.ResolveNameExpr(El: TPasExpr; const aName: string;
|
|||||||
RaiseMsg(20170516152455,nFreeNeedsVar,sFreeNeedsVar,[],El);
|
RaiseMsg(20170516152455,nFreeNeedsVar,sFreeNeedsVar,[],El);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure CheckResultEl(Ref: TResolvedReference);
|
||||||
|
var
|
||||||
|
Func: TPasFunction;
|
||||||
|
CurEl: TPasElement;
|
||||||
|
Lvl: Integer;
|
||||||
|
ProcScope, CurProcScope: TPas2JSProcedureScope;
|
||||||
|
begin
|
||||||
|
// result refers to a function result
|
||||||
|
// -> check if it is referring to a parent function result
|
||||||
|
Lvl:=0;
|
||||||
|
CurEl:=El;
|
||||||
|
CurProcScope:=nil;
|
||||||
|
while CurEl<>nil do
|
||||||
|
begin
|
||||||
|
if CurEl is TPasFunction then
|
||||||
|
begin
|
||||||
|
inc(Lvl);
|
||||||
|
ProcScope:=CurEl.CustomData as TPas2JSProcedureScope;
|
||||||
|
Func:=ProcScope.DeclarationProc as TPasFunction;
|
||||||
|
if Func=nil then
|
||||||
|
Func:=TPasFunction(CurEl);
|
||||||
|
if Lvl=1 then
|
||||||
|
begin
|
||||||
|
// current function (where the statement of El is)
|
||||||
|
if (Func.FuncType.ResultEl=Ref.Declaration) then
|
||||||
|
exit; // accessing current function -> ok
|
||||||
|
// accessing Result variable of higher function -> need rename
|
||||||
|
if ProcScope.ResultVarName<>'' then
|
||||||
|
exit; // is already renamed
|
||||||
|
CurProcScope:=ProcScope;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
CurEl:=CurEl.Parent;
|
||||||
|
end;
|
||||||
|
if Lvl<2 then
|
||||||
|
RaiseNotYetImplemented(20171003112020,El);
|
||||||
|
// El refers to a higher Result variable
|
||||||
|
// -> current function needs another name for its Result variable
|
||||||
|
CurProcScope.ResultVarName:=ResolverResultVar+'$'+IntToStr(Lvl-1);
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
Ref: TResolvedReference;
|
Ref: TResolvedReference;
|
||||||
begin
|
begin
|
||||||
@ -1926,7 +1974,9 @@ begin
|
|||||||
begin
|
begin
|
||||||
Ref:=TResolvedReference(El.CustomData);
|
Ref:=TResolvedReference(El.CustomData);
|
||||||
if (CompareText(aName,'free')=0) then
|
if (CompareText(aName,'free')=0) then
|
||||||
CheckTObjectFree(Ref);
|
CheckTObjectFree(Ref)
|
||||||
|
else if (Ref.Declaration is TPasResultElement) then
|
||||||
|
CheckResultEl(Ref);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2720,6 +2770,7 @@ begin
|
|||||||
StoreSrcColumns:=true;
|
StoreSrcColumns:=true;
|
||||||
Options:=Options+DefaultPasResolverOptions;
|
Options:=Options+DefaultPasResolverOptions;
|
||||||
ScopeClass_Class:=TPas2JSClassScope;
|
ScopeClass_Class:=TPas2JSClassScope;
|
||||||
|
ScopeClass_Procedure:=TPas2JSProcedureScope;
|
||||||
ScopeClass_WithExpr:=TPas2JSWithExprScope;
|
ScopeClass_WithExpr:=TPas2JSWithExprScope;
|
||||||
for bt in [pbtJSValue] do
|
for bt in [pbtJSValue] do
|
||||||
AddJSBaseType(Pas2jsBaseTypeNames[bt],bt);
|
AddJSBaseType(Pas2jsBaseTypeNames[bt],bt);
|
||||||
@ -4507,6 +4558,8 @@ var
|
|||||||
ProcType, TargetProcType: TPasProcedureType;
|
ProcType, TargetProcType: TPasProcedureType;
|
||||||
ArrLit: TJSArrayLiteral;
|
ArrLit: TJSArrayLiteral;
|
||||||
IndexExpr: TPasExpr;
|
IndexExpr: TPasExpr;
|
||||||
|
Func: TPasFunction;
|
||||||
|
FuncScope: TPas2JSProcedureScope;
|
||||||
begin
|
begin
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
if not (El.CustomData is TResolvedReference) then
|
if not (El.CustomData is TResolvedReference) then
|
||||||
@ -4683,7 +4736,7 @@ begin
|
|||||||
|
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
writeln('TPasToJSConverter.ConvertIdentifierExpr ',GetObjName(El),' Decl=',GetObjName(Decl),' Decl.Parent=',GetObjName(Decl.Parent));
|
writeln('TPasToJSConverter.ConvertIdentifierExpr ',GetObjName(El),' Decl=',GetObjName(Decl),' Decl.Parent=',GetObjName(Decl.Parent));
|
||||||
//if CompareText(aName,'Self')=0 then
|
//if CompareText(aName,'Result')=0 then
|
||||||
// begin
|
// begin
|
||||||
// writeln('TPasToJSConverter.ConvertIdentifierExpr AContext=',GetObjName(AContext),' SelfContext=',GetObjName(AContext.GetSelfContext),' LocalVar=',AContext.GetLocalName(Decl),' ',GetObjName(Decl));
|
// writeln('TPasToJSConverter.ConvertIdentifierExpr AContext=',GetObjName(AContext),' SelfContext=',GetObjName(AContext.GetSelfContext),' LocalVar=',AContext.GetLocalName(Decl),' ',GetObjName(Decl));
|
||||||
// AContext.WriteStack;
|
// AContext.WriteStack;
|
||||||
@ -4692,8 +4745,16 @@ begin
|
|||||||
|
|
||||||
if Decl is TPasModule then
|
if Decl is TPasModule then
|
||||||
Name:=TransformModuleName(TPasModule(Decl),true,AContext)
|
Name:=TransformModuleName(TPasModule(Decl),true,AContext)
|
||||||
else if (Decl is TPasFunctionType) and (CompareText(ResolverResultVar,aName)=0) then
|
else if (Decl is TPasResultElement) then
|
||||||
Name:=ResolverResultVar
|
begin
|
||||||
|
Name:=ResolverResultVar;
|
||||||
|
Func:=Decl.Parent as TPasFunction;
|
||||||
|
FuncScope:=Func.CustomData as TPas2JSProcedureScope;
|
||||||
|
if FuncScope.ImplProc<>nil then
|
||||||
|
FuncScope:=FuncScope.ImplProc.CustomData as TPas2JSProcedureScope;
|
||||||
|
if FuncScope.ResultVarName<>'' then
|
||||||
|
Name:=FuncScope.ResultVarName;
|
||||||
|
end
|
||||||
else if Decl.ClassType=TPasEnumValue then
|
else if Decl.ClassType=TPasEnumValue then
|
||||||
begin
|
begin
|
||||||
if UseEnumNumbers then
|
if UseEnumNumbers then
|
||||||
@ -6469,6 +6530,8 @@ function TPasToJSConverter.ConvertBuiltIn_Exit(El: TPasExpr;
|
|||||||
// convert "exit(param);" -> "return param;"
|
// convert "exit(param);" -> "return param;"
|
||||||
var
|
var
|
||||||
ProcEl: TPasElement;
|
ProcEl: TPasElement;
|
||||||
|
Scope: TPas2JSProcedureScope;
|
||||||
|
VarName: String;
|
||||||
begin
|
begin
|
||||||
Result:=TJSReturnStatement(CreateElement(TJSReturnStatement,El));
|
Result:=TJSReturnStatement(CreateElement(TJSReturnStatement,El));
|
||||||
if (El is TParamsExpr) and (length(TParamsExpr(El).Params)>0) then
|
if (El is TParamsExpr) and (length(TParamsExpr(El).Params)>0) then
|
||||||
@ -6483,8 +6546,14 @@ begin
|
|||||||
while (ProcEl<>nil) and not (ProcEl is TPasProcedure) do
|
while (ProcEl<>nil) and not (ProcEl is TPasProcedure) do
|
||||||
ProcEl:=ProcEl.Parent;
|
ProcEl:=ProcEl.Parent;
|
||||||
if ProcEl is TPasFunction then
|
if ProcEl is TPasFunction then
|
||||||
|
begin
|
||||||
// in a function, "return result;"
|
// in a function, "return result;"
|
||||||
TJSReturnStatement(Result).Expr:=CreatePrimitiveDotExpr(ResolverResultVar,El)
|
Scope:=ProcEl.CustomData as TPas2JSProcedureScope;
|
||||||
|
VarName:=Scope.ResultVarName;
|
||||||
|
if VarName='' then
|
||||||
|
VarName:=ResolverResultVar;
|
||||||
|
TJSReturnStatement(Result).Expr:=CreatePrimitiveDotExpr(VarName,El);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
; // in a procedure, "return;" which means "return undefined;"
|
; // in a procedure, "return;" which means "return undefined;"
|
||||||
end;
|
end;
|
||||||
@ -7624,6 +7693,7 @@ Var
|
|||||||
ProcScope: TPasProcedureScope;
|
ProcScope: TPasProcedureScope;
|
||||||
ProcBody: TPasImplBlock;
|
ProcBody: TPasImplBlock;
|
||||||
ResultEl: TPasResultElement;
|
ResultEl: TPasResultElement;
|
||||||
|
ResultVarName: String;
|
||||||
|
|
||||||
Procedure Add(NewEl: TJSElement; PosEl: TPasElement);
|
Procedure Add(NewEl: TJSElement; PosEl: TPasElement);
|
||||||
begin
|
begin
|
||||||
@ -7646,14 +7716,20 @@ Var
|
|||||||
PasFun: TPasFunction;
|
PasFun: TPasFunction;
|
||||||
FunType: TPasFunctionType;
|
FunType: TPasFunctionType;
|
||||||
SrcEl: TPasElement;
|
SrcEl: TPasElement;
|
||||||
|
Scope: TPas2JSProcedureScope;
|
||||||
begin
|
begin
|
||||||
PasFun:=El.Parent as TPasFunction;
|
PasFun:=El.Parent as TPasFunction;
|
||||||
FunType:=PasFun.FuncType;
|
FunType:=PasFun.FuncType;
|
||||||
ResultEl:=FunType.ResultEl;
|
ResultEl:=FunType.ResultEl;
|
||||||
|
Scope:=PasFun.CustomData as TPas2JSProcedureScope;
|
||||||
|
if Scope.ResultVarName<>'' then
|
||||||
|
ResultVarName:=Scope.ResultVarName
|
||||||
|
else
|
||||||
|
ResultVarName:=ResolverResultVar;
|
||||||
|
|
||||||
// add 'var result=initvalue'
|
// add 'var result=initvalue'
|
||||||
SrcEl:=ResultEl;
|
SrcEl:=ResultEl;
|
||||||
VarSt:=CreateVarStatement(ResolverResultVar,
|
VarSt:=CreateVarStatement(ResultVarName,
|
||||||
CreateValInit(ResultEl.ResultType,nil,SrcEl,aContext),ResultEl);
|
CreateValInit(ResultEl.ResultType,nil,SrcEl,aContext),ResultEl);
|
||||||
Add(VarSt,ResultEl);
|
Add(VarSt,ResultEl);
|
||||||
Result:=SLFirst;
|
Result:=SLFirst;
|
||||||
@ -7664,7 +7740,7 @@ Var
|
|||||||
RetSt: TJSReturnStatement;
|
RetSt: TJSReturnStatement;
|
||||||
begin
|
begin
|
||||||
RetSt:=TJSReturnStatement(CreateElement(TJSReturnStatement,ResultEl));
|
RetSt:=TJSReturnStatement(CreateElement(TJSReturnStatement,ResultEl));
|
||||||
RetSt.Expr:=CreatePrimitiveDotExpr(ResolverResultVar,ResultEl);
|
RetSt.Expr:=CreatePrimitiveDotExpr(ResultVarName,ResultEl);
|
||||||
Add(RetSt,ResultEl);
|
Add(RetSt,ResultEl);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -7687,6 +7763,7 @@ begin
|
|||||||
SLFirst:=nil;
|
SLFirst:=nil;
|
||||||
SLLast:=nil;
|
SLLast:=nil;
|
||||||
ResultEl:=nil;
|
ResultEl:=nil;
|
||||||
|
ResultVarName:='';
|
||||||
|
|
||||||
if HasResult then
|
if HasResult then
|
||||||
AddFunctionResultInit;
|
AddFunctionResultInit;
|
||||||
|
@ -2220,6 +2220,7 @@ begin
|
|||||||
Add('function Func1: longint;');
|
Add('function Func1: longint;');
|
||||||
Add('begin');
|
Add('begin');
|
||||||
Add(' Result:=3;');
|
Add(' Result:=3;');
|
||||||
|
Add(' Func1:=4;');
|
||||||
Add('end;');
|
Add('end;');
|
||||||
Add('begin');
|
Add('begin');
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
@ -2228,6 +2229,7 @@ begin
|
|||||||
'this.Func1 = function () {',
|
'this.Func1 = function () {',
|
||||||
' var Result = 0;',
|
' var Result = 0;',
|
||||||
' Result = 3;',
|
' Result = 3;',
|
||||||
|
' Result = 4;',
|
||||||
' return Result;',
|
' return Result;',
|
||||||
'};'
|
'};'
|
||||||
]),
|
]),
|
||||||
@ -2237,20 +2239,26 @@ end;
|
|||||||
procedure TTestModule.TestNestedProc;
|
procedure TTestModule.TestNestedProc;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('var vInUnit: longint;');
|
Add([
|
||||||
Add('function DoIt(pA,pD: longint): longint;');
|
'var vInUnit: longint;',
|
||||||
Add('var');
|
'function DoIt(pA,pD: longint): longint;',
|
||||||
Add(' vB: longint;');
|
'var',
|
||||||
Add(' vC: longint;');
|
' vB: longint;',
|
||||||
Add(' function Nesty(pA: longint): longint; ');
|
' vC: longint;',
|
||||||
Add(' var vB: longint;');
|
' function Nesty(pA: longint): longint; ',
|
||||||
Add(' begin');
|
' var vB: longint;',
|
||||||
Add(' Result:=pa+vb+vc+pd+vInUnit;');
|
' begin',
|
||||||
Add(' end;');
|
' Result:=pa+vb+vc+pd+vInUnit;',
|
||||||
Add('begin');
|
' nesty:=3;',
|
||||||
Add(' Result:=pa+vb+vc;');
|
' doit:=4;',
|
||||||
Add('end;');
|
' exit;',
|
||||||
Add('begin');
|
' end;',
|
||||||
|
'begin',
|
||||||
|
' Result:=pa+vb+vc;',
|
||||||
|
' doit:=6;',
|
||||||
|
' exit;',
|
||||||
|
'end;',
|
||||||
|
'begin']);
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestNestedProc',
|
CheckSource('TestNestedProc',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
@ -2260,12 +2268,17 @@ begin
|
|||||||
' var vB = 0;',
|
' var vB = 0;',
|
||||||
' var vC = 0;',
|
' var vC = 0;',
|
||||||
' function Nesty(pA) {',
|
' function Nesty(pA) {',
|
||||||
' var Result = 0;',
|
' var Result$1 = 0;',
|
||||||
' var vB = 0;',
|
' var vB = 0;',
|
||||||
' Result = (((pA + vB) + vC) + pD) + $mod.vInUnit;',
|
' Result$1 = (((pA + vB) + vC) + pD) + $mod.vInUnit;',
|
||||||
' return Result;',
|
' Result$1 = 3;',
|
||||||
|
' Result = 4;',
|
||||||
|
' return Result$1;',
|
||||||
|
' return Result$1;',
|
||||||
' };',
|
' };',
|
||||||
' Result = (pA + vB) + vC;',
|
' Result = (pA + vB) + vC;',
|
||||||
|
' Result = 6;',
|
||||||
|
' return Result;',
|
||||||
' return Result;',
|
' return Result;',
|
||||||
'};'
|
'};'
|
||||||
]),
|
]),
|
||||||
|
Loading…
Reference in New Issue
Block a user