Frame provides two basic capabilities: structure and inheritance. The synergy between these two features, as well as their use within the Livelink Scripting Framework, provides developers with many powerful capabilities.

In its most basic form, a Frame consists of a set of named slots. Each slot can contain a single value and can be referenced with the dot operator. Thus, a Frame is the equivalent of a structure in most programming languages. A frame's slots are identified with a String and cannot be accidentally created (e.g., due to a typo) during an assignment. In addition, referencing a slot that does not exist will produce a runtime exception, rather than returning an Undefined value. There are operations in the Frame class that permit a Frame's structure to be examined and even modified.

In addition to the structuring mechanisms described above, Frame has the additional ability to have special slots, parent slots, which affect how slots are looked up within a Frame. A parent slot acts like a normal slot, except that it cannot be assigned to. In addition, when a Frame's slot is referenced with a dot operator (e.g., myFrame.someSlot), the presence of one or more parent slots can affect how and where the slot is used.

When a frame dot expression occurs on the left side of an assignment (i.e., an lvalue), then the following steps occur:

  1. If the slot exists in the Frame, then its value is replaced with the result of the assigned value.
  2. If the slot does not exist in the Frame, then the parent slots are searched in definition order for the specified slot name.
    1. If not found, then an error is reported in the same way that any nonexistent slot would be handled.
    2. If the slot does exist in a parent frame, then a slot with the specified name is created in the lvalue frame and is assigned the value of the right-hand-side of the assignment expression.

When a frame dot expression occurs in any other context where its value is desired (i.e., an rvalue), then the following steps occur:

  1. If the slot exists in the Frame, then its value is returned as the result of the expression..
  2. If the slot does not exist in the Frame, then the parent slots are searched in definition order for the specified slot name.
    1. If not found, then an error is reported in the same way that any nonexistent slot would be handled.
    2. If the slot does exist in a parent frame, then the value of the parent's is returned as the result of the expression.

In other words, Frame behaves as a prototype-based object (similar to OSpace's ObjRef datatype). Frame has the following advantages compared to ObjRef:

Frame has some shortcomings with respect to ObjRef:

If inheritance is ignored, both Frame and Assoc share certain features that make them amenable to being used to build structures within the OScript environment. Assoc values can have arbitrary keys of any datatype, whereas Frames must have named slots of type String. In addition, Assoc is most useful when the structure is extremely dynamic and where keys may need to be added at any time. Frame is more useful for safety and debugging because references to incorrectly typed slot names will be cause an error during testing and debugging, rather than continuing with possibly erroneous results. Of course, Assoc is also very useful when it is used for the purpose for which it was designed, as an Associative array. Assoc can efficiently map between arbitrary keys (of any datatype) and their associated values.

Using Destructor

If a slot named "Destructor" is available on the Frame or its parents, and that slot's value is executable, then the slot will be invoked when the Frame is destroyed. Note that the Frame will still exist during the execution of Destructor(), and if the refcount of the Frame has increased during Destructor(), then the frame will NOT be deleted. Be careful with this feature.

Circular References

Livelink values use a simple reference-counting scheme to determine when an unused value can be deleted. Powerful datatypes such as Assoc and Frame both share the unfortunate characteristic that it is possible to create cyclic data structures whose values can never be deleted automatically. Please be careful, as this can result in memory leaks and other even nastier side effects.

Example

Here is an example of using Frame.New() to create a frame representing a 3D coordinate:

	Frame	coordinateProto = Frame.New( {}, { { "x", 0 }, { "y", 0 }, { "z", 0 } } )
	Frame	aCoordinate = Frame.New( { { "parentCoordinate", coordinateProto } }, \
				{ { "x", 5 } } )

	echo( coordinateProto.x )
	echo( coordinateProto.y )
	echo( coordinateProto.z )
	echo( aCoordinate.x )
	aCoordinate.x = 55
	echo( aCoordinate.x )
	coordinateProto.x = 10
	echo( aCoordinate.x )
	coordinateProto.y = 10
	echo( aCoordinate.y )
	aCoordinate.y = 100
	echo( aCoordinate.y )
	echo( coordinateProto.zzzz )		// runtime error. feature not found exception.

The output from the above is:

	0
	0
	0
	5
	55
	55		// Changing the value of the proto slot doesn't change the child's slot
	10		// Changing the value of the parent slot does change the child's inherited slot
	100	// Child's override hides parent's value.

Class Attributes Index

 o FrameType
A constant indicating the datatype number of the datatype Frame.
 o kAnywhere
Used with HasSlot to indicate that both the frame and its parents should be searched.
 o kFrame
Used with HasSlot to indicate that only the frame should be searched.
 o kParents
Used with HasSlot to indicate that only the frame's parents should be searched.

Class Methods Index

 o AddParent( Frame theFrame, Dynamic parentDef )
Adds a parent definition to a Frame
 o AddSlot( Frame theFrame, String slotName, [Dynamic initialValue] )
Adds a non-parent slot of the specified name to the frame, optionally providing an initial value.
 o HasParent( Frame theFrame, Dynamic parentValue )
Determines whether a parent with the specified value exists.
 o HasSlot( Frame theFrame, String slotName, [Integer searchOptions] )
Indicates whether a Frame has a slot with the specified name.
 o New( [List parentDefs], [List slotDefs] )
Creates a frame with the specified parents and slots.
 o Parents( Frame theFrame )
Returns a List of parent definitions for the specified frame.
 o RemoveParent( Frame theFrame, Dynamic parentDef )
Removes the specified parent definition from a Frame.
 o RemoveSlot( Frame theFrame, String slotName )
Removes a slot from a frame.
 o SlotNames( Frame theFrame )
Returns a List of Strings, corresponding to the names of the non-parent slots in theFrame.
 o Slots( Frame theFrame )
Returns a List of non-parent slot descriptions.

Class Attributes

 o FrameType
 Integer FrameType

A constant indicating the datatype number of the datatype Frame, such that, if Type( val ) == Frame.FrameType, then val is a Frame.

 o kAnywhere
 Integer kAnywhere

Used with Frame.HasSlot() to indicate that both the frame and its parents should be searched.

 o kFrame
 Integer kFrame

Used with Frame.HasSlot() to indicate that only the frame should be searched.

 o kParents
 Integer kParents

Used with Frame.HasSlot() to indicate that only the frame's parents should be searched.

Class Methods

 o AddParent
 Boolean AddParent(
              Frame theFrame,
              Dynamic parentDefinition )

Adds a parent to a frame.

Parameters:
theFrame  -  Frame to modify.
parentDefinition  -  A List ({ slotName, parentValue }) specifying the parent slot.
Returns:
TRUE if successful, FALSE otherwise.

Note that a parent slot cannot be added if a slot with the given name is already present on the Frame.

 o AddSlot
 Boolean AddSlot(
             Frame theFrame,
             String slotName,
            [Dynamic initialValue] )

Adds a non-parent slot of the specified name to the frame, optionally providing an initial value.

Parameters:
theFrame  -  Frame value to modify.
slotName  -  String name of the slot to add.
initialValue  -  Initial value for the slot.
Returns:
TRUE if the slot was added, FALSE if it failed.

Note that this function will do nothing if the slot already exists on the frame. In this case, it will return FALSE.

 
 o HasParent
 Boolean HasParent(
              Frame theFrame,
              Dynamic parentValue )

Determines whether a parent with the specified value exists.

Parameters:
theFrame  -  Frame to examine.
parentValue  -  Value of parent to look for.
Returns:
TRUE if this frame has a parent slot with the specified value as its value. FALSE otherwise.

Note that parentValue is not the slot name for the parent, but is the actual associated parent value.

 o HasSlot
 Boolean HasSlot(
             Frame theFrame,
             String slotName,
            [Integer searchOptions] )

Returns true if a Frame has a slot with the specified name.

Parameters:
theFrame  -  Frame within which to look for a slot.
slotName  -  Name of the slot for which to look.
searchOptions  -  If specified, Frame.kFrame, Frame.kParents, or the default Frame.kAnywhere.
Returns:
TRUE if the slot was found. FALSE otherwise.

Using the above example frames, aCoordinate and coordinateProto:

	echo( Frame.HasSlot( aCoordinate, "z" ) )
	echo( Frame.HasSlot( aCoordinate, "z", Frame.kFrame ) )
	echo( Frame.HasSlot( aCoordinate, "x", Frame.kParents ) )
	echo( Frame.HasSlot( aCoordinate, "z", Frame.kAnywhere ) )

The output from the above is:

	true
	false
	true
	true
 o New
 Frame New(
        [List parentDefs],
        [List instanceDefs] )

Create a new frame with parent slots as specified in parentDefs and with instance slots as specified in instanceDefs.

Parameters:
parentDefs  -  A List of parent slot defs, each of which can consist of either a parent value or a List containing { parentSlotName, parentValue } .
instanceDefs  -  A List of slot defs, each element of which is either a simple String slotName, or a List containing { slotName, slotValue } . See note below.
Returns:
The newly created frame.

Note that both parentDefs and instanceDefs above can specify slot definitions as a List consisting of a slotName and a slotValue. However, both of these definition lists permit slot definitions to be specified in a simpler, defaulted form. In the case of parentDefs, a definition can consist of a single, non-List value. This value becomes associated with an unnamed parent slot. In the case of instanceDefs, a String can be specified instead of a List-based slot definition. In this case, the String will become the slot name. See the class description for an example.

 o Parents
 List Parents(
          Frame theFrame )

Return a List of parent definitions for the specified frame.

Parameters:
theFrame  -  Frame to examine.
Returns:
A List of parent definitions, each of which is a two-element List containing { parentSlotName, parentValue } .

Using the above example frames, aCoordinate and coordinateProto:

	echo( Frame.Parents( coordinateProto ) )
	echo( Frame.Parents( aCoordinate ) )

The output from the above is:

	{}
{{'parentCoordinate',<LL:Frame>{{}x:10,y:10,z:0}</LL:Frame>}}
 o RemoveParent
 Boolean RemoveParent(
                Frame theFrame,
                Dynamic parentDefinition )

Removes the specified parent definition from a Frame.

Parameters:
theFrame  -  Frame to modify.
parentDefinition  -  A List ({ slotName, parentValue }) specifying the parent slot.
Returns:
TRUE if successful, FALSE otherwise.

This function does not remove the actual slot definition from the Frame, only the inheritance aspect. In order to remove the slot from the Frame, you must also use Frame.RemoveSlot().

 
 o RemoveSlot
 Boolean RemoveSlot(
               Frame theFrame,
               String slotName )

Removes a slot from a frame.

Parameters:
theFrame  -  Frame from which to remove the slot.
slotName  -  Name of the slot to remove.
Returns:
TRUE if successful, FALSE otherwise.

Note that this function will remove both parent slots and regular slots. However, when a parent slot is removed with this function, the parent will still be part of the Frame's prototype inheritance. In order to remove a parent from the Frame's inheritance, Frame.RemoveParent() must also be used.

 o SlotNames
 List SlotNames(
           Frame theFrame )

Returns a List of Strings, corresponding to the names of the non-parent slots in theFrame.

Parameters:
theFrame  -  The frame to examine.
Returns:
See above.

Using the above example frames, aCoordinate and coordinateProto:

	echo( Frame.SlotNames( coordinateProto ) )
	echo( Frame.SlotNames( aCoordinate ) )

The output from the above is:

	{'x','y','z'}
	{'x','y'}
 o Slots
 List Slots(
         Frame theFrame )

Returns a List of non-parent slot descriptions. Each descriptions consists of a two-element List containing { slotName, slotValue }.

Parameters:
theFrame  -  The frame to examine.
Returns:
See above.

Using the above example frames, aCoordinate and coordinateProto:

	echo( Frame.Slots( coordinateProto ) )
	echo( Frame.Slots( aCoordinate ) )

The output from the above is:

	{{'x',10},{'y',10},{'z',0}}
	{{'x',55},{'y',100}}	// New or overridden slots are displayed.