OScript API/Built-in Package Index

Class: Frame

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:

  • The ability to have a Destructor slot which is executed prior to deleting the object.
  • Multiple, ordered parents, instead of just a single one.
  • More efficient at performing feature lookups.
  • Parents can be any OScript datatype that can be dotted.

Frame has some shortcomings with respect to ObjRef:

  • Persistence is not built in.
  • Circular references can possibly lead to memory leaks.

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

A constant indicating the datatype number of the datatype Frame.

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

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

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

Class Methods

AddParent( Frame theFrame, Dynamic parentDefinition )

Adds a parent definition to a Frame

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

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

HasParent( Frame theFrame, Dynamic parentValue )

Determines whether a parent with the specified value exists.

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

Indicates whether a Frame has a slot with the specified name.

New( [List parentDefs], [List instanceDefs] )

Creates a frame with the specified parents and slots.

Parents( Frame theFrame )

Returns a List of parent definitions for the specified frame.

RemoveParent( Frame theFrame, Dynamic parentDefinition )

Removes the specified parent definition from a Frame.

RemoveSlot( Frame theFrame, String slotName )

Removes a slot from a frame.

SlotNames( Frame theFrame )

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

Slots( Frame theFrame )

Returns a List of non-parent slot descriptions.

Class Attributes

Integer FrameType

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

Integer kAnywhere

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

Integer kFrame

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

Integer kParents

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

Class Methods

AddParent

Boolean AddParent( Frame theFrame,
                   Dynamic parentDefinition )

Adds a parent to a frame.

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

Parameters

theFrame

Frame to modify.

parentDefinition

A List ({ slotName, parentValue }) specifying the parent slot.

Returns:

TRUE if successful, FALSE otherwise.

Example

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

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.

Example

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

HasParent

Boolean HasParent( Frame theFrame,
                   Dynamic parentValue )

Determines whether a parent with the specified value exists.

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

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.

Example

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

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.

Example

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

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.

Example

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.

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 } .

Example

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>}}

RemoveParent

Boolean RemoveParent( Frame theFrame,
                      Dynamic parentDefinition )

Removes the specified parent definition from a Frame.

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().

Parameters

theFrame

Frame to modify.

parentDefinition

A List ({ slotName, parentValue }) specifying the parent slot.

Returns:

TRUE if successful, FALSE otherwise.

Example

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().

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.

Example

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.

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.

Example

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'}

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.

Example

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.

 Copyright © 2023 OpenText Corporation. All rights reserved.