aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/external/metalang99/scripts/check-arities.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/external/metalang99/scripts/check-arities.py')
-rw-r--r--test/external/metalang99/scripts/check-arities.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/test/external/metalang99/scripts/check-arities.py b/test/external/metalang99/scripts/check-arities.py
new file mode 100644
index 0000000..c745a0b
--- /dev/null
+++ b/test/external/metalang99/scripts/check-arities.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python3
+
+# Make sure that arity specifiers of public metafunctions are consistent with their signatures.
+
+import os
+import re
+import xml.etree.ElementTree as ET
+import subprocess
+
+subprocess.call("doxygen > /dev/null 2> /dev/null", shell=True)
+
+
+def check_module(module):
+ print(f"Checking {module}.h ...")
+
+ tree = ET.parse(f"xml/{module}_8h.xml")
+ root = tree.getroot()
+
+ arity_specifiers = gather_arity_specifiers(root)
+
+ for metafunction_name, arity in gather_metafunctions(root).items():
+ expected_arity = int(arity)
+ actual_arity = int(arity_specifiers[metafunction_name])
+ assert expected_arity == actual_arity
+
+
+def gather_metafunctions(root):
+ metafunctions = {}
+
+ for definition in root.findall("./compounddef/sectiondef/memberdef"):
+ macro_name = definition.find("name").text
+ is_metalang99_compliant = re.search("ML99_[a-z]", macro_name)
+
+ exceptions = {
+ "ML99_call", "ML99_callUneval", "ML99_fatal", "ML99_abort", "ML99_tupleGet", "ML99_variadicsGet", "ML99_seqGet"}
+ is_exceptional = macro_name in exceptions
+
+ if (is_metalang99_compliant and not is_exceptional):
+ arity = len(list(definition.findall("param")))
+ metafunctions[macro_name] = arity
+
+ return metafunctions
+
+
+def gather_arity_specifiers(root):
+ arity_specifiers = {}
+
+ for definition in root.findall("./compounddef/programlisting/codeline/highlight[@class='preprocessor']"):
+ m = re.match(r"#define(\w+)_ARITY(\d)", "".join(definition.itertext()))
+ if m is not None:
+ metafunction_name = m.groups()[0]
+ arity = m.groups()[1]
+ arity_specifiers[metafunction_name] = arity
+
+ return arity_specifiers
+
+
+for path in os.listdir("include/metalang99"):
+ if path.endswith(".h"):
+ module = path.replace(".h", "")
+ check_module(module)