mirror of https://github.com/ecmwf/eccodes.git
upadte
This commit is contained in:
parent
ec5758e548
commit
5f79174d71
349
src/convert.py
349
src/convert.py
|
@ -41,6 +41,47 @@ class Member:
|
|||
self.type += "*"
|
||||
|
||||
|
||||
class Arg:
|
||||
def __init__(self, name, type) -> None:
|
||||
self.name = name
|
||||
self.type = type
|
||||
|
||||
if self.name[0] == "*":
|
||||
self.name = self.name[1:]
|
||||
self.type += "*"
|
||||
|
||||
|
||||
class Function:
|
||||
def __init__(self, name, result, args, template=None) -> None:
|
||||
self._name = name
|
||||
self._result = result
|
||||
self._template = template
|
||||
self._args = []
|
||||
self._lines = []
|
||||
|
||||
for arg in [a.strip() for a in args.split(",")]:
|
||||
bits = arg.split()
|
||||
type = " ".join(bits[:-1])
|
||||
name = bits[-1]
|
||||
self._args.append(Arg(name, type))
|
||||
|
||||
def add_line(self, line):
|
||||
self._lines.append(line)
|
||||
|
||||
@property
|
||||
def args_declaration(self):
|
||||
return ", ".join([f"{a.type} {a.name}" for a in self._args])
|
||||
|
||||
@property
|
||||
def call_args(self):
|
||||
return ", ".join([a.name for a in self._args])
|
||||
|
||||
@property
|
||||
def body(self):
|
||||
return ""
|
||||
return "\n".join(self._lines)
|
||||
|
||||
|
||||
class Method:
|
||||
def __init__(self, name, result, args, template=None) -> None:
|
||||
self.name = name
|
||||
|
@ -72,7 +113,6 @@ class Method:
|
|||
return True
|
||||
|
||||
|
||||
|
||||
class SimpleMethod(Method):
|
||||
def tidy_lines(self, klass):
|
||||
this = [r"\bself\b"]
|
||||
|
@ -111,7 +151,7 @@ class CompareMethod(Method):
|
|||
class DumpMethod(Method):
|
||||
def tidy_lines(self, klass):
|
||||
# For now, just remove the method
|
||||
self.lines = ['#if 0'] + self.lines[1:-1] + ['#endif']
|
||||
self.lines = ["#if 0"] + self.lines[1:-1] + ["#endif"]
|
||||
|
||||
|
||||
class StaticProc(Method):
|
||||
|
@ -147,70 +187,157 @@ class Class:
|
|||
*,
|
||||
path,
|
||||
class_,
|
||||
inherited_procs,
|
||||
other_procs,
|
||||
top_level,
|
||||
functions,
|
||||
top_level_code,
|
||||
includes,
|
||||
factory_name,
|
||||
SUPER=[],
|
||||
IMPLEMENTS=[],
|
||||
MEMBERS=[],
|
||||
super,
|
||||
implements,
|
||||
members,
|
||||
):
|
||||
assert factory_name is not None
|
||||
|
||||
self.class_ = class_
|
||||
self.name, self.cname = self.tidy_class_name(path)
|
||||
self.inherited_procs = inherited_procs
|
||||
self.factory_name = factory_name
|
||||
self._class = class_
|
||||
self._name, self.cname = self.tidy_class_name(path)
|
||||
self._top_level_code = top_level_code
|
||||
self._factory_name = factory_name
|
||||
self._members = members
|
||||
self._functions = functions
|
||||
|
||||
self.self = None
|
||||
self.a = None
|
||||
self.header_includes = []
|
||||
self.body_includes = includes
|
||||
if SUPER:
|
||||
self.super, _ = self.tidy_class_name(SUPER[0])
|
||||
self.src = args.target
|
||||
self._body_includes = includes
|
||||
|
||||
if super is None:
|
||||
self._super, _ = self.tidy_class_name(class_)
|
||||
self._include_dir = "cpp"
|
||||
else:
|
||||
self.super, _ = self.tidy_class_name(class_)
|
||||
self.src = "cpp"
|
||||
self._super, _ = self.tidy_class_name(super)
|
||||
self._include_dir = args.target
|
||||
|
||||
self.members = [Member(m) for m in MEMBERS if m != ""]
|
||||
def finalise(self, other_classes):
|
||||
self._other_classes = other_classes
|
||||
|
||||
for p in inherited_procs.values():
|
||||
p.tidy_lines(self)
|
||||
# Classify functions
|
||||
self._inherided_methods = []
|
||||
self._private_methods = []
|
||||
self._static_functions = []
|
||||
|
||||
self.inherited_methods = [
|
||||
p
|
||||
for p in inherited_procs.values()
|
||||
if p.name
|
||||
not in (
|
||||
"init",
|
||||
"destroy",
|
||||
)
|
||||
]
|
||||
init = [p for p in inherited_procs.values() if p.name == "init"]
|
||||
self.constructor = (
|
||||
init[0]
|
||||
if init
|
||||
else SimpleMethod(
|
||||
"init",
|
||||
"void",
|
||||
"grib_accessor* a, const long length, grib_arguments* args",
|
||||
)
|
||||
)
|
||||
|
||||
init = [p for p in inherited_procs.values() if p.name == "destroy"]
|
||||
self.destructor = init[0] if init else SimpleMethod("destroy", "void", "void")
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
for p in other_procs.values():
|
||||
p.tidy_lines(self)
|
||||
@property
|
||||
def factory_name(self):
|
||||
return self._factory_name
|
||||
|
||||
self.private_methods = [p for p in other_procs.values() if p.has_this()]
|
||||
self.static_procs = [p for p in other_procs.values() if not p.has_this()]
|
||||
@property
|
||||
def super(self):
|
||||
return self._super
|
||||
|
||||
self.top_level = defaultdict(list)
|
||||
for k, v in top_level.items():
|
||||
self.top_level[k] = [self.tidy_top_level(p) for p in v]
|
||||
@property
|
||||
def top_level_code(self):
|
||||
return self._top_level_code
|
||||
|
||||
@property
|
||||
def members(self):
|
||||
# if self.super in self.other_classes:
|
||||
# return self.other_classes[self.super].members + self._members
|
||||
return self._members
|
||||
|
||||
@property
|
||||
def include_super(self):
|
||||
return "/".join([self._include_dir] + self.namespaces + [self._super + ".h"])
|
||||
|
||||
@property
|
||||
def include_header(self):
|
||||
return "/".join([args.target] + self.namespaces + [self._super + ".h"])
|
||||
|
||||
@property
|
||||
def header_includes(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def body_includes(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def namespaces(self):
|
||||
return ["eccodes", self._class]
|
||||
|
||||
@property
|
||||
def namespaces_reversed(self):
|
||||
return reversed(self.namespaces)
|
||||
|
||||
@property
|
||||
def constructor(self):
|
||||
if "init" in self._functions:
|
||||
return self._functions["init"]
|
||||
|
||||
return Function("a")
|
||||
|
||||
@property
|
||||
def destructor(self):
|
||||
if "destroy" in self._functions:
|
||||
return self._functions["destroy"]
|
||||
|
||||
return Function("a", "b", "c")
|
||||
|
||||
@property
|
||||
def inherited_methods(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def private_methods(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def static_functions(self):
|
||||
return []
|
||||
|
||||
# if SUPER:
|
||||
# self.super, _ = self.tidy_class_name(SUPER[0])
|
||||
# self.src = args.target
|
||||
# else:
|
||||
# self.super, _ = self.tidy_class_name(class_)
|
||||
# self.src = "cpp"
|
||||
|
||||
# self.members = [Member(m) for m in MEMBERS if m != ""]
|
||||
|
||||
# for p in inherited_procs.values():
|
||||
# p.tidy_lines(self)
|
||||
|
||||
# self.inherited_methods = [
|
||||
# p
|
||||
# for p in inherited_procs.values()
|
||||
# if p.name
|
||||
# not in (
|
||||
# "init",
|
||||
# "destroy",
|
||||
# )
|
||||
# ]
|
||||
# init = [p for p in inherited_procs.values() if p.name == "init"]
|
||||
# self.constructor = (
|
||||
# init[0]
|
||||
# if init
|
||||
# else SimpleMethod(
|
||||
# "init",
|
||||
# "void",
|
||||
# "grib_accessor* a, const long length, grib_arguments* args",
|
||||
# )
|
||||
# )
|
||||
|
||||
# init = [p for p in inherited_procs.values() if p.name == "destroy"]
|
||||
# self.destructor = init[0] if init else SimpleMethod("destroy", "void", "void")
|
||||
|
||||
# for p in other_procs.values():
|
||||
# p.tidy_lines(self)
|
||||
|
||||
# self.private_methods = [p for p in other_procs.values() if p.has_this()]
|
||||
# self.static_procs = [p for p in other_procs.values() if not p.has_this()]
|
||||
|
||||
# self.top_level = defaultdict(list)
|
||||
# for k, v in top_level.items():
|
||||
# self.top_level[k] = [self.tidy_top_level(p) for p in v]
|
||||
|
||||
def update(self, classes):
|
||||
if self.super in classes:
|
||||
|
@ -222,47 +349,32 @@ class Class:
|
|||
|
||||
def tidy_class_name(self, path):
|
||||
path, ext = os.path.splitext(path)
|
||||
cname = os.path.basename(path)
|
||||
c_name = os.path.basename(path)
|
||||
|
||||
name = cname.replace(self.prefix, "")
|
||||
name = c_name.replace(self.prefix, "")
|
||||
|
||||
name = to_camel_class(name)
|
||||
return self.rename.get(name, name), cname
|
||||
return self.rename.get(name, name), c_name
|
||||
|
||||
def save(self, ext, content):
|
||||
target = os.path.join(args.target, *self.namespaces, f"{self.name}.{ext}")
|
||||
os.makedirs(os.path.dirname(target), exist_ok=True)
|
||||
print("Writting ", target)
|
||||
with open(target, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
ret = os.system(f"clang-format -i {target}")
|
||||
assert ret == 0
|
||||
print(" ", target)
|
||||
|
||||
def dump_header(self):
|
||||
template = env.get_template(f"{self.class_}.h.j2")
|
||||
template = env.get_template(f"{self._class}.h.j2")
|
||||
self.save(
|
||||
"h",
|
||||
template.render(
|
||||
name=self.name,
|
||||
super=self.super,
|
||||
members=self.members,
|
||||
includes=self.header_includes,
|
||||
inherited_methods=self.inherited_methods,
|
||||
private_methods=self.private_methods,
|
||||
static_procs=self.static_procs,
|
||||
constructor=self.constructor,
|
||||
destructor=self.destructor,
|
||||
namespaces=self.namespaces,
|
||||
namespace_reversed=reversed(self.namespaces),
|
||||
include_super="/".join(
|
||||
[self.src] + self.namespaces + [f"{self.super}.h"]
|
||||
),
|
||||
),
|
||||
template.render(c=self),
|
||||
)
|
||||
|
||||
def dump_body(self):
|
||||
template = env.get_template(f"{self.class_}.cc.j2")
|
||||
template = env.get_template(f"{self._class}.cc.j2")
|
||||
|
||||
def tidy_more(text):
|
||||
# Some more tidying
|
||||
|
@ -278,26 +390,7 @@ class Class:
|
|||
|
||||
self.save(
|
||||
"cc",
|
||||
tidy_more(
|
||||
template.render(
|
||||
name=self.name,
|
||||
super=self.super,
|
||||
members=self.members,
|
||||
includes=self.body_includes,
|
||||
inherited_methods=self.inherited_methods,
|
||||
private_methods=self.private_methods,
|
||||
static_procs=self.static_procs,
|
||||
constructor=self.constructor,
|
||||
destructor=self.destructor,
|
||||
namespaces=self.namespaces,
|
||||
namespace_reversed=reversed(self.namespaces),
|
||||
include_header="/".join(
|
||||
[self.src] + self.namespaces + [f"{self.name}.h"]
|
||||
),
|
||||
top_level=self.top_level,
|
||||
factory_name=self.factory_name,
|
||||
)
|
||||
),
|
||||
tidy_more(template.render(c=self)),
|
||||
)
|
||||
|
||||
def tidy_line(self, line, this=[]):
|
||||
|
@ -408,20 +501,19 @@ CLASSES = dict(
|
|||
)
|
||||
|
||||
|
||||
def make_class(classes, path):
|
||||
def parse_file(path):
|
||||
in_def = False
|
||||
in_imp = False
|
||||
in_proc = False
|
||||
in_function = False
|
||||
includes = []
|
||||
factory_name = None
|
||||
template = None
|
||||
|
||||
definitions = {}
|
||||
inherited_procs = {}
|
||||
other_procs = {}
|
||||
functions = {}
|
||||
top_level_lines = []
|
||||
top_level = defaultdict(list)
|
||||
print(path, file=sys.stderr)
|
||||
top_level_code = defaultdict(list)
|
||||
print("Parsing", path)
|
||||
|
||||
f = open(path, "r")
|
||||
for line in f:
|
||||
|
@ -465,36 +557,29 @@ def make_class(classes, path):
|
|||
|
||||
m = re.match(r"static\s+([^(]+)\s+(\w+)\s*\(([^(]+)\)", line)
|
||||
if m:
|
||||
p = m.group(2)
|
||||
top_level[p] = [x for x in top_level_lines]
|
||||
function_name = m.group(2)
|
||||
top_level_code[function_name] = [x for x in top_level_lines]
|
||||
top_level_lines = []
|
||||
|
||||
if p in definitions.get("IMPLEMENTS", []):
|
||||
in_proc = True
|
||||
method_class = METHOD_CLASS.get(p, SimpleMethod)
|
||||
proc = inherited_procs[p] = method_class(
|
||||
p, m.group(1), m.group(3), template
|
||||
)
|
||||
depth = stripped_line.count("{") - stripped_line.count("}")
|
||||
assert depth >= 0, line
|
||||
continue
|
||||
else:
|
||||
in_proc = True
|
||||
proc = StaticProc(p, m.group(1), m.group(3), template)
|
||||
other_procs[p] = proc
|
||||
depth = stripped_line.count("{") - stripped_line.count("}")
|
||||
assert depth >= 0, line
|
||||
continue
|
||||
in_function = True
|
||||
function = functions[function_name] = Function(
|
||||
function_name,
|
||||
m.group(1),
|
||||
m.group(3),
|
||||
template,
|
||||
)
|
||||
depth = stripped_line.count("{") - stripped_line.count("}")
|
||||
assert depth >= 0, line
|
||||
|
||||
if in_proc:
|
||||
proc.add_line(stripped_line)
|
||||
if in_function:
|
||||
function.add_line(stripped_line)
|
||||
depth += stripped_line.count("{")
|
||||
depth -= stripped_line.count("}")
|
||||
assert depth >= 0, line
|
||||
if depth == 0:
|
||||
in_proc = False
|
||||
in_function = False
|
||||
template = None
|
||||
del proc
|
||||
del function
|
||||
continue
|
||||
|
||||
if stripped_line.startswith("#include"):
|
||||
|
@ -511,29 +596,31 @@ def make_class(classes, path):
|
|||
top_level_lines.append(line)
|
||||
|
||||
if definitions:
|
||||
top_level["-end-"] = top_level_lines
|
||||
top_level_code["-end-"] = top_level_lines
|
||||
class_ = definitions.pop("CLASS")[0]
|
||||
klass = CLASSES[class_](
|
||||
path=path,
|
||||
class_=class_,
|
||||
inherited_procs=inherited_procs,
|
||||
other_procs=other_procs,
|
||||
top_level=top_level,
|
||||
functions=functions,
|
||||
top_level_code=top_level_code,
|
||||
includes=includes,
|
||||
factory_name=factory_name,
|
||||
**definitions,
|
||||
super=definitions["SUPER"][0] if "SUPER" in definitions else None,
|
||||
implements=definitions.get("IMPLEMENTS", []),
|
||||
members=[Member(m) for m in definitions.get("MEMBERS", []) if m != ""],
|
||||
)
|
||||
classes[klass.cname] = klass
|
||||
|
||||
return klass
|
||||
|
||||
|
||||
def main():
|
||||
classes = {}
|
||||
for a in args.path:
|
||||
make_class(classes, a)
|
||||
klass = parse_file(a)
|
||||
if klass is not None:
|
||||
classes[klass.cname] = klass
|
||||
|
||||
for klass in classes.values():
|
||||
klass.update(classes)
|
||||
klass.finalise(classes)
|
||||
|
||||
for klass in classes.values():
|
||||
klass.dump()
|
||||
|
|
|
@ -8,21 +8,21 @@
|
|||
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
||||
*/
|
||||
|
||||
#include "{{ include_header }}"
|
||||
#include "{{ c.include_header }}"
|
||||
|
||||
{% for i in includes %}
|
||||
{% for i in c.body_includes %}
|
||||
#include {{ i }}
|
||||
{% endfor %}
|
||||
|
||||
{% for n in namespaces %}namespace {{ n }} {
|
||||
{% for n in c.namespaces %}namespace {{ n }} {
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for line in top_level['-start-'] %}{{ line }}
|
||||
{% for line in c.top_level_code['-start-'] %}{{ line }}
|
||||
{% endfor %}
|
||||
|
||||
{% for m in static_procs %}
|
||||
{% for line in top_level[m.name] %}{{ line }}
|
||||
{% for m in c.static_functions %}
|
||||
{% for line in c.top_level_code[m.name] %}{{ line }}
|
||||
{% endfor %}
|
||||
static {{ m.result }} {{ m.name }}({{ m.args }}) {
|
||||
{{ m.body }}
|
||||
|
@ -30,20 +30,20 @@ static {{ m.result }} {{ m.name }}({{ m.args }}) {
|
|||
{% endfor %}
|
||||
|
||||
|
||||
{% for line in top_level['init'] %}{{ line }}
|
||||
{% for line in c.top_level_code['init'] %}{{ line }}
|
||||
{% endfor %}
|
||||
{{ name }}::{{ name }}({{constructor.args}}) : {{ super }}({{ constructor.call_args }}){
|
||||
{{ constructor.body }}
|
||||
{{ c.name }}::{{ c.name }}({{c.constructor.args_declaration}}) : {{ c.super }}({{ c.constructor.call_args }}){
|
||||
{{ c.constructor.body }}
|
||||
}
|
||||
|
||||
{% for line in top_level['destroy'] %}{{ line }}
|
||||
{% for line in c.top_level_code['destroy'] %}{{ line }}
|
||||
{% endfor %}
|
||||
{{ name }}::~{{ name }}() {
|
||||
{{ destructor.body }}
|
||||
{{ c.name }}::~{{ c.name }}() {
|
||||
{{ c.destructor.body }}
|
||||
}
|
||||
|
||||
{% for m in inherited_methods %}
|
||||
{% for line in top_level[m.name] %}{{ line }}
|
||||
{% for m in c.inherited_methods %}
|
||||
{% for line in c.top_level_code[m.name] %}{{ line }}
|
||||
{% endfor %}
|
||||
|
||||
{{ m.result }} {{ name }}::{{ m.name }}({{ m.args }}) const {
|
||||
|
@ -51,24 +51,24 @@ static {{ m.result }} {{ m.name }}({{ m.args }}) {
|
|||
}
|
||||
{% endfor %}
|
||||
|
||||
{% for m in private_methods %}
|
||||
{% for line in top_level[m.name] %}{{ line }}
|
||||
{% for m in c.private_methods %}
|
||||
{% for line in c.top_level_code[m.name] %}{{ line }}
|
||||
{% endfor %}
|
||||
{{ m.result }} {{ name }}::{{ m.name }}({{ m.args }}) const {
|
||||
{{ m.body }}
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
void {{ name }}::print(std::ostream& s) const {
|
||||
s << "{{ name }}["
|
||||
{% for m in members %} << "{{ m.name }}=" << {{ m.name }} {% if not loop.last %}<< ',' {% endif %}
|
||||
void {{ c.name }}::print(std::ostream& s) const {
|
||||
s << "{{ c.name }}["
|
||||
{% for m in c.members %} << "{{ m.name }}=" << {{ m.name }} {% if not loop.last %}<< ',' {% endif %}
|
||||
{% endfor %} << "]";
|
||||
}
|
||||
|
||||
{% for line in top_level['-end-'] %}{{ line }}
|
||||
{% for line in c.top_level_code['-end-'] %}{{ line }}
|
||||
{% endfor %}
|
||||
|
||||
static AccessorMaker<{{ name }}> maker("{{ factory_name }}");
|
||||
static AccessorMaker<{{ c.name }}> maker("{{ c.factory_name }}");
|
||||
|
||||
{% for n in namespace_reversed %}} // namespace {{ n }}
|
||||
{% for n in c.namespaces_reversed %}} // namespace {{ n }}
|
||||
{% endfor %}
|
||||
|
|
|
@ -10,48 +10,48 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "{{ include_super }}"
|
||||
#include "{{ c.include_super }}"
|
||||
|
||||
{% for i in includes %}
|
||||
{% for i in c.header_includes %}
|
||||
#include {{ i }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for n in namespaces %}namespace {{ n }} {
|
||||
{% for n in c.namespaces %}namespace {{ n }} {
|
||||
{% endfor %}
|
||||
|
||||
class {{ name }} : public {{ super }} {
|
||||
class {{ c.name }} : public {{ c.super }} {
|
||||
|
||||
public:
|
||||
|
||||
{{ name }}({{constructor.args}});
|
||||
virtual ~{{ name }}();
|
||||
{{ c.name }}({{c.constructor.args_declaration}});
|
||||
virtual ~{{ c.name }}();
|
||||
|
||||
private:
|
||||
// No copy allowed
|
||||
{{ name }}(const {{ name }}&);
|
||||
{{ name }}& operator=(const {{ name }}&);
|
||||
{{ c.name }}(const {{ c.name }}&);
|
||||
{{ c.name }}& operator=(const {{ c.name }}&);
|
||||
|
||||
protected:
|
||||
|
||||
// Inherited methods
|
||||
// Protected for now
|
||||
|
||||
{% for m in inherited_methods %}
|
||||
virtual {{ m.result }} {{ m.name }}({{ m.args }}) const override;{% endfor %}
|
||||
{% for m in c.inherited_methods %}
|
||||
virtual {{ m.result }} {{ m.name }}({{ m.args_declaration }}) {{ m.const }} override;{% endfor %}
|
||||
virtual void print(std::ostream& s) const override;
|
||||
|
||||
private:
|
||||
// Private methods
|
||||
{% for m in private_methods %}
|
||||
{% for m in c.private_methods %}
|
||||
{{ m.result }} {{ m.name }}({{ m.args }}) const;{% endfor %}
|
||||
|
||||
|
||||
// Members
|
||||
{% for m in members %}{{ m.type }} {{ m.name }};
|
||||
{% for m in c.members %}{{ m.type }} {{ m.name }};
|
||||
{% endfor %}
|
||||
|
||||
};
|
||||
|
||||
{% for n in namespace_reversed %}} // namespace {{ n }}
|
||||
{% for n in c.namespaces_reversed %}} // namespace {{ n }}
|
||||
{% endfor %}
|
||||
|
|
Loading…
Reference in New Issue