import clang.cindex as cindex import sys import re index = cindex.Index.create() tu = index.parse("igc.c") MPS_STRUCTS = ["Lisp_Symbol", "Lisp_String", "interval", "itree_node", "image", "Lisp_Cons"]; EXCLUDE_FIELDS = { "Lisp_Symbol": re.compile('u s val.*'), "Lisp_Cons": re.compile('.* chain'), } def type_for_struct_name (name) -> cindex.Type: for c in tu.cursor.get_children(): if (c.kind == cindex.CursorKind.STRUCT_DECL and c.spelling == name): return c.type.get_canonical() raise Exception("struct type not found: " + name) mps_types = [type_for_struct_name(name) for name in MPS_STRUCTS] lisp_obj_type = next(c.type.get_canonical() for c in tu.cursor.get_children() if c.spelling == 'Lisp_Object' if c.kind == cindex.CursorKind.TYPEDEF_DECL) def is_mps_ref (t:cindex.Type) -> bool: return (t.get_canonical() == lisp_obj_type or (t.get_pointee().get_canonical() in mps_types)) def field_paths (t:cindex.Type): l1 = [([f.spelling], f.type.get_canonical()) for f in t.get_fields()] l2 = [(p1 + p2,t2) for (p1,t1) in l1 for (p2,t2) in field_paths(t1)] return l1 + l2 def ref_fields (t:cindex.Type): excluded = EXCLUDE_FIELDS.get(t.get_declaration().spelling, re.compile("")) return [(p,t) for (p,t) in field_paths(t) if is_mps_ref (t) if not excluded.fullmatch(' '.join(p))] def emit_function_signature (t:cindex.Type): print("""static void mirror_%(fname)s (struct igc_mirror *m, %(atype)s *x) {"""% { "fname": t.get_declaration().spelling, "atype": t.spelling }) def emit_mirror (t:cindex.Type): emit_function_signature(t) for (path, type) in ref_fields(t): if type == lisp_obj_type: print(" mirror_lisp_obj (m, &x->%s);" % '.'.join(path)) else: print(" mirror_ptr (m, &x->%s);" % '.'.join(path)) print("}") def main(): for t in mps_types: emit_mirror(t) if __name__ == "__main__": main()