• Ingen resultater fundet

General Translation

3.2 FlowCode Translator

3.2.1 General Translation

I translateFlowCodetoFlowin two stages first we define and then we translate.

The first stage defines the elements to the TranslateEnvironment and then the second stage completes the translation of the product.

The stages are important because FlowCode does not require the programmer to write the functions in a linear fashion. TheFlowCode translator uses a two passes.

3.2.1.1 TranslateEnvironment

The TranslateEnvironment is a vital part of the translation. It holds all in-formation about the current translation. When defining something on the en-vironment a new declaration is added to the enen-vironment which allows other declarations to use it. We therefore have two classes a FunctionDefinition and

34 Implementation

a TypeDefinitions which helps The TranslateEnvironment to keep track of the Types and Functions defined.

FunctionDefinition The function definition holds function declarations of the same name, as overloaded functions in FlowCode , i.e. function declara-tions with the same name but different source types. Because we use automatic mapping, collections of a type is equal to the type when com-paring source types.

The Function declarations are stored internally in a list, and to get the a specific declaration out again, the following method can be used.

getFunction(srcTypes[0..*] : Type, template : Template ) : Function

The method check thru all the functions in the definition and returns the first function that gives a match. The method can certainly be optimized, but it wasn’t important for the prototype.

TypeDefinition Works a lot like the FunctionDefinition, the major differ-ence is that we store type declarations instead of function declarations and that the method used to get the Type is:

getType(template : Type) : Type

which uses the build-in hasTemplate method of the Type, to find the correct type.

But before we can put the function and type declarations in the Definition Objects we need to define them in a way so we can reference them.

To do this a Factory pattern is used. The Factory pattern allows us to create some temporary object that can build the type and function declarations, which is useful as we then can translate the parse tree in stages. A class diagram over the Factories is given inFig. 3.4.

The definition step is simply to create an empty function or type and fill in the necessary informations so that it can be used in a flow. One Problem is that a function needs the types of the arguments to be defined. The define procedure is first to define the types, then the Structs, because they may need a type template, and then lastly we define the function.

This brings us to the next stage, the translation. The translation is done in the same order as the definition. The strict ordering is again needed, as the struct fields are used when we translate the Function.

3.2 FlowCodeTranslator 35

FlowCodeFactory

+ translateEnvironment : TranslateEnvironment + define() : void

FunctionFactory

+ translate : Function

StructFactory + ParseTreeStructDefinition + StructType

+ translate : StructType TypeFactory

+ ParseTreeTypeDefinition + Type

+ translate : Type

FlowFunctionFactory + ParseTreeFunctionFlowDefinition + FlowFunction

CodeFunctionFactory + ParseTreeFunctionCodeDefinition + CodeFunction

Figure 3.4: Class diagram over Factories

TypeFactory The translation of types is strait forward as they are already translated when defined, except if it is a renamingType, where we need to find its associated type.

StructFactory To translate the Struct we find the associated Types in the TranslateEnvironment, and then assign them in the structure under the field names.

CodeFunctionFactory In the CodeFunctionFactory, we just add the the C code to function.

FlowFunctionFactory This the the most complicated part of the translation, and it is explained in its own section. Seesection 3.2.1.2.

3.2.1.2 FlowFunctionFactory Translation

I will just introduce some terminology: The ParseTrees FlowFunctions are sub-divided into statements. A statement is a continuous stream of sections and a section can either be a pipe collection or a function.

36 Implementation

The first thing we do to translate the function is to add the argument pipes to a HashMap, called pipes, that associates the names of the pipe to the actual pipe. We later use this to connect the functions with the pipes.

Then we translate the statements one at a time in a function called handelStatement(statements : ParseTreeFlow)

We can not assume a special ordering of the statements, which means that the first statement could be the last in the ordering.

handelStatementdivides the Statement into sections and then calculate them one at at time. In the sections there are an implicit ordering, therefore can we make assumptions according to the last section. The algorithm for calculating a Statement is as seen inalgorithm 1

Algorithm 1handelStatement function←null

pipes←null

while|sections|>0do s←next(section)

if s∈F then .s is a Function section

if function6=null then .The last section was a function pipes←pipe[function.numberOfTargets]

function.targets←pipes

end if .pipes are now set if possible function←createFunction(s)

function.sources←pipes pipes←null

else if s∈P then .s is a Pipes section if pipes6=null then .The last section was a pipe

function←doNothingFunction function.sources ←pipe end if

pipes←getPipes(s) .If pipes do not exist in the HashMap, create if function6=null then . This section is not the first

function.targets←pipes end if

function←null end if

end while

The algorithm tries to create the data flow, while knowing the the former section.

3.2 FlowCodeTranslator 37

The type of the section is decided by whether the pipes and function is null or not. If both the pipes and the function is null then the section we are working on is the first in the statement. If the function is not null the function was the last read, and the same goes for the pipes.

Every time we handle a pipes section we need to either find them in HashMap or create them and put them there. If we do not do this we cannot find the pipes again, if look for them, when we handle the rest of the sections.

The FlowFunctionFactory translation is ended by running theFlowCodeFinalizer tool on the flow.