Schwartz 1 6 – Template Based Graphics Code Generator

broken image


  1. Schwartz 1 6 – Template Based Graphics Code Generator Free
  2. Schwartz 1 6 – Template Based Graphics Code Generator Roblox
Subsections
  • Creating a basic class
  • Writing a template set
  • The template substitution process

Creating a new code generator tool depends on the code generation task you wantto accomplish. Nevertheless, the process generally needs to cover three broadtasks before you can get a working code generator:

Creating a basic class
This category covers the basics of creating a new code generator. You will need to create the basic Java skeleton class, determine the nodes for which generated code should be written to disk, identify files that need to be output only once per generation task, and create a set of language data type mappings.
Writing a template set
Most of the work of a code generator goes into the templates that store a majority of the code to generate.
Implementing basic functionality
Each code generator requires at least three function implementations. These three basic functions are:
writeOutput
This function will write generated code to the hard disk.
finalize
This function can generate global package files based on the set of input IDL3 source files.
getLanguageType
This function provides the generator with a mapping between IDL3 data types and the data types in the target language. The language mapping you create in the first stage usually comes in handy here.

In addition, depending on the complexity of the code generator you want towrite, you might need to perform some additional coding tasks. This couldinclude any of the following concepts, and likely others not listed.

  • Sometimes templates require special pre- or postprocessing. For example, the parameters to an operation are normally separated by commas (,). However, since there is normally only one template for a parameter type node in a graph, generators need process the entire parameter list at once to remove the last comma.
  • Sometimes nodes in a graph will need to know information about distant neighbors in the graph, not just nodes immediately adjacent.
  • Sometimes nodes need to have specifically formatted information about the entire graph traversal to date. For example, there are several different ways to format the current namespace in a C++ generator (e.g. using namespace A, namespace A { .. }, etc.).

The remainder of the template, lines 6 to 20, is a scriptlet — a piece of code executed inline. The code is written in C# as specified by the CodeTemplate directive. At line 8, this.Settings is used. All settings provided to the code generator (both in a settings file or on the commandline) are available to the Settings property of the template. We provide a new graph generator, based on a 'forest fire' spreading process, that has a simple, intuitive justification, requires very few parameters (like the 'flammability' of nodes), and produces graphs exhibiting the full range of properties observed both in prior work and in the present study. Family tree 1; gallery 10; games 5; live preview 3; mockups 28; mood board 6; ooc contact 21; other 36; permissions 4; playlist 14; profile code 10; thread header 4; thread tracker 5; timeline 5; color palettes 3. General 2; graphics 5. Template 2; tutorials 3; html page 18; icons 12; layouts 85. Add ons 6; layout remakes 5; s1 generator 26; s2.

The remainder of this section addresses these areas. Background on how the codegenerator base classes work is also included when it will help explain how to dothings.

Creating a basic class

To start writing a new code generator, you will need to create a new Java classto hold your generator's specific information, and fill it in with some basicinformation about the language you want to generate. Most of this process ismore or less boilerplate code; in fact, you might want to create the skeletalJava code by copying an existing generator and stripping out the functions. Seethe IDL2 generator class for an example of a minimal generator.4.2

The remainder of this process involves creating several arrays of informationrelating to your specific generation task. You will need to create arrayscontaining top level node types, environment files and templates, languagemappings, and keywords for your target langauge. Each of these is explainedbelow.

Top level node types

After you have a basic Java class skeleton, you need to determine the nodes forwhich generated code should be written to disk. These will be referred to as``top level node types'. Store these node types as strings in a privatefinal static String[] array in your new class. Note that ``MContainer' will beadded to these types, since the top node of all CCM Tools metamodel graphs is anMContainer class instance.

Environment files and templates

Next, you need to identify files that need to be output only once per generationtask; these files are referred to as ``environment files.' Most generatedfiles, like the code for a component, are written one or more times during codegeneration--once for each component (or operation, or whatever) in a graph.Environment files, on the other hand, are things like global header files,global utility functions, and so on. These files cannot be filled with anyinformation from a graph traversal; they are more or less static.

To get started, figure out the relative paths of each of the code generator'senvironment files (relative to the root directory of the generated code; do notuse absolute file paths!). Specify these files in your class in a privatefinal static File[] array. Next, you need to provide your generator with a listof the templates to use for writing each of these environment files. Define anarray of strings that contains the names of templates to use for eachenvironment file. These two arrays must be the same length.

Normally, templates for environment files do not contain any keys; the templatesare simply written to disk as is, since environment files are globally valid.Example 4.3.1 shows the environment filearrays in the C++ Python wrapper generator.


Language type mappings

Create a set of language mappings in a private final static String[]array. This language map array must be the same length as the MPrimitiveKindenumeration (located in Metamodel/ BaseIDL/ MPrimitiveKind.java in thesource tree). The language map array provides the strings that will be used totranslate IDL3 language types into the data types for the target language. Thusthe entries in this language mapping array must be in the same order as theentries in the MPrimitiveKind enumeration.Example 4.3.2 shows the language type mappingfor the C++ generators.


Keywords

The last piece of information your generator needs is a list of the keywords inyour generator's target langauge. Components, interfaces, operations, andexceptions cannot normally have the same name as a keyword, so if the generatorfinds a graph node with a keyword identifier, it will map the identifier to anew, safe identifier by prefixing the name with an underscore (_). Like theother arrays, the keyword array should be a private final static String[]data element in your class.

Writing your class constructor

Finally, you need to provide all of these arrays to the constructor of theabstract code generator base class in each constructor you write for yourgenerator class. The constructor for the C++ abstract base generator class inExample 4.3.3 shows how to call thesuperclass' constructor, providing the language mappings, keywords, andenvironment files to build the generator.

Omniplan pro 3 2 1 download free.

Writing a template set

Writing a template set can be divided into two types of writing tasks. First,you need to create templates for your code generator's environment files. Next,you need to create the normal templates for your generator. Now you might thinkthat this second step is easy, but it actually represents about 75 % of thework involved in creating a code generator.

Creating environment templates

Create templates for your environment files. Since environment files are usuallystatic from project to project, these templates are often just straight codewritten in the target language.

If you absolutely need to include dynamic data in an environment file, you willneed to perform a somewhat different operation. Instead of adding yoursemi-dynamic environment file to the normal environment files list, you canmake use of the finalize function. This process is not entirely the sameas generating normal environment files, however. Seesection 4.3.4 for details.

Now take a deep breath; you are about to start writing a template set. Thetutorial takes a small style detour at this point to explain in detail how thetemplate mechanism works. This is important for writing templates andaccompanying them with custom code in your generator class.

Template writing process

Writing a template set usually starts by writing templates for more globallyscoped CCM metamodel elements (e.g. MContainer and MModuleDef).4.3 Paragon extfs for mac 11 3 30 download free. Then, whenever apotential subelement is encountered (for example, an MInterfaceDef instancecould be contained in an MModuleDef instance in an IDL3 source file), thetemplate can reflect this possibility by including a `key' for the element type.

Template writing can theoretically proceed in this way from general elementsthrough the entire CCM metamodel to more specific elements (e.g. MParameterDefand MField) by following this process. Just by following this template process,you can often write a near-complete template set.

Example template writing task

For purposes of illustration, the remainder of this section will use the IDL3file shown in Example 4.3.4 as an example fortemplate writing. The parse tree produced by parsing such an IDL3 file, withjust the node types and identifiers indicated, is shown inExample 4.3.5. The target language for the examplewill be Java. For comparison, Example 4.3.6shows the generated Java code that should result from the example IDL3 file.




The template substitution process

As stated earlier, template writing can generally proceed from more globallibrary elements to more specific elements. Given the example IDL3 file as aguide, you'll need to write a template for MInterfaceDef (since it is thehighest level element in our IDL3 code example). For the time being, theMContainer template is empty.

The first step is to create a directory to hold the templates. The directoryneeds to be named Templates and needs to be installed under PREFIX/share/ccmtools-A.B, where the code generators can find it.Example shows a snippet of the Makefile.am for the local C++ generator.

In general, the template for a node type needs to have the same name as the nodetype, so to create a template for MInterfaceDef nodes, you need to make a newfile, JavaTemplates/MInterfaceDef. Peek a little ahead toExample 4.3.7 and take a look at onepotential way to define a template for MInterfaceDef.

As mentioned earlier, a template is a piece of code written in the targetlanguage (for this example, Java). But because one node type can have manydifferent instances--that is, there could be multiple MInterfaceDef classinstances in a graph--each template contains keys that the code generator willfill in when the code is generated. There are four different types of keysavailable, as described below.


Template key types

A key is just a text string of the form %(name)s.4.4 Keys come in four flavors:

Simple data elements
These keys are placeholders for simple graph node information (i.e. data types that do not require an iterator to investigate). The key is the name of the data element from the CCM metamodel class, with the initial letter capitalized. Information like component and operation identifiers (%(Identifier)s), or sequence bounds (%(Bound)s) are valid candidates for keys in this category.
Child node template information
The core of the template system, as explained in more detail below, is the notion of recursive template substitution. When a graph node needs to add information about all of its child elements in the graph, the template can simply include a key with the name of the child node type. All child node template information will be substituted in place of this key. See section 4.3.3 for details.
Parallel child node information
Sometimes a node of a given type needs to know information about its child nodes in more than one format. You can define a key (and create an associated template) that starts with a node type name and has some sort of specifier on the end, for example MParameterDefAll. See section 4.3.3 for details.
Common graph information
Finally, there are some common data elements that a template needs, but which are not immediate data members of the graph node. For example, a component template often needs to know the identifier of the component's home, which requires traversing the CCM metamodel graph from the component node to its home node.

Since this is a relatively common and simple operation, the home identifier can be included in a template using the %(HomeType)s key. As another example, many node types (especially operations, parameters, and attributes) need to include their target language data type in the template. The %(LanguageType)s key provides access to this information. Other special keys are available; Table 4.1 describes these special keys.


Table 4.1:Standard keys available for template writing.

Next comes an explanation of how this recursive template loading concept works.After grokking it you should be able to handle 90 % of template writing tasks.


Recursive template loading and substitution

The template substitution process goes even further than basic translationdirectly from graph nodes, as implied by the first key type. Consider, forexample, a code template for an IDL3 operation. This template will need keys forthings like the operation's identifier and the data type that the operationreturns. The values for these keys come directly from each operation node in agiven graph traversal.

But an operation also has parameters and can throw exceptions. The number ofparameters and exceptions is not fixed for all operations. That is, a givenoperation might take three parameters and throw four types of exceptions, whileanother operation might only take one parameter and throw no exceptions. Thetemplate for an operation cannot hold the code for all possibilities in thisrespect.

In fact, the specific code to implement these types of variables needs to becreated after all appropriate nodes in the graph are visited. More specifically,for an operation, the operation template needs to know information contained inthe child parameter and exception nodes in the graph. Luckily, though, all thethe relevant nodes (parameters and exceptions) are all immediate children of theoperation node, so the operation needs just the information from its childnodes.

To support this type of template interaction, the code generator implementationsupports recursive template substitution. Keys in a template just need to havethe name of child node types, and the code generator will automaticallysubstitute template information from the filled-in templates of child nodes inthe graph. The specifics of this substitution process are described below duringthe tutorial on template creation.

Because an MInterfaceDef object has a variable called identifier(and a corresponding access function named getIdentifier), it is easy forthe code generator to simply substitute the value of the current node'sidentifier for the Identifier key in a template.

The difficulty with a top down template like the one shown for our exampleMInterfaceDef is that it is not clear how to generically generate code for amore complex key like MOperationDef: MInterfaceDef class instancesdo not have variables and access functions for direct data members called``mOperationDef'. F lux 37 5 download free. To support such keys, the code generator uses a recursivetemplate loading and substitution process. This scheme simplifies templatedevelopment in many cases and allows for more general template keys. However, italso requires some extra coding in some cases.

Consider the parse tree for the example code generation task, shown inExample 4.3.5. Keep in mind that the graphtraverser is depth-first, so all child nodes will be visited before visiting asibling node in the graph. When the graph traverser starts reading theMyInterface node, then, it will proceed to the MyOperation node and on to theMyParameter node before returning back up the tree. The traverser will leave theMyParameter node, then leave the MyOperation node. Next it will visit theOtherOperation node (and also that node's child elements), and finally it willgo all the way back up and leave the MyInterface node at the top.

At each point during this process, the code generator stores information aboutthe nodes it has visited so far. In this way, when the code generator returns tothe MyInterface node after visiting its child nodes, it has all the necessaryinformation to fill in an MOperationDef key in the interface template.

The exact process that the code generator uses to gather this information isdescribed next. Following the description is an explanation of how to use thisinformation in template creation.

Template loading and substitution in the example

When the code generator receives notification that the traverser is leaving anode, the generator attempts to load a template for the given node type. Becausethe MyParameter node in the example is a MParameterDef instance, the codegenerator in our example will try to load a template from disk located at JavaTemplates/MParameterDef. So if the template for MParameterDef looks like

then after doing key substitution we would get
intMyParameter,
and the code generator would store that information in its internal variablehash. (The `' symbols are used to emphasize the fact that thereare space characters in the template and substituted code.)

The important thing to note now is that the substituted template value will beadded to the information in the parent node. This information will beindexed using the node type as a key in the code generator's variable hashtable. So the above string will be added to the code generator's variable hash,indexed under the MParameterDef variable of the MyOperation node.

After descending to read the first parameter node, the graph traverser will exitthe MyOperation node, at which point it will load the template from JavaTemplates/MOperationDef (because MyOperation is an instance of theMOperationDef class) and substitute the variables for this node. The templatefor MOperationDef nodes should look like the target Java code, with specificidentifiers replaced by keys. So if the MOperationDef template looks like this:

%(LanguageType)s
%(Identifier)s
( %(MParameterDef)s );
Then substituting the variables in this template will yield:Again, the important thing to keep in mind is that this information will beadded to the parent node's MOperationDef variable, so the node informationfor MyInterface will contain an MOperationDef variable that containsthis string.

The graph traverser will then continue on and start the AnotherOperationnode. When it has ended the second MParameterDef child node, the MParameterDef variable for the AnotherOperation node will look like:

charLetter,intNumber,
Then when the graph traverser has visited all children of the MyOperation nodeand finally ascends up one layer and signals the end of the MyOperation nodeitself, the code generator will load the template from JavaTemplates/MOperationDef from disk. After substituting the values for thesecond operation, the code generator adds the resulting value to theMOperationDef variable in the parent element. This yields an MOperationDef valuefor the MyInterface node:
float
MyOperation
( int MyParameter, );
int
AnotherOperation
( char Letter, int Number, );
Schwartz 1 6 – template based graphics code generator no human
and, as before, this value will in turn be added to the parent node'sinformation. So, in this example, this string will get added to theMOperationDef variable of the MyInterface node. When the traverser then exitsthe MyInterface node, the code generator again loads a template, this time fromJavaTemplates/MInterfaceDef. The template and resulting code after keysubstitution are shown in Example 4.3.7 andExample 4.3.8, respectively.



This recursive substitution process is what enables short, top down styletemplates that can handle a variety of input trees.


A couple more things about templates

You might have encountered a few questions while reading through this businessabout template substitution. Answers to two of these questions are mentionedhere, but now is a good time to mention other sources of support as well: If youdecide to hack on the CCM Tools, it is probably a good idea to subscribe to theccmtools-devel mailing list4.5; the folks on the listcan help address any development questions you might have.

Back to the questions. First, you might be wondering how just one template foreach node type can be enough to satisfy the wide variety of code generationtasks that you might be faced with. For example, in C++ the syntax for afunction prototype is different from the syntax for a function call--theparameter data types are not provided in the second case. In this case, anMOperationDef node in the CCM metamodel graph needs to have two types oftemplate information about its child MParameterDef nodes.

Luckily, the CCM Tools include a solution for this problem, as mentioned in thelist of four different key types. You can simply define two templates forMParameterDef nodes, each with a different name, and each containing a differenttemplate. For example, templates called MParameterDefName and MParameterDefAllmight contain the template information shown inExample 4.3.9. The MOperationDeftemplate(s) can include either or both of these keys, and the appropriateinformation will be substituted into the template. In brief, when a codegenerator receives a node start event from the graph traverser, the codegenerator will load all the templates in the template set that start withthe node type. This makes the generators potentially a bit slower, but it allowsfor unlimited numbers of templates for a given node type. For a rather complexexample of this, take a look at all the MUsesDef templates in the local C++template set.


Based
and, as before, this value will in turn be added to the parent node'sinformation. So, in this example, this string will get added to theMOperationDef variable of the MyInterface node. When the traverser then exitsthe MyInterface node, the code generator again loads a template, this time fromJavaTemplates/MInterfaceDef. The template and resulting code after keysubstitution are shown in Example 4.3.7 andExample 4.3.8, respectively.



This recursive substitution process is what enables short, top down styletemplates that can handle a variety of input trees.


A couple more things about templates

You might have encountered a few questions while reading through this businessabout template substitution. Answers to two of these questions are mentionedhere, but now is a good time to mention other sources of support as well: If youdecide to hack on the CCM Tools, it is probably a good idea to subscribe to theccmtools-devel mailing list4.5; the folks on the listcan help address any development questions you might have.

Back to the questions. First, you might be wondering how just one template foreach node type can be enough to satisfy the wide variety of code generationtasks that you might be faced with. For example, in C++ the syntax for afunction prototype is different from the syntax for a function call--theparameter data types are not provided in the second case. In this case, anMOperationDef node in the CCM metamodel graph needs to have two types oftemplate information about its child MParameterDef nodes.

Luckily, the CCM Tools include a solution for this problem, as mentioned in thelist of four different key types. You can simply define two templates forMParameterDef nodes, each with a different name, and each containing a differenttemplate. For example, templates called MParameterDefName and MParameterDefAllmight contain the template information shown inExample 4.3.9. The MOperationDeftemplate(s) can include either or both of these keys, and the appropriateinformation will be substituted into the template. In brief, when a codegenerator receives a node start event from the graph traverser, the codegenerator will load all the templates in the template set that start withthe node type. This makes the generators potentially a bit slower, but it allowsfor unlimited numbers of templates for a given node type. For a rather complexexample of this, take a look at all the MUsesDef templates in the local C++template set.


A second question you might be asking, specifically about the example code shownearlier, is what to do with that extra comma after the final operationparameters. This hints at a larger problem, that of template post processing.The solution is addressed insection 4.3.5. But first, you shouldget your mind off templates for a bit, have a burrito, and read the followingsection to get your code generator up to speed.


Implementing basic generator functions

If you've tried compiling your new code generator class, you should have noticedthat it will not compile. The class has not implemented a few functions that aredefined as abstract in the parent class. To implement your generator, you mustat the very least provide implementations for these functions.

First you must write a getLanguageType function. This function providesthe generator with a mapping between IDL3 data types and the data types in thetarget language. Sometimes this can be a basic function that simply provides themapped value from the language map you created earlier.4.6 More often, however, the complex data types willrequire more special treatment.Example 4.3.10 shows the rather compleximplementation in the local C++ generator.


Next you need to provide your generator with a writeOutput functionimplementation. This function is called for each top level node type encounteredin the graph. This function will produce all generated code; no other functionis generally implemented so that it writes things to disk. The writeOutputfunction should accept a Template object and have a void return type. Thisfunction can be as simple or as complex as you wish; it is the generator'sprimary source of control over the generation process. The implementation in theC++ mirror test generator is shown inExample 4.3.11 as an illustration.

An important utility defined in the code generator base class is the writeFinalizedFile funciton. This function accepts three strings as input: therelative directory of the file to write, the name of the file to write, and thestring to write to the file. This function spares most of the energy required towrite a file using Java.


Last, you need to write a finalize function implementation. This functionis called when a set of graphs has been completely traversed. Design letters templates 1 6 download free. A set of graphswould come from processing a set of IDL3 source files together, with one run ofthe code generators. This function provides a code generator with an opportunityto generate files based on the entire set of input IDL3 sourcefiles.4.7

Normally this function is used to create a set of global (i.e., per-package)header files that include other files that might have been created during eachseparate graph traversal. In addition to having the set of input IDL3 filesavailable in this function, you can use the ``define' mechanism available inthe ccmtools-generate tool, and provide -D flags on the commandline.

Note that many code generators will not need to use the finalize function.For most generators, an empty implementation ({ return; }) will suffice.


Customizing the code generator class

Schwartz 1 6 – Template Based Graphics Code Generator Free

Now that you've finished implementing the basics in your code generator, we'llget back to the problem of too many commas in the output code.

Schwartz 1 6 – Template Based Graphics Code Generator Roblox

Take a look back at Example 4.3.8,and recall that the template set is complete, except for the cursed extra commashanging around at the end of the parameter list. This hints at a larger problem,that of post processing the template information. In this case, the codegenerator class itself must supervise the template substitution process,removing the last comma from a paremeter list before it gets passed to anoperation's template.

To implement this kind of post processing functionality, you will need toprovide a function definition for the getLocalValue function in your codegenerator class. This function is actually called whenever the code generatorreceives notice that the traverser has left a graph node. Let's back up alittle, even: when the graph traverser leaves a graph node, the generator loadsup all templates for the node, looks through the templates, and figures outwhich keys are defined. The generator then calls getLocalValue for eachkey, providing the key and the current value of the variable from thegenerator's internal variable hash table. The resulting value from this functionis then stored back in the hash table.4.8

By overriding this function, then, you can add a lot of powerful post processingcapabilities to your code generator. For now, though, since you just want to getyour generator working,Example 4.3.12 shows one possible waywe could implement this function, along with the helper function that removesthe troublesome trailing comma.


By now you are likely sick of reading and coding. Take a nap. And take heart;you have finished dealing with this tutorial and know all that there is to knowabout the code generator library! Implementing code generators is simply amatter of applying the principles given above to each corner case that crops upin your generator. Again, remember to post questions to the ccmtools-develmailing list.4.9

2003-11-09



broken image