Re: Phix syntax

new topic     » goto parent     » topic index » view thread      » older message » newer message
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 thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu