Discussion:
Default properties
(too old to reply)
Ryan Joseph
2018-09-07 09:59:07 UTC
Permalink
I’m moving my technical questions about default properties here so I don’t clutter up the other list. I’m still new to the compiler please bear with me.

The first problem I’m having is how to resolve duplicate functions with overloads. For example in TWrapper there’s multiple overloads for DoThis and we need to determine if TWrapper.DoThis should use TWrapper or the THelperA from the default property.

type
THelperA = record
procedure DoThis;
end;

type
TWrapper = record
objA: THelperA;
property helperA: THelperA read objA write objA; default;
procedure DoThis(param: integer); overload;
procedure DoThis(param: string); overload;
end;


var
wrapper: TWrapper;
begin
wrapper.DoThis(1); // DoThis is from TWrapper but how can we determine this?



What I’m narrowing in on is:

in pexpr.pas do_member_read() takes the load node and converts it to a call node and this is where I need to determine what definition the function belongs to. So in the example above we get “DoThis” how can we determine if TWrapper or THelperA has a matching function with matching parameters? searchsym_in_record usually returns the correct definition but I need to scan 2 possible definitions instead of just the first one specified in the load node.

do_proc_call() parses parameters into a tcallparanode which is good.

do_typecheckpass on the tcallnode from do_proc_call() will find procsym candidates in the record def which the node was created with. I would use this to query but it forces a syntax error which isn’t what I want.

Hopefully that makes sense. So my question is, is there an existing way to search a tabstractrecorddef given a name and parameter list and return a found or not found answer? I could start pulling stuff out of do_typecheckpass() but I suspect there’s already a way to do this.

Regards,
Ryan Joseph

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cg
Sven Barth via fpc-devel
2018-09-07 11:27:44 UTC
Permalink
I’m moving my technical questions about default properties here so I don’t
clutter up the other list. I’m still new to the compiler please bear with
me.
The first problem I’m having is how to resolve duplicate functions with
overloads. For example in TWrapper there’s multiple overloads for DoThis
and we need to determine if TWrapper.DoThis should use TWrapper or the
THelperA from the default property.
type
THelperA = record
procedure DoThis;
end;
type
TWrapper = record
objA: THelperA;
property helperA: THelperA read objA write objA; default;
procedure DoThis(param: integer); overload;
procedure DoThis(param: string); overload;
end;
var
wrapper: TWrapper;
begin
wrapper.DoThis(1); // DoThis is from TWrapper but how can we
determine this?
in pexpr.pas do_member_read() takes the load node and converts it to a
call node and this is where I need to determine what definition the
function belongs to. So in the example above we get “DoThis” how can we
determine if TWrapper or THelperA has a matching function with matching
parameters? searchsym_in_record usually returns the correct definition but
I need to scan 2 possible definitions instead of just the first one
specified in the load node.
do_proc_call() parses parameters into a tcallparanode which is good.
do_typecheckpass on the tcallnode from do_proc_call() will find procsym
candidates in the record def which the node was created with. I would use
this to query but it forces a syntax error which isn’t what I want.
Hopefully that makes sense. So my question is, is there an existing way to
search a tabstractrecorddef given a name and parameter list and return a
found or not found answer? I could start pulling stuff out of
do_typecheckpass() but I suspect there’s already a way to do this.
tcallcandidates in htypechk.pas is your friend. That is the *only* class
that deals with overload resolution and collects the eligible overloads
from various sources (e.g. loaded units, current type, helper types).
Essentially you only need to search for a procsym with the name of method
inside the default field (all proceeds with the same name share the same
procsym) and pass that on, the remainder of tcallcandidates will deal with
overload resolution (you only need to make sure that the correct "Self",
namely the default field is picked for that).

Regards,
Sven
Ryan Joseph
2018-09-10 08:51:19 UTC
Permalink
tcallcandidates in htypechk.pas is your friend. That is the *only* class that deals with overload resolution and collects the eligible overloads from various sources (e.g. loaded units, current type, helper types). Essentially you only need to search for a procsym with the name of method inside the default field (all proceeds with the same name share the same procsym) and pass that on, the remainder of tcallcandidates will deal with overload resolution (you only need to make sure that the correct "Self", namely the default field is picked for that).
Thanks, I got this working.

Just a general question. Can you clarify the difference between “tloadnode”, “tsubscriptnode” and “tcallnode”? I want to make sure I’m using them correctly.

I ask because I’m trying to parse:

wrapper + 1 { wrapper being a record with a default property }

“wrapper” is being parsed as a load node but I want to convert it to “wrapper.helper” by appending the default property. I found I can make a new subscript node using the existing load node but is that the preferred method?

p1:=csubscriptnode.create(default_property,p1); { p1 being the load node for “wrapper” }

Regards,
Ryan Joseph

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://
Ryan Joseph
2018-09-10 09:23:39 UTC
Permalink
One more question. With the syntax:

wrapper + 1

I get to the point where I have 2 nodes parsed. p2 is an ordconst node (the value “1") and p1 is a load node (wrapper, which is a record). I need to check the resultdef for p1 to see if the + operator is overloaded so I can determine if the base record or the default property takes precedence.

I think I can use tcallcandidates.create_operator to test this but what do I pass for the call param node?

from pexpr.pas:


p2:=sub_expr(succ(pred_level),flags+[ef_accept_equal],nil);

case oldt of
_PLUS :
p1:=caddnode.create(addn,p1,p2);
_MINUS :
p1:=caddnode.create(subn,p1,p2);
_STAR :
p1:=caddnode.create(muln,p1,p2);
_SLASH :
p1:=caddnode.create(slashn,p1,p2);
_EQ:
p1:=caddnode.create(equaln,p1,p2);
_GT :
p1:=caddnode.create(gtn,p1,p2);
Regards,
Ryan Joseph

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-d
Ryan Joseph
2018-09-18 07:59:17 UTC
Permalink
Post by Ryan Joseph
I think I can use tcallcandidates.create_operator to test this but what do I pass for the call param node?
I didn’t get an answer on this but I was able to figure it out for myself, albeit only for arithmetic operators, i.e.

class operator + (left: TWrapper; right: integer): TWrapper;

ppn:=ccallparanode.create(right.getcopy,ccallparanode.create(left.getcopy,nil));
ppn.get_paratype;
candidates:=tcallcandidates.create_operator(optoken,ppn);
if candidates.count > 0 then
begin
candidates.get_information;
result := candidates.choose_best(tabstractprocdef(operpd),false) > 0;
end;

For assignment operators like: class operator := (right: integer): TWrapper; the code doesn’t return any candidates. I think this is because the tcallparanode is wrong but I don’t know what to provide.

Any ideas?

Regards,
Ryan Joseph

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/lis

Loading...