Introduction to gmSL
The name
gmSL stands for Great Migrations Scripting language. It is a high-level programming language that is compiled and executed by
gmBasic rather than compiled by the computer's processor as other programming languages (such as C and C#) are. Code written in
gmSL can be embedded within
gmPL scripts or can be in stand alone source files with the extension
gmSL. The
gmSL language fully supports
gmPL equivalents of the main line
gmPL statements and can be used as a substitute for
gmPL in most cases.
gmSL is a procedural language and does not reproduce the
gmPL declaration statements. Finally,
gmSL scripts can be converted into
gmNI dynamic link libraries that are executed by the tool when certain events occur. The goal of
gmSL is to enhance
gmPL not to replace it.
First and foremost,
gmSL is a compiled language. Its statements are converted into byte codes and those byte codes are then either executed immediately or are saved to be executed or authored at a later time. The byte codes themselves are 100% compatible with those used by
gmBasic to compile the various source languages that it processes. The engine used to execute the byte codes is the same as the one used to evaluate constant expressions in source codes.
There are many contexts in which
gmSL can be used to enhance a
gmPL script. The following topics describe these contexts and are intended to serve as an introduction to the capabilities of
gmSL. The remainder of this manual describes the details of the language.
As a simple example consider the following script, "HashTable1.xml", that translates a simple HashTable class written in
VB6 into a
.NET form.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" Identifier="HashTable1" />
<Select Dialect="csh" />
<Select AuthorLibrary="on" />
<Select BuildFile="on" />
<Select DeployLocation="\temp" />
<Compile Project="..\vb6\HashTable.vbp" />
<Analyse />
<Output Status="New" Filename="..\csh\HashTable1.bnd" />
<Author />
<Storage Action="Close" />
</gmBasic>
|
This script produces a translation bundle containing the
csproj file, the
C# source, and the
xml interface description file for the class. This discussion assumes that the reader is familiar with the
gmPL language used in the above script. The focus of the dicussion here is on how
gmSL can be used to enhance and/or change this script.
Note that throughout this discussion the simple notation
pBasic command options is used to represent the command line that executes translation scripts. The actual manner in which command options are introduced is dependent upon the particular version/license of the tool set. See the discussion under the page
gmCL.pBasic for a general discussion of these options. Also the actual source codes, scripts, and bundles referenced and/or discussed are
available in zip file form, contact GreatMigrations customer support for a copyillustrated in system metalang and the gmStudio Samples.
Embedding gmSL Expressions in gmPL Statements
The notation
(%= ... %) is used to embed
gmSL expressions in
gmPL statements. Consider that except for the name of the code this script is a generic translation script that could be used in other simple contexts like this one. There is a
Select attribute
SrcPath that can be used to contain user supplied strings. Within
gmSL expressions the values of the
Select attributes can be referenced via the fully specified identifier "Select.attributeName" or simply "attributeName". The following script "HashTable2.xml"
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" Identifier="(%= Select.SrcPath %)2" />
<Select Dialect="csh" />
<Select AuthorLibrary="on" />
<Select BuildFile="on" />
<Select DeployLocation="\temp" />
<Compile Project="..\vb6\(%= SrcPath %).vbp" />
<Analyse />
<Output Status="New" Filename="..\csh\(%= SrcPath %)2.bnd" />
<Author />
<Storage Action="Close" />
</gmBasic>
|
when executed via the command line
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable2 SrcPath=HashTable
|
produces the same outputs as the original HashTable1.xml script.
Embedding gmSL Statements in gmPL Scripts
It is often convenient to be able to perform simple operations during the execution of a
gmPL script that are not directly supported by
gmPL. An easy way to do this is to embed
gmSL statements in the script. The desired statements are enclosed within
<gmSL> and
</gmSL> tags or bounded by them. The statements themselves can be either be a simgle statement or multiple if the bounded form is used. They are executed immediately after the closing
</gmSL> tag is encountered. The following script "HashTable3.xml"
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<gmSL>System.LogMessage("Starting Translation of HashTable.vbp")</gmSL>
<Storage Action="Create" Identifier="HashTable3" />
<Select Dialect="csh" />
<Select AuthorLibrary="on" />
<Select BuildFile="on" />
<Select DeployLocation="\temp" />
<gmSL>
System.LogMessage("Starting Compilation of HashTable.vbp")
if(Select.Progress > 1) System.LogMessage "Compilation consists of two passes through the source code"
</gmSL>
<Compile Project="..\vb6\HashTable.vbp" />
<gmSL>System.LogMessage("Starting Analysis of HashTable.vbp")</gmSL>
<Analyse />
<Output Status="New" Filename="..\csh\HashTable3.bnd" />
<Author />
<Storage Action="Close" />
<gmSL>System.LogMessage("Completed Translation of HashTable.vbp")</gmSL>
</gmBasic>
|
can be used to add additional progress messages to the processing of the script. The same outputs are produced. When executed via the command line
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable3.xml Progress=1
|
gives the following log.
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Starting Translation of HashTable.vbp
Starting Compilation of HashTable.vbp
Loading reference:[Language.std] \gmIDF\Language.std.xml
Reprocessing file: Transform.cls
Reprocessing file: Transform.cls
Processing file: ..\vb6\HashTable.vbp
Loading reference:[StdOle2.tlb] \gmIDF\StdOle2.tlb.xml
Reprocessing file: ..\vb6\HashTable.cls
Reprocessing file: ..\vb6\HashTable.cls
Starting Analysis of HashTable.vbp
Loading reference:[MigrationSupport.dll] \gmIDF\MigrationSupport.dll.xml
Completed Translation of HashTable.vbp
|
When executed via the command line
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable3.xml progress=2
|
gives the following log in which the additional message appears.
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Starting Translation of HashTable.vbp
Starting Compilation of HashTable.vbp
Compilation consists of two passes through the source code
Loading reference:[Language.std] \gmIDF\Language.std.xml
Reprocessing file: Transform.cls
Reprocessing file: Transform.cls
Processing file: ..\vb6\HashTable.vbp
Loading reference:[StdOle2.tlb] \gmIDF\StdOle2.tlb.xml
Reprocessing file: ..\vb6\HashTable.cls
Reprocessing file: ..\vb6\HashTable.cls
Starting Analysis of HashTable.vbp
Loading reference:[MigrationSupport.dll] \gmIDF\MigrationSupport.dll.xml
Completed Translation of HashTable.vbp
|
Note
gmSL does require a user storage area to compile; therefore, all such statements must follow
gmPL Storage statement in the script.
Embedding gmSL Methods in gmPL Scripts
In addition to being able to introduce simple
gmSL statements into a
gmPL script, it is also possible introduce methods that perform operations during the execution of the script that are not directly supported by
gmPL. The method can then be executed later by the
gmPL RunComand statement. In the HashTable example being used in this discussion, everything goes well and the target code builds with no problems, but in examining that code
Code Block |
---|
language | cpp |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
int m_PrimaryIndex = 0;
private int m_SecondaryIndex = 0;
// This variable is used to make the GetNextItem faster
object m_GetNextValue = null;
HashTableTyp m_HT = new HashTableTyp();
public bool FindKey(string i_Key)
|
one wonders if it is possible to add the "private" modifier for some of the fields, that were declared with "Dim" in the original code instead of "Private".
Code Block |
---|
language | vb |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Dim m_PrimaryIndex As Integer
Private m_SecondaryIndex As Integer
' This variable is used to make the GetNextItem faster
Dim m_GetNextValue As Object
Dim m_HT As HashTableTyp
|
There is presently no refactoring statement that can change the accessibility of a field to private; however, it can be done easily using an embedded
gmSL method. Consider the following revised "HashTable4.xml" script.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" Identifier="HashTable4" />
<Select Dialect="csh" />
<Select AuthorLibrary="on" />
<Select BuildFile="on" />
<Select DeployLocation="\temp" />
<gmSL Class="Demo" >
void MakePrivate(string identifier)
{
int iRoot;
tVariable varInfo;
iRoot = Symbol.FindIdentifier(identifier);
if(iRoot)
{
varInfo = Store.DeltaVector(iRoot);
varInfo.Private = True;
System.LogMessage("Changed status of " + Symbol.FullName(iRoot,1) + " to Private") ;
}
else System.LogMessage("Could not locate " + identifier);
}
</gmSL>
<Compile Project="..\vb6\HashTable.vbp" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_PrimaryIndex" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_GetNextValue" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.HelpFile" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_HT" />
<Analyse />
<Output Status="New" Filename="..\csh\HashTable4.bnd" />
<Author />
<Storage Action="Close" />
</gmBasic>
|
The
MakePrivate method is the one that will set the
private attribute for the specified fields to true. It is this change that is needed so that the target declarations for these symbols will be "private". If the method finds the symbol whose fully qualified identifier is in the parameter
identifier then it also logs a success message to the log file; else it logs a failure message. The
RunCommand statement needed has its
id attribute set to the name of the method and its
Prams attribute set to the identifiers of the fields to be changed. Note that the
HelpFile field does not exist. The resultant log file is as expected
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Setting components to Private
Changed status of HashTableProject.HashTable.m_PrimaryIndex to Private
Changed status of HashTableProject.HashTable.m_GetNextValue to Private
Could not locate HashTableProject.HashTable.HelpFile
Changed status of HashTableProject.HashTable.m_HT to Private
|
Comparing the two translation bundles
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
***** HashTable4.bnd
<class id="HashTable" parent="IDispatch" default="Value">
<method id="FindKey" type="Boolean">
***** HASHTABLE1.BND
<class id="HashTable" parent="IDispatch" default="Value">
<field id="m_PrimaryIndex" type="Integer" status="InOut"/>
<field id="m_GetNextValue" type="Object" status="InOut"/>
<field id="m_HT" type="HashTableProject.HashTable.HashTableTyp" status="InOut"/>
<method id="FindKey" type="Boolean">
***** HashTable4.bnd
}
private int m_PrimaryIndex = 0;
private int m_SecondaryIndex = 0;
***** HASHTABLE1.BND
}
int m_PrimaryIndex = 0;
private int m_SecondaryIndex = 0;
***** HashTable4.bnd
// This variable is used to make the GetNextItem faster
private object m_GetNextValue = null;
private HashTableTyp m_HT = new HashTableTyp();
public bool FindKey(string i_Key)
***** HASHTABLE1.BND
// This variable is used to make the GetNextItem faster
object m_GetNextValue = null;
HashTableTyp m_HT = new HashTableTyp();
public bool FindKey(string i_Key)
|
does show that the accessibility of the three fields has been changed. Notice in particular that the declarations of the now private fields have also been removed from the interface description of the class.
Writing Stand Alone gmSL Methods
Methods written in
gmSL do not have to be embedded directly in the
gmPL scripts. They can be entered in stand alone files with the extension
gmSL which can be loaded into the script. Consider this file "MakePrivate.gmsl"
Code Block |
---|
language | cpp |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
void MakePrivate(string identifier)
{
int iRoot;
tVariable varInfo;
iRoot = Symbol.FindIdentifier(identifier);
if(iRoot)
{
varInfo = Store.DeltaVector(iRoot);
varInfo.Private = True;
System.LogMessage("Changed status of " + Symbol.FullName(iRoot,1) + " to Private") ;
}
else System.LogMessage("Could not locate " + identifier);
}
|
which contains the same method as defined in the previous example. It can then be used by this script "HashTable5.xml".
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" Identifier="HashTable5" />
<Select Dialect="csh" />
<Select AuthorLibrary="on" />
<Select BuildFile="on" />
<Select DeployLocation="\temp" />
<gmSL Class="Demo" source="..\gmsl\MakePrivate.gmsl" />
<Compile Project="..\vb6\HashTable.vbp" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_PrimaryIndex" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_GetNextValue" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.HelpFile" />
<RunCommand id="MakePrivate" Prams="HashTableProject.HashTable.m_HT" />
<Analyse />
<Output Status="New" Filename="..\csh\HashTable5.bnd" />
<Author />
<Storage Action="Close" />
</gmBasic>
|
to produce the identical result as in the previous example.
Writing Stand Alone gmSL scripts
Not just methods, but entire stand alone scripts can be written using gmSL. The following file "HashTable.gmsl"
Code Block |
---|
language | cpp |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Execute.Storage Action := "Create", Identifier := "HashTable"
Select.Dialect = Dialects.csh
Select.AuthorLibrary = AuthorLibType.On
Select.BuildFile = BuildFileStatus.On
Select.DeployLocation = "\temp"
Execute.Compile Project := "..\vb6\HashTable.vbp"
Execute.Analyse
Execute.Output Status := "New", Filename := "..\csh\HashTable.bnd"
Execute.Author
Execute.Storage Action := "Close"
|
contains
gmSL statements that perform the same operations as those presented in the original translation scripts. The
Select attributes are fields in a
Select class and the various
gmPL mainline execution statements are methods in an
Execute class. The
gmSL language supports named arguments so that the calls to methods can look more like their original
gmPL forms. For example the
Execute.Storage method is defined as follows in the language files.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<Method id="Storage" type="void" opcode="SCM.Execute_Storage" >
<Argument id="action" type="String" status="ByVal" optional="NULL" />
<Argument id="identifier" type="String" status="ByVal" optional="NULL" />
<Argument id="startup" type="String" status="ByVal" optional="NULL" />
</Method>
|
When executed via the command line
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable.gmsl
|
the resultant bundle file "HashTable.bnd" is identical to the one produced by the original "HashTable1.xml".
Previous examples have shown various ways in which
gmSL source code can be introduced into translation scripts or executed directly. Methods written in
gmSL can also be precompiled and stored in a virtual binary information file. In fact many of the operations performed by the tool set are actually implemented via
gmSL methods stored in the
vb7Lang.vbi language information file.
Consider the following script "HashTable6.xml" which contains the same
gmSL statements discussed above, except that the name of the output file is specified via the field
Select.BndPath.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" Identifier="HashTable6" />
<gmSL namespace="RuntimeDll" class="Methods" >
void HashTable6()
{
Execute.Storage Action := "Create", Identifier := "HashTable"
Select.Dialect = Dialects.csh
Select.AuthorLibrary = AuthorLibType.On
Select.BuildFile = BuildFileStatus.On
Select.DeployLocation = "\temp"
Execute.Compile Project := "..\vb6\HashTable.vbp"
Execute.Analyse
Execute.Output Status := "New", Filename := Select.BndPath
Execute.Author
Execute.Storage Action := "Close"
}
</gmSL>
<Storage Action="Close" />
</gmBasic>
|
When processed by the tool this script creates a file "HashTable6.vbi" that contains the compiled form of the method. Here is the audit of the content of this information file.
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Audit of Symbol tree in HashTable6.vbi storage area:
Lev | Address | Parent | Symbol Type | Full Symbol Identifier
--- | ------- | ------ | ----------- | ----------------------
1 | 2119 | 0 | ProjectFile | RuntimeDll.Methods.slp
2 | 3240 | 2119 | ClassFile | Methods.cls
3 | 3423 | 3240 | Subprogram | RuntimeDll.Methods.HashTable6
2 | 3342 | 2119 | Vb_Name | RuntimeDll.Methods
1 | 3382 | 0 | Vb_Name | RuntimeDll
|
The compiled form of
gmSL uses the same
gmIL intermediate language as is used to compile the other source languages processed via this tool set. The operations themselves are executed via the same engine and the operations can be authored in the same way as well. To review here is the start of the actual codeblock showing the compiled form of the first statement.
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Actual csh Codeblock Associated with HashTable6:
Offset | Sl.Start | Ql.Start | Quantity type | Opcode | Operation support information
------ | -------- | -------- | ------------- | ------ | -----------------------------
0 | | | | LEV | Nest0
2 | 1.2 | 1.2 | String | LSC | 6:Create
7 | 1.2 | | | ARG | String
9 | 1.2 | | | LEV | Nest0
11 | 2.11 | 1.11 | String | LSC | 24:\gmManual\csh\HashTable6
16 | 2.11 | | | ARG | String
18 | 2.11 | | | LEV | Nest0
20 | 3.20 | 1.20 | Variant | SPV | Null
22 | 3.20 | | | ARG | String
24 | | 1.24 | Void | SCM | Execute_Storage
|
The following script "HashTable7.xml" can be used to execute this method.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<gmSL>Store.Open("HashTable6.vbi",StorageUnit.METHODS,0)</gmSL>
<Select BndPath="..\csh\HashTable7.bnd" />
<RunCommand id="HashTable6" />
</gmBasic>
|
When executed via the command line
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable7.xml
|
the resultant bundle file "HashTable7.bnd" is identical to the one produced by the original "HashTable1.xml" script.
Converting gmSL Methods in gmNI Runtime Libraries
The same binary information file whose "HashTable6" method was executed above can also be used to create a
gmNI runtime library. The "Hashtable8.xml" script below uses a method
Gemini.AuthorExecuteCommandDll stored in the
vb7Lang.vbi language information file to produce a file "gmNI\Hashtable.bnd. It should be noted that all methods stored in the language file are written in
gmSL
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<Storage Action="Create" />
<Select DeployLocation="..\gmNI" />
<Select Library="\gmTools\gmnidll" />
<Select BuildFile="on" />
<RunCommand Id="Gemini.AuthorExecuteCommandDll" Prams="HashTable6;..\gmNI\HashTable.bnd" />
<Storage Action="Close" />
</gmBasic>
|
The bundle file produced contains the following files and instructions.
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
HashTable6Migration.c
HashTable6Migration.lnk
HashTable6.c
EXECUTE instructions to do the build
|
The
gmPL documentation contains details about these files. To summarize they contain the code needed to implement an
ExecuteCommand event handler; the linkage instructions needed to build the runtime dll; the actual code needed to execute a
HashTable6 command; the actual implementation of the
HashTable6() method; and finally the build commands needed to create the runtime dll. The following deployment command then
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
Deploy HashTable.bnd DEPLOY
|
creates the file "gmni\HashTable6Migration.dll" which can then be used to do the same translation as produced by "HashTable7.xml" above. The file "HashTable9.xml" below does this.
Code Block |
---|
language | xml |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
<gmBasic>
<LoadRuntime FileName="..\gmNI\HashTable6Migration.dll" />
<Select BndPath="..\csh\HashTable9.bnd" />
<HashTable6 />
/gmBasic>
|
Remember that the
gmPL processor, when it sees a command like "HashTable6" that it does not recognize, checks to see if it names a currently loaded
ExecuteCommand event handler. When executing this script
Code Block |
---|
language | none |
---|
theme | Eclipse |
---|
linenumbers | true |
---|
|
pBasic HashTable9.xml
|
the resultant bundle file "HashTable9.bnd" is identical to the one produced by the original "HashTable1.xml" script.