Re: Phix syntax
- Posted by petelomax Dec 22, 2020
- 864 views
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"