mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-10 21:06:11 +02:00
pas2js: doc about dispatch
git-svn-id: trunk@41676 -
This commit is contained in:
parent
89c921a11c
commit
bc8df85d00
@ -792,11 +792,11 @@ const
|
|||||||
'rc', // rtl.rc
|
'rc', // rtl.rc
|
||||||
'rcCharAt', // rtl.rcCharAt
|
'rcCharAt', // rtl.rcCharAt
|
||||||
'rcSetCharAt', // rtl.rcSetCharAt
|
'rcSetCharAt', // rtl.rcSetCharAt
|
||||||
'$assign',
|
'$assign', // pbifnRecordAssign
|
||||||
'$clone',
|
'$clone', // pbifnRecordClone
|
||||||
'recNewT',
|
'recNewT', // pbifnRecordNew
|
||||||
'$eq',
|
'$eq', // pbifnRecordEqual
|
||||||
'$new',
|
'$new', // pbifnRecordNew
|
||||||
'addField',
|
'addField',
|
||||||
'addFields',
|
'addFields',
|
||||||
'addMethod',
|
'addMethod',
|
||||||
@ -5110,7 +5110,7 @@ begin
|
|||||||
else if C=TPasRecordType then
|
else if C=TPasRecordType then
|
||||||
begin
|
begin
|
||||||
// typecast to recordtype
|
// typecast to recordtype
|
||||||
if FromResolved.BaseType=btNone then
|
if FromResolved.BaseType=btUntyped then
|
||||||
// recordtype(untyped) -> ok
|
// recordtype(untyped) -> ok
|
||||||
else if FromResolved.BaseType=btContext then
|
else if FromResolved.BaseType=btContext then
|
||||||
begin
|
begin
|
||||||
@ -9516,7 +9516,7 @@ var
|
|||||||
Param, Value: TPasExpr;
|
Param, Value: TPasExpr;
|
||||||
JSBaseType: TPas2jsBaseType;
|
JSBaseType: TPas2jsBaseType;
|
||||||
C: TClass;
|
C: TClass;
|
||||||
aName: String;
|
aName, ArgName: String;
|
||||||
aClassTypeEl: TPasClassType;
|
aClassTypeEl: TPasClassType;
|
||||||
ParamTypeEl, TypeEl: TPasType;
|
ParamTypeEl, TypeEl: TPasType;
|
||||||
NeedIntfRef: Boolean;
|
NeedIntfRef: Boolean;
|
||||||
@ -9666,6 +9666,15 @@ begin
|
|||||||
aResolver.ComputeElement(Param,ParamResolved,[]);
|
aResolver.ComputeElement(Param,ParamResolved,[]);
|
||||||
ParamTypeEl:=ParamResolved.LoTypeEl;
|
ParamTypeEl:=ParamResolved.LoTypeEl;
|
||||||
|
|
||||||
|
if (C=TPasRecordType) and (ParamResolved.BaseType=btUntyped)
|
||||||
|
and (ParamResolved.IdentEl is TPasArgument) then
|
||||||
|
begin
|
||||||
|
// RecordType(UntypedArg) -> UntypedArg
|
||||||
|
ArgName:=TransformArgName(TPasArgument(ParamResolved.IdentEl),AContext);
|
||||||
|
Result:=CreatePrimitiveDotExpr(ArgName,El);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
Result:=ConvertExpression(Param,AContext);
|
Result:=ConvertExpression(Param,AContext);
|
||||||
|
|
||||||
if C=TPasRangeType then
|
if C=TPasRangeType then
|
||||||
@ -21594,6 +21603,9 @@ begin
|
|||||||
|
|
||||||
aResolver.ComputeElement(El,ExprResolved,ExprFlags);
|
aResolver.ComputeElement(El,ExprResolved,ExprFlags);
|
||||||
|
|
||||||
|
if (TargetArg.ArgType=nil) and (ExprResolved.LoTypeEl is TPasRecordType) then
|
||||||
|
NeedVar:=false; // pass aRecord to UntypedArg -> no reference needed
|
||||||
|
|
||||||
// consider TargetArg access
|
// consider TargetArg access
|
||||||
if NeedVar then
|
if NeedVar then
|
||||||
Result:=CreateProcCallArgRef(El,ExprResolved,TargetArg,AContext)
|
Result:=CreateProcCallArgRef(El,ExprResolved,TargetArg,AContext)
|
||||||
@ -22232,6 +22244,40 @@ begin
|
|||||||
TypeEl:=AContext.Resolver.ResolveAliasType(Arg.ArgType);
|
TypeEl:=AContext.Resolver.ResolveAliasType(Arg.ArgType);
|
||||||
IsRecord:=TypeEl is TPasRecordType;
|
IsRecord:=TypeEl is TPasRecordType;
|
||||||
|
|
||||||
|
if AContext.Access=caAssign then
|
||||||
|
begin
|
||||||
|
AssignContext:=AContext.AccessContext as TAssignContext;
|
||||||
|
if IsRecord then
|
||||||
|
begin
|
||||||
|
// aRecordArg:=right -> "aRecordArg.$assign(right)"
|
||||||
|
if AssignContext.Call<>nil then
|
||||||
|
RaiseNotSupported(Arg,AContext,20190105174026);
|
||||||
|
Result:=CreateSetter(GetBIName(pbifnRecordAssign),AssignContext);
|
||||||
|
exit;
|
||||||
|
end
|
||||||
|
else if (Arg.ArgType=nil)
|
||||||
|
and (AssignContext.RightResolved.LoTypeEl is TPasRecordType)
|
||||||
|
and (rrfReadable in AssignContext.RightResolved.Flags) then
|
||||||
|
begin
|
||||||
|
// UntypedArg:=aRecordVar -> "UntypedArg.$assign(right)"
|
||||||
|
// Note: records are passed directly to Untyped parameters
|
||||||
|
if AssignContext.Call<>nil then
|
||||||
|
RaiseNotSupported(Arg,AContext,20190311140048);
|
||||||
|
Result:=CreateSetter(GetBIName(pbifnRecordAssign),AssignContext);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if IsRecord and (AContext is TParamContext) then
|
||||||
|
begin
|
||||||
|
ParamContext:=TParamContext(AContext);
|
||||||
|
if ParamContext.ResolvedExpr.BaseType=btUntyped then
|
||||||
|
begin
|
||||||
|
// pass aRecordVar to UntypedArg -> pass aRecordVar directly, no temp ref object
|
||||||
|
Result:=CreatePrimitiveDotExpr(ArgName,PosEl);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
if (Arg.Access in [argVar,argOut]) and not IsRecord then
|
if (Arg.Access in [argVar,argOut]) and not IsRecord then
|
||||||
begin
|
begin
|
||||||
// Arg is a reference object
|
// Arg is a reference object
|
||||||
@ -22266,18 +22312,6 @@ begin
|
|||||||
else
|
else
|
||||||
RaiseNotSupported(Arg,AContext,20170214120739);
|
RaiseNotSupported(Arg,AContext,20170214120739);
|
||||||
end;
|
end;
|
||||||
end
|
|
||||||
else if AContext.Access=caAssign then
|
|
||||||
begin
|
|
||||||
AssignContext:=AContext.AccessContext as TAssignContext;
|
|
||||||
if AssignContext.LeftResolved.LoTypeEl is TPasRecordType then
|
|
||||||
begin
|
|
||||||
// aRecordArg:=right -> "aRecordArg.$assign(right)"
|
|
||||||
if AssignContext.Call<>nil then
|
|
||||||
RaiseNotSupported(Arg,AContext,20190105174026);
|
|
||||||
Result:=CreateSetter(GetBIName(pbifnRecordAssign),AssignContext);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
Result:=CreatePrimitiveDotExpr(ArgName,PosEl);
|
Result:=CreatePrimitiveDotExpr(ArgName,PosEl);
|
||||||
end;
|
end;
|
||||||
|
@ -10078,15 +10078,19 @@ begin
|
|||||||
' U:=vd;',
|
' U:=vd;',
|
||||||
' U:=vc;',
|
' U:=vc;',
|
||||||
' U:=vv;',
|
' U:=vv;',
|
||||||
|
' vl:=TRecord(U);',
|
||||||
|
' vd:=TRecord(U);',
|
||||||
|
' vv:=TRecord(U);',
|
||||||
' doit(vd,vd,vd,vd);',
|
' doit(vd,vd,vd,vd);',
|
||||||
' doit(vc,vc,vl,vl);',
|
' doit(vc,vc,vl,vl);',
|
||||||
' doit(vv,vv,vv,vv);',
|
' doit(vv,vv,vv,vv);',
|
||||||
' doit(vl,vl,vl,vl);',
|
' doit(vl,vl,vl,vl);',
|
||||||
//' TRecord(U).i:=3;',
|
' TRecord(U).i:=3;',
|
||||||
'end;',
|
'end;',
|
||||||
'var i: TRecord;',
|
'var i: TRecord;',
|
||||||
'begin',
|
'begin',
|
||||||
' doit(i,i,i,i);']);
|
' doit(i,i,i,i);',
|
||||||
|
'']);
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestRecord_AsParams',
|
CheckSource('TestRecord_AsParams',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
@ -10107,55 +10111,23 @@ begin
|
|||||||
' vL.$assign(vC);',
|
' vL.$assign(vC);',
|
||||||
' vV.$assign(vV);',
|
' vV.$assign(vV);',
|
||||||
' vV.i = vV.i;',
|
' vV.i = vV.i;',
|
||||||
' U.set(vL);',
|
' U.$assign(vL);',
|
||||||
' U.set(vD);',
|
' U.$assign(vD);',
|
||||||
' U.set(vC);',
|
' U.$assign(vC);',
|
||||||
' U.set(vV);',
|
' U.$assign(vV);',
|
||||||
' $mod.DoIt($mod.TRecord.$clone(vD), vD, vD, {',
|
' vL.$assign(U);',
|
||||||
' get: function () {',
|
' vD.$assign(U);',
|
||||||
' return vD;',
|
' vV.$assign(U);',
|
||||||
' },',
|
' $mod.DoIt($mod.TRecord.$clone(vD), vD, vD, vD);',
|
||||||
' set: function (v) {',
|
' $mod.DoIt($mod.TRecord.$clone(vC), vC, vL, vL);',
|
||||||
' vD.$assign(v);',
|
' $mod.DoIt($mod.TRecord.$clone(vV), vV, vV, vV);',
|
||||||
' }',
|
' $mod.DoIt($mod.TRecord.$clone(vL), vL, vL, vL);',
|
||||||
' });',
|
' U.i = 3;',
|
||||||
' $mod.DoIt($mod.TRecord.$clone(vC), vC, vL, {',
|
|
||||||
' get: function () {',
|
|
||||||
' return vL;',
|
|
||||||
' },',
|
|
||||||
' set: function (v) {',
|
|
||||||
' vL.$assign(v);',
|
|
||||||
' }',
|
|
||||||
' });',
|
|
||||||
' $mod.DoIt($mod.TRecord.$clone(vV), vV, vV, {',
|
|
||||||
' get: function () {',
|
|
||||||
' return vV;',
|
|
||||||
' },',
|
|
||||||
' set: function (v) {',
|
|
||||||
' vV.$assign(v);',
|
|
||||||
' }',
|
|
||||||
' });',
|
|
||||||
' $mod.DoIt($mod.TRecord.$clone(vL), vL, vL, {',
|
|
||||||
' get: function () {',
|
|
||||||
' return vL;',
|
|
||||||
' },',
|
|
||||||
' set: function (v) {',
|
|
||||||
' vL.$assign(v);',
|
|
||||||
' }',
|
|
||||||
' });',
|
|
||||||
'};',
|
'};',
|
||||||
'this.i = $mod.TRecord.$new();'
|
'this.i = $mod.TRecord.$new();'
|
||||||
]),
|
]),
|
||||||
LinesToStr([
|
LinesToStr([
|
||||||
'$mod.DoIt($mod.TRecord.$clone($mod.i), $mod.i, $mod.i, {',
|
'$mod.DoIt($mod.TRecord.$clone($mod.i), $mod.i, $mod.i, $mod.i);',
|
||||||
' p: $mod,',
|
|
||||||
' get: function () {',
|
|
||||||
' return this.p.i;',
|
|
||||||
' },',
|
|
||||||
' set: function (v) {',
|
|
||||||
' this.p.i.$assign(v);',
|
|
||||||
' }',
|
|
||||||
'});',
|
|
||||||
'']));
|
'']));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
<a href="#functiontype">Translating function types</a><br>
|
<a href="#functiontype">Translating function types</a><br>
|
||||||
<a href="#absolute">Translating var modifier absolute</a><br>
|
<a href="#absolute">Translating var modifier absolute</a><br>
|
||||||
<a href="#assert">Translating assert()</a><br>
|
<a href="#assert">Translating assert()</a><br>
|
||||||
|
<a href="#dispatch">TObject.Dispatch</a><br>
|
||||||
<a href="#calljavascript">Calling JavaScript from Pascal</a><br>
|
<a href="#calljavascript">Calling JavaScript from Pascal</a><br>
|
||||||
<a href="#asm">The asm block</a><br>
|
<a href="#asm">The asm block</a><br>
|
||||||
<a href="#assembler">The procedure modifier assembler</a><br>
|
<a href="#assembler">The procedure modifier assembler</a><br>
|
||||||
@ -630,8 +631,8 @@ End.
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Pascal</th>
|
<th>Pascal</th>
|
||||||
<th>JS Pas2js 1.2</th>
|
|
||||||
<th>JS Pas2js 1.3</th>
|
<th>JS Pas2js 1.3</th>
|
||||||
|
<th>JS Pas2js 1.2</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -656,36 +657,6 @@ End.
|
|||||||
<td>
|
<td>
|
||||||
<pre>rtl.module("MyModule",
|
<pre>rtl.module("MyModule",
|
||||||
["System"],
|
["System"],
|
||||||
function(){
|
|
||||||
var $mod = this;
|
|
||||||
this.TMyRecord = function(s) {
|
|
||||||
if (s){
|
|
||||||
this.i = s.i;
|
|
||||||
this.s = s.s;
|
|
||||||
this.d = s.d;
|
|
||||||
} else {
|
|
||||||
this.i = 0;
|
|
||||||
this.s = "";
|
|
||||||
this.d = 0.0;
|
|
||||||
};
|
|
||||||
this.$equal = function (b) {
|
|
||||||
return (this.i == b.i) &&
|
|
||||||
(this.s == b.i) && (this.d == b.d);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
this.r = new this.TMyRecord();
|
|
||||||
$mod.$init = function() {
|
|
||||||
$mod.r.i=123;
|
|
||||||
$mod.r = new $mod.TMyRecord($mod.s);
|
|
||||||
if ($mod.r.$equal($mod.s)) ;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[]);
|
|
||||||
</pre>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<pre>rtl.module("MyModule",
|
|
||||||
["System"],
|
|
||||||
function(){
|
function(){
|
||||||
var $mod = this;
|
var $mod = this;
|
||||||
rtl.recNewT($mod, "TMyRecord", function() {
|
rtl.recNewT($mod, "TMyRecord", function() {
|
||||||
@ -711,6 +682,36 @@ function(){
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
[]);
|
[]);
|
||||||
|
</pre>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<pre>rtl.module("MyModule",
|
||||||
|
["System"],
|
||||||
|
function(){
|
||||||
|
var $mod = this;
|
||||||
|
this.TMyRecord = function(s) {
|
||||||
|
if (s){
|
||||||
|
this.i = s.i;
|
||||||
|
this.s = s.s;
|
||||||
|
this.d = s.d;
|
||||||
|
} else {
|
||||||
|
this.i = 0;
|
||||||
|
this.s = "";
|
||||||
|
this.d = 0.0;
|
||||||
|
};
|
||||||
|
this.$equal = function (b) {
|
||||||
|
return (this.i == b.i) &&
|
||||||
|
(this.s == b.i) && (this.d == b.d);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
this.r = new this.TMyRecord();
|
||||||
|
$mod.$init = function() {
|
||||||
|
$mod.r.i=123;
|
||||||
|
$mod.r = new $mod.TMyRecord($mod.s);
|
||||||
|
if ($mod.r.$equal($mod.s)) ;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]);
|
||||||
</pre>
|
</pre>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -756,6 +757,9 @@ function(){
|
|||||||
<li><i>Dispose(PointerOfRecord)</i> Sets the variable to null if possible.</li>
|
<li><i>Dispose(PointerOfRecord)</i> Sets the variable to null if possible.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li>Passing a record to an untyped arguments (e.g. ''TObject.Dispatch(var Msg)'')
|
||||||
|
passes the record JS object directly, not creating a temporary reference object.</li>
|
||||||
|
<li>Typecasting RecordType(UntypedArgument) returns the argument, i.e. no conversion.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -2266,6 +2270,21 @@ End.
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<h2 id="dispatch">TObject.Dispatch</h2>
|
||||||
|
The procedure modifier '''message''' and the ''TObject.Dispatch'' works
|
||||||
|
similar to FPC/Delphi, as it expects a record of a specific format and
|
||||||
|
''Dispatch'' calls the method with that message number or string.<br>
|
||||||
|
The procedure modifier '''message <integer>''' adds an entry to the
|
||||||
|
''$msgint'' object, and modifier '''message <string>''' adds an entry
|
||||||
|
to the ''$msgstr'' object.<br>
|
||||||
|
The '''TObject.Dispatch''' expects as argument a record with an integer
|
||||||
|
field ''Msg'' (case sensitive).<br>
|
||||||
|
The '''TObject.DispatchStr''' expects as argument a record with a string
|
||||||
|
field ''MsgStr'' (case sensitive).<br>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2 id="calljavascript">Calling JavaScript from Pascal</h2>
|
<h2 id="calljavascript">Calling JavaScript from Pascal</h2>
|
||||||
Pas2js allows to write low level functions and/or access a JavaScript library
|
Pas2js allows to write low level functions and/or access a JavaScript library
|
||||||
|
Loading…
Reference in New Issue
Block a user