Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Templating in F95

261 views
Skip to first unread message

card

unread,
Oct 20, 2009, 8:59:53 PM10/20/09
to
Hi All,

I just want to make everyone aware of tool that I developed to allow
templating (and much more) in F95. It's really a framework that you
can build on, but as part of the project there is PyF95++ which is a
standalone code that block parses your templated code and outputs pure
F90/95 realizations of the templates (generic programming). You can
template any block of code (functions/subroutines/modules/types,
etc...) and anything you define to be a block. There is a Standard
Template Library (much like C++ STL) also under development and part
of the project. I'm currently working on the documentation and will
hopefully have it finished within the next few weeks. The project is
at SourceForge:

http://sourceforge.net/projects/blockit/

Just wanted to make Fortran users that they can do generic template
programming in Fortran using this. There is documentation in the TeX
also, but it's incomplete at the moment.

-David

Bil Kleb

unread,
Oct 20, 2009, 9:43:21 PM10/20/09
to
card wrote:
> Hi All,

Hi.

> I just want to make everyone aware of tool that I developed to allow

> templating (and much more) in F95. [...] The project is
> at SourceForge:
>
> http://sourceforge.net/projects/blockit/

Neat.

Can you compare/contrast with Forpedo?

http://www.macanics.net/forpedo/

Regards,
--
http://twitter.com/bil_kleb

card

unread,
Oct 20, 2009, 10:46:24 PM10/20/09
to

I was made aware of forpedo after I had developed this framework and I
haven't looked at forpedo in great detail. So I can't draw very
specific distinctions, but I can see that we took different
approaches. The concept behind the BlockIt framework is to parse the
code base into a block (think namespaces if you're familiar with that)
b-tree hierarchy. A block is anything that you want to define it to
be, but mostly they will be constructs within the particular language
your parsing (the framework is really language agnostic). Blocks
which encapsulate other blocks, i.e. have nested blocks within them,
absorb (inherit isn't really the correct word here) dependencies of
their children. So, creating a template is as simple as encapsulating
what is to be templated within a template block. So, to create a
templated module (which acts like a class in C++), you simple
encapsulate the module block inside a template block. Any
dependencies within the module are propagated to the parent template
block. There is a lot behind this that I'll cover in the
documentation and too much detail to spell out here. Based on this
framework, PyF95++ is built. For a taste, some of the things you can
do would be:

1) Nested templated types within other templated types. For example,
the STL in the project has a DLList type, which is simply a linked
list. To instantiate a linked list of integers would be:

type (DLList<integer>) :: myLinkedList

If you want a list of lists of integers, you simply would need:

type (DLList<DLList<integer>>) :: myListofLists

2) Multiple template parameters with default types. An example of
this is the HashTable in the STL. It takes 3 parameters. A key, an
element and a chain type for the links (its a chained hash table).
The specification is in the class_HashTable.F90T. The template spec
is this:

template <class Key=String, class Element, class
Chain=DLList<Element>>
module class_HashTable
.
.
.
end module classHashTable
end template

From the template spec you see that it takes 3 types, two of which
have default specifications; the Key and the Chain. So, if I want to
instantiate a hashtable with a String type as the key (this is project
too) and stores integers for the Elements and uses the DLList for the
chaining the I would have:

type (HashTable<*, integer, *>) :: table

The * signify use of the default parameters. If I want to use another
type for the Key, then:

type (HashTable<myType, integer, *>) :: table

Say I want to create a HashTable that stores linked lists of some
other type as the elements then:

type (HashTable<myType, DLList<myOtherType>, *> :: table

3) The STL containers are referenced counted types so they can be
stored within other containers without worry about deallocation. I
won't go into alot of detail here at the moment. Essentially, lets
say you create a list of lists. So you have something like:

type (DLList<integer>) :: list1, list2
type (DLList<DLList<integer>>) :: list3

err = init(list1)
err = init(list2)
err = init(list3)

err = push(list1, 2)
err = push(list1, 3)

err = push(list2, 1)

err = push(list3, list1)
err = push(list3, list2)

err = delete(list1)
err = delete(list2)

Don't worry about the syntax above, its part of the STL, but you can
get the gist. I created three lists: list1, list2, list3. I then
pushed some stuff into them and in particular pushed list1 and list2
into list3 which is a list of lists of integers. I then deleted list1
and list2, but list3 still has list1 and list2 internally since they
are reference counted (like Python). So, when list1 and list2 were
deleted, only the ref counts were decremented since a ref still
existed for each of them in list3. You get the idea.

4) Added little extensions to some F95 constructs like function
declarations and subroutines within modules. There is an "as" clause
so that they can be named within a generic interface in a module.
This is important for templated blocks, since blocks within them will
be name mangled, but you want to have a common interface. For
example:

template <class Object>
module foo
....
....
autointerface
end autointerface

contains

function init(bar) result(blah) as init
.
.
end function init

end module foo
end template

Instantiating an integer version and a real version of the template
would create two init() functions which are name mangled:
init_integer, init_real. But the 'as' clause with the 'autointerface'
block will create a generic interface for those functions called
init. So, you don't need to worry about that in your code. You
simply do:

type (foo<integer>) :: a
type (foo<real>) :: b

x = init(a)
y = init(b)

without the need to worry about the name mangling.

I could go on and on, but I hope this gives a taste of some of the
stuff in the project. I'll try to finish the documentation within the
next few weeks. Also, it's very easy to define your own custom blocks
by simple inheriting from the F90Block class. It's very flexible.

-David

0 new messages