gmplAccessorStatement

Accessor Statement Summary

Accessor is a nonterminal, declaration statement that occurs within Class statements within description files authored from IDF-- i.e., external COM components. It declares a property with both set and get access that has arguments.

The attributes of the Accessor statement are as follows:

Attribute Description
Id This attribute is the identifier of the accessor. It must be unique within the scope of the class containing the accessor. The identifier is not case-sensitive.
Type This attribute is a Type attribute as discussed on the Declaration page. It specifies the value type of the accessor.
Status This attribute is the Status attribute as discussed on the Declaration page. It specifies the various context flags to be associated with the accessor.
NetName This attribute is the identifier of the accessor to be used when declaring or referring to it in the target language.
MigName This attribute is identical to NetName. If both are used in the declaration the Migname takes precedence.
MigStatus This attribute is a MigStatus attribute as discussed on the Declaration page. It contains generalized migration settings for the accessor.
MigComment This deprecated string attribute associates a comment with the accessor. This comment does not trigger the gmNI event handlers and can interfere with the MigStatus attribute.
MigPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the All pattern.
CshPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the Csh pattern.
VbnPattern This string attribute associates a surface pattern string with code references to the accessor. See the Patterns page for details on the content of pattern strings. It is equivalent to the Vbn pattern.
Npram This integer attribute specifies the number of parameters associated with the surface pattern strings.
Role This attribute contains an optional keyword describing the overall role of the operation being authored via the surface pattern strings: Unknown, Property, Method, Define, Utility, Command, Constant, Function, Event, Control, Collection, Resource, Index, or Migclass. The default is None.
Patstatus An optional keyword describing the overall status of the operation authored via the surface pattern strings: Ok, Delete, Deprecated, NotImplemented, MustCorrect, NotIdent, Postfix, or NeedsPren. The default is Ok.
Canbenull This is an On/Off flag attribute. The On setting sets the CanbeNull status flag On. This means that checks of the value for being empty can be Null as well. References to them in the intermediate code have to be checked if they are Null or Empty.

The declarations within the Accessor statement are as follows:

Substatement Description
Argument Defines one of the accessor arguments.

The script errors associated with the Accessor statement are as follows:

Error Description
1130 Method command missing required id attribute.
1131 Unable to store METHOD vector: %1d
1132 The syntax cannot be found.
1133 The subprogram type is undefined.
1134 Encountered following when expecting 'argument': %1d

In essence, accessors are constructs within gmBasic intended to deal with COM components whose IDL method adornments include PROPGET that also have arguments. They are related to methods that are indexers and to GetSetLet properties that combine PROPGET, PROPPUT, and PROPPUTREF. What all of these components share is that they can be used both in contexts where they supply a value and in contexts where they accept a value. Remember that in VB6, the supplying and accepting of values is intertwined with a distinction between setting the instance of an object Set as opposed to assigning the value of an object Let. In addition, VB6 allows default properties in which the simple reference to the instance of an object can actually be a reference to the default component of that object. This component might be a simple property, but it might also be an accessor, an indexer, or a GetSetLet property. Fortunately, in .NET these complications have been removed. There is no default property, there is no let versus set distinction, and indexers are clearly distinguished from methods. This is good news for .NET programmers, and even better news for those who have to maintain .NET programs over time. However, it is bad news for migrations of VB6 applications that make extensive use of COM components that have these adornments. There is no single or simple approach that can be taken.

The approach taken by gmBasic to migrate accessors begins with a consistent gmPL approach described below. Using this approach has limitations. If those limitations interfere with a migration of some components, then gmSL is available to correct them, though with a great deal more effort. The discussion here is focused on accessors though much of it is relevant to indexers and GetSetLet properties.

Beginning with the initial classification of methods as accessors, here is a fragment from the gmSL language method IdlAuthor.IdlWriteClass. At this point the method is processing the components of a class.


(1) else if(iComp == IdlObject.Method)
    {
(2)    if(component.PROPGET && nArg > 0)
       {
          isAccessor = 1;
          if(iChild == defprop)
          {
             iarg = Store.GetFirst(iChild);
             arg = Store.GetVector(iarg);
(3)          if(!arg.Out)
             {
                isIndexer = 1;
                isAccessor = 0;
             }
          }
       }
       if(isAccessor) Write.Text("<accessor")
First only IdlMethods become accessors, not properties, and second those methods must have at least one argument and must have the PROPGET attribute. This attribute specifies a method used to retrieve the value of a property exposed by the interface. The last parameter passed to the method must be an out parameter that will be used to retrieve the property's value. The third condition only applies to those methods that are the default component for the class. For such, there is the check that the argument must have Out status. Note that there is no limit to the number of arguments that an accessor may have, other than at least one.

First consider the following two accessors, one from MSComctlLib and one from MSHierarchicalFlexGridLib which has two arguments.


<class id="IListItems" parent="IDispatch" default="ControlDefault">
   <accessor id="ControlDefault" type="ListItem">
      <argument id="Index" type="Variant" status="ByRef"/>
   </accessor
...
 <class id="IMSHFlexGrid" parent="IDispatch" default="Text">
    <accessor id="TextMatrix" type="String">
       <argument id="Row" type="Integer" status="ByVal"/>
       <argument id="Col" type="Integer" status="ByVal"/>
    </accessor>
References to these accessors are compiled like references to other components except that the join of the accessors to its instance is done via MEM.Get and MEM.Set operations as opposed to the usually used MEM.Child operation.


 896 |     2.896 |     1.896 | MSComctlLib.ListView | LDA    | MSComctlLib.ListView:lvwEstHistory:1703466
 901 |     3.901 |     1.896 | MSComctlLib.ListItem | LLP    | Component:ListItems:1543857
 906 |     2.896 |     1.896 | MSComctlLib.ListItem | MEM    | Child
 908 |     3.908 |     1.896 | MSComctlLib.ListItem | LLP    | Component:ControlDefault:1549078
 913 |     2.896 |     1.896 | MSComctlLib.ListItem | MEM    | Get
    ...
 381 |     2.381 |     1.381 | MSHierarchicalFlexGr | LDA    | MSHierarchicalFlexGridLib.MSHFlexGrid:grdItems:1884621
 386 |     3.386 |     1.381 | String               | LLP    | Component:TextMatrix:1606485
 391 |     2.381 |     1.381 | String               | MEM    | Set
Now the patterns for these operations are as follows


 <pattern id="MEM">
    <subcode id="child">
       <all narg="2" code="%1d.%2d"/>
    </subcode>
    <subcode id="get">
       <vbn narg="2" code="%1d.%2d"/>
       <csh narg="2" code="%1d.%2d"/>
    </subcode>
    <subcode id="set">
       <vbn narg="2" code="%1d.set_%2d"/>
       <csh narg="2" code="%1d.set_%2d"/>
    </subcode>
The pattern for MEM.Get is the same as the pattern for MEM.Child; while the pattern for the MEM.Set prefixes the name with "set_".


 object argTemp6 = 1;
 lvwEstHistory.ListItems.ControlDefault(ref argTemp6).Selected = true;
    ...
 grdItems.set_TextMatrix(grdItems.Rows - 1,4,Convert.ToString(rsInvEst.Fields["risk_item"].Value));
    ...
 InvAmount = UtilFunx.TextToAmount(grdItems.TextMatrix(grdItems.Row,3));
    ..
 public MSComctlLib.ListSubItem ControlDefault(ref object Index)
 {
    return null;
 }
 public void set_ControlDefault(ref object Index,MSComctlLib.ListSubItem value)
 {
 }
 public string TextMatrix(int Row,int Col)
 {
    return String.Empty;
 }
  ...
 public void set_TextMatrix(int Row,int Col,string value)
 {
 }
Notice that there are the code references to these components, but there are also the stub declarations that must correspond to these references. A simple change could be achieved by simply changing the patterns of the two operations. They might be instead.


<pattern id="MEM">
   <subcode id="child">
      <all narg="2" code="%1d.%2d"/>
   </subcode>
   <subcode id="get">
      <vbn narg="2" code="%1d.Get%2d"/>
      <csh narg="2" code="%1d.Get%2d"/>
   </subcode>
   <subcode id="set">
      <vbn narg="2" code="%1d.Set%2d"/>
      <csh narg="2" code="%1d.Set%2d"/>
    </subcode>
Now the above translations are as follows


 object argTemp6 = 1;
 lvwEstHistory.ListItems.GetControlDefault(ref argTemp6).Selected = true;
     ...
 grdItems.SetTextMatrix(grdItems.Rows - 1,4,Convert.ToString(rsInvEst.Fields["risk_item"].Value));
     ...
 InvAmount = UtilFunx.TextToAmount(grdItems.GetTextMatrix(grdItems.Row,3));
    ...
 public MSComctlLib.ColumnHeader GetControlDefault(ref object Index)
 {
     return null;
 }
 public void SetControlDefault(ref object Index,MSComctlLib.ColumnHeader value)
 {
 }
   ...
 public string GetTextMatrix(int Row,int Col)
 {
    return String.Empty;
 }
 public void SetTextMatrix(int Row,int Col,string value)
 {
 }
Again, notice that both the references and the wrappers change with the changing pattern. Of course every other component that uses the MEM.Get and MEM.Set operations changes as well. Accessors are intertwined with other similar components. It is possible that this change will cause problems with other migrations. To isolate the individual components the migration status attribute GetSetLet can be used. As an example, using this for TextMatrix


    <accessor id="TextMatrix" type="String" status="GetSetLet">
       <argument id="Row" type="Integer" status="ByVal"/>
       <argument id="Col" type="Integer" status="ByVal"/>
    </accessor>
   <pattern id="TextMatrix.Get">
      <all narg="3" code="%1d.GetTextMatrix(%2d,%3d)"/>
   </pattern>
   <pattern id="TextMatrix.Set">
       <all narg="4" code="%2d.SetTextMatrix(%3d,%4d,%1d)\c"/>
    </pattern>
Changes the references to this component to match the ones produced above without changing the references to any of the other components, but it also does not change the stub for the TextMatrix so this now has to be dealt with separately.
Table of Contents