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 |
///////////////////////////////////////////////////////////////////////// // Structured Textual Code generated using TextComposerLib under GMac // /////////////////////////////////////////////////////////////////////// namespace GMacBlade.cga5d { /// <summary> /// This class represents an immutable blade in the cga5d frame with arbitrary grade /// (i.e. grade is determined at runtime) based on additive representation of the blade as a /// linear combination of basis blades of the same grade (i.e. it's actually a k-vector representation). /// </summary> public sealed partial class cga5dBlade { /// <summary> /// The maximum grade for any blade of this class /// </summary> public const int MaxGrade = 5; /// <summary> /// The accuracy factor for computations. Any value below this is considered zero /// </summary> public static double Epsilon = 1e-12; /// <summary> /// A lookup table for finding the k-vctor space dimension of a blade using its grade /// as index to this array /// </summary> internal static readonly int[] GradeToKvSpaceDim = { 1, 5, 10, 10, 5, 1 }; /// <summary> /// An array of arrays containing basis blades names for this frame grouped by grade /// </summary> private static readonly string[][] BasisBladesNamesArray = { new [] { "E0" }, new [] { "E1", "E2", "E4", "E8", "E16" }, new [] { "E3", "E5", "E6", "E9", "E10", "E12", "E17", "E18", "E20", "E24" }, new [] { "E7", "E11", "E13", "E14", "E19", "E21", "E22", "E25", "E26", "E28" }, new [] { "E15", "E23", "E27", "E29", "E30" }, new [] { "E31" } }; /// <summary> /// The zero blade /// </summary> public static readonly cga5dBlade ZeroBlade = new cga5dBlade(); public static readonly cga5dBlade E0 = new cga5dBlade(0, new[] { 1.0D }); public static readonly cga5dBlade E1 = new cga5dBlade(1, new[] { 1.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E2 = new cga5dBlade(1, new[] { 0.0D, 1.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E4 = new cga5dBlade(1, new[] { 0.0D, 0.0D, 1.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E8 = new cga5dBlade(1, new[] { 0.0D, 0.0D, 0.0D, 1.0D, 0.0D }); public static readonly cga5dBlade E16 = new cga5dBlade(1, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); public static readonly cga5dBlade E3 = new cga5dBlade(2, new[] { 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E5 = new cga5dBlade(2, new[] { 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E6 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E9 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E10 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E12 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E17 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E18 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E20 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D }); public static readonly cga5dBlade E24 = new cga5dBlade(2, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); public static readonly cga5dBlade E7 = new cga5dBlade(3, new[] { 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E11 = new cga5dBlade(3, new[] { 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E13 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E14 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E19 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E21 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E22 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E25 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E26 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D, 0.0D }); public static readonly cga5dBlade E28 = new cga5dBlade(3, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); public static readonly cga5dBlade E15 = new cga5dBlade(4, new[] { 1.0D, 0.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E23 = new cga5dBlade(4, new[] { 0.0D, 1.0D, 0.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E27 = new cga5dBlade(4, new[] { 0.0D, 0.0D, 1.0D, 0.0D, 0.0D }); public static readonly cga5dBlade E29 = new cga5dBlade(4, new[] { 0.0D, 0.0D, 0.0D, 1.0D, 0.0D }); public static readonly cga5dBlade E30 = new cga5dBlade(4, new[] { 0.0D, 0.0D, 0.0D, 0.0D, 1.0D }); public static readonly cga5dBlade E31 = new cga5dBlade(5, new[] { 1.0D }); /// <summary> /// Create a new coefficients array to be used for later creation of a blade /// </summary> /// <param name="grade"></param> /// <returns></returns> public static double[] CreateCoefsArray(int grade) { return new double[GradeToKvSpaceDim[grade]]; } } } |
In science, if you don’t do it, somebody else will. Whereas in art, if Beethoven didn’t compose the ‘Ninth Symphony,’ no one else before or after is going to compose the ‘Ninth Symphony’ that he composed; no one else is going to paint ‘Starry Night’ by van Gogh. — Neil deGrasse Tyson.
The final stage in any compiler is code generation from some intermediate representation of the input source code. This stage is the most demanding for creativity because it relies on designing and implementing many optimizations to generate target code suitable for its specific consumer. Traditional compilers typically generate machine code for native hardware or bytecode for virtual machine frameworks. This form of code is machine-oriented, cold and repetitive code not intended for reading or understanding by humans. GMac, being a DSL based source-to-source compiler, produces programmer-oriented textual source code in some high-level human-readable language. The difference between designing the code generator of any typical compiler vs. the code generator of a system like GMac is similar to the difference between designing a machine that creates mechanical parts and designing a tool-set for an artist.
About TextComposerLib
TextComposerLib is a set of .NET classes and interfaces specifically designed for structured text generation. The most important kind of text generation is the composition of software code from a suitable data source. TextComposerLib contains many integrating classes to implement structured text generation tasks using various methods of procedural composition of text; ranging from simple text concatenation to complex code library construction.
To use TextComposerLib you need to have a Windows 7 or later operating system and the .NET Framework version 4.5. You naturally need a .NET development environment like Visual Studio 2010 or later to use TextComposerLib in your .NET projects.
You can find the latest version of TextComposerLib source code as part of the GMac source code in GitHub here: https://github.com/ga-explorer/GMac
You can download a Visual Studio 2015 samples project to explore and learn TextComposerLib features from here:
[Download not found]After downloading the compressed files just expand it inside a folder of your choice, open the solution in Visual Studio 2015, add references to the following DLLs and run the solution:
- TextComposerLib.dll
- FastColoredTextBox.dll
- Irony.dll
- Irony.Interpreter.dll
TextComposerLib Features include:
- A wide range of structured procedural text composition methods adopting the Linq to objects capabilities of the .NET framework.
- Simple text composition by concatenation of lists of strings as extension methods.
- Text composition from common data structures like stacks, queues, and priority queues.
- Text composition from string mappings and transforms for more complex applications.
- Linear text composition component resulting in well-formatted text documents including indentation management and precise selection of each line of text in the final document.
- Template-based text composition using parametric substitution text templates. This is one of the more common methods of code generation.
- A component of text injection inside a bulk of mostly-fixed text document. This is suitable for code injection within marked regions in the code file.
- The composition of text from expression trees suitable for creating un-parsers (systems that can generate text by visiting a tree-like structure). This is a key component in source-to-source compilers like GMac.
- A powerful composition component for creating text files nested inside arbitrary directories. This component can be used with other components to create any desired structure of text files or code files.
- A logging component capable of reporting events and progress of long-running computational processes at any desired level of detail including errors, warnings, start and end of intermediate steps, etc.
- Full-featured composers for creating SVG and POV-Ray files.
- A full-featured .NET wrapper for the GraphViz graph visualization software. This component includes a powerful AST representation of GraphViz dot code that can procedurally create graphs, nodes, edges, subgraphs, and clusters, in addition to managing all their properties and attributes using managed .NET properties and methods. The component also includes a simple to use interface for rendering the generated graph from within the TextComposerLib itself provided the executable GraphViz is present on the same computer.
- A capability for creating full libraries of structured code text documents using a well-designed code library generator base class. This class can be inherited to implement arbitrarily complex code library generators for any application including source-to-source compilers like GMac.
Why call it a Composer, not a Generator?
If we lookup the verb compose in the Merriam-Webster online dictionary we’ll find the following meanings:
- A) to form by putting together : fashion; ‘a committee composed of three representatives’
B) to form the substance of : constitute; ‘composed of many ingredients’
C) to produce (as columns or pages of type) by composition - A) to create by mental or artistic labor : produce; ‘compose a sonnet’
B) to formulate and write (a piece of music) : to compose music for - to deal with or act on so as to reduce to a minimum ‘compose their differences’
- to arrange in proper or orderly form
- to free from agitation : calm, settle ‘composed himself’
My view of coding is a form of:
Creative composition of highly structured, human-understandable, and machine-compilable text holding all the meanings of the verb compose stated above.
To me writing code is not just about execution efficiency or blind implementation of algorithms; writing code is fundamentally artistic such that no two skilled software developers may produce the same code for a single problem. Like there can be no machine that may creatively produce music or paintings, there can be no single code generator that can, by itself, write human-understandable code with all its rich content of information, creativity, and beauty. Nevertheless, we can certainly make many smaller tool sets to help the skilled code developer layout code in the way humanly and creatively desired, while automatically generating machine-oriented code from the intermediate representation to free the coding artist from its repetitive cold nature.
The text generation toolset specifically created for GMac, but independently usable otherwise, is a C# library called TextComposerLib. In this guide, we give a description of the main functionality of this toolset through examples. The TextComposerLib consists of several composers each having unique capabilities and intended use. We will illustrate many of them in this guide from the most simple to the more complex. The TextComposerLib composers can easily and flexibly be integrated to produce text files with arbitrary internal (i.e. text related) and external (i.e. folders related) structure. The quality of the generated text is, however, a direct expression of how the toolset is creatively used by the code designer. In my experience with GMac, in the hands of a good coding artist, TextComposerLib is a very helpful tool. This guide is not intended to give the full details of all classes in TextComposerLib but is a means of illustrating the general behavior of its main composers. Many other samples can be found under the TextComposerLib.Samples namespace.
This guide will illustrate the following:
- Text Composers
- Expression Trees Composition
- Files Composer
- Progress Logs Composer
- Markdown Composer
- GraphViz Composer
- SVG Composer
- POV-Ray Composer
- Software Code Composition