Role of data structure in compiler design Mithiun kumar gupta
[email protected]
Reg. no. – 11102557 Roll. No. – RD1107A13
ABSTRACT:-
strategy used by a compiler helps the
Most programmers write software in a high-level language, such as Pascal, C,
engineer
understand
the
high-level
language at a deeper level.
C++, java, Cobol and others. Many are not aware of the fact that they are really making
INTRODUCTION
use of a sophisticated program called a
DESIGN
OF
COMPILER
compiler that bridges the gap between their computer
A compiler is a computer program
architecture. Some have no concept at all,
(or set of programs) that transforms source
or a very poor grasp of the computer's
code written in a programming language
instruction set, memory organization, and
(the
other details that make their software work.
computer language (the target language,
A compiler therefore provides a valuable
often having a binary form known as object
form
Most
code). The most common reason for
programmers don't need to know anything
wanting to transform source code is to
about the details
create an executable program.
chosen
language
of
and
information of
a
hiding. translation
and
execution, only the properties claimed to be supported by the high-level language and its libraries.
Compilers design are a
valuable and reliable tool for the most part, but no software is perfect. If a bug arises in code, it's sometimes useful to be able to trace it down into the assembler/micro instruction level. High performance may require
certain
low-level
operations.
Finally, knowing something about the
source
language)
into
another
The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a lower level language (e.g., assembly language or machine code). If the compiled program can run on a computer whose CPU or operating system is
different from the
one on which the compiler runs, the compiler is known as across-compiler. A program that translates from a low level
language to a higher level one is called a
collector, or retarget the compiler to an
decompiles. A program that translates
abstract
machine.
between high-level languages is usually called a language translator, source to source translator, or language converter. A language rewriter is usually a program that translates the form of expressions without a change of language. A compiler is likely to perform many or all of the following operations: lexical analysis, pre-processing, parsing, semantic
analysis
(Syntax-directed
translation), code generating, and code optimization. Program faults caused by incorrect compiler behaviour can be very difficult to track down and work around; therefore, compiler implementers invest a lot of time
REQUIREMENT
OF
COMPILER DESIGN There are many requirement related
ensuring the correctness of their software.
to compiler as follow:Compiler design is focusing on more low-level and systems aspects rather than
high-level
questions
such
as
polymorphic type inference or separate compilation. You will be building several complete
end-to-end
compilers
for
successively more complex languages, culminating
in
a
mildly
optimizing
compiler for a safe variant of the C programming language to x86-64 assembly language. For the last project you will have the
opportunity
to
optimize
more
aggressively, to implement a garbage
CORRECTNESS:-
Correctness
is
absolutely
paramount. A buggy compiler is next to useless in practice. Since we cannot formally prove the correctness of your compilers, we use extensive testing. This testing
is
end-to-end,
verifying
the
correctness of the generated code on sample inputs. We also verify that your compiler rejects programs as expected when the input
is
not
well-formed
(lexically,
syntactically, or with respect to the static
semantics), and that the generated code raises an exception as expected if the
INTEROPERABI LITY: -
language specification prescribes this. We
Programs do not run in isolation,
go so far as to test that your generated code
but are linked with library code before they
fails to terminate (with a time-out) when
are executed, or will be called as a library
the
diverge.
from other code. This puts some additional
Emphasis on correctness means that we
requirements on the compiler, which must
very carefully define the semantics of the
respect certain interface specifications. This
source language. The semantics of the
means that you will have to respect calling
target language is given by the GNU
conventions early on (for example, properly
assembler on the lab machines together
save caller-save registers) and data layout
with the semantics of the actually machine.
conventions later, when code will be calling
Unlike C, we try to make sure that as little
library functions.
source
program
should
as possible about the source language remains undefined.
Usability:A compiler interacts with the
EFFICIENCY: -
programmer primarily when there are errors
In a production compiler, efficiency
in the program. As such, it should give
of the generated code and also efficiency of
helpful error messages. Also, compilers
the
important
may be instructed to generate debug
considerations. In this course, we set very
information together with executable code
lax
in order help users debug runtime errors in
compiler targets
itself for
are
both,
emphasizing
correctness instead. In one of the later labs
their program.
in the course, you will have the opportunity
In this course, we will not formally
to optimize the generated code. The early
evaluate the quality or detail of your error
emphasis on correctness has consequences
messages, although you should strive to
for your approach to the design of the
achieve at least a minimum standard so that
implementation. Modularity and simplicity
you can use your own compiler effectively.
of the code are important for two reasons: first, your code is much more likely to be
Retarget ability:-
correct, and, second, you will be able to
At the outset, we think of a
respond to changes in the source language
compiler of going from one source
specification from lab to lab much more
language to one target language. In
easily.
practice, compilers may be required to
generate more than one target from a given
performed by collecting type information.
source (for example, x86-64 and ARM
The frontend then generates an intermediate
code), sometimes at very different levels of
representation or IR of the source code for
abstraction (for example, x86-64 assembly
processing by the middle-end.
or LLVM intermediate code). The middle end: THE STRUCTURE OF COMPILER DESIGN
It is indicate where optimization takes place. Typical transformations for
Compilers bridge source programs in high-level languages with the underlying hardware. A compiler requires;-
optimization are removal of useless or unreachable
code,
discovery
and
propagation of constant values, relocation of computation to a less frequently
1) determining the correctness of the
executed place (e.g., out of a loop), or specialization of computation based on the
syntax of programs,
context. The middle-end generates another 2) generating correct and efficient object code,
IR for the following backend. Most optimization efforts are focused on this part.
3) run-time organization, and 4) formatting output according to assembler and/or linker conventions.
The back end:-
is responsible for
translating the IR from the middle-end into assembly code. The target instruction(s) are
A compiler consists of three main
chosen for each IR instruction. Register
parts: the frontend, the middle-end, and the
allocation assigns processor registers for
backend.
the program variables where possible. The backend utilizes the hardware by figuring
The front end: -
out how to keep parallel execution units
It checks whether the program is correctly
written
programming
in
language
terms
of
syntax
the and
semantics. Here legal and illegal programs are recognized. Errors are reported, if any, in a useful way. Type checking is also
busy, filling delay slots, and so on. Although most algorithms for optimization are in NP, heuristic techniques are welldeveloped.
than one way, in the compile-time world, we have only recursion to do everything including looping; therefore, we are going to use recursion in the run-time version to compile Time Linked List If we are going to make a single linked list, then our structureof linked list would be something like this: /////////////////////////////////////////////////////////// // Node of Runtime Link List ///////////////////////////////////////////////////////////
Figure of structure of compiler design
struct ListNode
We have seen different applications of template meta-programming such as
{ int value;ListNode* next; };
static data structures, algorithms, design
Here is the compile time version of this
patterns, Reflection, expression templates,
structure:
and number theory. Compile Time Data
/////////////////////////////////////////////////////////// //
Structure is, in fact, not a new concept in
Termination of Link List
C++. Further information about it can be
///////////////////////////////////////////////////////////
found in the References. Here, we are going
struct End
to study the Linked List as an example of a
{
compile time data structure, and will try to implement
it
with
template
meta-
programming. Template
meta-programming
is
};
/////////////////////////////////////////////////////////// // Node of Static Link List /////////////////////////////////////////////////////////// template
usually difficult to understand at first,
struct Node
especially for those who are not familiar
{
with it. Therefore, we will discuss the run-
enum { value = iData }; typedef Type Next;};
time counterpart at the same time. We use a
Here, we need one more structure to
naming convention “List” for all the
indicate the termination condition of the
runtime programs to distinguish it with the
linked list. You can also call it is an end
compile-time version. Although we can
marker. In the runtime version, we don’t
implement the run-time programs in more
need it because in that case, we simply
if(*pHead==NULL)
check the value of the next filed in the
{
node. If its value is NULL, then it means
*pHead = new ListNode();
that it is the last node of the linked list
(*pHead)->value = value; }
However, in the case of template meta-programming, we have to do template specialization
(or
partial
Else {
template
ListPushBack(&(*pHead)->next, value); }
specialization) to stop the recursion. We can do template specialization for any specific type or for any specific value. Here, we can’t do template specialization on a value, because the second template parameter is a type. Therefore, we have to create a new type to stop the recursive instantiation of the template. The name of the end marker can be anything, and it can store whatever you like it to. In our example, it would be sufficient to make an empty structure to create a new type as an end marker. Now, let’s try to implement a few auxiliary functions that work on lists. Here
}
The name of the linked list is prefixed with “List” to distinguish it from the compile time version. Interestingly,
the
compile time
version of the same function doesn’t use recursion, and its implementation is very easy /////////////////////////////////////////////////////////// // Insert item into Static Link List /////////////////////////////////////////////////////////// template struct PushBack { typedef Node staticList; };
is our first function to insert data in the
And, here is the usage of this function at
linked list. We explicitly made its name
compile time:
look similar to the member function of the
typedef PushBack<2, End>::staticList node1;
STL list class, because we are going to
typedef PushBack<4, node1>::staticList node2;
implement a few more STL algorithms. Here is the simplest implementation for inserting items in the runtime single
typedef PushBack<6, node2>::staticList node3; typedef PushBack<8, node3>::staticList node4; typedef PushBack<10, node4>::staticList node5; typedef PushBack<12, node5>::staticList myList;
linked list. ///////////////////////////////////////////////////////////
Although we can create a static linked list
// Insert item into Runtime Link List
like this:
/////////////////////////////////////////////////////////// void ListPushBack(ListNode** pHead, int value) {
typedef Node<-15, Node<15, Node<18, Node<13, End> > > >myList;
the above method to create a static linked list has a few advantages, which we
}; template <>
will see when we implement a few STL
struct Size
algorithms in the compile-time version.
{enum { value = 0 };
Now, let’s implement a few more STL list algorithms at compile time. But, first take a look at its runtime version to better
understand
template
meta-
programming. /////////////////////////////////////////////////////////// // Structure to calculate the length of Runtime Link List ///////////////////////////////////////////////////////////
};
Although the STL list class doesn’t have an at() function, because list doesn’t have a random access iterator, we are trying to implement this function for the linked list. Because we can’t access any item of the linked list randomly, it is a linear time function, not a constant time one just like the at() function of the vector. Here
int ListSize(ListNode* pHead)
is
the
simple
run-time
implementation of the at() function on a
{ if (pHead == NULL) return 0; else return 1 + ListSize(pHead->next); }
single linked list with linear complexity: /////////////////////////////////////////////////////////// // Structure to find item from specific location from RuntimeLink List
This function is quite simple, and uses tail recursion for optimization. The
/////////////////////////////////////////////////////////// int ListAt(ListNode* pHead, int iPos) {
compiler can optimize tail recursion with
static int iIndex = 0;
looping to avoid any runtime stack
++iIndex; if (iIndex == iPos)
overhead. Here is the compile-time version of the same function:
return pHead->value; else if (pHead->next == NULL)
/////////////////////////////////////////////////////////// // Structure to calculate the length of Static Link List
return -1; else return ListAt(pHead->next, iPos); }
/////////////////////////////////////////////////////////// template struct Size; template
The code presented here is just a proof of concept, not a production quality
struct Size >
code. One major problem with this function
{
is the return code. If the input position is enum { value = 1 + Size::value };
greater than the length of the linked list,
int val;
like the length of the linked list is 4, but we
if (ListAt(pHead, 3, ∓val))
are trying to access 6th element, then this
{std::cout << val << std::endl;}
function returns-1. This code is misleading,
}
because -1 can be a data in the linked list at
Here is the compile time version of the
a given position, so it would be impossible
same function:
to differentiate whether it is an error code
///////////////////////////////////////////////////////////
or the actual data at the given position.
// Structure to find item from specific
This
one
is
a
much
better
location from Static Link List
implementation than the previous one:
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
template struct At;
// Structure to find item from specific location from Runtime Link List
template struct At, iStart> { enum { value = iIndex == iStart ?iData : At
/////////////////////////////////////////////////////////// bool ListAt(ListNode* pHead, int iPos, int* iVal)
Type, (iStart + 1)>::value }; };
{
template struct
static int iIndex = 0; ++iIndex; if (iIndex == iPos)
At, iStart> { enum { value = iIndex == iStart ? iData : -1 };
{ *iVal = pHead->value;return true;
};
}
This program has the same problem
else if (pHead->next == NULL) {return false; } Else
that it returns -1 when the item is not found. In template meta-programming, we can’t
{ return ListAt(pHead->next, iPos, iVal); }
return a value by parameter just like its runtime
}
equivalent.
The
solution
is
to
introduce one more enum variable inside This function returns the value at a specific location by parameter. If the user passes a position that is greater than the
the structure to store whether the item was found or not. Here is the next version of the same
length of the linked list, then it will return
program:
false; otherwise, it stores the value at the
///////////////////////////////////////////////////////////
parameter and returns true.
// Structure to find item from specific
Here is the usage of this function:
location from Static Link List
if (pHead != NULL)
///////////////////////////////////////////////////////////
{
template struct At;
template struct At, iStart> { enum { value = iIndex == iStart ?iData : At::value }; enum { found = iIndex == iStart ? 1 :At::found };
The Find algorithm returns the first occurrence of the specified value in the given range. If it couldn’t find the specified value, then it returns the end iterator, i.e., one past the last element given a range. Here is a simple usage of the Find
}; template struct At, iStart> {
algorithm onan STL list: std::listlst; lst.push_back(7);
enum { value = iIndex == iStart ? iData : -1 }; enum { found = iIndex == iStart ? 1 : 0 }; };
lst.push_back(14); lst.push_back(21); lst.push_back(28); lst.push_back(35);
Although the value variable still stores -1 when an item not found in the
std::list::iterator
iter_
=
std::find(lst.begin(),
lst.end(), 7); if (iter_ != lst.end())
linked list, if we use the other variable, i.e.,
std::cout << *iter_ << std::endl;
the “found” variable, then we can ignore
else std::cout << "Not found" << std::endl;
this value. Here is the usage of this algorithm :
Here is the closest implementation
if (At<8, myList>::found == 1)
of the Find algorithm in template meta-
{ std::cout << At<8, myList>::value << std::endl; }
4. Compile Time Algorithms
programming: /////////////////////////////////////////////////////////// // Structure to find the location of specific item in Static Link List
In this section, we are going to
///////////////////////////////////////////////////////////
study different STL algorithms and their working with the STL list class, and how to
template
TBegin,typename
TEnd,int
iFindData,int iStart = 0>struct Find;
implement those at compile time using
template
template meta-programming. From now,
iFindData,int iStart>
instead of using creating our own single linked list and implementing all the related
struct Find, TEnd, iFindData, iStart> { enum { value = iFindData == iData ? iStart
functions ourselves, we are going to use the STL list class. 4.1. Find Algorithm
:Find::value }; };
TEnd,
iFindData,
(iStart
+
template struct Find, TEnd, iFindData, iStart>
4.2. Count Algorithm This algorithm returns the numbers
{ enum { value = iFindData == iData ? iStart : -1 };
of items in a given range that has the given
}; template
TEnd,
int
iFindData>struct
value. Here is a sample to demonstrate
Find {
this: enum { value = -1 };
std::list
};
lst;lst.push_back(7); lst.push_back(14);
This implementation returns the
lst.push_back(7); lst.push_back(14);
position of the specified value, if found in
lst.push_back(21);
the given range of a single linked list;
lst.push_back(7);
otherwise, it returns -1.
std::cout << std::count(lst.begin(), lst.end(), 7)
Here is the usage of the above implementation:
<< std::endl;
The output of this program is 3, because 7 exists three times inthe given
typedef PushBack<7, End>::staticList node1; typedef PushBack<14, node1>::staticList node2;
range.
typedef PushBack<21, node2>::staticList node3;
implemented atcompile time:
typedef PushBack<28, node3>::staticList node4; typedef PushBack<35, node4>::staticList myList;std::cout
Here
is
a
similar
algorithm
/////////////////////////////////////////////////////////// // Count Algorithm. Returns the number of
<< Find::value << std::endl;
We can even pass the range, just like in the STL algorithms, to find elements
elements in StaticLink List ///////////////////////////////////////////////////////////
in between a given range. std::cout << Find::value << std::endl;
template
This is one of the reasons to use the static
version
of
the
Push
Back
implementation rather than create a whole static linked list in one statement. By using
int iVal>struct Count; template struct Count, TEnd, iVal> {
the compile time version of the Push Back
enum { value = (iData == iVal ? 1 : 0) +
implementation, we are able to get the
Count::value };
iterator equivalent in the compile time world.
}; template struct Count, TEnd, iVal> {
enum { value = iData == iVal ? 1 : 0 };
in the given predicate. The predicate can be
}; template struct Count
a simple function or a function object, i.e., a
TEnd, iVal>
class with an overloaded () operator, that
{
returns true. In that function (or function enum { value = 0 };
object), we can check any condition we
};
This implementation is very similar
want. Let’s take a look at the run-time
to the “Find” algorithm, and its usage is
version to better understand it before going
also similar to that. Here is the closest
to the compile time version. std::listlst;
implementation of the compile-time version
lst.push_back(7);
of the same code we saw in this section
lst.push_back(14);
using the STL “count” algorithm.
lst.push_back(7); lst.push_back(14);
typedef PushBack<7, End>::staticList node1; typedef
PushBack<14,
lst.push_back(21);
node1>::staticList
lst.push_back(7);
node2;
std::list::iterator
typedef PushBack<7, node2>::staticList node3; typedef
PushBack<14,
node3>::staticList
iter_
=std::find_if(lst.begin(), lst.end(), MyPredicate()); if (iter_ != lst.end())
node4; typedef
PushBack<21,
std::cout << *iter_ << std::endl;
node4>::staticList
else
node5;
std::cout << "Not found" << std::endl;
typedef PushBack<7, node5>::staticList myList; std::cout << Count::value << std::endl;
Here, we pass MyPridicate as a function Just like the “Find” algorithm, we
object,
here
is
the
implementation of it:
can also count the number of specified
struct MyPredicate
items in a given range rather than searching
{
in the complete static linked list.
and
bool operator()(int val) { return val > 10 && val < 20 ? true : false;
4.3. Find If Algorithm If we want to find whether a linked list contains an item that is greater than 10 but less than 20, then we couldn’t do it with the Find algorithm. Here is the solution to this problem, the Find If algorithm. This algorithm returns the iterator of the element in the linked list that satisfies the condition
} };
Implementing the compile time version of The Find If algorithm is not very difficult, and its looks very similar to the Find algorithm, except one addition to the predicate type parameter. Here is the compile algorithm:
time
version
of
theFind
If
///////////////////////////////////////////////////////////
template class Predicate>struct
// Find If Algorithm.
FindIf
// Locate the specific items in Static Link
{enum { value = -1 }; };
List that satisfy thepredicate ///////////////////////////////////////////////////////////
Here we use template-template parameter to make it easy tocall and similar to STL algorithm. Here is the usage of this
template
algorithm.
typename TEnd,
typedef PushBack<7, End>::staticList node1;
template class Predicate,
typedef PushBack<14, node1>::staticList node2;
int iStart = 0>
typedef PushBack<7, node2>::staticList node3; typedef PushBack<14, node3>::staticList node4;
struct FindIf;
typedef PushBack<21, node4>::staticList node5; typedef PushBack<7, node5>::staticList myList;std::cout
template
<< FindIf::value <
In compile time world, the predicate
typename TEnd, template class Predicate,
is a structure (or class), not a function or
int iStart>
function object. Here is our compile time
struct FindIf, TEnd,
version of the same predicate we used
Predicate, iStart>
earlier in this section for the run time
{
version: enum { value = Predicate::value
== 1 ? iStart :FindIf
template struct MyPredicate { enum { value = val > 10 && val < 20 ? 1 : 0 }; };
Predicate, (iStart+1)>::value };
4.4. Count If Algorithm
};
The “Count if” algorithm is a template
cousin of the “Find If”; the only difference
template
is, it will return the number of elements in
class
Predicate,int
FindIf
iStart>struct
TEnd>,
TEnd,
Predicate, iStart>
the linked list that satisfies the condition given in the predicate. Let’s take a look at the run time version of this algorithm first. std::listlst;
{
lst.push_back(7);
enum { value = Predicate::value == 1 ? iStart : -1 }; }; template
lst.push_back(14); lst.push_back(7); lst.push_back(14); lst.push_back(21);
lst.push_back(7); std::cout
<<
}; std::count_if(lst.begin(),
lst.end(),
MyPredicate())<< std::endl;
template class Prediate>struct CountIf {enum { value = 0 };
And, we use the same predicate that we
};
made earlier:
This implementation is very similar
struct MyPredicate{bool operator()(int val)
to the “Find If” algorithm. The only
{
difference is, here, we are actually count return val > 10 && val < 20 ? true : false;
the number of elements that satisfy the
}
condition given in the predicate rather than
};
find it. Here is the usage of this algorithm: typedef PushBack<7, End>::staticList node1;
The output of this program is 2, because there are two elements in the list
typedef
PushBack<14,
node1>::staticList
node2;
which are greater than 10 and less than 20.
typedef PushBack<7, node2>::staticList node3;
Now, let’s take a look at the compile time
typedef
PushBack<14,
node3>::staticList
typedef
PushBack<21,
node4>::staticList
typedef
PushBack<7,
node5>::staticList
node4;
version of the same algorithm. /////////////////////////////////////////////////////////// // Count If Algorithm. // Returns the number of elements in Static Link List
node5; myList;std::cout
<<
CountIf
End,
MyPredicate>::value <
4.5. Min, Max Algorithm
// that satisfy the predicate condition
Although the STL version of the
///////////////////////////////////////////////////////////
min and max algorithms don’t work on a range, but for consistency, we implemented
template class Predicate>struct CountIf;
both algorithms in a similar way, i.e., you
template
can find the maximum or minimum value
TEnd,template
in a static linked list in a given range.
iData>
class
Predicate>struct
CountIf, TEnd, Predicate>
Here are the simple implementations of
{ enum
{
value
=
(Predicate::value)
+CountIf::value };
///////////////////////////////////////////////////////////
}; template class
Predicate>struct
CountIf
TEnd, Predicate> {
both the algorithms:
TEnd>,
// Structure to find the Maximum value in the Link List /////////////////////////////////////////////////////////// template struct Max;
enum { value = Predicate::value };
template struct Max, TEnd > { enum { value = iData > Max::value ? iData : Max::value };
iData,
typename
linked list, respectively. Just like the other algorithms, here, we can also specify the range to get the maximum or minimum
}; template
maximum and minimum values in the static
TEnd>struct
value in a given range, not in the complete
Max, TEnd>
static linked list.
{
4.6. For Each Algorithm enum { value = iData };
Till now, all the algorithms we
};
///////////////////////////////////////////////////////////
discussed were just getting information from the linked list. None of the above
// Structure to find the Minimum value in
algorithms changed any values in the linked
the Link List
list. This is because once you have some
///////////////////////////////////////////////////////////
value, then it is very difficult, if not
template struct Min;
impossible, to change the value we
template
assigned at compile time. Now, we are
TEnd>struct Min, TEnd> {
going to discuss an algorithm that performs
enum { value = iData < Min::value ?
some operation on the values of the linked
iData : Min::value };
list,
}; template
iData,
typename
TEnd>struct
but
here,
we
explicitly
restrict
ourselves to not change any value in the
Min, TEnd>
linked list. Let’s take a look at this simple
{
example of the “For Each” algorithm to
enum { value = iData }; };
And, here is a simple usage of these algorithms:
print the elements of the linked list: std::for_each(lst.begin(), lst.end(),PrintFunctionObject()); Here, “PrintFunctionObject” is our function object to do the actual work. Here is a simple implementation of this predicate:
std::cout << Max::value <<
struct PrintFunctionObject {
std::endl; std::cout << Min::value <<
void operator()(int val) {std::cout << val << std::endl;}
std::endl;
};
If we use the same static linked list that we created in the previous section, then we will get 21 and 7 as the output as the
Remember, it can also be a simple function instead of a function object. Here is the compile time equivalent version of the same algorithm:
///////////////////////////////////////////////////////////
and compile-time programming. All of the
// For each algorithm. Apply some action
programs
on all items of the list
completely resolved by the compiler at the
///////////////////////////////////////////////////////////
time of compiling and the actual result
template
stored in the executable. However, in this
class Function>struct ForEach; template
we
discussed
earlier
were
case, although we are doing compile time
TEnd,template class Function>struct
computation
ForEach, TEnd, Function>
Recursion, the actual function call will still
{ void operator ()()
during
compilation
using
execute when you run this program. This is the only way to perform some IO
{ Function()(iData); ForEach()(); }
operations while doing template metaprogramming, i.e., using functions that will
};
execute at runtime. Here, we are not only
template
limited to performing IO operations but can
T> class Function>struct ForEach, TEnd, Function>
do a few more interesting things, like create
{
a class using the new operator or a set of
void operator ()(){Function()(iData);
class hierarchies, as described in “Modern
}
C++ Design”[1]. Here is the function object
}; template class
for this compile time implementation of the
Function>struct ForEach
“For Each” algorithm.
{void operator ()(){} };
template
T>struct
PrintFunctonObject {
If you have taken a close look at this implementation, then you may have
void operator ()(int iData) {std::cout << iData << std::endl;} };
already noticed that this implementation is quite different from all of those we
The usage of this algorithm is also
discussed earlier. In this implementation,
slightly different. Here, we actually want to
there isn’t any “enum” variable; on the
execute some code at run-time; therefore,
contrary, here we have the overload ()
we have to create an object of the
operator. This is because when we have to
“ForEach” structure. Here is one possible
perform some action, we have to call some
way to execute this algorithm using an
function to do the actual work. This
anonymous object:
program is actually a mixture of run-time
ACKNOWLEGEMENT Firstly I want to say to thanks of my
subject
teacher
and education
(2) http://www.capsl.udel.edu/conferen
ces/open64/2008/Papers/111.pdf
management, because they think able me of this topic of term paper and give the golden opportunity to prepare of term paper. M y term
paper
topic
is
“Role
(3) http://en.wikipedia.org/wiki/Compil
er
of
D a t a Structure in Compiler Design”. This topic is related to my subject Data
(4) Modern C++ Programming.
Design
Generic
Structure; this topic help know how can compile the software’s. This topic is clear my more concept. I wish to express to my gratitude to all the people involved in the writing of this project, specially “Sandeep Sharma” sir who was very generous in sharing their time and knowledge with me. I thank to “LPU” Wi-Fi; they are give fully support. REFERENCES: (1) http://www.engr.sjsu.edu/wbarrett/P
arser/CompDesign.pdf
(5) C++ Template Metaprogramming:
Concepts. (6) Reflection support by means of
template Guiseppe Cisternino
Meta-programming, Attardi, Antonio
(7) Static Data Structure: Reconciling
Template Meta-programming and Generic Programming. (8) Loops, Metaloops & C++, Roshan
Naik.6. Expression Templates, Veldhuizen, C++ Report 1995,Generative Programming – Methods, Tools and Applications7. Template Meta Programm