{Begin SubSec Object Variables and Properties}
{Title Object Variables and Properties}
{Text

{Tag ObjectVariables}

There are two kinds of variables associated with an instance: its private {it instance variables}{index instance variables} and the {it class variables}{index class variables} that it shares with all instances of the class.  This section deals with the functions for getting and putting values, and with a compact programming notation for referring to these variables from inside functions that implement methods.  In addition, there are properties which are associated with instance variables and class variables, with the methods of a class, and with classes themselves.  Given an object or a class, one can fetch or set any of these properties.  This section describes the functions for accessing all of these properties and values.


{note need better explaination of properties of variables, methods, classes}


{Begin SubSec Access Expressions}
{Title Access Expressions}
{Text

As mentioned above, there are a number of different types of variables and properties that can be associated with each class.  However, most of the accessing operations (getting and putting) in methods refer to the values or properties of instance variables or class variables of an instance.  LOOPS provides general functions (described later) for accessing these values, allowing variable names and property names to be computed.  However, most of the time the programmer knows the variable and property name to be used, and writing calls to these functions can be cumbersome.

Therefore, a simplified notation has been introduced for writing many common accessing operations, which is translated into calls to the appropriate functions:

{MacDef {Name @} {Args object accessExpr}}
{MacDef {Name @} {Args accessExpr}
{Text
Returns the variable or property value of the object {arg object} as specified by {arg accessExpr}.  Note that {arg accessExpr} is not evaluated; {arg object} is evaluated.

If only one argument is given to {lisp @}, it is assumed that the object is bound to the variable {var self}.  This is very useful because by convention the first argument to any method is named {var self}.
}}

{MacDef {Name ←@} {Args object accessExpr newValue}}
{MacDef {Name ←@} {Args accessExpr newValue}
{Text
Similar to {lisp @}, sets the value of the variable or property specified by {arg accessExpr} (unevaluated) in the object {arg object} to {arg newValue}.  Returns {arg newValue}.  Note that {arg accessExpr} is not evaluated; the other arguments are evaluated.

Like {lisp @}, if {arg object} is ommitted, it defaults to the value of the variable {var self}.
}}


Both {lisp @} and {lisp ←@} take the argument {arg accessExpr}, which is an "access expression"{index access expressions} which specifies exactly which variable or property value should be retrieved or set.  {arg accessExpr} is an atom which specifies a variable name, an optional property name, and whether the variable is an instance variable or a class variable.

Some examples:

{Begin LabeledList examples of access expressions}
{Label {lisp (@ :FOO)}}
{Text
Retrieve the value of instance variable {lisp FOO} (from the object that is the value of {lisp self}).
}

{Label {lisp (@ XX ::FOO)}}
{Text
Retrieve the value of class variable {lisp FOO} (from the object that is the value of {lisp XX}).
}

{Label {lisp (←@ ::FOO:,BAR 5)}}
{Text
Store {lisp 5} as the value of the {lisp BAR} property of class variable {lisp FOO} (of the object that is the value of {lisp self}).
}

{End LabeledList examples of access expressions}


{note need much more info on access expressions.}

{note will access expression syntax be changed/extended to allow accessing class/method properties, or special access (...only, ...here)? ---mjsann}

}{End SubSec Access Expressions}




{Begin SubSec Getting Variable and Property Values}
{Title Getting Variable and Property Values}
{Text

The functions {fn GetValue} and {fn GetClassValue} retrieve from an instance the values of variables or their properties.  If the value bound to an instance variable or class variable is an {it active value}{index active values} with a {arg getFn}, then {fn GetValue} and {fn GetClassValue} of these functions trigger the {arg getFn} (see {PageRef Tag ActiveValues}).


{FnDef {Name GetValue} {Args object varName propName}
{Text
Returns the value or property value of the instance variable {arg varName} in the object {arg object}.  Each instance of a class has its own separate set of instance variables.

If {arg propName} is {lisp NIL}, {fn GetValue} returns the value of the variable.  In proper usage, {arg object} is an instance and the local value of the variable is returned.  If no local value has been set, {fn GetValue} returns the default value from the class.  Since this is a common case, default values inherited from super classes of the class are cached in the class itself, thus avoiding a runtime search.

If {arg propName} is not {lisp NIL}, {fn GetValue} returns the value associated with the property named  {arg propName} of the variable {arg varName}.  If none is found in the instance, it returns the default property value found in the class or one of its super classes.  If no property value is found in any of the super classes, the default value used is the value of the global variable {var NotSetValue}{index NotSetValue Var} (currently bound to {lisp ?}).  Note: this is different from Interlisp, where if no value of a property is found, then {lisp NIL} is returned.

{fn GetValue} fetches a value from an {it instance} of a class.  It is an error to try to use {fn GetValue} to fetch an instance variable from a class.   To fetch the default value of an instance variable from a class, use {fn GetClassIV} (see {PageRef Fn GetClassIV}).
}}



{FnDef {Name GetClassValue} {Args object varName propName}
{Text
Returns the value (if {arg propName}={lisp NIL}) or property value of the class variable {arg varName} for the class of the {arg object} (which may be either an instance or a class).

Class variables are inherited from the super classes.  If {arg object} is an instance, lookup begins at the class of {arg object} since instances do not have class variables stored locally.  If the class does not have a class variable {arg varName}, {fn GetClassValue} searches through the super classes of the class until it finds {arg varName}.  Since this is thought to be an relatively rare in code, class variables are stored only in the class in which they are defined, and the runtime search is necessary. 

Conceptually, one should think of a class variable of a class as being shared by all instances of that class, and by all instances of any of its subclasses.  For example, suppose {lisp Transistor} is a class with class variable, {lisp TransSeqNum}, and {lisp DepletionTransistor} is a subclass of {lisp Transistor}.  Then setting the class variable {lisp TransSeqNum} from an instance of {lisp DepletionTransistor} would be seen by all instances of {lisp Transistor}.  
}}



{Begin Note}
A common case for both GetValue and GetClassValue is when the variable name is known (a quoted atom).  The functions @ and @@, which quote some of their arguments, are provided so that one can write accessing expressions more concisely.  A single @ refers to an instance variable, a double @@ refers to a class variable.

For instance variables, the following abbreviation can be used:

(@ object varName)   ==>   (GetValue object (QUOTE varName))
(@ object varName propName)   ==>   (GetValue object (QUOTE varName) (QUOTE propName))
(@ varName)   ==>   (GetValue self (QUOTE varName))

A similar abbreviation is available for class variables:

(@@ object varName)   ==>   (GetClassValue object (QUOTE varName))
(@@ object varName propName)   ==>   (GetClassValue object (QUOTE varName) (QUOTE propName))
(@@ varName)   ==>   (GetClassValue self (QUOTE varName))


As indicated above, if only one argument is given to @ or @@, it is assumed that the object is bound to the variable self.  This is very useful because by convention the first argument to any method is named self.

Finally, there are read macros available in the system that allow an even more concise prefix notation for variable access:
Prefix:	  	@X	@(obj X)	@(obj X P)		@@X		@@(obj X)		@@(obj X P)
Function:	 (@ X)	 (@ obj X)	(@ obj X P)	(@@ X)	(@@ obj X)		(@@ obj X P)

In prefix form, parenthetical expressions of length 2 access values of instance variables for objects other than self, and parenthetical expresssions of length 3 access properties of variables.  This notation has been integrated into the Interlisp system so that the prefix form will appear whenever functions are prettyprinted.
------
de-documented ---mjsann
{End Note}


}{End SubSec Getting Variable and Property Values}



{Begin SubSec Putting Variable Values and Property Values}
{Title Putting Variable Values and Property Values}
{Text

{fn PutValue} and {fn PutClassValue} are functions used for storing variable or property values in an instance.  They are analogous to {fn GetValue} and {fn GetClassValue}; as with these functions, if the value of the variable or property is an active value{index active values} with a {arg putFn}, trying to store a value for that variable or property will invoke the {arg putFn} (see {PageRef Tag ActiveValues}).


{FnDef {Name PutValue} {Args object varName newValue propName}
{Text
Stores {arg newValue} as the value or property value of the instance variable {arg varName} in the object {arg object}.  Returns {arg newValue}.

If {arg propName} is {lisp NIL}, {fn PutValue} stores {arg newValue} as the value of {arg varName} in {arg object}.  If {arg propName} is non-{lisp NIL}, then {arg newValue} is stored as the value of the property {arg propName} of the instance variable {arg varName}.  

For example, {lisp (PutValue {arg pos} 'X 0)}, stores {lisp 0} as the value of the instance variable {lisp X} of the object {arg pos}.

{fn PutValue} works for storing values in an instance of a class.  It is an error to try to store a default instance variable in a class with {fn PutValue}.   To store the default value for an instance variable directly in the class, use {fn PutClassIV} (see {PageRef Fn PutClassIV}).
}}


{FnDef {Name PutClassValue} {Args object varName newValue propName}
{Text
Similar to {fn PutValue}, except it stores {arg newValue} as the value or property value of a class variable and property.  {arg object} may either be an instance or a class.  Returns {arg newValue}.

If {arg varName} is not local to the class, then the value will be put in the first class in the inheritance list that {arg varName} is found.
}}



The following functions push a value on the front of a list already stored in a variable:

{FnDef {Name PushValue} {args object varName newValue propName} }
{FnDef {Name PushClassValue} {args object varName newValue propName}
{Text
{fn PushValue} and {fn PushClassValue} add {arg newValue} on the front of the list that is the value of the indicated variable or property, and store the result back in the variable or property.

These functions are defined so that if the value accessed is an active value, the {arg getFn} will be triggered when the old value of the list is fetched, and the {arg putFn} when the new value is stored back (see {PageRef Tag ActiveValues}).
}}



The following function adds a value on the end of an instance variable list:


{FnDef {Name AddValue} {args object varName newValue propName}
{Text
Similar to {fn PushValue}, except that {arg newValue} is added to the {it end} of the variable list.

There is no function for adding values to the end of class variable lists.{note why not?}
}}




{Begin Note}
Commonly, varName and propName are quoted, (and object is bound to self), so the functions @← and @@← give provided so one can call PutValue and PutClassValue more concisely.  @← refers to instance variables, @@← refers to class variables.

(@← object varName newValue)   ==>   (PutValue object (QUOTE varName) newValue) 
(@← object varName propName newValue)   ==>   (PutValue object (QUOTE varName) newValue (QUOTE propName))
(@← varName newValue)   ==>   (PutValue self (QUOTE varName) (QUOTE newValue))

(@@← object varName newValue)   ==>   (PutClassValue object (QUOTE varName) newValue)
(@@← object varName propName newValue)   ==>   (PutClassValue object (QUOTE varName) newValue (QUOTE propName) )
(@@← varName newValue)   ==>   (PutClassValue self (QUOTE varName) newValue)

Note that in the abbreviated notatation (using @← or @@←), the new value for the variable is always the last element in the list.  This is different from PutValue or PutClassValue, where the new value is the third argument and the last argument is the property name (or NIL).  

There are also read macros which provide a more concise prefix/infix notation for variable setting.  The correspondence between the two notations are:
IV Prefix/Infix:	  	@X←val			@(obj X)←val			@(obj X P)	←val
IV Function:	 	(@← X val)			(@← obj X val)			(@← obj X P val)

CV Prefix/Infix:	@@X←val			@@(obj X)	←val		@@(obj X P)←val
CV Function:	 	(@@← X val)		(@@← obj X val)		(@@← obj X P val)

@(obj X P)←+newVal for (PushValue obj (QUOTE X) newVal (QUOTE P))
and @@(obj X P)←+newVal for (PushClassValue obj (QUOTE X) newVal (QUOTE P))
{End Note}



}{End SubSec Putting Variable Values and Property Values}





{Begin SubSec Non-triggering Get and Put}
{Title Non-triggering Get and Put}
{Text

{Tag NonTriggering}


{note move into active value section?}

Using active values ({PageRef Tag ActiveValues}), it is possible to associate functions with a variable (or property) that will be called whenever the variable (or property) is read or set.  In some cases, it is useful to be able to access a value from an instance or class variable without triggering any active value which might be stored.  This can be done using the following functions:

{FnDef {Name GetValueOnly} {Args object varName propName} }
{FnDef {Name GetClassValueOnly} {Args object varName propName}
{Text
{fn GetValueOnly} and {fn GetClassValueOnly} retrieve the value of instance variables and class variables, respectively, without triggering any active values.

{fn GetValueOnly} retrieves the default value from the class if none exists in the instance.
}}


To store a value without triggering any active values, the following functions are provided:

{FnDef {Name PutValueOnly} {Args object varName newValue propName} }
{FnDef {Name PutClassValueOnly} {Args object varName newValue propName}
{Text
These functions store {arg newValue} in the instance variable or class variable, without triggering any active values, and return {arg newValue}.
}}


Note that {fn GetClassValueOnly} and {fn PutClassValueOnly} can take either a class or an instance.  {fn GetValueOnly} and {fn PutValueOnly} will only take instances.

}{End SubSec Non-triggering Get and Put}



{Begin SubSec Local Get Functions}
{Title Local Get Functions}
{Text

Sometimes it is desirable to find out if a value or property is set in a particular class or instance, without inheriting any information which is not local, and not activating any active values.  This can be done with the following functions:

{FnDef {Name GetIVHere} {Args object varName propName}
{Text
{arg object} must be an instance.  Returns the instance variable value that is found in the instance;  if none is found, then returns the value of the global variable {var NotSetValue}{index NotSetValue Var} (initially {lisp ?}).

{note before a value is put into an IV, GetIVHere will return ?, even if there is a default in the class.  Even Getting the default value will not "put it into" the IV.  doc?? ---mjsann}
}}



{FnDef {Name GetCVHere} {Args object varName propName}
{Text
{arg object} must be a class.  Returns the class variable value that is found in the class;  if none is found, then returns the value of {var NotSetValue}.
}}

In both {fn GetIVHere} and {fn GetCVHere}, if the value is an active value, the actual active value is returned, without being triggered.


Note that there are no need to have special local put functions, since all put functions are local to the instance or class.  For local nontriggering storage functions, use {fn PutValueOnly} and {fn PutClassValueOnly} ({PageRef Fn PutValueOnly}).

}{End SubSec Local Get Functions}



{Begin SubSec Accessing Class and Method Properties}
{Title Accessing Class and Method Properties}
{Text

Most of the get and put functions described in the preceding sections work with instances, but not with classes.  Some exceptions are {fn GetClassValue}, {fn PutClassValue}, {fn GetClassValueOnly}, and {fn PutClassValueOnly}, which can take either an instance or a class, and access class variables, and {fn GetCVHere} which takes a class.

The following functions access the {it default} value or property value of an instance variable (which is stored in the class):

{FnDef {Name GetClassIV} {Args class varName propName}
{Text
Returns the {it default} value or property value of the instance variable {arg varName} in the class {arg class}.
}}

{FnDef {Name PutClassIV} {Args class varName newValue propName}
{Text
Stores {arg newValue} as the {it default} value or property value of the instance variable {arg varName} in the class {arg class}.  If {arg varName} is not local to the class, this will cause an error.  Returns {arg newValue}.
}}


Note:  {fn GetClassIV} and {fn PutClassIV} do not trigger active values ({PageRef Tag NonTriggering}).





LOOPS provides property list storage for classes themselves and for methods of classes.  A typical use of these properties is to document a class and its methods.  Like the put and get functions for variables, these functions can trigger active values.  The functions for class properties are:


{FnDef {Name GetClass} {Args class propName}
{Text
Returns the value of the property {arg propName} of {arg class}.  If {arg propName} is {lisp NIL}, {fn GetClass} returns the metaclass of {arg class}.

Class properties are inherited like class variables, so {fn GetClass} will search through the super classes of {arg class} if {arg propName} is not found in {arg class} itself.
}}


{FnDef {Name PutClass} {Args class newValue propName}
{Text
Sets the value of the property {arg propName} of {arg class} to {arg newValue}.  If {arg propName} is {lisp NIL}, {fn GetClass} sets the metaclass of {arg class} to {arg newValue}.
}}


{FnDef {Name GetClassOnly} {Args class propName {anonarg}}}
{FnDef {Name PutClassOnly} {Args class newValue propName}
{Text
These functions are analogous to {fn GetClass} and {fn PutClass}, except that they never trigger active values.  
}}


{FnDef {Name GetClassHere} {Args class propName}
{Text
Returns the local value of the property {arg propName} of {arg class}.  If {arg propName} is not found locally, {fn GetClassHere} returns the value of the global variable {var NotSetValue}{index NotSetValue Var} (initially {lisp ?}).
}}


The functions for accessing method properties are:

{FnDef {Name GetMethod} {Args class selector propName}
{Text
If {arg propName} is {lisp NIL}, {fn GetMethod} returns the method (Interlisp function name) which implements the message {arg selector} of the class {arg class}.  If {arg propName} is non-{lisp NIL}, it returns the value of the property {arg propName} of the method.

Method properties are inherited; the retrieval process involves searching through super classes of {arg class} if the property is not found in {arg class} itself.  
}}


{FnDef {Name PutMethod} {Args class selector newValue propName}
{Text
If {arg propName} is {lisp NIL}, {fn PutMethod} sets the method which implements the message {arg selector} of the class {arg class} to {arg newValue}.  If {arg propName} is non-{lisp NIL}, it sets the value of the property {arg propName} of the method to {arg newValue}.  Returns {arg newValue}.
}}


{FnDef {Name GetMethodOnly} {Args class selector propName}}
{FnDef {Name PutMethodOnly} {Args class selector newValue propName}
{Text
Analogous to {fn GetMethod} and {fn PutMethod} except that they never trigger active values.
}}


{FnDef {Name GetMethodHere} {Args class selector propName}
{Text
Returns the local value of the property {arg propName} the the method which implements the message {arg selector} of {arg class}.  If {arg propName} is not found locally, {fn GetMethodHere} returns the value of the global variable {var NotSetValue}{index NotSetValue Var} (initially {lisp ?}).
}}


All of the above functions only work directly on classes, not on instances of those classes.  In addition, if a method or class variable is inherited, then the put functions change the property in the class in which the method or class variable is found in the supers list, not in the class which was the argument of the put function.

}{End SubSec Accessing Class and Method Properties}



{Begin SubSec General Get and Put Functions}
{Title General Get and Put Functions}
{Text

The following functions are generalized get and put functions which accept a type argument and invoke the more specialized functions:

{FnDef {Name GetIt} {Args object varOrSelector propName type} }
{FnDef {Name PutIt} {Args object varOrSelector newValue propName type} }
{FnDef {Name GetItOnly} {Args object varOrSelector propName type} }
{FnDef {Name PutItOnly} {Args object varOrSelector newValue propName type} }
{FnDef {Name GetItHere} {Args object varOrSelector propName type}
{Text
For all of these functions, the value of the {arg type} argument can be one of {lisp IV}, {lisp CV}, {lisp CLASS}, or {lisp METHOD} for instance variable, class variable, class, or method, respectively.  If {arg type} is {lisp NIL}, {lisp IV} is assumed.  The argument {arg varOrSelector} is interpreted as a variable name if {arg type} is {lisp IV} or {lisp CV}, a selector name if {arg type} is {lisp METHOD}, and is ignored if {arg type} is {lisp CLASS}.

{note actually, if type=CLASS, the prop name used is (OR varname propname)}
}}

These functions are interpreted as follows:

{lispcode
(GetIt {ellipsis} 'IV)  ==>  (GetValue {ellipsis})
(GetIt {ellipsis} 'CV)  ==>  (GetClassValue {ellipsis})
(GetIt {ellipsis} 'CLASS)  ==>  (GetClass {ellipsis})
(GetIt {ellipsis} 'METHOD)  ==>  (GetMethod {ellipsis})}

The other functions are similar.

Note:  Actually, if {arg type}={lisp IV}, these functions will call different functions depending on whether the object is a class or instance.


}{End SubSec General Get and Put Functions}



{Begin SubSec Summary of Get and Put Functions}
{Title Summary of Get and Put Functions}
{Text

In the following table, * indicates that no function is available.



{Begin Table Summary of Get and Put Functions}

{COLUMN}	{COLUMN}	{COLUMN}	{COLUMN}

{First}	{Next Inherit/Trigger}	{Next Inherit/DontTrigger}	{Next Local/DontTrigger}

{First from instances:}

{First Get/Put fns for instance variables}
		{Next {lisp GetValue} / {lisp PutValue}}
		{Next {lisp GetValueOnly} / {lisp PutValueOnly}}
		{Next {lisp GetIVHere}}

{First Get/Put fns for class variables}
		{Next {lisp GetClassValue} / {lisp PutClassValue}}
		{Next {lisp GetClassValueOnly} / {lisp PutClassValueOnly}}
		{Next *}

{First from classes:}

{First Get/Put fns for instance variables}
		{Next *}
		{Next *}
		{Next {lisp GetClassIV} / {lisp PutClassIV}}

{First Get/Put fns for class variables}
		{Next {lisp GetClassValue} / {lisp PutClassValue}}
		{Next {lisp GetClassValueOnly} / {lisp PutClassValueOnly}}
		{Next {lisp GetCVHere}}

{First Get/Put fns for class properties}
		{Next {lisp GetClass} / {lisp PutClass}}
		{Next {lisp GetClassValueOnly} / {lisp PutClassValueOnly}}
		{Next {lisp GetClassHere}}

{First Get/Put fns for method properties}
		{Next {lisp GetMethod} / {lisp PutMethod}}
		{Next {lisp GetMethodOnly} / {lisp PutMethodOnly}}
		{Next {lisp GetMethodHere}}

{End Table Summary of Get and Put Functions}


}{End SubSec Summary of Get and Put Functions}



}{End SubSec Object Variables and Properties}