The gmSL Intrinsics
The
gmSL language contains a few intrinsic methods and enumerations.
OPC Enumeration
Opcodes are defined in the metalanguage file
Opcode.xml. The intrinsic enumeration
OPC allows the code to reference the entries in this file. Note that in the current
version of
opcodes.xml there are 189 opcodes and over 4100 opcode.subcode
combinations. The
OPC enumeration has two forms -- opcode and subcode. The opcode
form is written
OPC.opc where
opc is one of the 189 defined opcodes. The
subcode form is written
OPC.opc.subcode where
opc.subcode is one of the
4100 valid combinations defined. Note that
gmSL is not case sensitive, but by
convention upper case is used for the opcodes here to make them easier to see in the
code.
Consider the following opcode definition from the
opcode.xml metalanguage file.
<opcode id="CNV" opc="55" type="DoubleByte" role="convert" subcodes="65" >
<subcode id="ToChar" value="0" />
<subcode id="ToDateTime" value="1" />
<subcode id="ToString" value="2" />
...
The numbers defined by the
opc and
value attributes are referred to as the
"emission" value, since they are the actual numbers emitted for the codes in the
intermediate language. The
OPC enumeration value is the emission value. If an
undefined identifier is used then its value is -1. The code below demonstrates this
System.LogMessage("Emission of opcode CNV is " + OPC.CNV);
System.LogMessage("Emission of subcode ToString of CNV is " + OPC.CNV.ToString);
System.LogMessage("Value of undefined subcode myString is " + OPC.CNV.myString);
The output shows the emission or undefined value. Note that emissions are always greater
than or equal to zero.
Emission of opcode CNV is 55
Emission of subcode ToString of CNV is 2
Value of undefined subcode myString is -1
mask Method
gmSL: int mask(int seqNumb)
The method
mask is used to convert a sequence number between 0 and 31 into a power of
2 mask value that can be used as a boolean flag. As an example consider the
PropertyStatus enumeration that combines various ContextFlags enumeration entries
under single identifiers.
<Enumeration id="PropertyStatus" >
<Entry id="SetByRef" value="(%= Mask(ContextFlags.ByRef) + Mask(ContextFlags.UseGet) %)" />
<Entry id="GetSet" value="(%= Mask(ContextFlags.UseGet) %)" />
...
<Entry id="AsNew" value="(%= Mask(ContextFlags.ByRef) + Mask(ContextFlags.New) %)" />
</Enumeration>
The following code shows how these values are computed, combined, and used.
int SetByRef;
int AsNew;
SetByRef = Mask(ContextFlags.ByRef) + Mask(ContextFlags.UseGet);
AsNew = Mask(ContextFlags.ByRef) + Mask(ContextFlags.New);
System.LogMessage("ContextFlags.ByRef = " + ContextFlags.ByRef);
System.LogMessage("mask(ContextFlags.ByRef) = " + Mask(ContextFlags.ByRef));
System.LogMessage("ContextFlags.UseGet = " + ContextFlags.UseGet);
System.LogMessage("mask(ContextFlags.UseGet) = " + Mask(ContextFlags.UseGet));
System.LogMessage("ContextFlags.New = " + ContextFlags.New);
System.LogMessage("mask(ContextFlags.New) = " + Mask(ContextFlags.New));
System.LogMessage("SetByRef = " + SetByRef);
System.LogMessage("AsNew = " + AsNew);
if(SetByRef & mask(ContextFlags.ByRef)) System.LogMessage("SetByRef has ByRef flag");
else System.LogMessage("SetByRef does not have ByRef flag");
if(SetByRef & mask(ContextFlags.New)) System.LogMessage("SetByRef has New flag");
else System.LogMessage("SetByRef does not have New flag");
The output shows the initial enumeration values and their power of 2 mask values.
ContextFlags.ByRef = 7
mask(ContextFlags.ByRef) = 64
ContextFlags.UseGet = 10
mask(ContextFlags.UseGet) = 512
ContextFlags.New = 19
mask(ContextFlags.New) = 262144
SetByRef = 576
AsNew = 262208
SetByRef has ByRef flag
SetByRef does not have New flag
Though the
mask method is used extensively in the metalanguage definitions to ensure
the enumeration entries and their associated attribute flags are consistent, the
if
statements shows a typical use of
mask to determine if a specified flag is set in some
field.
sizeof Method
gmSL: int sizeof(object attributeClass)
The method
sizeof is used to determine the size of the
gmSL attribute classes.
This size value is needed when storing or allocating room for instances of these classes.
The parameter
className can only refer to one of these language classes, not to an
arbitrary binary type or component. A typical use of this method might be
iRefer = Store.FindVector(basName,0);
if(iRefer == 0)
{
iRefer = Store.Vector(basName,0,sizeof(tVbName),ObjectType.Vb_Name);
}
Another type of information vector associated with
gmSL are the opcode emissions
whose sizes vary from one byte to five bytes depending upon the type of the opcode.
For example consider code that might to insert a conversion operation into a codeblock
pcnt = Opcode.ExpandCode(iRefer,pcnt,sizeof(OPC.CNV));
Opcode.SetOperation(codptr,iRefer,OPC.CNV,OPC.CNV.ToString);
The logic must first expand the code block by the length of the CNV emission and then it can
insert it. The sizeof(opcode) provides the length of the emission associated with the opcode.
The code below shows how these sizes are referenced and their values.
System.LogMessage("sizeof(tMigInfo) = " + sizeof(tMigInfo));
System.LogMessage("sizeof(tInfoFile) = " + sizeof(tInfoFile));
System.LogMessage("sizeof(tVbName) = " + sizeof(tVbName));
System.LogMessage("sizeof(tVariable) = " + sizeof(tVariable));
System.LogMessage("sizeof(tOpcInfo) = " + sizeof(tOpcInfo));
System.LogMessage("sizeof(OPC.LDA) = " + sizeof(OPC.LDA));
System.LogMessage("sizeof(OPC.LIC) = " + sizeof(OPC.LIC));
System.LogMessage("sizeof(OPC.CBN) = " + sizeof(OPC.CBN));
System.LogMessage("sizeof(OPC.USC) = " + sizeof(OPC.USC));
The size values reported are as follows.
sizeof(tMigInfo) = 28
sizeof(tInfoFile) = 72
sizeof(tVbName) = 36
sizeof(tVariable) = 60
sizeof(tOpcInfo) = 17
sizeof(OPC.LDA) = 5
sizeof(OPC.LIC) = 3
sizeof(OPC.CBN) = 1
sizeof(OPC.USC) = 2