mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 19:29:27 +02:00
pas2js: started pass property by reference
git-svn-id: trunk@35716 -
This commit is contained in:
parent
632b973ed6
commit
e9791ceffc
@ -212,6 +212,9 @@ Works:
|
|||||||
- use 0o for octal literals
|
- use 0o for octal literals
|
||||||
|
|
||||||
ToDos:
|
ToDos:
|
||||||
|
- external class array accessor: pass by ref
|
||||||
|
- remove 'Object' array workaround
|
||||||
|
- pass by ref: arr[3] -> omit this.a
|
||||||
- FuncName:= (instead of Result:=)
|
- FuncName:= (instead of Result:=)
|
||||||
- ord(s[i]) -> s.charCodeAt(i)
|
- ord(s[i]) -> s.charCodeAt(i)
|
||||||
- $modeswitch -> define <modeswitch>
|
- $modeswitch -> define <modeswitch>
|
||||||
@ -297,6 +300,7 @@ const
|
|||||||
nNewInstanceFunctionMustBeVirtual = 4016;
|
nNewInstanceFunctionMustBeVirtual = 4016;
|
||||||
nNewInstanceFunctionMustHaveTwoParameters = 4017;
|
nNewInstanceFunctionMustHaveTwoParameters = 4017;
|
||||||
nNewInstanceFunctionMustNotHaveOverloads = 4018;
|
nNewInstanceFunctionMustNotHaveOverloads = 4018;
|
||||||
|
nArrayAccessorOfExternalClassMustHaveOneParameter = 4019;
|
||||||
// resourcestring patterns of messages
|
// resourcestring patterns of messages
|
||||||
resourcestring
|
resourcestring
|
||||||
sPasElementNotSupported = 'Pascal element not supported: %s';
|
sPasElementNotSupported = 'Pascal element not supported: %s';
|
||||||
@ -317,6 +321,10 @@ resourcestring
|
|||||||
sNewInstanceFunctionMustBeVirtual = 'NewInstance function must be virtual';
|
sNewInstanceFunctionMustBeVirtual = 'NewInstance function must be virtual';
|
||||||
sNewInstanceFunctionMustHaveTwoParameters = 'NewInstance function must have two parameters';
|
sNewInstanceFunctionMustHaveTwoParameters = 'NewInstance function must have two parameters';
|
||||||
sNewInstanceFunctionMustNotHaveOverloads = 'NewInstance function must not have overloads';
|
sNewInstanceFunctionMustNotHaveOverloads = 'NewInstance function must not have overloads';
|
||||||
|
sArrayAccessorOfExternalClassMustHaveOneParameter = 'Array accessor of external class must have one parameter';
|
||||||
|
|
||||||
|
const
|
||||||
|
ExtClassArrayAccessor = 'Array'; // external name 'Array' marks the array param getter/setter
|
||||||
|
|
||||||
type
|
type
|
||||||
TPas2JSBuiltInName = (
|
TPas2JSBuiltInName = (
|
||||||
@ -641,10 +649,12 @@ type
|
|||||||
procedure RenameSubOverloads(Declarations: TFPList);
|
procedure RenameSubOverloads(Declarations: TFPList);
|
||||||
procedure PushOverloadScope(Scope: TPasIdentifierScope);
|
procedure PushOverloadScope(Scope: TPasIdentifierScope);
|
||||||
procedure PopOverloadScope;
|
procedure PopOverloadScope;
|
||||||
|
procedure ResolveImplAsm(El: TPasImplAsmStatement); override;
|
||||||
procedure FinishModule(CurModule: TPasModule); override;
|
procedure FinishModule(CurModule: TPasModule); override;
|
||||||
procedure FinishClassType(El: TPasClassType); override;
|
procedure FinishClassType(El: TPasClassType); override;
|
||||||
procedure FinishVariable(El: TPasVariable); override;
|
procedure FinishVariable(El: TPasVariable); override;
|
||||||
procedure FinishProcedureType(El: TPasProcedureType); override;
|
procedure FinishProcedureType(El: TPasProcedureType); override;
|
||||||
|
procedure FinishPropertyOfClass(PropEl: TPasProperty); override;
|
||||||
procedure CheckNewInstanceFunction(ClassScope: TPas2JSClassScope); virtual;
|
procedure CheckNewInstanceFunction(ClassScope: TPas2JSClassScope); virtual;
|
||||||
function AddExternalName(const aName: string; El: TPasElement): TPasIdentifier; virtual;
|
function AddExternalName(const aName: string; El: TPasElement): TPasIdentifier; virtual;
|
||||||
function FindExternalName(const aName: String): TPasIdentifier; virtual;
|
function FindExternalName(const aName: String): TPasIdentifier; virtual;
|
||||||
@ -684,6 +694,7 @@ type
|
|||||||
function ExtractPasStringLiteral(El: TPasElement; const S: String): TJSString; virtual;
|
function ExtractPasStringLiteral(El: TPasElement; const S: String): TJSString; virtual;
|
||||||
function ComputeConst(Expr: TPasExpr; StoreCustomData: boolean): TJSValue; virtual;
|
function ComputeConst(Expr: TPasExpr; StoreCustomData: boolean): TJSValue; virtual;
|
||||||
function ComputeConstString(Expr: TPasExpr; StoreCustomData, NotEmpty: boolean): String; virtual;
|
function ComputeConstString(Expr: TPasExpr; StoreCustomData, NotEmpty: boolean): String; virtual;
|
||||||
|
function IsExternalArrayAccessor(El: TPasElement): boolean;
|
||||||
// CustomData
|
// CustomData
|
||||||
function GetElementData(El: TPasElementBase;
|
function GetElementData(El: TPasElementBase;
|
||||||
DataClass: TPas2JsElementDataClass): TPas2JsElementData; virtual;
|
DataClass: TPas2JsElementDataClass): TPas2JsElementData; virtual;
|
||||||
@ -797,7 +808,7 @@ type
|
|||||||
// created by ConvertElement:
|
// created by ConvertElement:
|
||||||
Getter: TJSElement;
|
Getter: TJSElement;
|
||||||
Setter: TJSElement;
|
Setter: TJSElement;
|
||||||
ReusingReference: boolean; // truer = result is a reference, do not create another
|
ReusingReference: boolean; // true = result is a reference, do not create another
|
||||||
constructor Create(PasEl: TPasElement; JSEl: TJSElement; aParent: TConvertContext); override;
|
constructor Create(PasEl: TPasElement; JSEl: TJSElement; aParent: TConvertContext); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1389,6 +1400,28 @@ begin
|
|||||||
FOverloadScopes.Delete(FOverloadScopes.Count-1);
|
FOverloadScopes.Delete(FOverloadScopes.Count-1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPas2JSResolver.ResolveImplAsm(El: TPasImplAsmStatement);
|
||||||
|
{type
|
||||||
|
TAsmToken = (
|
||||||
|
atNone,
|
||||||
|
atWord,
|
||||||
|
atDot,
|
||||||
|
atRoundBracketOpen,
|
||||||
|
atRoundBracketClose
|
||||||
|
);
|
||||||
|
|
||||||
|
procedure Next;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;}
|
||||||
|
|
||||||
|
var
|
||||||
|
Lines: TStrings;
|
||||||
|
begin
|
||||||
|
Lines:=El.Tokens;
|
||||||
|
if Lines=nil then exit;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPas2JSResolver.FinishModule(CurModule: TPasModule);
|
procedure TPas2JSResolver.FinishModule(CurModule: TPasModule);
|
||||||
var
|
var
|
||||||
ModuleClass: TClass;
|
ModuleClass: TClass;
|
||||||
@ -1650,6 +1683,46 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TPas2JSResolver.FinishPropertyOfClass(PropEl: TPasProperty);
|
||||||
|
var
|
||||||
|
Getter, Setter: TPasElement;
|
||||||
|
GetterIsArrayAccessor, SetterIsArrayAcessor: Boolean;
|
||||||
|
Arg: TPasArgument;
|
||||||
|
ArgResolved: TPasResolverResult;
|
||||||
|
begin
|
||||||
|
inherited FinishPropertyOfClass(PropEl);
|
||||||
|
Getter:=GetPasPropertyGetter(PropEl);
|
||||||
|
GetterIsArrayAccessor:=IsExternalArrayAccessor(Getter);
|
||||||
|
Setter:=GetPasPropertySetter(PropEl);
|
||||||
|
SetterIsArrayAcessor:=IsExternalArrayAccessor(Setter);
|
||||||
|
if GetterIsArrayAccessor then
|
||||||
|
begin
|
||||||
|
if PropEl.Args.Count<>1 then
|
||||||
|
RaiseMsg(20170403001743,nArrayAccessorOfExternalClassMustHaveOneParameter,
|
||||||
|
sArrayAccessorOfExternalClassMustHaveOneParameter,
|
||||||
|
[],PropEl);
|
||||||
|
end;
|
||||||
|
if SetterIsArrayAcessor then
|
||||||
|
begin
|
||||||
|
if PropEl.Args.Count<>1 then
|
||||||
|
RaiseMsg(20170403001806,nArrayAccessorOfExternalClassMustHaveOneParameter,
|
||||||
|
sArrayAccessorOfExternalClassMustHaveOneParameter,
|
||||||
|
[],PropEl);
|
||||||
|
end;
|
||||||
|
if GetterIsArrayAccessor or SetterIsArrayAcessor then
|
||||||
|
begin
|
||||||
|
Arg:=TPasArgument(PropEl.Args[0]);
|
||||||
|
if not (Arg.Access in [argDefault,argConst]) then
|
||||||
|
RaiseMsg(20170403090225,nXExpectedButYFound,sXExpectedButYFound,
|
||||||
|
['default or "const"',AccessNames[Arg.Access]],PropEl);
|
||||||
|
ComputeElement(Arg,ArgResolved,[rcType],Arg);
|
||||||
|
if not (ArgResolved.BaseType in (btAllInteger+btAllStringAndChars+btAllBooleans+btAllFloats)) then
|
||||||
|
RaiseMsg(20170403090628,nIncompatibleTypesGotExpected,
|
||||||
|
sIncompatibleTypesGotExpected,
|
||||||
|
[GetResolverResultDescription(ArgResolved,true),'string'],Arg);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TPas2JSResolver.CheckNewInstanceFunction(ClassScope: TPas2JSClassScope
|
procedure TPas2JSResolver.CheckNewInstanceFunction(ClassScope: TPas2JSClassScope
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
@ -2306,6 +2379,16 @@ begin
|
|||||||
Result:=String(V.AsString);
|
Result:=String(V.AsString);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPas2JSResolver.IsExternalArrayAccessor(El: TPasElement): boolean;
|
||||||
|
var
|
||||||
|
ExtName: String;
|
||||||
|
begin
|
||||||
|
if (not (El is TPasProcedure)) or (TPasProcedure(El).LibrarySymbolName=nil) then
|
||||||
|
exit(false);
|
||||||
|
ExtName:=ComputeConstString(TPasProcedure(El).LibrarySymbolName,false,false);
|
||||||
|
Result:=ExtName=ExtClassArrayAccessor;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPas2JSResolver.GetElementData(El: TPasElementBase;
|
function TPas2JSResolver.GetElementData(El: TPasElementBase;
|
||||||
DataClass: TPas2JsElementDataClass): TPas2JsElementData;
|
DataClass: TPas2JsElementDataClass): TPas2JsElementData;
|
||||||
begin
|
begin
|
||||||
@ -3526,6 +3609,7 @@ begin
|
|||||||
RaiseNotSupported(El,AContext,20170206000310);
|
RaiseNotSupported(El,AContext,20170206000310);
|
||||||
AssignContext.PropertyEl:=Prop;
|
AssignContext.PropertyEl:=Prop;
|
||||||
AssignContext.Setter:=Decl;
|
AssignContext.Setter:=Decl;
|
||||||
|
// Setter
|
||||||
Call:=CreateCallExpression(El);
|
Call:=CreateCallExpression(El);
|
||||||
AssignContext.Call:=Call;
|
AssignContext.Call:=Call;
|
||||||
Call.Expr:=CreateReferencePathExpr(Decl,AContext,false,Ref);
|
Call.Expr:=CreateReferencePathExpr(Decl,AContext,false,Ref);
|
||||||
@ -4005,6 +4089,71 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function IsJSArrayAccessorAndConvert(Prop: TPasProperty;
|
||||||
|
AccessEl: TPasElement;
|
||||||
|
AContext: TConvertContext; ChompPropName: boolean): boolean;
|
||||||
|
// If El.Value contains property name set ChompPropName = true
|
||||||
|
var
|
||||||
|
Bracket: TJSBracketMemberExpression;
|
||||||
|
OldAccess: TCtxAccess;
|
||||||
|
PathEl: TPasExpr;
|
||||||
|
Ref: TResolvedReference;
|
||||||
|
Path: String;
|
||||||
|
begin
|
||||||
|
if not AContext.Resolver.IsExternalArrayAccessor(AccessEl) then
|
||||||
|
exit(false);
|
||||||
|
Result:=true;
|
||||||
|
// array accessor of external class
|
||||||
|
if Prop.Args.Count<>1 then
|
||||||
|
RaiseInconsistency(20170403003753);
|
||||||
|
// array accessor of external class -> create PathEl[param]
|
||||||
|
Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,Prop));
|
||||||
|
try
|
||||||
|
PathEl:=El.Value;
|
||||||
|
if ChompPropName then
|
||||||
|
begin
|
||||||
|
if (PathEl is TPrimitiveExpr)
|
||||||
|
and (TPrimitiveExpr(PathEl).Kind=pekIdent)
|
||||||
|
and (PathEl.CustomData is TResolvedReference) then
|
||||||
|
begin
|
||||||
|
// propname without path, e.g. propname[param]
|
||||||
|
Ref:=TResolvedReference(PathEl.CustomData);
|
||||||
|
Path:=CreateReferencePath(Prop,AContext,rpkPath,false,Ref);
|
||||||
|
if Path<>'' then
|
||||||
|
Bracket.MExpr:=CreateBuiltInIdentifierExpr(Path);
|
||||||
|
PathEl:=nil;
|
||||||
|
end
|
||||||
|
else if (PathEl is TBinaryExpr)
|
||||||
|
and (TBinaryExpr(PathEl).OpCode=eopSubIdent)
|
||||||
|
and (TBinaryExpr(PathEl).right is TPrimitiveExpr)
|
||||||
|
and (TPrimitiveExpr(TBinaryExpr(PathEl).right).Kind=pekIdent) then
|
||||||
|
begin
|
||||||
|
// instance.propname[param] -> instance[param]
|
||||||
|
PathEl:=TBinaryExpr(PathEl).left;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
RaiseNotSupported(El.Value,AContext,20170402225050);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (PathEl<>nil) and (Bracket.MExpr=nil) then
|
||||||
|
begin
|
||||||
|
OldAccess:=AContext.Access;
|
||||||
|
AContext.Access:=caRead;
|
||||||
|
Bracket.MExpr:=ConvertElement(PathEl,AContext);
|
||||||
|
AContext.Access:=OldAccess;
|
||||||
|
end;
|
||||||
|
|
||||||
|
OldAccess:=ArgContext.Access;
|
||||||
|
ArgContext.Access:=caRead;
|
||||||
|
Bracket.Name:=ConvertElement(El.Params[0],AContext);
|
||||||
|
ArgContext.Access:=OldAccess;
|
||||||
|
ConvertArrayParams:=Bracket;
|
||||||
|
Bracket:=nil;
|
||||||
|
finally
|
||||||
|
Bracket.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure ConvertIndexProperty(Prop: TPasProperty; AContext: TConvertContext);
|
procedure ConvertIndexProperty(Prop: TPasProperty; AContext: TConvertContext);
|
||||||
var
|
var
|
||||||
Call: TJSCallExpression;
|
Call: TJSCallExpression;
|
||||||
@ -4023,14 +4172,20 @@ var
|
|||||||
case AContext.Access of
|
case AContext.Access of
|
||||||
caAssign:
|
caAssign:
|
||||||
begin
|
begin
|
||||||
AssignContext:=AContext.AccessContext as TAssignContext;
|
|
||||||
AccessEl:=AContext.Resolver.GetPasPropertySetter(Prop);
|
AccessEl:=AContext.Resolver.GetPasPropertySetter(Prop);
|
||||||
|
if IsJSArrayAccessorAndConvert(Prop,AccessEl,AContext,true) then
|
||||||
|
exit;
|
||||||
|
AssignContext:=AContext.AccessContext as TAssignContext;
|
||||||
AssignContext.PropertyEl:=Prop;
|
AssignContext.PropertyEl:=Prop;
|
||||||
AssignContext.Setter:=AccessEl;
|
AssignContext.Setter:=AccessEl;
|
||||||
AssignContext.Call:=Call;
|
AssignContext.Call:=Call;
|
||||||
end;
|
end;
|
||||||
caRead:
|
caRead:
|
||||||
|
begin
|
||||||
AccessEl:=AContext.Resolver.GetPasPropertyGetter(Prop);
|
AccessEl:=AContext.Resolver.GetPasPropertyGetter(Prop);
|
||||||
|
if IsJSArrayAccessorAndConvert(Prop,AccessEl,AContext,true) then
|
||||||
|
exit;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
RaiseNotSupported(El,AContext,20170213213317);
|
RaiseNotSupported(El,AContext,20170213213317);
|
||||||
end;
|
end;
|
||||||
@ -4082,12 +4237,42 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ConvertDefaultProperty(Prop: TPasProperty);
|
procedure ConvertDefaultProperty(const ResolvedEl: TPasResolverResult;
|
||||||
|
Prop: TPasProperty);
|
||||||
var
|
var
|
||||||
DotContext: TDotContext;
|
DotContext: TDotContext;
|
||||||
Left, Right: TJSElement;
|
Left, Right: TJSElement;
|
||||||
OldAccess: TCtxAccess;
|
OldAccess: TCtxAccess;
|
||||||
|
AccessEl: TPasElement;
|
||||||
begin
|
begin
|
||||||
|
case AContext.Access of
|
||||||
|
caAssign:
|
||||||
|
begin
|
||||||
|
AccessEl:=AContext.Resolver.GetPasPropertySetter(Prop);
|
||||||
|
if IsJSArrayAccessorAndConvert(Prop,AccessEl,AContext,false) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
caRead:
|
||||||
|
begin
|
||||||
|
AccessEl:=AContext.Resolver.GetPasPropertyGetter(Prop);
|
||||||
|
if IsJSArrayAccessorAndConvert(Prop,AccessEl,AContext,false) then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
{caByReference:
|
||||||
|
begin
|
||||||
|
ParamContext:=AContext.AccessContext as TParamContext;
|
||||||
|
AccessEl:=AContext.Resolver.GetPasPropertyGetter(Prop);
|
||||||
|
SetAccessEl:=AContext.Resolver.GetPasPropertySetter(Prop);
|
||||||
|
if IsJSArrayAccessorAndConvert(Prop,AccessEl,AContext,false) then
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
RaiseNotSupported(El,AContext,20170403000550);
|
||||||
|
end;}
|
||||||
|
else
|
||||||
|
RaiseNotSupported(El,AContext,20170402233834);
|
||||||
|
end;
|
||||||
|
|
||||||
DotContext:=nil;
|
DotContext:=nil;
|
||||||
Left:=nil;
|
Left:=nil;
|
||||||
Right:=nil;
|
Right:=nil;
|
||||||
@ -4098,7 +4283,7 @@ var
|
|||||||
AContext.Access:=OldAccess;
|
AContext.Access:=OldAccess;
|
||||||
|
|
||||||
DotContext:=TDotContext.Create(El.Value,Left,AContext);
|
DotContext:=TDotContext.Create(El.Value,Left,AContext);
|
||||||
AContext.Resolver.ComputeElement(El.Value,DotContext.LeftResolved,[]);
|
DotContext.LeftResolved:=ResolvedEl;
|
||||||
ConvertIndexProperty(Prop,DotContext);
|
ConvertIndexProperty(Prop,DotContext);
|
||||||
Right:=Result;
|
Right:=Result;
|
||||||
Result:=nil;
|
Result:=nil;
|
||||||
@ -4166,7 +4351,7 @@ begin
|
|||||||
aClass:=TPasClassType(TypeEl);
|
aClass:=TPasClassType(TypeEl);
|
||||||
ClassScope:=TypeEl.CustomData as TPas2JSClassScope;
|
ClassScope:=TypeEl.CustomData as TPas2JSClassScope;
|
||||||
if ClassScope.DefaultProperty<>nil then
|
if ClassScope.DefaultProperty<>nil then
|
||||||
ConvertDefaultProperty(ClassScope.DefaultProperty)
|
ConvertDefaultProperty(ResolvedEl,ClassScope.DefaultProperty)
|
||||||
else if AContext.Resolver.IsExternalClassName(aClass,'Array')
|
else if AContext.Resolver.IsExternalClassName(aClass,'Array')
|
||||||
or AContext.Resolver.IsExternalClassName(aClass,'Object') then
|
or AContext.Resolver.IsExternalClassName(aClass,'Object') then
|
||||||
ConvertJSObject
|
ConvertJSObject
|
||||||
@ -4178,7 +4363,7 @@ begin
|
|||||||
ClassScope:=TPasClassOfType(TypeEl).DestType.CustomData as TPas2JSClassScope;
|
ClassScope:=TPasClassOfType(TypeEl).DestType.CustomData as TPas2JSClassScope;
|
||||||
if ClassScope.DefaultProperty=nil then
|
if ClassScope.DefaultProperty=nil then
|
||||||
RaiseInconsistency(20170206180503);
|
RaiseInconsistency(20170206180503);
|
||||||
ConvertDefaultProperty(ClassScope.DefaultProperty);
|
ConvertDefaultProperty(ResolvedEl,ClassScope.DefaultProperty);
|
||||||
end
|
end
|
||||||
else if TypeEl.ClassType=TPasArrayType then
|
else if TypeEl.ClassType=TPasArrayType then
|
||||||
ConvertArray(TPasArrayType(TypeEl))
|
ConvertArray(TPasArrayType(TypeEl))
|
||||||
@ -5758,6 +5943,8 @@ function TPasToJSConverter.CreateBuiltInIdentifierExpr(AName: string
|
|||||||
var
|
var
|
||||||
Ident: TJSPrimaryExpressionIdent;
|
Ident: TJSPrimaryExpressionIdent;
|
||||||
begin
|
begin
|
||||||
|
if AName='' then
|
||||||
|
RaiseInconsistency(20170402230134);
|
||||||
Ident:=TJSPrimaryExpressionIdent.Create(0,0);
|
Ident:=TJSPrimaryExpressionIdent.Create(0,0);
|
||||||
// do not lowercase
|
// do not lowercase
|
||||||
Ident.Name:=TJSString(AName);
|
Ident.Name:=TJSString(AName);
|
||||||
@ -6977,16 +7164,37 @@ begin
|
|||||||
begin
|
begin
|
||||||
RightParent:=Right;
|
RightParent:=Right;
|
||||||
Right:=TJSCallExpression(Right).Expr;
|
Right:=TJSCallExpression(Right).Expr;
|
||||||
|
if Right=nil then
|
||||||
|
begin
|
||||||
|
// left-most is nil -> insert Left
|
||||||
|
TJSCallExpression(RightParent).Expr:=Left;
|
||||||
|
ok:=true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if (Right.ClassType=TJSBracketMemberExpression) then
|
else if (Right.ClassType=TJSBracketMemberExpression) then
|
||||||
begin
|
begin
|
||||||
RightParent:=Right;
|
RightParent:=Right;
|
||||||
Right:=TJSBracketMemberExpression(Right).MExpr;
|
Right:=TJSBracketMemberExpression(Right).MExpr;
|
||||||
|
if Right=nil then
|
||||||
|
begin
|
||||||
|
// left-most is nil -> insert Left
|
||||||
|
TJSBracketMemberExpression(RightParent).MExpr:=Left;
|
||||||
|
ok:=true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if (Right.ClassType=TJSDotMemberExpression) then
|
else if (Right.ClassType=TJSDotMemberExpression) then
|
||||||
begin
|
begin
|
||||||
RightParent:=Right;
|
RightParent:=Right;
|
||||||
Right:=TJSDotMemberExpression(Right).MExpr;
|
Right:=TJSDotMemberExpression(Right).MExpr;
|
||||||
|
if Right=nil then
|
||||||
|
begin
|
||||||
|
// left-most is nil -> insert Left
|
||||||
|
TJSDotMemberExpression(RightParent).MExpr:=Left;
|
||||||
|
ok:=true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else if (Right.ClassType=TJSPrimaryExpressionIdent) then
|
else if (Right.ClassType=TJSPrimaryExpressionIdent) then
|
||||||
begin
|
begin
|
||||||
@ -8654,8 +8862,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// if ParamContext.Getter is set then
|
// if ParamContext.Getter is set then
|
||||||
// ParamContext.Getter is the last part of the FullGetter, that needs to
|
// ParamContext.Getter is the last part of the FullGetter
|
||||||
// be replaced by ParamContext.Setter to create a FullSetter
|
// FullSetter is created from FullGetter by replacing the Getter with the Setter
|
||||||
{$IFDEF VerbosePas2JS}
|
{$IFDEF VerbosePas2JS}
|
||||||
writeln('TPasToJSConverter.CreateProcedureCallArg VAR FullGetter=',GetObjName(FullGetter),' Getter=',GetObjName(ParamContext.Getter),' Setter=',GetObjName(ParamContext.Setter));
|
writeln('TPasToJSConverter.CreateProcedureCallArg VAR FullGetter=',GetObjName(FullGetter),' Getter=',GetObjName(ParamContext.Getter),' Setter=',GetObjName(ParamContext.Setter));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -8679,11 +8887,12 @@ begin
|
|||||||
GetDotPos:=PosLast('.',GetPath);
|
GetDotPos:=PosLast('.',GetPath);
|
||||||
if GetDotPos>0 then
|
if GetDotPos>0 then
|
||||||
begin
|
begin
|
||||||
// e.g. this.readvar
|
// e.g. path1.path2.readvar
|
||||||
// create
|
// create
|
||||||
// GetPathExpr: this
|
// GetPathExpr: path1.path2
|
||||||
// GetExpr: p.readvar
|
// GetExpr: this.p.readvar
|
||||||
// Will create "{p:GetPathExpr, get:function(){return GetExpr;},set:...}"
|
// Will create "{p:GetPathExpr, get:function(){return GetExpr;},
|
||||||
|
// set:function(v){GetExpr = v;}}"
|
||||||
GetPathExpr:=CreateBuiltInIdentifierExpr(LeftStr(GetPath,GetDotPos-1));
|
GetPathExpr:=CreateBuiltInIdentifierExpr(LeftStr(GetPath,GetDotPos-1));
|
||||||
GetExpr:=CreateDotExpression(El,CreateBuiltInIdentifierExpr('this.'+GetPathName),
|
GetExpr:=CreateDotExpression(El,CreateBuiltInIdentifierExpr('this.'+GetPathName),
|
||||||
CreateBuiltInIdentifierExpr(copy(GetPath,GetDotPos+1)));
|
CreateBuiltInIdentifierExpr(copy(GetPath,GetDotPos+1)));
|
||||||
@ -8757,10 +8966,10 @@ begin
|
|||||||
// get:function{return this.p[this.a];},
|
// get:function{return this.p[this.a];},
|
||||||
// set:function(v){this.p[this.a]=v;}
|
// set:function(v){this.p[this.a]=v;}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// create "a:value"
|
|
||||||
BracketExpr:=TJSBracketMemberExpression(FullGetter);
|
BracketExpr:=TJSBracketMemberExpression(FullGetter);
|
||||||
ParamExpr:=BracketExpr.Name;
|
ParamExpr:=BracketExpr.Name;
|
||||||
|
|
||||||
|
// create "a:value"
|
||||||
BracketExpr.Name:=CreateBuiltInIdentifierExpr('this.'+ParamName);
|
BracketExpr.Name:=CreateBuiltInIdentifierExpr('this.'+ParamName);
|
||||||
AddVar(ParamName,ParamExpr);
|
AddVar(ParamName,ParamExpr);
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ type
|
|||||||
Procedure TestContinue;
|
Procedure TestContinue;
|
||||||
Procedure TestProcedureExternal;
|
Procedure TestProcedureExternal;
|
||||||
Procedure TestProcedureExternalOtherUnit;
|
Procedure TestProcedureExternalOtherUnit;
|
||||||
Procedure TestProcedureAsm;
|
Procedure TestProcedure_Asm;
|
||||||
Procedure TestProcedureAssembler;
|
Procedure TestProcedureAssembler;
|
||||||
Procedure TestProcedure_VarParam;
|
Procedure TestProcedure_VarParam;
|
||||||
Procedure TestProcedureOverload;
|
Procedure TestProcedureOverload;
|
||||||
@ -253,6 +253,7 @@ type
|
|||||||
Procedure TestForLoop_Nested;
|
Procedure TestForLoop_Nested;
|
||||||
Procedure TestRepeatUntil;
|
Procedure TestRepeatUntil;
|
||||||
Procedure TestAsmBlock;
|
Procedure TestAsmBlock;
|
||||||
|
Procedure TestAsmPas_Impl;
|
||||||
Procedure TestTryFinally;
|
Procedure TestTryFinally;
|
||||||
Procedure TestTryExcept;
|
Procedure TestTryExcept;
|
||||||
Procedure TestCaseOf;
|
Procedure TestCaseOf;
|
||||||
@ -368,7 +369,9 @@ type
|
|||||||
Procedure TestExternalClass_TypeCastToRootClass;
|
Procedure TestExternalClass_TypeCastToRootClass;
|
||||||
Procedure TestExternalClass_TypeCastStringToExternalString;
|
Procedure TestExternalClass_TypeCastStringToExternalString;
|
||||||
Procedure TestExternalClass_CallClassFunctionOfInstanceFail;
|
Procedure TestExternalClass_CallClassFunctionOfInstanceFail;
|
||||||
|
Procedure TestExternalClass_BracketOperatorOld;
|
||||||
Procedure TestExternalClass_BracketOperator;
|
Procedure TestExternalClass_BracketOperator;
|
||||||
|
// ToDo: check default property accessors have one parameter
|
||||||
|
|
||||||
// proc types
|
// proc types
|
||||||
Procedure TestProcType;
|
Procedure TestProcType;
|
||||||
@ -2063,7 +2066,7 @@ begin
|
|||||||
]));
|
]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestProcedureAsm;
|
procedure TTestModule.TestProcedure_Asm;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('function DoIt: longint;');
|
Add('function DoIt: longint;');
|
||||||
@ -3806,6 +3809,44 @@ begin
|
|||||||
]));
|
]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAsmPas_Impl;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('const cIntf: longint = 1;');
|
||||||
|
Add('var vIntf: longint;');
|
||||||
|
Add('implementation');
|
||||||
|
Add('const cImpl: longint = 2;');
|
||||||
|
Add('var vImpl: longint;');
|
||||||
|
Add('procedure DoIt;');
|
||||||
|
Add('const cLoc: longint = 3;');
|
||||||
|
Add('var vLoc: longint;');
|
||||||
|
Add('begin;');
|
||||||
|
Add(' asm');
|
||||||
|
//Add(' pas(vIntf)=pas(cIntf);');
|
||||||
|
//Add(' pas(vImpl)=pas(cImpl);');
|
||||||
|
//Add(' pas(vLoc)=pas(cLoc);');
|
||||||
|
Add(' end;');
|
||||||
|
Add('end;');
|
||||||
|
ConvertUnit;
|
||||||
|
// ToDo: check use analyzer
|
||||||
|
CheckSource('TestAsmPas_Impl',
|
||||||
|
LinesToStr([
|
||||||
|
'var $impl = {',
|
||||||
|
'};',
|
||||||
|
'this.$impl = $impl;',
|
||||||
|
'this.cIntf = 1;',
|
||||||
|
'this.vIntf = 0;',
|
||||||
|
'var cLoc = 3;',
|
||||||
|
'$impl.cImpl = 2;',
|
||||||
|
'$impl.vImpl = 0;',
|
||||||
|
'$impl.DoIt = function () {',
|
||||||
|
' var vLoc = 0;',
|
||||||
|
'};',
|
||||||
|
'']),
|
||||||
|
'');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestTryFinally;
|
procedure TTestModule.TestTryFinally;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
@ -8499,7 +8540,7 @@ begin
|
|||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestExternalClass_BracketOperator;
|
procedure TTestModule.TestExternalClass_BracketOperatorOld;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('{$modeswitch externalclass}');
|
Add('{$modeswitch externalclass}');
|
||||||
@ -8586,6 +8627,56 @@ begin
|
|||||||
'']));
|
'']));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestExternalClass_BracketOperator;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('{$modeswitch externalclass}');
|
||||||
|
Add('type');
|
||||||
|
Add(' TJSArray = class external name ''Array2''');
|
||||||
|
Add(' function GetItems(Index: longint): jsvalue; external name ''Array'';');
|
||||||
|
Add(' procedure SetItems(Index: longint; Value: jsvalue); external name ''Array'';');
|
||||||
|
Add(' property Items[Index: longint]: jsvalue read GetItems write SetItems; default;');
|
||||||
|
Add(' end;');
|
||||||
|
Add('procedure DoIt(vI: JSValue; const vJ: jsvalue; var vK: jsvalue; out vL: jsvalue);');
|
||||||
|
Add('begin end;');
|
||||||
|
Add('var');
|
||||||
|
Add(' Arr: tjsarray;');
|
||||||
|
Add(' s: string;');
|
||||||
|
Add(' i: longint;');
|
||||||
|
Add(' v: jsvalue;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' v:=arr[0];');
|
||||||
|
Add(' v:=arr.items[1];');
|
||||||
|
Add(' arr[2]:=s;');
|
||||||
|
Add(' arr.items[3]:=s;');
|
||||||
|
Add(' arr[4]:=i;');
|
||||||
|
Add(' arr[5]:=arr[6];');
|
||||||
|
Add(' arr.items[7]:=arr.items[8];');
|
||||||
|
Add(' with arr do items[9]:=items[10];');
|
||||||
|
//Add(' doit(arr[7],arr[8],arr[9],arr[10]);');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestExternalClass_BracketOperator',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.DoIt = function (vI, vJ, vK, vL) {',
|
||||||
|
'};',
|
||||||
|
'this.Arr = null;',
|
||||||
|
'this.s = "";',
|
||||||
|
'this.i = 0;',
|
||||||
|
'this.v = undefined;',
|
||||||
|
'']),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'this.v = this.Arr[0];',
|
||||||
|
'this.v = this.Arr[1];',
|
||||||
|
'this.Arr[2] = this.s;',
|
||||||
|
'this.Arr[3] = this.s;',
|
||||||
|
'this.Arr[4] = this.i;',
|
||||||
|
'this.Arr[5] = this.Arr[6];',
|
||||||
|
'this.Arr[7] = this.Arr[8];',
|
||||||
|
'var $with1 = this.Arr;',
|
||||||
|
'$with1[9] = $with1[10];',
|
||||||
|
'']));
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestProcType;
|
procedure TTestModule.TestProcType;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user