netxsimdg
Loading...
Searching...
No Matches
module_maker.py
1def denamespace(nname):
2 """Returns the last element of the name, without any of the qualifying
3 namespaces."""
4 return nname.split(":")[-1]
5
6def generator(module_class_name, fq_interface_name, fq_impl_names, help_names):
7 """Generates the text for a module support file."""
8 interface_name = denamespace(fq_interface_name)
9
10 # Add the include file for the module class
11 print(f"#include \"include/{module_class_name}.hpp\"")
12 print("")
13 # List the include files from the implementation names
14 for fq_impl_name in fq_impl_names:
15 print(f"#include \"include/{denamespace(fq_impl_name)}.hpp\"")
16
17 # Standard includes
18 print("")
19 print("#include <string>")
20
21 print("")
22 print("namespace Module {")
23
24 # String constants to name the implementations
25 for fq_impl_name in fq_impl_names:
26 print(f"const std::string {denamespace(fq_impl_name).upper()} = \"{fq_impl_name}\";")
27 print("")
28
29 # Create the functionMap from the FQ implementation and FQ module names
30 print("template <>")
31 print(f"Module<{fq_interface_name}>::map Module<{fq_interface_name}>::functionMap" + " = {")
32 for fq_impl_name in fq_impl_names:
33 print(f" {{ {denamespace(fq_impl_name).upper()}, newImpl<{fq_interface_name}, {fq_impl_name}> }},")
34 print("};")
35 print("")
36
37 # Set up the function and static pointer (FQ Module)
38 print("template <>")
39 print(f"Module<{fq_interface_name}>::fn Module<{fq_interface_name}>::spf = functionMap.at({denamespace(fq_impl_names[0]).upper()});")
40 print("template <>")
41 print(f"std::unique_ptr<{fq_interface_name}> Module<{fq_interface_name}>::staticInstance")
42 print(f"= std::move(newImpl<{fq_interface_name}, {fq_impl_names[0]}>());")
43 print("")
44
45 # Module name string
46 print("template <>")
47 print(f"std::string Module<{fq_interface_name}>::moduleName(){{ return \"{fq_interface_name}\"; }}")
48 print("")
49
50 # global functions (FQ module & module class names)
51
52 # Recursive help generation
53 # List of uppercased implementation names
54 impl_names_uc = []
55 for fq_impl_name in fq_impl_names:
56 impl_names_uc.append(denamespace(fq_impl_name).upper())
57
58 print(f"template<> HelpMap& getHelpRecursive<{fq_interface_name}>(HelpMap& map, bool getAll)")
59 print("{")
60 print(" const std::string& pfx = Nextsim::ConfiguredModule::MODULE_PREFIX;")
61 print(f" map[pfx].push_back({{ pfx + \".\" + Module<{fq_interface_name}>::moduleName(), ConfigType::MODULE,")
62 impl_namelist_uc = ", ".join(impl_names_uc)
63 print(f" {{ {impl_namelist_uc} }}, {impl_names_uc[0]}, \"\",")
64 print(" \"MODULE DESCRIPTION HERE\" });")
65 for help_name in help_names:
66 print(f" {help_name}::getHelpRecursive(map, getAll);")
67 print(" return map;")
68 print("}")
69
70 print("template <>")
71 print(f"{fq_interface_name}& getImplementation<{fq_interface_name}>()")
72 print("{")
73 print(f" return getImplTemplate<{fq_interface_name}, {module_class_name}>();")
74 print("}")
75
76 print("template <>")
77 print(f"void setImplementation<{fq_interface_name}>(const std::string& implName)")
78 print("{")
79 print(f" setImplTemplate<{module_class_name}>(implName);")
80 print("}")
81
82 print("template <>")
83 print(f"std::unique_ptr<{fq_interface_name}> getInstance()")
84 print("{")
85 print(f" return getInstTemplate<{fq_interface_name}, {module_class_name}>();")
86 print("}")
87
88 print(f"{module_class_name}::Constructor {module_class_name}::ctor;")
89 print(f"{module_class_name}::Constructor::Constructor()")
90 print("{")
91 print(f" addToConfiguredModules<{fq_interface_name}, {module_class_name}>();")
92 print("}")
93 print("")
94 print("} /* namespace Module */")
95
96if __name__ == "__main__":
97
98 import argparse
99 parser = argparse.ArgumentParser(description = "Write out the text for a Nextsim module class source file.",
100 epilog = "Suffix the interface or any implementation name with an asterisk (*) to include a call to getHelpRecursive().")
101 parser.add_argument("impl", metavar = "impls", nargs = '*', default = None, help = "Fully qualified name of the implementation classes.")
102 parser.add_argument("--interface", dest = "interface", required = True, help = "Fully qualified name of the interface class.")
103 parser.add_argument("--module-prefix", dest = "modulepfx", help = "Name of the module, will be suffixed by 'Module'.")
104 args = parser.parse_args()
105
106 if (len(args.impl) == 0):
107 raise SystemExit
108
109 # filter all the interface and implementation names for trailing asterisks,
110 # signifying that getHelpRecursive should be called on these classes.
111 help_names = []
112 impl_names = []
113 interface_name = args.interface
114 if interface_name[-1] == "*":
115 interface_name = interface_name[:-1]
116 help_names.append(interface_name)
117 for impl_name in args.impl:
118 if impl_name[-1] == "*":
119 impl_names.append(impl_name[:-1])
120 help_names.append(impl_names[-1])
121 else:
122 impl_names.append(impl_name)
123
124 # Generate a module prefix if none is set
125 if args.modulepfx is None:
126 iface = denamespace(interface_name)
127 if (iface[0] == "I") and iface[1].isupper():
128 modulepfx = iface[1:]
129 else:
130 modulepfx = denamespace(interface_name)
131 modulepfx += "Module"
132 else:
133 modulepfx = denamespace(args.modulepfx)
134
135
136 generator(modulepfx, interface_name, impl_names, help_names)