Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2018-09

Default properties

5 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ryan Joseph

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

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph schrieb am Fr., 7. Sep. 2018,
11:59:

Show quoted text 52 lines
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.

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

Reply by email

Ryan Joseph
to Sven Barth
On Sep 7, 2018, at 6:27 PM, Sven Barth via fpc-devel wrote: 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

Reply by email

Ryan Joseph
to Sven Barth: Ryan Joseph schrieb am Fr., 7. Sep. 2018, 11:59: tcallcandidates in htypechk.pas is your…

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

Reply by email

Ryan Joseph
to Ryan Joseph
On Sep 10, 2018, at 4:23 PM, Ryan Joseph wrote: 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

Reply by email