reflection.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
---------------------------> Sather 1.1 source file <--------------------------

-- REFLECTION - Version 1.0, by CMF (fleiner@icsi.berkeley.edu) -- Modified&documented by BAG (gomes@icsi.berkeley.edu) -- -- !! DANGER - some of these classes can gravely violate encapsualtion -- Use at your own risk for extra-linguistic support -- and not for standard code. -- -- Using the classes below could expose your program to the forces of -- the dark side, where pointers are untyped and encapsulation is an -- illusion. Besides, these functions might disappear from future -- Sather releaes with neither warning nor apology. Of the 3 classes -- below, REFLECT_INCLUDE is least likely to disappear. -- -- They were created by CMF (fleiner@icsi), because they are neat and -- extremely useful. Their use (aside from REFLECT_INCLUDE) should -- probably be confined to tools. Our initial inclination was to not -- document these classes at all, to discourage usage, but we fear -- that they are too useful to be ignored. -- -- Of the classes below: -- REFLECT_INCLUDE may be used in a relatively safe manner -- to expose the internals of particular classes that include it. -- REFLECT can be used to break all typesafety and encapsulation. -- by exposing the internals of any arbitrary classes. -- META_OBJECT is a wrapper for REFLECT. -- -- Once again: These classes VIOLATE ALL SATHER GUARANTEES and should -- be used with great care. -- -- -----------------------------------------------------------------

class REFLECT_INCLUDE

class REFLECT_INCLUDE is -- REFLECT_INCLUDE, unlike the other reflection classes, can be used with -- relative safety. It is used by inclusion and all its routines -- are, by default, private. -- Nevertheless, this is still is an *undocumented language extension*. -- Use the compiler option -reflect in order to access these functions. -- -- Encapsulation: Its routines *cannot* be used to break the -- encapsulation of arbitrary other classes. However, if a class -- chooses to include REFLECT_INCLUDE and make the interface -- public, it looses all its encapsulation. -- -- Type-safety: Calling the set_attrib routine inappropriately can -- result in run-time type errors (which are currently not -- checked), but this is no worse than a typical typecase. -- -- Usage: -- class FOO is include REFLECT_INCLUDE; -- -- all functions are still private -- -- copy: SAME is -- res::= new; -- loop a:$OB := attrib!; name: STR := attrib_name!; -- typecase a -- when $COPY then res.set_attrib!(a.attrib!); -- else #OUT+"Could not copy:"+name+"\n"; end; -- end; -- return res; -- end; -- When used in the above manner, these functions cannot break the -- encapsulation of any *other* classes in the system. private n_attribs:INT pre ~void(self) is return REFLECT::n_attribs(self); end; private attrib_name(i:INT):STR pre ~void(self) is return REFLECT::attrib_name(self,i); end; private attrib(i:INT):$OB pre ~void(self) is return REFLECT::attrib(self,i); end; private set_attrib(i:INT,n:$OB) pre ~void(self) is REFLECT::set_attrib(self,i,n); end; private attrib!:$OB pre ~void(self) is loop yield(REFLECT::attrib(0.upto!(attrs-1))); end; end; private attrib_name!:STR pre ~void(self) is loop yield(REFLECT::attrib_name(0.upto!(attrs-1))); end; end; private array_size:INT pre ~void(self) is return REFLECT::array_size(self); end; private array_element(i:INT):$OB pre ~void(self) is return REFLECT::array_element(self,i); end; private set_array_element(i:INT,n:$OB) pre ~void(self) is REFLECT::set_array_element(self,i,n); end; end;

class REFLECT

class REFLECT is -- Avoid using this class. Use REFLECT_INCLUDE, instead, if -- possible. REFLECT is the most dangerous of the reflection -- classes, and permits arbitrary breakage of encapsulation and -- type-safety in any class. It allows you to create, inspect and -- modify (including private attributes) objects of any type. -- -- "There are wonderous things out here. Treasures to satiate -- your every desire, both subtle and gross" -- Q ,from Star Trek -- -- Warning! This class is *not* part of the specification. -- and should *ONLY* be used for writing extra-linguistic tools. -- such as debugging or persistance. Not for standard libraries. -- -- Usage: -- b ::= #FOO; n_attrs_in_b: INT := REFLECT::n_attribs(o) create_object(i:INT):$OB pre i/=0 is -- Create a new object whose type tag is "i" o:$OB; SYS::inlined_C("#o=(OB)create_object(#i,0);"); return o; end; create_object(i:INT,asize:INT):$OB pre i/=0 is -- Create a new array object of arbitrary type (i specifies the type tag) o:$OB; SYS::inlined_C("#o=(OB)create_object(#i,#asize);"); return o; end; tp_for_str(class_name: STR): INT is -- Returns the type tag associated with the class name "class_name" -- Returns 0 if no such tag exists (0 is never a valid tag) -- This function should be in SYS, but is only possible with the -- reflection information tp: INT := C_REFLECT::tp_for_str(class_name); return tp; end; n_attribs(o:$OB):INT pre ~void(o) is -- Return the number of attributes of object"o" r:INT; SYS::inlined_C("#r=get_attrs(#o);"); return r; end; attrib(o:$OB,i:INT):$OB pre ok_attrib(o,i) is -- Return the "i" th attribute of object "o" r:$OB; SYS::inlined_C("#r=(OB)get_attr(#o,#i);"); return r; end; attrib_name(o:$OB,i:INT):STR pre ok_attrib(o,i) is -- Return the name of the "i"th attribute of object "o" r:EXT_OB; SYS::inlined_C("#r=(void *)get_attr_name(#o,#i);"); return STR::create_from_c_string(r); end; set_attrib(o:$OB,i:INT,n:$OB) pre ok_attrib(o,i) is -- Set the "i"th attribute of object "o" to "n" SYS::inlined_C("set_attr(#o,#i,#n);"); end; array_size(o:$OB):INT pre ~void(o) is r:INT; SYS::inlined_C("#r=get_array_size(#o);"); return r; end; array_element(o:$OB,i:INT):$OB pre ok_array_elt(o,i) is r:$OB; SYS::inlined_C("#r=(OB)get_array_element(#o,#i);"); return r; end; set_array_element(o:$OB,i:INT,n:$OB) pre ok_array_elt(o,i) is SYS::inlined_C("set_array_element(#o,#i,#n);"); end; private ok_attrib(ob: $OB, i: INT): BOOL is if ~void(ob) then return i < n_attribs(ob); else return false; end; end; private ok_array_elt(o: $OB,i: INT): BOOL is if ~void(o) then return i < array_size(o) else return false end; end; end;

class META_OBJECT

class META_OBJECT is -- META_OBJECT is another convenient way to obtain the reflection -- functionality for an arbitrary object, A, of any type. Instead -- of repeatedly providing A as the first argument to the functions -- in REFLECT, you can create a META_OBJECT which holds a pointer -- to A, and supplies it as the first argument. -- Use REFLECT_INCLUDE instead of this class, if possible -- -- Warning! This class is *not* part of the language specification. -- and should *ONLY* be used for writing extra-linguistic tools. -- such as debugging or persistance. Not for standard library code. -- -- Usage: -- b ::= #FOO; -- meta_object_for_b := #META_OBJECT(b); -- n_attrs_in_b: INT := meta_object_for_b.n_attribs; -- private include REFLECT; readonly attr object:$OB; create(o:$OB):SAME is r::=new; r.object:=o; return r; end; n_attribs:INT pre is_ok is return n_attribs(object); end; attrib_name(i:INT):STR pre is_ok is return attrib_name(object,i); end; attrib(i:INT):$OB pre is_ok is return attrib(object,i); end; set_attrib(i:INT,n:$OB) pre is_ok is set_attrib(object,i,n); end; array_size:INT pre is_ok is return array_size(object); end; array_element(i:INT):$OB pre is_ok is return array_element(object,i); end; set_array_element(i:INT,n:$OB) pre is_ok is set_array_element(object,i,n); end; attrib!:$OB pre is_ok is loop i::=0.upto!(n_attribs-1); yield(attrib(object,i)); end; end; attrib_name!:STR pre is_ok is loop i::=0.upto!(n_attribs-1); yield(attrib_name(object,i)); end; end; private is_ok: BOOL is return ~void(self) and ~void(object) end; end;

external class C_REFLECT

external class C_REFLECT is -- Only for one routine right now. -- (ben) Shouldn't all those inlined C things be in external routines too? tp_for_str(s: STR): INT; -- Return the tp associated with the string "s" -- Returns 0 if no type match is found end;