mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 20:09:18 +02:00
pastojs: implemented inc/dec for var/out arg
git-svn-id: trunk@36035 -
This commit is contained in:
parent
f44f2f9194
commit
a4e26a7222
@ -1107,6 +1107,7 @@ type
|
|||||||
Function CreateBuiltInIdentifierExpr(AName: string): TJSPrimaryExpressionIdent;
|
Function CreateBuiltInIdentifierExpr(AName: string): TJSPrimaryExpressionIdent;
|
||||||
Function CreateSubDeclNameExpr(El: TPasElement; const Name: string;
|
Function CreateSubDeclNameExpr(El: TPasElement; const Name: string;
|
||||||
AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
||||||
|
Function CreateIdentifierExpr(El: TPasElement; AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
||||||
Function CreateIdentifierExpr(AName: string; El: TPasElement; AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
Function CreateIdentifierExpr(AName: string; El: TPasElement; AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
||||||
Function CreateSwitchStatement(El: TPasImplCaseOf; AContext: TConvertContext): TJSElement;
|
Function CreateSwitchStatement(El: TPasImplCaseOf; AContext: TConvertContext): TJSElement;
|
||||||
Function CreateTypeDecl(El: TPasType; AContext: TConvertContext): TJSElement;
|
Function CreateTypeDecl(El: TPasType; AContext: TConvertContext): TJSElement;
|
||||||
@ -3403,13 +3404,13 @@ Var
|
|||||||
OuterSrc , Src: TJSSourceElements;
|
OuterSrc , Src: TJSSourceElements;
|
||||||
RegModuleCall: TJSCallExpression;
|
RegModuleCall: TJSCallExpression;
|
||||||
ArgArray: TJSArguments;
|
ArgArray: TJSArguments;
|
||||||
UsesList: TFPList;
|
|
||||||
FunDecl, ImplFunc: TJSFunctionDeclarationStatement;
|
FunDecl, ImplFunc: TJSFunctionDeclarationStatement;
|
||||||
UsesSection: TPasSection;
|
UsesSection: TPasSection;
|
||||||
ModuleName, ModVarName: String;
|
ModuleName, ModVarName: String;
|
||||||
IntfContext: TSectionContext;
|
IntfContext: TSectionContext;
|
||||||
ImplVarSt: TJSVariableStatement;
|
ImplVarSt: TJSVariableStatement;
|
||||||
HasImplUsesList: Boolean;
|
HasImplUsesList: Boolean;
|
||||||
|
UsesList: TFPList;
|
||||||
begin
|
begin
|
||||||
Result:=Nil;
|
Result:=Nil;
|
||||||
OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El));
|
OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El));
|
||||||
@ -4261,12 +4262,20 @@ begin
|
|||||||
Result:=CreateDotExpression(El,Left,Right);
|
Result:=CreateDotExpression(El,Left,Right);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasToJSConverter.CreateIdentifierExpr(El: TPasElement;
|
||||||
|
AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
||||||
|
var
|
||||||
|
I: TJSPrimaryExpressionIdent;
|
||||||
|
begin
|
||||||
|
I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent,El));
|
||||||
|
I.Name:=TJSString(TransformVariableName(El,AContext));
|
||||||
|
Result:=I;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.CreateIdentifierExpr(AName: string; El: TPasElement;
|
function TPasToJSConverter.CreateIdentifierExpr(AName: string; El: TPasElement;
|
||||||
AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
AContext: TConvertContext): TJSPrimaryExpressionIdent;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
I : TJSPrimaryExpressionIdent;
|
I : TJSPrimaryExpressionIdent;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent,El));
|
I:=TJSPrimaryExpressionIdent(CreateElement(TJSPrimaryExpressionIdent,El));
|
||||||
AName:=TransformVariableName(El,AName,AContext);
|
AName:=TransformVariableName(El,AName,AContext);
|
||||||
@ -6025,21 +6034,96 @@ end;
|
|||||||
|
|
||||||
function TPasToJSConverter.ConvertBuiltIn_IncDec(El: TParamsExpr;
|
function TPasToJSConverter.ConvertBuiltIn_IncDec(El: TParamsExpr;
|
||||||
AContext: TConvertContext): TJSElement;
|
AContext: TConvertContext): TJSElement;
|
||||||
// convert inc(a,b) to a+=b
|
{ inc(a) or inc(a,b)
|
||||||
// convert dec(a,b) to a-=b
|
if a is a variable:
|
||||||
|
convert inc(a,b) to a+=b
|
||||||
|
if a is a var/out arg:
|
||||||
|
convert inc(a,b) to a.set(a.get+b)
|
||||||
|
if a is a property
|
||||||
|
Getter: field, procedure
|
||||||
|
if a is an indexed-property
|
||||||
|
Getter: field, procedure
|
||||||
|
if a is a property with index-specifier
|
||||||
|
Getter: field, procedure
|
||||||
|
}
|
||||||
var
|
var
|
||||||
AssignSt: TJSAssignStatement;
|
AssignSt: TJSAssignStatement;
|
||||||
|
Expr: TPasExpr;
|
||||||
|
ExprResolved: TPasResolverResult;
|
||||||
|
ExprArg: TPasArgument;
|
||||||
|
ValueJS: TJSElement;
|
||||||
|
Call: TJSCallExpression;
|
||||||
|
IsInc: Boolean;
|
||||||
|
AddJS: TJSAdditiveExpression;
|
||||||
begin
|
begin
|
||||||
if CompareText((El.Value as TPrimitiveExpr).Value,'inc')=0 then
|
Result:=nil;
|
||||||
AssignSt:=TJSAddEqAssignStatement(CreateElement(TJSAddEqAssignStatement,El))
|
IsInc:=CompareText((El.Value as TPrimitiveExpr).Value,'inc')=0;
|
||||||
else
|
Expr:=El.Params[0];
|
||||||
AssignSt:=TJSSubEqAssignStatement(CreateElement(TJSSubEqAssignStatement,El));
|
AContext.Resolver.ComputeElement(Expr,ExprResolved,[]);
|
||||||
Result:=AssignSt;
|
|
||||||
AssignSt.LHS:=ConvertExpression(El.Params[0],AContext);
|
// convert value
|
||||||
if length(El.Params)=1 then
|
if length(El.Params)=1 then
|
||||||
AssignSt.Expr:=CreateLiteralNumber(El,1)
|
ValueJS:=CreateLiteralNumber(El,1)
|
||||||
else
|
else
|
||||||
AssignSt.Expr:=ConvertExpression(El.Params[1],AContext);
|
ValueJS:=ConvertExpression(El.Params[1],AContext);
|
||||||
|
|
||||||
|
// check target variable
|
||||||
|
AssignSt:=nil;
|
||||||
|
Call:=nil;
|
||||||
|
try
|
||||||
|
if ExprResolved.IdentEl is TPasArgument then
|
||||||
|
begin
|
||||||
|
ExprArg:=TPasArgument(ExprResolved.IdentEl);
|
||||||
|
if ExprArg.Access in [argVar,argOut] then
|
||||||
|
begin
|
||||||
|
// target variable is a reference
|
||||||
|
// -> convert inc(ref,b) to ref.set(ref.get()+b)
|
||||||
|
Call:=CreateCallExpression(El);
|
||||||
|
// create "ref.set"
|
||||||
|
Call.Expr:=CreateDotExpression(El,
|
||||||
|
CreateIdentifierExpr(ExprResolved.IdentEl,AContext),
|
||||||
|
CreateBuiltInIdentifierExpr(TempRefObjSetterName));
|
||||||
|
// create "+"
|
||||||
|
if IsInc then
|
||||||
|
AddJS:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El))
|
||||||
|
else
|
||||||
|
AddJS:=TJSAdditiveExpressionMinus(CreateElement(TJSAdditiveExpressionMinus,El));
|
||||||
|
Call.AddArg(AddJS);
|
||||||
|
// create "ref.get()"
|
||||||
|
AddJS.A:=TJSCallExpression(CreateElement(TJSCallExpression,El));
|
||||||
|
TJSCallExpression(AddJS.A).Expr:=CreateDotExpression(El,
|
||||||
|
CreateIdentifierExpr(ExprResolved.IdentEl,AContext),
|
||||||
|
CreateBuiltInIdentifierExpr(TempRefObjGetterName));
|
||||||
|
// add "b"
|
||||||
|
AddJS.B:=ValueJS;
|
||||||
|
ValueJS:=nil;
|
||||||
|
|
||||||
|
Result:=Call;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if ExprResolved.IdentEl is TPasProperty then
|
||||||
|
begin
|
||||||
|
RaiseNotSupported(Expr,AContext,20170501151316);
|
||||||
|
end;
|
||||||
|
|
||||||
|
// convert inc(avar,b) to a+=b
|
||||||
|
if IsInc then
|
||||||
|
AssignSt:=TJSAddEqAssignStatement(CreateElement(TJSAddEqAssignStatement,El))
|
||||||
|
else
|
||||||
|
AssignSt:=TJSSubEqAssignStatement(CreateElement(TJSSubEqAssignStatement,El));
|
||||||
|
AssignSt.LHS:=ConvertExpression(El.Params[0],AContext);
|
||||||
|
AssignSt.Expr:=ValueJS;
|
||||||
|
ValueJS:=nil;
|
||||||
|
Result:=AssignSt;
|
||||||
|
finally
|
||||||
|
ValueJS.Free;
|
||||||
|
if Result=nil then
|
||||||
|
begin
|
||||||
|
AssignSt.Free;
|
||||||
|
Call.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TPasToJSConverter.ConvertBuiltIn_Assigned(El: TParamsExpr;
|
function TPasToJSConverter.ConvertBuiltIn_Assigned(El: TParamsExpr;
|
||||||
|
@ -357,6 +357,7 @@ type
|
|||||||
Procedure TestClass_NestedSelf;
|
Procedure TestClass_NestedSelf;
|
||||||
Procedure TestClass_NestedClassSelf;
|
Procedure TestClass_NestedClassSelf;
|
||||||
Procedure TestClass_NestedCallInherited;
|
Procedure TestClass_NestedCallInherited;
|
||||||
|
Procedure TestClass_TObjectFree; // ToDO
|
||||||
|
|
||||||
// class of
|
// class of
|
||||||
Procedure TestClassOf_Create;
|
Procedure TestClassOf_Create;
|
||||||
@ -1678,16 +1679,27 @@ end;
|
|||||||
procedure TTestModule.TestIncDec;
|
procedure TTestModule.TestIncDec;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('var');
|
Add([
|
||||||
Add(' Bar: longint;');
|
'procedure DoIt(var i: longint);',
|
||||||
Add('begin');
|
'begin',
|
||||||
Add(' inc(bar);');
|
' inc(i);',
|
||||||
Add(' inc(bar,2);');
|
' inc(i,2);',
|
||||||
Add(' dec(bar);');
|
'end;',
|
||||||
Add(' dec(bar,3);');
|
'var',
|
||||||
|
' Bar: longint;',
|
||||||
|
'begin',
|
||||||
|
' inc(bar);',
|
||||||
|
' inc(bar,2);',
|
||||||
|
' dec(bar);',
|
||||||
|
' dec(bar,3);',
|
||||||
|
'']);
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestIncDec',
|
CheckSource('TestIncDec',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
|
'this.DoIt = function (i) {',
|
||||||
|
' i.set(i.get()+1);',
|
||||||
|
' i.set(i.get()+2);',
|
||||||
|
'};',
|
||||||
'this.Bar = 0;'
|
'this.Bar = 0;'
|
||||||
]),
|
]),
|
||||||
LinesToStr([ // this.$main
|
LinesToStr([ // this.$main
|
||||||
@ -8024,6 +8036,59 @@ begin
|
|||||||
'']));
|
'']));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestClass_TObjectFree;
|
||||||
|
begin
|
||||||
|
exit;
|
||||||
|
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' Obj: tobject;',
|
||||||
|
' procedure Free;',
|
||||||
|
' end;',
|
||||||
|
'procedure tobject.free;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'function DoIt(o: tobject): tobject;',
|
||||||
|
'var l: tobject;',
|
||||||
|
'begin',
|
||||||
|
' o.free;',
|
||||||
|
' o.free();',
|
||||||
|
' l.free;',
|
||||||
|
' o.obj.free;',
|
||||||
|
' o.obj.free();',
|
||||||
|
' result.Free;',
|
||||||
|
' result.Free();',
|
||||||
|
'end;',
|
||||||
|
'var o: tobject;',
|
||||||
|
'begin',
|
||||||
|
' o.free;',
|
||||||
|
' o.obj.free;',
|
||||||
|
'']);
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestClass_NestedCallInherited',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'rtl.createClass($mod, "TObject", null, function () {',
|
||||||
|
' this.$init = function () {',
|
||||||
|
' this.Obj = null;',
|
||||||
|
' };',
|
||||||
|
' this.$final = function () {',
|
||||||
|
' };',
|
||||||
|
' this.Free = function () {',
|
||||||
|
' };',
|
||||||
|
'});',
|
||||||
|
'this.DoIt = function (o) {',
|
||||||
|
' var Result = null;',
|
||||||
|
' var l = null;',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
|
'this.o = null;',
|
||||||
|
'']),
|
||||||
|
LinesToStr([ // $mod.$main
|
||||||
|
'']));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestClassOf_Create;
|
procedure TTestModule.TestClassOf_Create;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user