root/tools/typemapgenerator/mpigenerator.rb @ 179:9984c20cf0f7

Revision 179:9984c20cf0f7, 5.0 KB (checked in by Andreas Schaefer <gentryx@…>, 13 months ago)

fixed some bitrot in the typemap generator

Line 
1# Copyright (C) 2006,2007 Andreas Schaefer <gentryx@gmx.de>
2#
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful, but
9# WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11# General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16# 02110-1301 USA.
17
18require 'pathname'
19
20
21# Here we generate the C++ code that will in turn create the typemaps
22# for MPI.
23class MPIGenerator 
24  def initialize(template_path="./", namespace=nil)
25    @path = Pathname.new(template_path)
26    if namespace
27      @namespace_guard = namespace.downcase + "_"
28      @namespace_begin = "namespace #{namespace} {\n"
29      @namespace_end = "};\n"
30    else
31      @namespace_guard = ""
32      @namespace_begin = ""
33      @namespace_end = ""
34    end
35  end
36
37  def simple_name(name)
38    name.gsub(/[ :<>]+/, '_')
39  end
40
41  # returns the code of a method suitable to create a typemap for the
42  # given klass.
43  def generate_single_map(klass, members, parents)
44    ret = File.read(@path + "template_generatesinglemap.cc");
45
46    ret.gsub!(/KLASS_NAME/, simple_name(klass))
47    ret.gsub!(/KLASS/, klass)
48    ret.gsub!(/NUM_MEMBERS/, members.size.to_s)
49
50    member_specs1 = members.map do |name, properties|
51      "        MemberSpec(MPI::Get_address(&obj->#{name}), #{properties[:type]}, #{properties[:cardinality]})"
52    end
53    member_specs2 = []
54    if parents
55      member_specs2 = parents.map do |name, mpiname|
56        "        MemberSpec(MPI::Get_address((#{name}*)obj), #{mpiname}, 1)"
57      end
58    end
59    member_specs = member_specs1 + member_specs2
60    ret.sub!(/ *MEMBERSPECS/, member_specs.join(",\n"))
61  end
62
63  # The Typemap Class needs a header file, declaring all the static
64  # variables, macros and so on. This method will generate it's code.
65  def generate_header(classes, datatype_map, headers, header_pattern=nil, header_replacement=nil)
66    ret = File.read(@path + "template_typemaps.h");
67    ret.gsub!(/HEADERS/, map_headers(headers, header_pattern, header_replacement))
68    ret.gsub!(/NAMESPACE_GUARD/, @namespace_guard)
69    ret.gsub!(/NAMESPACE_BEGIN\n/, @namespace_begin)
70    ret.gsub!(/NAMESPACE_END\n/, @namespace_end)
71
72    class_vars = classes.map do |klass|
73      klass_name = datatype_map[klass].sub(/MPI::/, "")
74      "    extern Datatype #{klass_name};"
75    end
76    ret.sub!(/.*CLASS_VARS/, class_vars.join("\n"))
77   
78    mapgens = classes.map do |klass|
79      "    static MPI::Datatype generateMap#{simple_name(klass)}();"
80    end
81    ret.sub!(/.*MAPGEN_DECLARATIONS/, mapgens.join("\n"))
82   
83    lookup_types = (Datatype.new.keys.sort + classes).uniq
84    lookups = lookup_types.map do |klass|
85      "    static inline MPI::Datatype lookup(#{klass}*) { return #{datatype_map[klass]}; }"
86    end
87    ret.sub!(/.*LOOKUP_DEFINITIONS/, lookups.join("\n"))
88
89    return ret
90  end
91
92  def map_headers(headers, header_pattern, header_replacement)
93    h = headers.map do |header|
94      header_name = header
95      if !header_replacement.nil?
96        header_name = header.gsub(header_pattern, header_replacement)
97      end
98      "#include <#{header_name}>"
99    end
100    return h.join("\n")
101  end
102
103  # The Typemap Class needs a source file, containing all the method
104  # bodys and variable definitions. This methods creates the code.
105  def generate_source(topological_class_sortation, datatype_map, resolved_classes, resolved_parents)
106    ret = File.read(@path + "template_typemaps.cpp");
107
108    class_vars = topological_class_sortation.map do |klass|
109      klass_name = datatype_map[klass].sub(/MPI::/, "")
110      "    Datatype #{klass_name};"
111    end
112    ret.sub!(/ *CLASS_VARS/, class_vars.join("\n"))
113    ret.sub!(/NAMESPACE_BEGIN\n/, @namespace_begin)
114    ret.sub!(/NAMESPACE_END\n/, @namespace_end)
115
116    methods = topological_class_sortation.map do |klass|
117      generate_single_map(klass, resolved_classes[klass], resolved_parents[klass])
118    end
119    ret.sub!(/METHOD_DEFINITIONS/, methods.join("\n"))
120
121    assignments = topological_class_sortation.map do |klass|
122      "    #{datatype_map[klass]} = generateMap#{simple_name(klass)}();"
123    end
124    ret.sub!(/.+ASSIGNMENTS/, assignments.join("\n"))
125
126    return ret;
127  end
128
129  # wraps the code generation for multiple typemaps.
130  def generate_forest(resolved_classes, resolved_parents, datatype_map, topological_class_sortation, headers, header_pattern=nil, header_replacement=nil)
131    return [generate_header(topological_class_sortation, datatype_map, headers, header_pattern, header_replacement), 
132            generate_source(topological_class_sortation, datatype_map, resolved_classes, resolved_parents)]
133  end
134end
Note: See TracBrowser for help on using the browser.