In this guide we will explain the details of GMacAST by covering the following points:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
namespace common constant Pi = 'Pi' constant E = 'E' macro sin(d : scalar) : scalar begin return 'Sin[$d$]' end macro cos(d : scalar) : scalar begin return 'Cos[$d$]' end macro sqrt(d : scalar) : scalar begin return 'Sqrt[$d$]' end template macro versorInverse( mv : Multivector) : Multivector begin let b = reverse( mv ) let a = mv gp b return b / a.#E0# end template macro normalize ( mv : Multivector ) : Multivector begin return mv / 'Sqrt[$ norm2( mv ) $]' end namespace geometry2d frame e2d (e1, e2) euclidean frame cgaOrtho (ep, e1, e2, en) orthonormal '+++-' subspace vectors2D = @e1, e2@ subspace euclidean2D = @ga{e1, e2}@ subspace bivectors2D = @e1^e2@ frame cga (no, e1, e2, ni) CBM cgaOrtho @" { {1/2, 0, 0, 1/2}, { 0, 1, 0, 0}, { 0, 0, 1, 0}, { -1, 0, 0, 1} }" subspace vectors2D = @e1, e2@ subspace bivectors2D = @e1^e2@ subspace euclidean2D = @ga{e1, e2}@ open common implement versorInverse, normalize using e2d, cgaOrtho, cga namespace geometry3d frame e3d (e1, e2, e3) euclidean frame cgaOrtho (ep, e1, e2, e3, en) orthonormal '++++-' subspace vectors3d = @e1, e2, e3@ subspace bivectors3d = @e1^e2, e1^e3, e2^e3@ subspace euclidean3d = @ga{e1, e2, e3}@ frame cga (no, e1, e2, e3, ni) CBM cgaOrtho @" { {1/2, 0, 0, 0, 1/2}, { 0, 1, 0, 0, 0}, { 0, 0, 1, 0, 0}, { 0, 0, 0, 1, 0}, { -1, 0, 0, 0, 1} }" subspace vectors3d = @e1, e2, e3@ subspace bivectors3d = @e1^e2, e1^e3, e2^e3@ subspace euclidean3d = @ga{e1, e2, e3}@ constant cga.I3 = Multivector(#e1^e2^e3# = '1') constant cga.I3i = Multivector(#e1^e2^e3# = '-1') open common implement versorInverse, normalize using e3d, cgaOrtho, cga structure e3d.ray ( origin : Multivector, direction : Multivector ) structure e3d.HitInfo ( Ray : ray, tParameter : scalar, HitPoint : Multivector, NormalVector : Multivector ) macro cga.ToCgaPoint (point : Multivector) : Multivector begin let point = point.@vectors3d@ return no + point + (point sp point) / 2 gp ni end macro cga.To3DPoint ( p : Multivector ) : Multivector begin return Multivector( #e1# = p.#e1#, #e2# = p.#e2#, #e3# = p.#e3# ) end macro cga.TranslationVersor (translationVector : Multivector) : Multivector begin return 1 - translationVector.@vectors3d@ gp ni / 2 end macro cga.RotationVersorUnit (angle : scalar, unitBivector : Multivector) : Multivector begin return cos(angle / 2) - sin(angle / 2) gp unitBivector end macro cga.RotationVersor (angle : scalar, bivector : Multivector) : Multivector begin return sin(angle / 2) - cos(angle / 2) gp normalize(bivector) end macro cga.ApplyUnitRtor (versor : Multivector, mv : Multivector) : Multivector begin return versor gp mv gp reverse(versor) end macro cga.ApplyGenlVersor ( versor : Multivector, mv : Multivector) : Multivector begin return versor gp mv gp versorInverse(versor) end macro cga.NormalToBivector3D(normal : Multivector) : Multivector begin return normal lcp reverse(I3) end macro cga.BivectorToNormal3D(bivector : Multivector ) : Multivector begin return bivector lcp I3 end |
Sample code used in this guide
1. GMacAST Overview
GMacAST is an intermediate data structure constructed by GMacCompiler from GMacDSL source code. GMac uses this data structure as the primary source of information for final code generation. Understanding the structure of GMacAST is fundamental to using GMac creatively. GMacAST is, in fact, simple to understand once we get familiar with GMacDSL since GMacAST nodes correspond closely to GMacDSL code elements. The GMacAST data structure is a tree of heterogeneous nodes all derived from a single base class and implementing a small set of simple interfaces. The main nodes of the tree are:
- The AST root node: This is where we can access all other nodes and obtain relevant information on the tree. The root node contains a single primitive scalar type node and one or more child namespaces.
- Namespace nodes: This node type is the main container of other types of nodes. A namespace node may have one or more of the following types of child nodes: namespaces, frames, structures, constants, macros, and transforms. Using child namespace nodes inside parent namespace nodes allows for arbitrary nesting of namespaces just as described in the GMacDSL Guide.
- Frame nodes : A frame is the main GA-related information structure of GMac typically having child nodes of types: basis vectors, basis blades, a single multivector type, subspaces, constants, structures, macros, and transforms. Frames can not contain other frames or namespaces thus nesting is not possible here.
- Constant nodes : These are expressions computed at compile time into constant values and given names for referencing later in GMac expressions. Constants are essentially read-only data stores for values that can be defined under frames or namespaces.
- Structure nodes : A structure node is a composite (i.e. combinatorial) type consisting of several data members of any legal type including other structures.
- Macro nodes : A macro is the main processing element in GMac and the primary source of information in most code generation operations. A macro node contains several macro parameter nodes and a single command block containing the commands defining the operations to be performed on the macro’s parameters.
- Transform nodes : A transform is a constant matrix used to represent a fixed outer-morphism or general linear transform on multivectors.
- Basis vector nodes : These define the basis of a frame along with their relevant information. Basis vectors are like constants in that they are read-only data stores that can be referenced in later GMac expressions.
- Basis blade nodes : Each frame defines a set of basis blades using the outer product of its basis vectors. more about basis blade nodes later on.
- Multivector type nodes : Associated with each frame GMac automatically creates a single multivector type node acting as the main composite GA-related type in GMac as described in the GMacDSL Guide.
- Subspace nodes : The user can define one or more subspaces for each frame in GMac. this node type is typically used for defining sparse versions of multivectors during code generation by restricting the computation to some subspace of multivector typed variables.
2. Main Interfaces and Classes
To represent the nodes in GMacAST many classes are used. All these classes are derived from a single base class called AstObject. The GMacCompiler actually generates an internal AST structure that GMacAST is a wrapper around. The internal AST structure is complicated and is intended for parsing and compilation rather than query and code generation. GMacAST classes are intended for simplicity and efficiency of queries related to code generation. The GMacAST classes can be found under the GMac.GMacAST namespace.
The AstObject class and its derived classes also implement several simple interfaces to expose their common behavior:
- The IAstObject interface that is implemented by all GMacAST objects through the AstObject base class. Through this interface, each GMacAST node provides the IsValid and IsInvalid properties to test if the node contains valid\invalid AST information internally. In addition each node returns the root AST object through the Root property.
- The IAstObjectWithType interface implemented by GMacAST type nodes and other nodes that may return typed information (for example values, expressions, macro parameters, etc.). Each node implementing this interface defines the two properties GMacType and GMacTypeSignature to get GMac type information either as an AstType object, to be explained later, or as a string.
- The IAstObjectWithExpression interface implemented by GMacAST expression nodes and other nodes that may contain expressions information (for example the let command node, as we will see shortly).
- The IAstObjectWithDatastoreValueAccess interface implemented by GMacAST data-store value access nodes and some other node types that may contain data-store information (like constants, macro parameters, and basis vectors for example).
- The IAstObjectWithValue interface implemented by GMacAST value nodes and some other node types that may contain value data (like constants and basis vectors).
We will not go back to the properties of these interfaces when we talk about each GMacAST node class implementing them. In each class we describe we will point out the most important of its members while giving a detailed class diagram showing all public members.
The AstObject class has 5 derived classes that we will explain shortly:
- AstRoot : Used to represent the root of the GMacAST structure.
- AstType : Used to represent GMac types inside GMacAST
- AstSymbol : Used as a base class for all GMacAST symbol nodes, like namespaces, frames, constants, structures, etc.
- AstCommand : Used as a base class for all GMacAST command nodes, like let, declare, and block commands.
- AstExpression : Used as a base class for all GMacAST expressions and values.
3. GMacAST Root
AstRoot
The AstRoot class, inherited from AstObject class, holds all information relevant to the root of GMacAST and general child node access information. The main members of this class include:
- ScalarType : This property returns the GMac primitive scalar type as an AstType object.
- MainSymbols : This property returns a list of AstSymbol objects representing main symbols in all levels in the GMacAST. Main symbols include namespaces, frames, constants, structures, macros, and transforms.
- ChildNamespaces : This property returns the namespace nodes directly under the root node. All other namespaces in other lower levels in the tree are not returned by this property.
- Several properties that return lists of GMacAST nodes of certain kinds in any level in the tree. These include: Namespaces, Frames, FrameBasisVectors, FrameMultivectors, Subspaces, Constants, Structures, Macros, Transforms, and Types.
- Several methods taking a qualified access string for some GMacAST node and return the node that may reside in any level in the tree. These include: Symbol(), Namespace(), Frame(), BasisVector(), FrameMultivector(), Subspace(), Constant(), Structure(), Transform() , Macro(), and Type()
- The IsNullOrInvalid() extension method can be used to test if a given AstObject object is null or contains invalid internal data.
4. Symbols
Symbols are the main entities in GMacAST. In GMacDSL namespaces, frames, structures, macros, constants, and many other code concepts are represented as AST symbols. All GMacAST symbol nodes have common properties that are present in the base class for all symbol nodes: the AstSymbol class.
AstSymbol
This class is the base class of all GMacAST symbol nodes as shown in its class diagram. The most useful class members include:
- Name : The name of the symbol.
- AccessName : The qualified access name of the symbol.
- AccessNameParts : The qualified access name of the symbol usually consists of string parts separated by dots; this property returns the parts as an array of strings.
- RoleName : Each kind of symbols has a role in GMacAST, like “frame”, “basis_vector”, and “macro_parameter” for example ; this property return the role name as a string.
- ParentSymbolsCount : Any symbol can possibly have another parent symbol. For example a frame always has a parent namespace, a basis vector has a parent frame, and a macro parameter has a parent macro. This property returns the number of parent symbols for this symbol up until its root namespace.
- ParentSymbol : The parent symbol of this symbol.
- ParentNamespace : The parent namespace of this symbol, if any.
- ParentFrame : The parent frame of this symbol, if any.
- NearestParentNamespace : Go up the parent symbols until a parent namespace is found.
- NearestNamespace : If this symbol is a namespace return it, else go up the parents until a parent namespace is found.
- RelativeAccessName() : Gets the qualified access name of this symbol relative to the given access name of some other symbol.
AstSymbolsCollection
This class is a collection of, non repeating, AstSymbol objects useful for code generation and symbol grouping operations. The class includes the following helpful members:
- Root : The root node of the GMacAST.
- SymbolAccessNames : A list of access names for the symbols in the collection.
- Count : The number of
- SetSymbols() : Clears the collection and adds a set of symbols to the collection.
- AddRange() : Adds a set of symbols to the collection.
- Add() : Adds a single symbol to the collection.
- Clear() : Clears the collection.
- Contains() : True if the given symbol is present in the collection.
- ContainsChildOf() : True if the given symbol has a child symbol, of any level, in the collection. The parent symbol itself is not required to be present in the collection.
- IsEmptyOrContains() : True if the collection is empty or it contains the given symbol
- IsEmptyOrContainsChildOf() : True if the collection is empty or if the given symbol has a child symbol, of any level, in the collection. The parent symbol itself is not required to be present in the collection.
AstNamespace
This GMacAST node class corresponds to GMacDSL namespace code element. The main members of this class include:
- MainSymbols : This property returns a list of AstSymbol objects representing main symbols in all levels in the GMacAST under this namespace node. Main symbols include namespaces, frames, constants, structures, macros, and transforms.
- Several properties that return lists of GMacAST child nodes directly under this namespace node include: ChildSymbols, ChildNamespaces, ChildFrames, ChildConstants, ChildStructures, ChildTransforms, and ChildMacros.
- Several properties that return lists of GMacAST nodes under this namespace node at any level in the tree: Namespaces, Frames, FrameBasisVectors, FrameMultivectors, Subspaces, Constants, Structures, Macros, Transforms, and Types.
- Several methods taking a qualified access string for some GMacAST node under this namespace node and return the node: Symbol(), Namespace(), Frame(), BasisVector(), FrameMultivector(), Subspace(), Constant(), Structure(), Transform() , Macro(), and Type()
- The NamespacesChain property returns this namespace node followed by all its parents up to the root namespace.
AstFrame
Defining GMacDSL frames is the basis for all GA-related computations in GMac. In GMacAST, the AstFrame node class and related classes are responsible for holding all information related to frames. The main members of this class include:
- Some properties to obtain lists of child objects under the frame including : ChildSymbols, MainSymbols, BasisVectors, Constants, Subspaces, Structures, Transforms, Macros, and Types.
- Some methods to find a child symbol by its name under the frame including : Symbol(), BasisVector(), Subspace(), Constant(), Structure(), Transform(), Macro(), and Type().
- VSpaceDimension : The number of basis vectors of the frame; its vector-space dimension.
- GaSpaceDimension : The number of basis blades of the frame; its GS-space dimension.
- MaxBasisBladeId : The ID of the last basis blade of the frame; the ID of the basis pseudo-scalar of the GA space.
- GradesCount : The number of different grades in the frame; equal to its vector-space dimension plus one.
- Grades : A list of grades of the frame; a list of numbers between zero and its vector-space dimension.
- BaseFrame : The base frame of this frame. See GMacDSL Guide for more details.
- FrameMultivector : The multivector type automatically created by GMac for this frame.
- GetInnerProductMatrix() : An array of symbolic scalars representing the inner product matrix of the frame.
- KvSpaceDimension() : The number of basis blades of a given grade; the dimension of a k-vector space of a given grade.
- BasisBladeIDs(), BasisBladeIDsByGrade(), BasisBladeIDsOfGrades() : The IDs of some basis blades of this frame. Overloaded versions can obtain specific basis blade IDs based on the inputs.
- BasisBlades(), BasisBladesByGrade() : Obtain some basis blades of this frame as a list of AstFrameBasisBlade objects. Overloaded versions can obtain specific basis blades based on the inputs.
- BasisVector() : Obtains a basis vector of this frame as an AstFrameBasisVector object using its name or index.
- BasisBlade() : Obtains a basis vector of this frame as an AstFrameBasisBlade object using its ID or its grade and index.
- IsLegalId(), IsLegalGrade(), and IsLegalGradeIndex() : Test if the inputs are within acceptable range in this frame.
The second figure illustrates the contents of the AstFrame node object and its related objects for the geometry3d.cga frame in the sample code provided in the top of this guide. Note that some elements in the shown graph are automatically generated or computed by GMac during parsing and compilation of GMacDSL code like the subspaces G0, G1, G2, G3, G4, and G5 for example.
AstFrameMultivector
Whenever a a frame is defined, GMac automatically defines an associated multivector type inside the frame. The AstFrameMultivector class represents this multivector type. The important members of this class include:
- GMacType : Return this multivector type as an AstType object.
- DefaultValue : The default value associated with the multivector type as an AstValueMultivector object. The default object for this type is the zero multivector having all basis blade scalar coefficients of value zero.
AstFrameBasisVector
Each AstFrame object contains a number of AstFrameBasisVector objects to represent the basis vectors of the frame. The most important members of this class include:
- ToMultivectorTermValue() and ToMultivectorValue() : Get the value associated with this basis vector as a single term multivector value or a full multivector value.
- FrameMultivector : The multivector type of this basis vector as a AstFrameMultivector object.
- ToBasisBlade : Convert this basis vector into a basis blade as a AstFrameBasisBlade object.
- GaSignatureScalar : The Mathematica symbolic scalar resulting from the scalar product of this basis vector with itself; the signature of the basis vector.
- GaSignatureValue: The signature of the basis vector as an AstValueScalar object.
- Grade : The grade of the basis vector; always 1.
- Index : The index of the basis vector.
- BinaryIndexedName, IndexedName, GradeIndexName, and CoefName : Several names of this basis vector when treated as a basis blade.
AstFrameBasisBlade
Each frame contains basis blades created from the outer product of basis vectors. The AstFrameBasisBlade node class represents a basis blade of the frame and contains many useful members:
- BasisBladeId : The ID of the basis blade. Each frame of dimension n contains 2^{n} basis blades each having a unique integer ID within the frame ranging from 0 to 2^{n}-1.
- FrameMultivector : The multivector type of this frame.
- Grade : The grade of this basis blade; the number of basis vectors constructing this basis blade by their outer product.
- Index : The index of this basis blade; All basis blades of the same grades are ordered based on their IDs, the index is an integer number representing the order of the basis blade among its same-grade basis blades.
- BinaryIndexedName, IndexedName, GradeIndexName, and CoefName : Several names of this basis blade.
- IsScalar, IsVector, IsPseudoVector, and IsPseudoScalar : Properties to test the common kinds of basis blades based on their grade.
- BasisVectorsIDs, BasisVectorsIndexes, and BasisVectors : Properties to return the basis vectors (as IDs, indexes, or as AstFrameBasisVector objects) that construct the basis blade by their outer product.
- ToMultivectorTermValue() and ToMultivectorValue() : Get the value associated with this basis vector as a single term multivector value or a full multivector value.
AstFrameSubspace
Inside each frame we can define one or more subspaces that are spanned by several basis blades of the frame. In addition, GMac automatically defines several subspaces when compiling any new frame definition. The AstFrameSubspace node class represents a subspace under a frame. The most important members of the AstFrameSubspace include:
- FrameMultivector : The multivector type of the frame of this subspace.
- BasisBladeIDs : The IDs of the basis blades spanning this subspace.
- BasisBladeGrades : The grades of the basis blades spanning this subspace.
- BasisBlades : The basis blades spanning this subspace.
- IsSingleGradeSubspace : True if the basis blades spanning this subspace are all of the same grade.
AstStructure
In GMacDSL, structures are combinatorial trees of geometric data used for grouping multivectors in a single container. The AstStructure node class represents a structure in GMacAST. The important members of this class include:
- DefaultValue : The default value associated with the structure as an AstValueStructure object.
- DefaultValue : A list of data members of the structure.
- DataMemberNames : A list of data member names of the structure.
- DataMemberTypes : The common types of the data members of the structure.
- GroupDataMembersByType() : Create a grouping of data members by their types.
- DataMember() : Find a data member of the structure by its name.
- DataMemberType() : Find a data member’s type by its name.
AstStructureDataMember
Each structure is a collection of several named data members having any GMac type needed. The AstStructureDataMember node class represents data members. The class has the following members:
- GMacType : The GMac type of the structure data member as an AstType object.
- ParentStructure : The parent structure of the data member.
AstMacro
In GMacDSL, a macro is the main processing code element taking inputs, performing GA operations, and producing an output of any desired GMac type. The AstMacro node class represents macros and contains many useful members:
- Parameters : A list of macro parameter for the macro.
- ParametersNames : A list or macro parameters names for the macro.
- InputParameters : A list of input parameters for the macro.
- InputParametersNames : A list of input parameters names for the macro.
- OutputParameter : The output parameter of the macro
- OutputParameterName : The output parameter name of the macro.
- OutputType : The output parameter GMac type of the macro.
- ParametersTypes : The types used for the macro’s parameters.
- CalledMacros : A list of other macros called inside the command block body of the macro.
- CommandBlock : The command block body of the macro in its parsed form.
- CompiledCommandBlock : The command block body of the macro in its compiled form. Compiled forms contain no other macro called or nested blocks. A macro called are replaced by the called macro’s code and command blocks are flattened into a single command block. Because GMac macros are not allowed to be recursive, this method is effective in producing optimized code for any macro at compile time.
- OptimizedCommandBlock : The command block body of the macro after optimizing the high-level code of the compiled form.
- GroupParametersByType() : The macro parameters grouped by their type.
- Parameter() : Gets a macro parameter given its name.
- ParameterType() : Gets a macro parameter GMac type given its name.
AstMacroParameter
Inside any macro a number of parameters can be defined to act as inputs and output to the macro. The AstMacroParameter node class holds the information of macro parameters and contains the following useful members:
- GMacType : The type of the macro parameter.
- ParentMacro : The parent macro of the parameter where it’s defined.
- IsInput : True if the parameter is an input macro parameter.
- IsOutput : True if the parameter is an output macro parameter.
- DatastoreValueAccess : Creates a full access data-store value access expression (as an AstDatastoreValueAccess object) from the macro parameter.
- Expression : Create a GMac expression as an AstExpression object from the macro parameter.
AstLocalVariable
Inside any command block several local variables can be used to perform intermediate GA computations. The AstLocalVariable class hold information of local variables and contains several useful members:
- GMacType : The type of the local variable.
- ParentBlock : The command block where the local variable is declared.
- ParentCommandDeclare : The declare command where the command is declared.
- DatastoreValueAccess : Creates a full access data-store value access expression (as an AstDatastoreValueAccess object) from the local variable.
- Expression : Create a GMac expression as an AstExpression object from the local variable.
AstConstant
A GMacDSL constant is a named value that gets calculated at compile time and is substituted in any expression where the constant name is used in later code. AstConstant is the AST node class holding information about constants. The class contains useful members such as:
- AccessName : The fully qualified name of the constant.
- GMacType : The GMac type of the constant.
- Value : The value associated with the constant.
- DatastoreValueAccess : Creates a full data-store value access expression based on the constant.
AstTransform
A transform in GMacDSL is a symbolic array containing constant entries that can be used as an outer-morphism or general linear transform on multivectors. Transforms are very useful in mapping multivectors between base frames and their derived frames based on Change-Of-Basis matrices in both directions (i.e. transforming multivectors from base to derived frame, and from derived to base frame). The AstTransform AST node class holds information relevant to transforms and contains the following useful members:
- SourceFrame : The frame of which multivectors are to be transformed by the transform.
- TargetFrame : The frame of which multivectors are images of the source frame’s multivector under the transform.
5. Types
In GMacDSL like many other programming languages, specific types are used to designate the set of values and operations allowed on specific variables and other value data-stores in the language. There are three kinds of types in GMac:
- The primitive scalar type.
- The composite multivector types automatically defined under frames.
- The composite structure types holding combinatorial trees of scalars, multivectors, or other structures.
In GMacAST, the AstType class holds all information relevant to GMac types. AstStructure and AstFrameMultivector objects can be converted into AstType objects and vice-versa as required, because these classes are not inherited from the AstType class but rather from the AstSymbol class. The reason behind this design is that internally the AstType class holds information about the GMac type as an interface implemented by several base classes not by a single base class.
AstType
The AstType class contains the following useful members:
- GMacTypeSignature : The string representing the unique type signature of the GMac type.
- IsValidScalarType : True if the GMac type is a scalar.
- IsValidMultivectorType : True if the GMac type is a frame multivector.
- IsValidStructureType : True if the GMac type is a structure.
- IsValidPrimitiveType : True if the GMac type is a primitive type.
- IsValidCompositeType : True if the GMac type is a composite type.
- IsSameType() : True if the given type is the same as the GMac type.
- ToFrameMultivector : Convert this AstType object into an AstFrameMultivector object.
- ToStructure : Convert this AstType object into an AstStructure object.
- DefaultValue : The default value of the GMac type as an AstValue object.
6. Commands
In GMacDSL a command is the basic unit of execution inside macros and composite expressions. Commands have several kinds represented by several GMacAST node classes.
AstCommand
The AstCommand class is the base class for all GMacAST nodes that represent commands. This class contains these useful members inherited by all derived classes:
- IsValidCommandBlock : True if this command is a valid command block.
- IsValidCommandDeclare : True if this command is a valid local variable declaration command.
- IsValidCommandLet : True if this command is a valid let command assigning an expression to a data-store.
- HasParentBlock : True if this command is part of a parent command block.
- HasParentSymbol : True if this command is a directly under a parent symbol’s scope not under a command block’s scope.
- HasParentMacro : True if this command is directly under the scope of a parent macro.
- NearestParentSymbol : Finds the nearest parent symbol of this command.
- NearestParentMacro : Finds the nearest parent macro of this command, if any
- ParentBlock : Gets the parent command block of this command, if any.
- ParentSymbol : Gets the parent symbol of this command, if any.
- ParentMacro : Gets the parent macro of this command, if any.
AstCommandBlock
The AstCommandBlock class represents information about a command block that typically contains other commands to be executed as a single grouping. Other command blocks and composite expressions can be nested inside the command block as desired in GMacDSL code. This class contains the following useful members:
- LocalVariables : A list of local variables directly declared under this command block.
- Commands : A list of this command block’s commands.
- LetCommands : A list of this command block’s let commands only.
- DeclareCommands : A list of this command block’s declare commands only.
- BlockCommands : A list of this command block’s child command blocks only.
- NonDeclareCommands : A list of this command block’s commands except declare commands.
AstCommandDeclare
The AstCommandDeclare node class represents a declare command in GMacDSL code. The class contains the following useful members:
- LocalVariable : The local variable declared by this command.
- GMacType : The GMac type of the local variable declared by this command.
AstCommandLet
The AstCommandLet node class holds information about the most important processing command in GMacDSL code, the let command. The let command assigns some computational expression to a data-store based on a local variable or a macro parameter. This class contains the following useful members:
- DatastoreValueAccess : The Left-Hand-Side data-store value access that will contain the value of the assigned expression. This LHS data-store may only be a macro parameter or a local variable.
- Expression : The Right-Hand-Side expression that will be used to assign values to the LHS data-store.
- GMacType : The GMac type of the LHS (and typically the RHS) of this let command.
- IsLocalAssignment : True if the LHS is a local variable data-store.
- IsInputAssignment : True if the LHS is an input macro parameter data-store.
- IsOutputAssignment : True if the LHS is an output macro parameter data-store.
7. Expressions
Computing in GMac is accomplished through the use of expressions acting on values. Many kinds of expressions exist to satisfy the computational goals of GMac. The AstExpression class is the base GMacAST class for all AST node classes that represent expressions. More details about GMac expressions can be found in GMacDSL Guide.
AstExpression
This class contains the following useful members inherited by its sub-classes:
- GMacType : Returns the GMac type of this expression.
- Some properties returning true if the expression is a valid expression of some kind: IsValidDatastoreValueAccess, IsValidValue, IsValidCompositeExpression, IsValidBinary, IsValidUnary, IsValidTransformCall, IsValidMacroCall, IsValidParametricSymbolic, IsValidMultivectorConstructor, IsValidStructureConstructor, and IsValidTypeCast.
AstTypeCast
This class represents an expression that converts (casts) on expression of some type to another type; for example a scalar can be cast into a multivector. The Operand property holds the expression that will be cast as an AstExpression object while the GetAstType property holds the type that will be cast into.
AstTransformCall
This class represents a transform that is applied to a multivector expression. The Operand property holds the multivector-typed expression to be transformed while the CalledTransform property holds the transform that will be called on the multivector expression.
AstUnaryExpression
This class represents a unary operator expression like the negative of some value or the grade involution of a multivector. The Operand property holds the expression to be operated on while the OperatorName and OperatorSymbol properties hold information about the unary operator itself.
AstBinaryExpression
This class represents a binary operator expression like the geometric product two multivectors or the division of two scalars. The FirstOperand and SecondOperand properties hold the expressions to be operated on while the OperatorName and OperatorSymbol properties hold information about the binary operator itself.
AstMultivectorConstructor
As described in the GMacDSL Guide, a multivector constructor expression creates a multivector of some frame by assigning scalar values to its basis blade coefficients after possibly initializing the multivector by some value. The AstMultivectorConstructor expression node class represents this kind of expressions and contains the following useful members:
- ConstructedMultivector : The frame multivector type constructed by this expression.
- HasDefaultExpression : True if this constructor expression is initialized by a default expression.
- DefaultExpression : The default expression of this constructor expression, if any.
- UsedBasisBladesIds : The basis blade IDs used to create the constructed multivector.
- UsedBasisBlades : The basis blades used to create the constructed multivector.
- Assignments : A list of basis blades and their assigned expressions used for constructing the multivector.
AstStructureConstructor
A structure constructor is similar to a multivector constructor but creates a structure of some kind. The AstStructureConstructor class represents this kind of expressions and contains the following useful members:
- ConstructedStructure : The structure type constructed by this expression.
- HasDefaultExpression : True if this constructor expression is initialized by a default expression.
- DefaultExpression : The default expression of this constructor expression, if any.
- UsedDataMembers : The data members used to create the constructed structure as a list of AstDatastoreValueAccess objects.
- Assignments : A list of data members and their assigned expressions used for constructing the structure.
AstMacroCall
This class represents a macro call that assigns values to macro parameters. We can assign an expression to a full parameter or to a part of the parameter using a partial data-store value access expression. The class contains several useful members including:
- CalledMacro : The called macro.
- UsedParameters : The parameters used in this macro call expression as a list of AstDatastoreValueAccess objects.
- Assignments : A list of parameters and their assigned expressions used for calling the macro.
AstParametricSymbolicExpression
As described in the GMacDSL Guide, the parametric symbolic expression is a simple form of inline macro that operates on a set of scalar parameters to create a symbolic scalar expression. The AstParametricSymbolicExpression class represents this kind of expressions and contains the following useful members:
- SymbolicScalar : The Mathematica symbolic scalar of the expression.
- UsedSymbolicVariables : A list of symbolic variables names used in the expression.
- Assignments : A list of symbolic variables and their assigned expressions used for the expression.
AstCompositeExpression
A composite expression is simply a command block containing GMacDSL commands to be executed in order to compute a special output variable for the composite expression that will be returned as the expression’s final result. The AstCompositeExpression node class represents this kind of expressions and contains the following useful members:
- LocalVariables : The local variables declared inside the composite expression.
- Commands : The commands used inside the composite expression.
- OutputVariable : The output local variable of the composite expression.
- ToCommandBlock : Convert this AstCompositeExpression into a AstCommandBlock object.
AstDatastoreValueAccess
In GMac, a data-store is a constant, local variable, or macro parameter that can hold a primitive or composite value that can be accessed in other code (i.e. read inside expressions or written to in let commands, and other similar code constructs). A value access operation on a data-store can be executed by fully accessing (reading\writing) the whole value (full value access) or by accessing a part of the value (partial value access). The AstDatastoreValueAccess class holds information about such value access operations for GMac data-stores and contains many useful members:
- ValueAccessName : The full name of the value access steps separated by dots.
- PartialAccessName : The full name of the value access steps separated by dots except for the root symbol.
- RootSymbol : The root data-store symbol of this value access operation.
- Several properties returning the root symbol as a specific AST node including: RootAsMacroParameter, RootAsLocalVariable, RootAsBasisVector, RootAsConstant, and RootAsDataMember.
- TypeAsFrameMultivector : Returns the type of this value access as a frame multivector type if possible.
- TypeAsStructure : Returns the type of this value access as a structure type if possible.
- IsFullAccess : True if this value access operation is on the whole data-store.
- IsPartialAccess : True if this value access operation is on a part of the data-store.
- Several properties to test the final GMac type of this value access operation including: IsPrimitive, IsComposite, IsScalar, IsMultivector, and IsStructure.
- IsFullMultivector : True if this value access operation is on the whole data-store of multivector type.
- IsPartialMultivector : True if we are accessing part of a multivector-typed data-store.
- IsMultivectorCoefficient : True if this value access is done on a multivector-typed data-store to access a single basis blade coefficient.
- Several properties to test the kind of data-store of this value access operation: IsMacroParameter, IsInputParameter, IsOutputParameter, IsLocalVariable, IsNamedValue, IsBasisVector, IsConstant, and IsDataMember.
- GetBasisBlade() : If this value access is on a multivector coefficient, get the basis blade of the coefficient.
- GetBasisBladeId() : If this value access is on a multivector coefficient, get the ID of the basis blade.
- GetBasisBladesList() : If this value access is on a multivector partial coefficients access, get the basis blades of the coefficients.
- GetBasisBladeIDsList() : If this value access is on a multivector partial coefficients access, get the basis blades IDs of the coefficients.
- ExpandAll() : Expand this data-store value access into a list of primitive value access expressions on leaf scalar values.
- ExpandStructures() : Expand this data-store value access into a list of value access expressions on scalar and multivector values; i.e. the resulting items in the list are of scalar or multivector types.
- SplitAs_MultivectorCoefficient() : If this value access is on a multivector coefficient, split this value access into two parts: a value access on the multivector type and a basis blade.
- SplitAs_PartialMultivector() : If this value access is on a partial multivector coefficients list, split this value access into two parts: a value access on the multivector type and a list of basis blades.
AstValue
The AstValue class is the base class of all AST nodes that represent values of GMacDSL code. Some useful members common to all its inherited classes include properties for testing the specific kind of value: IsValidScalarValue, IsValidMultivectorValue, IsValidMultivectorTermValue, IsValidStructureValue, IsValidStructureTermValue, IsValidPrimitiveValue, and IsValidCompositeValue.
AstValueScalar
The simplest kind of values in GMacDSL is the primitive scalar value. The AstValueScalar node class holds information related to scalar values with some useful members:
- ScalarValue : The internal Mathematica scalar of this value.
- ScalarValueExpr : The internal Methematica symbolic expression object of this value.
AstValueMultivector
A composite multivector value consists of several basis blade scalar coefficients with assigned scalar values, called terms, where a term is the ID of the basis blade and the scalar value associated with it. The AstValueMultivector class contains members to represent this kind of values:
- this[] : An indexer taking the basis blade ID and returning the scalar value associated with the basis blade’s coefficient.
- FrameMultivector : The multivector type of this value.
- Frame : The parent frame of the multivector type of this value.
- Terms : The terms of this value.
- ActiveIDs : The basis blade IDs used in this value.
- ActiveGrades : The basis blade grades used in this value.
AstValueMultivectorTerm
A multivector value consists of some terms each having a basis blade and its coefficient’s scalar value. The AstValueMultivectorTerm class holds information relevant to terms and contains the following useful members:
- TermId : The basis blade ID of this term.
- TermCoefScalar : The basis blade coefficient scalar value as an internal Mathematica scalar object.
- TermCoefExpr : The basis blade coefficient scalar value as an internal Mathematica expression object.
- FrameMultivector : The multivector type of this term value.
- Frame : The parent frame of the multivector type of this term value.
- BasisBlade : The basis blade of this term value.
- CoefValue : The basis blade coefficient scalar value as an AstValueScalar object.
- ToMultivectorValue : Convert this term into a multivector value (an AstValueMultivector object).
AstValueStructure
A composite structure value consists of several data members with assigned values of proper types, called structure terms, where a term is the name of the data member and the value associated with it. The AstValueStructure class contains members to represent this kind of values:
- this[] : An indexer taking the data member name and returning the value associated with the data member.
- Structure : The structure type of this value.
- Terms : The structure terms of this value.
AstValueStructureTerm
A structure value consists of some terms each having a data member and its value. The AstValueStructureTerm class holds information relevant to terms and contains the following useful members:
- DataMember : The structure data member of this term.
- DataMemberName : The structure data member name of this term.
- DataMemberValue : structure data member value of this term.
- Structure : The structure type of this term.
- ToStructureValue : Convert this term into a structure value (an AstValueStructure object).
8. Dependency Information
In the AstRoot class we can see two methods that construct type and macro dependency graphs of all types and macros under this AST. The dependency information are returned in AstTypeDependencyGraph and AstMacroDependencyGraph objects. Both of these classes are derived from the DependencyGraph<TKey, TItem> generic class under the UtilLib.DataStructures.Dependency namespace of the UtilsLib project. The DependencyGraph class contains a list of DependencyInfo objects that hold the actual dependency information per item. To construct the type dependency information of a GMacAST, for example, we need to know for each GMac type, which of the other types are used by the base type, and which are users of the base type. This information is then used to construct an AstTypeDependencyGraph object easily through the inherited methods from the DependencyGraph class.
For each item (a GMac type in our example) we have the following information in the DependencyInfo<AstType> item dependency objects:
- BaseItem : The base AstType of this dependency information structure.
- UserItems : A list of AstType objects that are users (i.e. that depend on) the base AstType item.
- UsedItems : A list of AstType objects the base AstType item uses (i.e. the types it depends on).
- UserCount : The number of types depending on the base type.
- UsedCount : The number of types the base type depends on.
The AstTypeDependencyGraph class contains internally a dictionary of DependencyInfo<AstType> objects each stored by its type signature string of its base GMac type item as the key to the dictionary.
- The ItemToKey() method is used for obtaining a unique key from the GMac type item (in our example it simply returns the GMacTypeSignature property of the AstType object).
- The Populate() method fills the graph by information obtained from the AST using a series of calls to the protected AddDependency() method, each taking a user item and a used item as inputs.
- The Clear() method can be used to clear all dependency information in the graph.
- After filling the dependency information graph we can use several methods to access such information by the item’s key (i.e. the GMac type signature) like the GetDependency(), TryGetDependency(), ContainsKey(), and this[] indexer.
- We can also get lists of items dependency information with particular kinds of dependency from the properties: Dependencies, ItemsWithNoUser, ItemsWithUser, ItemsWithNoUsed, ItemsWithUsed, ItemsWithNoDependency, and ItemsWithDependency.
9. GMacAST Visitors
Many operations on AST nodes can be modeled as a visitor pattern on trees. The problem with this particular pattern is its tendency to add much unnecessary code just to pick the correct method to apply to a certain sub-class depending on its concrete type. Using the dynamic feature in C# made implementing this pattern very easy and elegant in GMacAST; see this article for more details. By implementing the IAstObjectDynamicVisitor or the IAstObjectDynamicVisitor<out TReturnValue> interfaces under the GMac.GMacAST.Visitors namespace, we can create a class to implement the visitor pattern and add any number of Visit() methods having a single input of any sub-class inherited from the AstObject class.
One very useful visitor implementation is done in the GraphVizConverter abstract class implementing the IAstObjectDynamicVisitor interface to be used as a base class for drawing diagrams from GMacAST nodes using the GraphViz composer explained in TextComposerLib Guide. An excellent sample for this fruitful combination is found in the AstToGraphViz class inherited from the GraphVizConverter abstract class where several Visit() methods are created to add nodes to the diagram based on the specific AST node class used.
To summarize the classes used in this task:
- The AstVisitorDotGraph class inherited from TextComposerLib’s DotGraph class to implement some useful kinds of node shapes and colors common to all desired GMacAST diagrams.
- The GraphVizConverter abstract class implementing the dynamic visitor pattern interface IAstObjectDynamicVisitor and containing a AstVisitorDotGraph object for interfacing with GraphViz.
- The AstToGraphViz class inherited from GraphVizConverter and containing several Visit() methods to draw specific GraphViz nodes for specific GMacAST nodes.