1. Phix syntax

Here's something to think about:

When using classes, the syntax seems backward. For example:

Window w = new() 
w.set_name("Main") -- calls procedure gtk_widget_set_name()  
? w.get_name() -- calls function gtk_widget_get_name() - displays "Main" 

It would seem to me less awkward if it looked more like:

Window w = new() 
w.name="Main"   -- sets the name, like x=3 would set the value of x 
? w.name -- displays "Main" same as ?x would display 3 

IOW, class properties would work like normal variables. Is there any possibility that there's a way to do this?


We can already get partway there by declaring public fields:

export class Window extends Widget 
  public string name; 
  • ? w.name works if you have previously included a line to set the public field as a part of procedure gtk_widget_set_name()
  • the assignment: w.name="Foo" doesn't have a way to call function gtk_widget_set_name(), AFAIK.
new topic     » topic index » view message » categorize

2. Re: Phix syntax

That's not an entirely mad idea.

As you say, if name is public, then w.name operates as normal and doesn't invoke any "magic", and I wouldn't change that.

At the moment, if name is private, it is a runtime error, which is too late to do anything about it.
If I first changed it, as I probably should, to a compile-time error, that could open up further possibilities.
It could, just before issuing such an error, check for (public) get_name/set_name methods and invoke those instead,
or to be pedantic about it, emit the appropriate code to invoke them/pretend they'd been written that way.

I don't think it would need any specific syntax, accessing a private xyz would make it look, depending on context,
for either a single parameter (and public) set_xyz procedure, or a parameter-less get_xyz function.

Note that w["name"] style access wouldn't change.

new topic     » goto parent     » topic index » view message » categorize

3. Re: Phix syntax

I think that this would be well worthwhile to explore. Classes make the job of wrapping the huge GTK library fairly painless.

So far, even the complex widgets can be coded in less than 100 lines of code. And that code is clear and manageable.

This improved (more logical) syntax would help a lot in that regard.


Note: It appears that you may be able to have two (or more?) routines by the same name within a class without triggering an error. Run test below, it runs without warning or crashing.

class TestObj 
 
    private integer handle; 
    private string name; 
     
    function TestObj() 
    this.handle=rand(100000) 
    return this 
    end function 
     
    procedure name(string s) this.name = s end procedure 
    function name() return this.name end function 
 
end class 
 
TestObj y = new() 
?y 

So how does this work? Would it be possible to call the name() function when the syntax calls for a "read from" action, and call the name() procedure when the syntax indicates "write to"?

  • ? y.handle or puts(1,y.handle) -- read from
  • y.handle=n -- write to
new topic     » goto parent     » topic index » view message » categorize

4. Re: Phix syntax

irv said...

Note: It appears that you may be able to have two (or more?) routines by the same name within a class without triggering an error.
So how does this work?

It doesn't, you've found a bug (thanks).

If you declare a second name field, as expected you get a "duplicate" compilation error.

However all methods are "virtual", in the sense that they can be overidden.
If your base Widget class has a set_name() procedure, and your Window class also has one, it quietly replaces it.
(And before you ask, there isn't any kind of super.get_name(), or any firm plans to add such, as yet.)
(For now, I'd just suggest putting any such code in a private get_name_() and invoking that directly, twice.)
The bug(s) are: it should check that any such replacement has the right type/signature, and that whatever it is
replacing is from an extended/base class rather than the current one. As it stands, those declarations store an
integer routine_id in the string name[1], and you'd need a bit of indirection/sleight of hand to fake out the
compiler such that you could invoke (the second) via call_func (the procedure's routine_id has already been lost).

[1] Technically, that is, in the default for the name field, ie some internal {0,"",3074} ==> {0,3076,3074}, so
it is neatly sidestepping all the usual builtin typechecking mechanisms, and of course new() totally trusts the
integrity of said internal.

PS. I'm committed to this idea now, but with no timescale as yet.

new topic     » goto parent     » topic index » view message » categorize

5. Re: Phix syntax

petelomax said...

It doesn't, you've found a bug (thanks).

If you declare a second name field, as expected you get a "duplicate" compilation error.

However all methods are "virtual", in the sense that they can be overidden.
If your base Widget class has a set_name() procedure, and your Window class also has one, it quietly replaces it.

PS. I'm committed to this idea now, but with no timescale as yet.

Great, understood. It appears that I can mostly automate the process of converting the EuGTK "dispatch table" into classes. Maybe it won't be as painful as I first thought.

I tried a few tests with the universal "set" procedure as used in EuGTK, but it won't work since the class routines don't have routine-ids. Still possible to test using the existing syntax for calls, however.

new topic     » goto parent     » topic index » view message » categorize

6. Phix-EuGTK development

Irv,

Just to be clear - your Phix-EuGTK development platform is Linux, yes?

If Linux is still your development platform please tell us your current distribution and release (again).

Your patience is appreciated. I will certainly give Linux/Phix+EuGTK a closer look, if you are able to pull off the port (is port the correct term?).

Thanks again for your ongoing development of EuGTK and thanks to Pete for his ongoing development of Phix.

Regards, Ken

new topic     » goto parent     » topic index » view message » categorize

7. Re: Phix-EuGTK development

LinuxMint 19.2 (tina)

4.15.0-54-generic (#58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019)

Don't hold your breath waiting for a version of EuGTK for Phix. I'm trying to utilize it properly, setting up classes with inheritance using Phix class functions.

The Euphoria version required me to create my own fake 'classes' and inheritance, no point in trying that with Phix. And, as already noted, Phix lacka a lot of the convenience functions that are in Euphoria, and I'm not about to try re-creating those (badly).

In short, it's a complete re-write, and in the process I'll learn about Phix, and probably find some (more) bugs. At this point, it's a dozen steps back for every step forward.

ETA: (edited to add, and/or estimated time of arrival) It's a close race between finishing this and our galaxy colliding with another.

new topic     » goto parent     » topic index » view message » categorize

8. Re: Phix syntax

petelomax said...

if name is private, it is a runtime error, which is too late to do anything about it.

I don't half spout some twaddle sometimes, so glad I slept on this before jumping straight in.

First, a minor fix to builtins\get_routine_info.e, function get_routine_info() line 49, replace

    string name = sr[S_Name] 
--  object name = sr[S_Name] 

with

--  string name = sr[S_Name] 
    object name = sr[S_Name]    -- 22/12/20 class methods have a [symtab] name of -1, on purpose 
                                --          (their proper names are kept in builtins/structs.e, 
                                --           and are passed in as text anyway, so you don't need 
                                --           multiple conflicting entries messing up the symtab, 
                                --           or ever allow a "do()" that should be an "s.do()".) 

I have updated the docs to mention that class methods return a name of -1.

In builtins/structs.e, procedure store_field() (line 1048), replace

                if cdii=NULL or not find(context,cdii) then 
                    crash("attempt to modify private field (%s)",{field_name},2) 
                end if 

with

                if cdii=NULL or not find(context,cdii) then 
                    -- 22/12/20 (setter handling) 
                    if stype<=S_CLASS then 
                        integer setter = field_dx(sdx,"set_"&field_name) 
                        if setter!=0 then 
                            integer flags = structs[sdx][S_FIELDS][setter][S_FLAGS] 
                            if flags=SF_PROC then -- (and not SF_PRIVATE, obvs) 
                                integer setfn = instances[sdx][C_INSTANCES][s[I_DATA]][setter] 
                                {integer maxp, integer minp, string sig} = get_routine_info(setfn) 
                                if maxp>=2 and minp<=2 and sig[1..2] = "PO" then 
                                    call_proc(setfn,{s,v}) -- (this,v) 
                                    return 
                                end if 
                            end if 
                        end if 
                    end if 
                    crash("attempt to modify private field (%s)",{field_name},2) 
                end if 

And just a bit further down, in function fetch_field(), replace

        if not sequence(cdii) 
        or not find(context,cdii) then 
            crash("attempt to read private field (%s)",{field_name},2) 
        end if 

with

        if not sequence(cdii) 
        or not find(context,cdii) then 
            -- 22/12/20 (getter handling) 
            if stype<=S_CLASS then 
                integer getter = field_dx(sdx,"get_"&field_name) 
                if getter!=0 then 
                    integer flags = structs[sdx][S_FIELDS][getter][S_FLAGS] 
                    if flags=SF_FUNC then -- (and not SF_PRIVATE, obvs) 
                        integer getfn = instances[sdx][C_INSTANCES][s[I_DATA]][getter] 
                        {integer maxp, integer minp, string sig} = get_routine_info(getfn) 
                        if maxp>=1 and minp<=1 and sig[1..2] = "FO" then 
                            return call_func(getfn,{s}) -- (this) 
                        end if 
                    end if 
                end if 
            end if 
            crash("attempt to read private field (%s)",{field_name},2) 
        end if 

If attempting to fetch or modify a private field would otherwise trigger a fatal error, but
there is a suitable public get_field function or set_field procedure, it is invoked instead.
Note that getters and setters do not work inside class methods, otherwise we would have
eg get_field() invoking itself ad infinitum instead of just fetching the field directly.
You can of course call any such getters and setters directly.

Example:

class test 
    private string s = "1" 
 
    public function get_s() 
        printf(1,"get_s() called\n") 
        return s 
    end function 
 
    public procedure set_s(string v) 
        printf(1,"set_s(%s) called\n",v) 
        s = v 
    end procedure 
end class 
 
test t = new() 
?t.s        -- get_s() called, "1" 
t.s = "2"   -- set_s(2) called 
?t.s        -- get_s() called, "2" 
new topic     » goto parent     » topic index » view message » categorize

9. Re: Phix syntax

petelomax said...

Note that w["name"] style access wouldn't change.

More twaddle / I lied - the new handling applies to that exactly the same.

new topic     » goto parent     » topic index » view message » categorize

10. Re: Phix syntax

irv said...

I tried a few tests with the universal "set" procedure as used in EuGTK, but it won't work since the class routines don't have routine-ids.

Actually they do. There are two catches:
1) you don't use routine_id, it's already there for you
2) you have to explicitly provide a "this" as first parameter on the call_func/proc.

This works fine for me (outside the class):

?w.handle  -- 18 
call_proc(w.set_handle,{w,19}) -- same as w.set_handle(19) 
?w.handle  -- 19 
new topic     » goto parent     » topic index » view message » categorize

11. Re: Phix syntax

First change did no harm.

After making the chances to store_field and fetch_field, compiling itself fails:

irv@irv-Mint19:~/phix$ p -cp 
 
Check for and shut down any running instances of phix 
  (retry messages are given if required after round 4) 
 
Self-host round 1: compiling p.exw 
Self-host round 1: compiled OK (0.57s), creating pnew xType=0 on symtab[8069] (refs in psched.e) 
xType=0 on symtab[8070] (agis in psched.e) 
xType=0 on symtab[8071] (mods in psched.e) 
xType=0 on symtab[8072] (pairs in psched.e) 
xType=0 on symtab[8073] (flags in psched.e) 
xType=0 on symtab[8074] (ids in psched.e) 
xType=0 on symtab[8075] (posns in psched.e) 
xType=0 on symtab[8076] (lte in psched.e) 
.... (lots more where this came from) 
xType=0 on symtab[8076] (lte in psched.e) 
 
/home/irv/phix/pmsgs.e:561 
--/**/  #isginfo{msg,string,MIN,MAX,integer,-2} 
         ^ gInfo is {5567,15,-1073741824,1073741823,15,-2} 

new topic     » goto parent     » topic index » view message » categorize

12. Re: Phix syntax

irv said...

compiling itself fails:

True. Do this:

--                              {integer maxp, integer minp, string sig} = get_routine_info(setfn) 
--                              if maxp>=2 and minp<=2 and sig[1..2] = "PO" then 
                                    call_proc(setfn,{s,v}) -- (this,v) 
                                    return 
--                              end if 
 
--                      {integer maxp, integer minp, string sig} = get_routine_info(getfn) 
--                      if maxp>=1 and minp<=1 and sig[1..2] = "FO" then 
                            return call_func(getfn,{s}) -- (this) 
--                      end if 

It will then trust to luck a bit, that you haven't given it a procedure get_field or a function set_field. Mind you, it'll crash if needed anyway.

I'll have to probably should figure out some way to turn that off during compilation (it's stomping on the symbol table!) but back on at runtime.

EDIT: I've now successfully disabled get_routine_info() during compilation, which needed removal of the long-broken instruction scheduler, which was about time and like 2000+ edits...

new topic     » goto parent     » topic index » view message » categorize

13. Re: Phix syntax

OK!

Looks like this will be much neater. Thanks.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu