17db96d56Sopenharmony_ci#! /usr/bin/env python 27db96d56Sopenharmony_ci"""Generate C code from an ASDL description.""" 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ciimport os 57db96d56Sopenharmony_ciimport sys 67db96d56Sopenharmony_ciimport textwrap 77db96d56Sopenharmony_ciimport types 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_cifrom argparse import ArgumentParser 107db96d56Sopenharmony_cifrom contextlib import contextmanager 117db96d56Sopenharmony_cifrom pathlib import Path 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ciimport asdl 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ciTABSIZE = 4 167db96d56Sopenharmony_ciMAX_COL = 80 177db96d56Sopenharmony_ciAUTOGEN_MESSAGE = "// File automatically generated by {}.\n\n" 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_cidef get_c_type(name): 207db96d56Sopenharmony_ci """Return a string for the C name of the type. 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci This function special cases the default types provided by asdl. 237db96d56Sopenharmony_ci """ 247db96d56Sopenharmony_ci if name in asdl.builtin_types: 257db96d56Sopenharmony_ci return name 267db96d56Sopenharmony_ci else: 277db96d56Sopenharmony_ci return "%s_ty" % name 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_cidef reflow_lines(s, depth): 307db96d56Sopenharmony_ci """Reflow the line s indented depth tabs. 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci Return a sequence of lines where no line extends beyond MAX_COL 337db96d56Sopenharmony_ci when properly indented. The first line is properly indented based 347db96d56Sopenharmony_ci exclusively on depth * TABSIZE. All following lines -- these are 357db96d56Sopenharmony_ci the reflowed lines generated by this function -- start at the same 367db96d56Sopenharmony_ci column as the first character beyond the opening { in the first 377db96d56Sopenharmony_ci line. 387db96d56Sopenharmony_ci """ 397db96d56Sopenharmony_ci size = MAX_COL - depth * TABSIZE 407db96d56Sopenharmony_ci if len(s) < size: 417db96d56Sopenharmony_ci return [s] 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci lines = [] 447db96d56Sopenharmony_ci cur = s 457db96d56Sopenharmony_ci padding = "" 467db96d56Sopenharmony_ci while len(cur) > size: 477db96d56Sopenharmony_ci i = cur.rfind(' ', 0, size) 487db96d56Sopenharmony_ci # XXX this should be fixed for real 497db96d56Sopenharmony_ci if i == -1 and 'GeneratorExp' in cur: 507db96d56Sopenharmony_ci i = size + 3 517db96d56Sopenharmony_ci assert i != -1, "Impossible line %d to reflow: %r" % (size, s) 527db96d56Sopenharmony_ci lines.append(padding + cur[:i]) 537db96d56Sopenharmony_ci if len(lines) == 1: 547db96d56Sopenharmony_ci # find new size based on brace 557db96d56Sopenharmony_ci j = cur.find('{', 0, i) 567db96d56Sopenharmony_ci if j >= 0: 577db96d56Sopenharmony_ci j += 2 # account for the brace and the space after it 587db96d56Sopenharmony_ci size -= j 597db96d56Sopenharmony_ci padding = " " * j 607db96d56Sopenharmony_ci else: 617db96d56Sopenharmony_ci j = cur.find('(', 0, i) 627db96d56Sopenharmony_ci if j >= 0: 637db96d56Sopenharmony_ci j += 1 # account for the paren (no space after it) 647db96d56Sopenharmony_ci size -= j 657db96d56Sopenharmony_ci padding = " " * j 667db96d56Sopenharmony_ci cur = cur[i+1:] 677db96d56Sopenharmony_ci else: 687db96d56Sopenharmony_ci lines.append(padding + cur) 697db96d56Sopenharmony_ci return lines 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_cidef reflow_c_string(s, depth): 727db96d56Sopenharmony_ci return '"%s"' % s.replace('\n', '\\n"\n%s"' % (' ' * depth * TABSIZE)) 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_cidef is_simple(sum_type): 757db96d56Sopenharmony_ci """Return True if a sum is a simple. 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci A sum is simple if it's types have no fields and itself 787db96d56Sopenharmony_ci doesn't have any attributes. Instances of these types are 797db96d56Sopenharmony_ci cached at C level, and they act like singletons when propagating 807db96d56Sopenharmony_ci parser generated nodes into Python level, e.g. 817db96d56Sopenharmony_ci unaryop = Invert | Not | UAdd | USub 827db96d56Sopenharmony_ci """ 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci return not ( 857db96d56Sopenharmony_ci sum_type.attributes or 867db96d56Sopenharmony_ci any(constructor.fields for constructor in sum_type.types) 877db96d56Sopenharmony_ci ) 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_cidef asdl_of(name, obj): 907db96d56Sopenharmony_ci if isinstance(obj, asdl.Product) or isinstance(obj, asdl.Constructor): 917db96d56Sopenharmony_ci fields = ", ".join(map(str, obj.fields)) 927db96d56Sopenharmony_ci if fields: 937db96d56Sopenharmony_ci fields = "({})".format(fields) 947db96d56Sopenharmony_ci return "{}{}".format(name, fields) 957db96d56Sopenharmony_ci else: 967db96d56Sopenharmony_ci if is_simple(obj): 977db96d56Sopenharmony_ci types = " | ".join(type.name for type in obj.types) 987db96d56Sopenharmony_ci else: 997db96d56Sopenharmony_ci sep = "\n{}| ".format(" " * (len(name) + 1)) 1007db96d56Sopenharmony_ci types = sep.join( 1017db96d56Sopenharmony_ci asdl_of(type.name, type) for type in obj.types 1027db96d56Sopenharmony_ci ) 1037db96d56Sopenharmony_ci return "{} = {}".format(name, types) 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ciclass EmitVisitor(asdl.VisitorBase): 1067db96d56Sopenharmony_ci """Visit that emits lines""" 1077db96d56Sopenharmony_ci 1087db96d56Sopenharmony_ci def __init__(self, file, metadata = None): 1097db96d56Sopenharmony_ci self.file = file 1107db96d56Sopenharmony_ci self._metadata = metadata 1117db96d56Sopenharmony_ci super(EmitVisitor, self).__init__() 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_ci def emit(self, s, depth, reflow=True): 1147db96d56Sopenharmony_ci # XXX reflow long lines? 1157db96d56Sopenharmony_ci if reflow: 1167db96d56Sopenharmony_ci lines = reflow_lines(s, depth) 1177db96d56Sopenharmony_ci else: 1187db96d56Sopenharmony_ci lines = [s] 1197db96d56Sopenharmony_ci for line in lines: 1207db96d56Sopenharmony_ci if line: 1217db96d56Sopenharmony_ci line = (" " * TABSIZE * depth) + line 1227db96d56Sopenharmony_ci self.file.write(line + "\n") 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci @property 1257db96d56Sopenharmony_ci def metadata(self): 1267db96d56Sopenharmony_ci if self._metadata is None: 1277db96d56Sopenharmony_ci raise ValueError( 1287db96d56Sopenharmony_ci "%s was expecting to be annnotated with metadata" 1297db96d56Sopenharmony_ci % type(self).__name__ 1307db96d56Sopenharmony_ci ) 1317db96d56Sopenharmony_ci return self._metadata 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci @metadata.setter 1347db96d56Sopenharmony_ci def metadata(self, value): 1357db96d56Sopenharmony_ci self._metadata = value 1367db96d56Sopenharmony_ci 1377db96d56Sopenharmony_ciclass MetadataVisitor(asdl.VisitorBase): 1387db96d56Sopenharmony_ci ROOT_TYPE = "AST" 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 1417db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 1427db96d56Sopenharmony_ci 1437db96d56Sopenharmony_ci # Metadata: 1447db96d56Sopenharmony_ci # - simple_sums: Tracks the list of compound type 1457db96d56Sopenharmony_ci # names where all the constructors 1467db96d56Sopenharmony_ci # belonging to that type lack of any 1477db96d56Sopenharmony_ci # fields. 1487db96d56Sopenharmony_ci # - identifiers: All identifiers used in the AST declarations 1497db96d56Sopenharmony_ci # - singletons: List of all constructors that originates from 1507db96d56Sopenharmony_ci # simple sums. 1517db96d56Sopenharmony_ci # - types: List of all top level type names 1527db96d56Sopenharmony_ci # 1537db96d56Sopenharmony_ci self.metadata = types.SimpleNamespace( 1547db96d56Sopenharmony_ci simple_sums=set(), 1557db96d56Sopenharmony_ci identifiers=set(), 1567db96d56Sopenharmony_ci singletons=set(), 1577db96d56Sopenharmony_ci types={self.ROOT_TYPE}, 1587db96d56Sopenharmony_ci ) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci def visitModule(self, mod): 1617db96d56Sopenharmony_ci for dfn in mod.dfns: 1627db96d56Sopenharmony_ci self.visit(dfn) 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci def visitType(self, type): 1657db96d56Sopenharmony_ci self.visit(type.value, type.name) 1667db96d56Sopenharmony_ci 1677db96d56Sopenharmony_ci def visitSum(self, sum, name): 1687db96d56Sopenharmony_ci self.metadata.types.add(name) 1697db96d56Sopenharmony_ci 1707db96d56Sopenharmony_ci simple_sum = is_simple(sum) 1717db96d56Sopenharmony_ci if simple_sum: 1727db96d56Sopenharmony_ci self.metadata.simple_sums.add(name) 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci for constructor in sum.types: 1757db96d56Sopenharmony_ci if simple_sum: 1767db96d56Sopenharmony_ci self.metadata.singletons.add(constructor.name) 1777db96d56Sopenharmony_ci self.visitConstructor(constructor) 1787db96d56Sopenharmony_ci self.visitFields(sum.attributes) 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci def visitConstructor(self, constructor): 1817db96d56Sopenharmony_ci self.metadata.types.add(constructor.name) 1827db96d56Sopenharmony_ci self.visitFields(constructor.fields) 1837db96d56Sopenharmony_ci 1847db96d56Sopenharmony_ci def visitProduct(self, product, name): 1857db96d56Sopenharmony_ci self.metadata.types.add(name) 1867db96d56Sopenharmony_ci self.visitFields(product.attributes) 1877db96d56Sopenharmony_ci self.visitFields(product.fields) 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci def visitFields(self, fields): 1907db96d56Sopenharmony_ci for field in fields: 1917db96d56Sopenharmony_ci self.visitField(field) 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci def visitField(self, field): 1947db96d56Sopenharmony_ci self.metadata.identifiers.add(field.name) 1957db96d56Sopenharmony_ci 1967db96d56Sopenharmony_ci 1977db96d56Sopenharmony_ciclass TypeDefVisitor(EmitVisitor): 1987db96d56Sopenharmony_ci def visitModule(self, mod): 1997db96d56Sopenharmony_ci for dfn in mod.dfns: 2007db96d56Sopenharmony_ci self.visit(dfn) 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci def visitType(self, type, depth=0): 2037db96d56Sopenharmony_ci self.visit(type.value, type.name, depth) 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci def visitSum(self, sum, name, depth): 2067db96d56Sopenharmony_ci if is_simple(sum): 2077db96d56Sopenharmony_ci self.simple_sum(sum, name, depth) 2087db96d56Sopenharmony_ci else: 2097db96d56Sopenharmony_ci self.sum_with_constructors(sum, name, depth) 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_ci def simple_sum(self, sum, name, depth): 2127db96d56Sopenharmony_ci enum = [] 2137db96d56Sopenharmony_ci for i in range(len(sum.types)): 2147db96d56Sopenharmony_ci type = sum.types[i] 2157db96d56Sopenharmony_ci enum.append("%s=%d" % (type.name, i + 1)) 2167db96d56Sopenharmony_ci enums = ", ".join(enum) 2177db96d56Sopenharmony_ci ctype = get_c_type(name) 2187db96d56Sopenharmony_ci s = "typedef enum _%s { %s } %s;" % (name, enums, ctype) 2197db96d56Sopenharmony_ci self.emit(s, depth) 2207db96d56Sopenharmony_ci self.emit("", depth) 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci def sum_with_constructors(self, sum, name, depth): 2237db96d56Sopenharmony_ci ctype = get_c_type(name) 2247db96d56Sopenharmony_ci s = "typedef struct _%(name)s *%(ctype)s;" % locals() 2257db96d56Sopenharmony_ci self.emit(s, depth) 2267db96d56Sopenharmony_ci self.emit("", depth) 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_ci def visitProduct(self, product, name, depth): 2297db96d56Sopenharmony_ci ctype = get_c_type(name) 2307db96d56Sopenharmony_ci s = "typedef struct _%(name)s *%(ctype)s;" % locals() 2317db96d56Sopenharmony_ci self.emit(s, depth) 2327db96d56Sopenharmony_ci self.emit("", depth) 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ciclass SequenceDefVisitor(EmitVisitor): 2357db96d56Sopenharmony_ci def visitModule(self, mod): 2367db96d56Sopenharmony_ci for dfn in mod.dfns: 2377db96d56Sopenharmony_ci self.visit(dfn) 2387db96d56Sopenharmony_ci 2397db96d56Sopenharmony_ci def visitType(self, type, depth=0): 2407db96d56Sopenharmony_ci self.visit(type.value, type.name, depth) 2417db96d56Sopenharmony_ci 2427db96d56Sopenharmony_ci def visitSum(self, sum, name, depth): 2437db96d56Sopenharmony_ci if is_simple(sum): 2447db96d56Sopenharmony_ci return 2457db96d56Sopenharmony_ci self.emit_sequence_constructor(name, depth) 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci def emit_sequence_constructor(self, name,depth): 2487db96d56Sopenharmony_ci ctype = get_c_type(name) 2497db96d56Sopenharmony_ci self.emit("""\ 2507db96d56Sopenharmony_citypedef struct { 2517db96d56Sopenharmony_ci _ASDL_SEQ_HEAD 2527db96d56Sopenharmony_ci %(ctype)s typed_elements[1]; 2537db96d56Sopenharmony_ci} asdl_%(name)s_seq;""" % locals(), reflow=False, depth=depth) 2547db96d56Sopenharmony_ci self.emit("", depth) 2557db96d56Sopenharmony_ci self.emit("asdl_%(name)s_seq *_Py_asdl_%(name)s_seq_new(Py_ssize_t size, PyArena *arena);" % locals(), depth) 2567db96d56Sopenharmony_ci self.emit("", depth) 2577db96d56Sopenharmony_ci 2587db96d56Sopenharmony_ci def visitProduct(self, product, name, depth): 2597db96d56Sopenharmony_ci self.emit_sequence_constructor(name, depth) 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ciclass StructVisitor(EmitVisitor): 2627db96d56Sopenharmony_ci """Visitor to generate typedefs for AST.""" 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_ci def visitModule(self, mod): 2657db96d56Sopenharmony_ci for dfn in mod.dfns: 2667db96d56Sopenharmony_ci self.visit(dfn) 2677db96d56Sopenharmony_ci 2687db96d56Sopenharmony_ci def visitType(self, type, depth=0): 2697db96d56Sopenharmony_ci self.visit(type.value, type.name, depth) 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci def visitSum(self, sum, name, depth): 2727db96d56Sopenharmony_ci if not is_simple(sum): 2737db96d56Sopenharmony_ci self.sum_with_constructors(sum, name, depth) 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci def sum_with_constructors(self, sum, name, depth): 2767db96d56Sopenharmony_ci def emit(s, depth=depth): 2777db96d56Sopenharmony_ci self.emit(s % sys._getframe(1).f_locals, depth) 2787db96d56Sopenharmony_ci enum = [] 2797db96d56Sopenharmony_ci for i in range(len(sum.types)): 2807db96d56Sopenharmony_ci type = sum.types[i] 2817db96d56Sopenharmony_ci enum.append("%s_kind=%d" % (type.name, i + 1)) 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci emit("enum _%(name)s_kind {" + ", ".join(enum) + "};") 2847db96d56Sopenharmony_ci 2857db96d56Sopenharmony_ci emit("struct _%(name)s {") 2867db96d56Sopenharmony_ci emit("enum _%(name)s_kind kind;", depth + 1) 2877db96d56Sopenharmony_ci emit("union {", depth + 1) 2887db96d56Sopenharmony_ci for t in sum.types: 2897db96d56Sopenharmony_ci self.visit(t, depth + 2) 2907db96d56Sopenharmony_ci emit("} v;", depth + 1) 2917db96d56Sopenharmony_ci for field in sum.attributes: 2927db96d56Sopenharmony_ci # rudimentary attribute handling 2937db96d56Sopenharmony_ci type = str(field.type) 2947db96d56Sopenharmony_ci assert type in asdl.builtin_types, type 2957db96d56Sopenharmony_ci emit("%s %s;" % (type, field.name), depth + 1); 2967db96d56Sopenharmony_ci emit("};") 2977db96d56Sopenharmony_ci emit("") 2987db96d56Sopenharmony_ci 2997db96d56Sopenharmony_ci def visitConstructor(self, cons, depth): 3007db96d56Sopenharmony_ci if cons.fields: 3017db96d56Sopenharmony_ci self.emit("struct {", depth) 3027db96d56Sopenharmony_ci for f in cons.fields: 3037db96d56Sopenharmony_ci self.visit(f, depth + 1) 3047db96d56Sopenharmony_ci self.emit("} %s;" % cons.name, depth) 3057db96d56Sopenharmony_ci self.emit("", depth) 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def visitField(self, field, depth): 3087db96d56Sopenharmony_ci # XXX need to lookup field.type, because it might be something 3097db96d56Sopenharmony_ci # like a builtin... 3107db96d56Sopenharmony_ci ctype = get_c_type(field.type) 3117db96d56Sopenharmony_ci name = field.name 3127db96d56Sopenharmony_ci if field.seq: 3137db96d56Sopenharmony_ci if field.type in self.metadata.simple_sums: 3147db96d56Sopenharmony_ci self.emit("asdl_int_seq *%(name)s;" % locals(), depth) 3157db96d56Sopenharmony_ci else: 3167db96d56Sopenharmony_ci _type = field.type 3177db96d56Sopenharmony_ci self.emit("asdl_%(_type)s_seq *%(name)s;" % locals(), depth) 3187db96d56Sopenharmony_ci else: 3197db96d56Sopenharmony_ci self.emit("%(ctype)s %(name)s;" % locals(), depth) 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci def visitProduct(self, product, name, depth): 3227db96d56Sopenharmony_ci self.emit("struct _%(name)s {" % locals(), depth) 3237db96d56Sopenharmony_ci for f in product.fields: 3247db96d56Sopenharmony_ci self.visit(f, depth + 1) 3257db96d56Sopenharmony_ci for field in product.attributes: 3267db96d56Sopenharmony_ci # rudimentary attribute handling 3277db96d56Sopenharmony_ci type = str(field.type) 3287db96d56Sopenharmony_ci assert type in asdl.builtin_types, type 3297db96d56Sopenharmony_ci self.emit("%s %s;" % (type, field.name), depth + 1); 3307db96d56Sopenharmony_ci self.emit("};", depth) 3317db96d56Sopenharmony_ci self.emit("", depth) 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci 3347db96d56Sopenharmony_cidef ast_func_name(name): 3357db96d56Sopenharmony_ci return f"_PyAST_{name}" 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ciclass PrototypeVisitor(EmitVisitor): 3397db96d56Sopenharmony_ci """Generate function prototypes for the .h file""" 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci def visitModule(self, mod): 3427db96d56Sopenharmony_ci for dfn in mod.dfns: 3437db96d56Sopenharmony_ci self.visit(dfn) 3447db96d56Sopenharmony_ci 3457db96d56Sopenharmony_ci def visitType(self, type): 3467db96d56Sopenharmony_ci self.visit(type.value, type.name) 3477db96d56Sopenharmony_ci 3487db96d56Sopenharmony_ci def visitSum(self, sum, name): 3497db96d56Sopenharmony_ci if is_simple(sum): 3507db96d56Sopenharmony_ci pass # XXX 3517db96d56Sopenharmony_ci else: 3527db96d56Sopenharmony_ci for t in sum.types: 3537db96d56Sopenharmony_ci self.visit(t, name, sum.attributes) 3547db96d56Sopenharmony_ci 3557db96d56Sopenharmony_ci def get_args(self, fields): 3567db96d56Sopenharmony_ci """Return list of C argument into, one for each field. 3577db96d56Sopenharmony_ci 3587db96d56Sopenharmony_ci Argument info is 3-tuple of a C type, variable name, and flag 3597db96d56Sopenharmony_ci that is true if type can be NULL. 3607db96d56Sopenharmony_ci """ 3617db96d56Sopenharmony_ci args = [] 3627db96d56Sopenharmony_ci unnamed = {} 3637db96d56Sopenharmony_ci for f in fields: 3647db96d56Sopenharmony_ci if f.name is None: 3657db96d56Sopenharmony_ci name = f.type 3667db96d56Sopenharmony_ci c = unnamed[name] = unnamed.get(name, 0) + 1 3677db96d56Sopenharmony_ci if c > 1: 3687db96d56Sopenharmony_ci name = "name%d" % (c - 1) 3697db96d56Sopenharmony_ci else: 3707db96d56Sopenharmony_ci name = f.name 3717db96d56Sopenharmony_ci # XXX should extend get_c_type() to handle this 3727db96d56Sopenharmony_ci if f.seq: 3737db96d56Sopenharmony_ci if f.type in self.metadata.simple_sums: 3747db96d56Sopenharmony_ci ctype = "asdl_int_seq *" 3757db96d56Sopenharmony_ci else: 3767db96d56Sopenharmony_ci ctype = f"asdl_{f.type}_seq *" 3777db96d56Sopenharmony_ci else: 3787db96d56Sopenharmony_ci ctype = get_c_type(f.type) 3797db96d56Sopenharmony_ci args.append((ctype, name, f.opt or f.seq)) 3807db96d56Sopenharmony_ci return args 3817db96d56Sopenharmony_ci 3827db96d56Sopenharmony_ci def visitConstructor(self, cons, type, attrs): 3837db96d56Sopenharmony_ci args = self.get_args(cons.fields) 3847db96d56Sopenharmony_ci attrs = self.get_args(attrs) 3857db96d56Sopenharmony_ci ctype = get_c_type(type) 3867db96d56Sopenharmony_ci self.emit_function(cons.name, ctype, args, attrs) 3877db96d56Sopenharmony_ci 3887db96d56Sopenharmony_ci def emit_function(self, name, ctype, args, attrs, union=True): 3897db96d56Sopenharmony_ci args = args + attrs 3907db96d56Sopenharmony_ci if args: 3917db96d56Sopenharmony_ci argstr = ", ".join(["%s %s" % (atype, aname) 3927db96d56Sopenharmony_ci for atype, aname, opt in args]) 3937db96d56Sopenharmony_ci argstr += ", PyArena *arena" 3947db96d56Sopenharmony_ci else: 3957db96d56Sopenharmony_ci argstr = "PyArena *arena" 3967db96d56Sopenharmony_ci self.emit("%s %s(%s);" % (ctype, ast_func_name(name), argstr), False) 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_ci def visitProduct(self, prod, name): 3997db96d56Sopenharmony_ci self.emit_function(name, get_c_type(name), 4007db96d56Sopenharmony_ci self.get_args(prod.fields), 4017db96d56Sopenharmony_ci self.get_args(prod.attributes), 4027db96d56Sopenharmony_ci union=False) 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_ci 4057db96d56Sopenharmony_ciclass FunctionVisitor(PrototypeVisitor): 4067db96d56Sopenharmony_ci """Visitor to generate constructor functions for AST.""" 4077db96d56Sopenharmony_ci 4087db96d56Sopenharmony_ci def emit_function(self, name, ctype, args, attrs, union=True): 4097db96d56Sopenharmony_ci def emit(s, depth=0, reflow=True): 4107db96d56Sopenharmony_ci self.emit(s, depth, reflow) 4117db96d56Sopenharmony_ci argstr = ", ".join(["%s %s" % (atype, aname) 4127db96d56Sopenharmony_ci for atype, aname, opt in args + attrs]) 4137db96d56Sopenharmony_ci if argstr: 4147db96d56Sopenharmony_ci argstr += ", PyArena *arena" 4157db96d56Sopenharmony_ci else: 4167db96d56Sopenharmony_ci argstr = "PyArena *arena" 4177db96d56Sopenharmony_ci self.emit("%s" % ctype, 0) 4187db96d56Sopenharmony_ci emit("%s(%s)" % (ast_func_name(name), argstr)) 4197db96d56Sopenharmony_ci emit("{") 4207db96d56Sopenharmony_ci emit("%s p;" % ctype, 1) 4217db96d56Sopenharmony_ci for argtype, argname, opt in args: 4227db96d56Sopenharmony_ci if not opt and argtype != "int": 4237db96d56Sopenharmony_ci emit("if (!%s) {" % argname, 1) 4247db96d56Sopenharmony_ci emit("PyErr_SetString(PyExc_ValueError,", 2) 4257db96d56Sopenharmony_ci msg = "field '%s' is required for %s" % (argname, name) 4267db96d56Sopenharmony_ci emit(' "%s");' % msg, 4277db96d56Sopenharmony_ci 2, reflow=False) 4287db96d56Sopenharmony_ci emit('return NULL;', 2) 4297db96d56Sopenharmony_ci emit('}', 1) 4307db96d56Sopenharmony_ci 4317db96d56Sopenharmony_ci emit("p = (%s)_PyArena_Malloc(arena, sizeof(*p));" % ctype, 1); 4327db96d56Sopenharmony_ci emit("if (!p)", 1) 4337db96d56Sopenharmony_ci emit("return NULL;", 2) 4347db96d56Sopenharmony_ci if union: 4357db96d56Sopenharmony_ci self.emit_body_union(name, args, attrs) 4367db96d56Sopenharmony_ci else: 4377db96d56Sopenharmony_ci self.emit_body_struct(name, args, attrs) 4387db96d56Sopenharmony_ci emit("return p;", 1) 4397db96d56Sopenharmony_ci emit("}") 4407db96d56Sopenharmony_ci emit("") 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci def emit_body_union(self, name, args, attrs): 4437db96d56Sopenharmony_ci def emit(s, depth=0, reflow=True): 4447db96d56Sopenharmony_ci self.emit(s, depth, reflow) 4457db96d56Sopenharmony_ci emit("p->kind = %s_kind;" % name, 1) 4467db96d56Sopenharmony_ci for argtype, argname, opt in args: 4477db96d56Sopenharmony_ci emit("p->v.%s.%s = %s;" % (name, argname, argname), 1) 4487db96d56Sopenharmony_ci for argtype, argname, opt in attrs: 4497db96d56Sopenharmony_ci emit("p->%s = %s;" % (argname, argname), 1) 4507db96d56Sopenharmony_ci 4517db96d56Sopenharmony_ci def emit_body_struct(self, name, args, attrs): 4527db96d56Sopenharmony_ci def emit(s, depth=0, reflow=True): 4537db96d56Sopenharmony_ci self.emit(s, depth, reflow) 4547db96d56Sopenharmony_ci for argtype, argname, opt in args: 4557db96d56Sopenharmony_ci emit("p->%s = %s;" % (argname, argname), 1) 4567db96d56Sopenharmony_ci for argtype, argname, opt in attrs: 4577db96d56Sopenharmony_ci emit("p->%s = %s;" % (argname, argname), 1) 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci 4607db96d56Sopenharmony_ciclass PickleVisitor(EmitVisitor): 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def visitModule(self, mod): 4637db96d56Sopenharmony_ci for dfn in mod.dfns: 4647db96d56Sopenharmony_ci self.visit(dfn) 4657db96d56Sopenharmony_ci 4667db96d56Sopenharmony_ci def visitType(self, type): 4677db96d56Sopenharmony_ci self.visit(type.value, type.name) 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci def visitSum(self, sum, name): 4707db96d56Sopenharmony_ci pass 4717db96d56Sopenharmony_ci 4727db96d56Sopenharmony_ci def visitProduct(self, sum, name): 4737db96d56Sopenharmony_ci pass 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci def visitConstructor(self, cons, name): 4767db96d56Sopenharmony_ci pass 4777db96d56Sopenharmony_ci 4787db96d56Sopenharmony_ci def visitField(self, sum): 4797db96d56Sopenharmony_ci pass 4807db96d56Sopenharmony_ci 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ciclass Obj2ModPrototypeVisitor(PickleVisitor): 4837db96d56Sopenharmony_ci def visitProduct(self, prod, name): 4847db96d56Sopenharmony_ci code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena);" 4857db96d56Sopenharmony_ci self.emit(code % (name, get_c_type(name)), 0) 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_ci visitSum = visitProduct 4887db96d56Sopenharmony_ci 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ciclass Obj2ModVisitor(PickleVisitor): 4917db96d56Sopenharmony_ci 4927db96d56Sopenharmony_ci attribute_special_defaults = { 4937db96d56Sopenharmony_ci "end_lineno": "lineno", 4947db96d56Sopenharmony_ci "end_col_offset": "col_offset", 4957db96d56Sopenharmony_ci } 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci @contextmanager 4987db96d56Sopenharmony_ci def recursive_call(self, node, level): 4997db96d56Sopenharmony_ci self.emit('if (_Py_EnterRecursiveCall(" while traversing \'%s\' node")) {' % node, level, reflow=False) 5007db96d56Sopenharmony_ci self.emit('goto failed;', level + 1) 5017db96d56Sopenharmony_ci self.emit('}', level) 5027db96d56Sopenharmony_ci yield 5037db96d56Sopenharmony_ci self.emit('_Py_LeaveRecursiveCall();', level) 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci def funcHeader(self, name): 5067db96d56Sopenharmony_ci ctype = get_c_type(name) 5077db96d56Sopenharmony_ci self.emit("int", 0) 5087db96d56Sopenharmony_ci self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) 5097db96d56Sopenharmony_ci self.emit("{", 0) 5107db96d56Sopenharmony_ci self.emit("int isinstance;", 1) 5117db96d56Sopenharmony_ci self.emit("", 0) 5127db96d56Sopenharmony_ci 5137db96d56Sopenharmony_ci def sumTrailer(self, name, add_label=False): 5147db96d56Sopenharmony_ci self.emit("", 0) 5157db96d56Sopenharmony_ci # there's really nothing more we can do if this fails ... 5167db96d56Sopenharmony_ci error = "expected some sort of %s, but got %%R" % name 5177db96d56Sopenharmony_ci format = "PyErr_Format(PyExc_TypeError, \"%s\", obj);" 5187db96d56Sopenharmony_ci self.emit(format % error, 1, reflow=False) 5197db96d56Sopenharmony_ci if add_label: 5207db96d56Sopenharmony_ci self.emit("failed:", 1) 5217db96d56Sopenharmony_ci self.emit("Py_XDECREF(tmp);", 1) 5227db96d56Sopenharmony_ci self.emit("return 1;", 1) 5237db96d56Sopenharmony_ci self.emit("}", 0) 5247db96d56Sopenharmony_ci self.emit("", 0) 5257db96d56Sopenharmony_ci 5267db96d56Sopenharmony_ci def simpleSum(self, sum, name): 5277db96d56Sopenharmony_ci self.funcHeader(name) 5287db96d56Sopenharmony_ci for t in sum.types: 5297db96d56Sopenharmony_ci line = ("isinstance = PyObject_IsInstance(obj, " 5307db96d56Sopenharmony_ci "state->%s_type);") 5317db96d56Sopenharmony_ci self.emit(line % (t.name,), 1) 5327db96d56Sopenharmony_ci self.emit("if (isinstance == -1) {", 1) 5337db96d56Sopenharmony_ci self.emit("return 1;", 2) 5347db96d56Sopenharmony_ci self.emit("}", 1) 5357db96d56Sopenharmony_ci self.emit("if (isinstance) {", 1) 5367db96d56Sopenharmony_ci self.emit("*out = %s;" % t.name, 2) 5377db96d56Sopenharmony_ci self.emit("return 0;", 2) 5387db96d56Sopenharmony_ci self.emit("}", 1) 5397db96d56Sopenharmony_ci self.sumTrailer(name) 5407db96d56Sopenharmony_ci 5417db96d56Sopenharmony_ci def buildArgs(self, fields): 5427db96d56Sopenharmony_ci return ", ".join(fields + ["arena"]) 5437db96d56Sopenharmony_ci 5447db96d56Sopenharmony_ci def complexSum(self, sum, name): 5457db96d56Sopenharmony_ci self.funcHeader(name) 5467db96d56Sopenharmony_ci self.emit("PyObject *tmp = NULL;", 1) 5477db96d56Sopenharmony_ci self.emit("PyObject *tp;", 1) 5487db96d56Sopenharmony_ci for a in sum.attributes: 5497db96d56Sopenharmony_ci self.visitAttributeDeclaration(a, name, sum=sum) 5507db96d56Sopenharmony_ci self.emit("", 0) 5517db96d56Sopenharmony_ci # XXX: should we only do this for 'expr'? 5527db96d56Sopenharmony_ci self.emit("if (obj == Py_None) {", 1) 5537db96d56Sopenharmony_ci self.emit("*out = NULL;", 2) 5547db96d56Sopenharmony_ci self.emit("return 0;", 2) 5557db96d56Sopenharmony_ci self.emit("}", 1) 5567db96d56Sopenharmony_ci for a in sum.attributes: 5577db96d56Sopenharmony_ci self.visitField(a, name, sum=sum, depth=1) 5587db96d56Sopenharmony_ci for t in sum.types: 5597db96d56Sopenharmony_ci self.emit("tp = state->%s_type;" % (t.name,), 1) 5607db96d56Sopenharmony_ci self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1) 5617db96d56Sopenharmony_ci self.emit("if (isinstance == -1) {", 1) 5627db96d56Sopenharmony_ci self.emit("return 1;", 2) 5637db96d56Sopenharmony_ci self.emit("}", 1) 5647db96d56Sopenharmony_ci self.emit("if (isinstance) {", 1) 5657db96d56Sopenharmony_ci for f in t.fields: 5667db96d56Sopenharmony_ci self.visitFieldDeclaration(f, t.name, sum=sum, depth=2) 5677db96d56Sopenharmony_ci self.emit("", 0) 5687db96d56Sopenharmony_ci for f in t.fields: 5697db96d56Sopenharmony_ci self.visitField(f, t.name, sum=sum, depth=2) 5707db96d56Sopenharmony_ci args = [f.name for f in t.fields] + [a.name for a in sum.attributes] 5717db96d56Sopenharmony_ci self.emit("*out = %s(%s);" % (ast_func_name(t.name), self.buildArgs(args)), 2) 5727db96d56Sopenharmony_ci self.emit("if (*out == NULL) goto failed;", 2) 5737db96d56Sopenharmony_ci self.emit("return 0;", 2) 5747db96d56Sopenharmony_ci self.emit("}", 1) 5757db96d56Sopenharmony_ci self.sumTrailer(name, True) 5767db96d56Sopenharmony_ci 5777db96d56Sopenharmony_ci def visitAttributeDeclaration(self, a, name, sum=sum): 5787db96d56Sopenharmony_ci ctype = get_c_type(a.type) 5797db96d56Sopenharmony_ci self.emit("%s %s;" % (ctype, a.name), 1) 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci def visitSum(self, sum, name): 5827db96d56Sopenharmony_ci if is_simple(sum): 5837db96d56Sopenharmony_ci self.simpleSum(sum, name) 5847db96d56Sopenharmony_ci else: 5857db96d56Sopenharmony_ci self.complexSum(sum, name) 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ci def visitProduct(self, prod, name): 5887db96d56Sopenharmony_ci ctype = get_c_type(name) 5897db96d56Sopenharmony_ci self.emit("int", 0) 5907db96d56Sopenharmony_ci self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) 5917db96d56Sopenharmony_ci self.emit("{", 0) 5927db96d56Sopenharmony_ci self.emit("PyObject* tmp = NULL;", 1) 5937db96d56Sopenharmony_ci for f in prod.fields: 5947db96d56Sopenharmony_ci self.visitFieldDeclaration(f, name, prod=prod, depth=1) 5957db96d56Sopenharmony_ci for a in prod.attributes: 5967db96d56Sopenharmony_ci self.visitFieldDeclaration(a, name, prod=prod, depth=1) 5977db96d56Sopenharmony_ci self.emit("", 0) 5987db96d56Sopenharmony_ci for f in prod.fields: 5997db96d56Sopenharmony_ci self.visitField(f, name, prod=prod, depth=1) 6007db96d56Sopenharmony_ci for a in prod.attributes: 6017db96d56Sopenharmony_ci self.visitField(a, name, prod=prod, depth=1) 6027db96d56Sopenharmony_ci args = [f.name for f in prod.fields] 6037db96d56Sopenharmony_ci args.extend([a.name for a in prod.attributes]) 6047db96d56Sopenharmony_ci self.emit("*out = %s(%s);" % (ast_func_name(name), self.buildArgs(args)), 1) 6057db96d56Sopenharmony_ci self.emit("return 0;", 1) 6067db96d56Sopenharmony_ci self.emit("failed:", 0) 6077db96d56Sopenharmony_ci self.emit("Py_XDECREF(tmp);", 1) 6087db96d56Sopenharmony_ci self.emit("return 1;", 1) 6097db96d56Sopenharmony_ci self.emit("}", 0) 6107db96d56Sopenharmony_ci self.emit("", 0) 6117db96d56Sopenharmony_ci 6127db96d56Sopenharmony_ci def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0): 6137db96d56Sopenharmony_ci ctype = get_c_type(field.type) 6147db96d56Sopenharmony_ci if field.seq: 6157db96d56Sopenharmony_ci if self.isSimpleType(field): 6167db96d56Sopenharmony_ci self.emit("asdl_int_seq* %s;" % field.name, depth) 6177db96d56Sopenharmony_ci else: 6187db96d56Sopenharmony_ci _type = field.type 6197db96d56Sopenharmony_ci self.emit(f"asdl_{field.type}_seq* {field.name};", depth) 6207db96d56Sopenharmony_ci else: 6217db96d56Sopenharmony_ci ctype = get_c_type(field.type) 6227db96d56Sopenharmony_ci self.emit("%s %s;" % (ctype, field.name), depth) 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci def isNumeric(self, field): 6257db96d56Sopenharmony_ci return get_c_type(field.type) in ("int", "bool") 6267db96d56Sopenharmony_ci 6277db96d56Sopenharmony_ci def isSimpleType(self, field): 6287db96d56Sopenharmony_ci return field.type in self.metadata.simple_sums or self.isNumeric(field) 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci def visitField(self, field, name, sum=None, prod=None, depth=0): 6317db96d56Sopenharmony_ci ctype = get_c_type(field.type) 6327db96d56Sopenharmony_ci line = "if (_PyObject_LookupAttr(obj, state->%s, &tmp) < 0) {" 6337db96d56Sopenharmony_ci self.emit(line % field.name, depth) 6347db96d56Sopenharmony_ci self.emit("return 1;", depth+1) 6357db96d56Sopenharmony_ci self.emit("}", depth) 6367db96d56Sopenharmony_ci if not field.opt: 6377db96d56Sopenharmony_ci self.emit("if (tmp == NULL) {", depth) 6387db96d56Sopenharmony_ci message = "required field \\\"%s\\\" missing from %s" % (field.name, name) 6397db96d56Sopenharmony_ci format = "PyErr_SetString(PyExc_TypeError, \"%s\");" 6407db96d56Sopenharmony_ci self.emit(format % message, depth+1, reflow=False) 6417db96d56Sopenharmony_ci self.emit("return 1;", depth+1) 6427db96d56Sopenharmony_ci else: 6437db96d56Sopenharmony_ci self.emit("if (tmp == NULL || tmp == Py_None) {", depth) 6447db96d56Sopenharmony_ci self.emit("Py_CLEAR(tmp);", depth+1) 6457db96d56Sopenharmony_ci if self.isNumeric(field): 6467db96d56Sopenharmony_ci if field.name in self.attribute_special_defaults: 6477db96d56Sopenharmony_ci self.emit( 6487db96d56Sopenharmony_ci "%s = %s;" % (field.name, self.attribute_special_defaults[field.name]), 6497db96d56Sopenharmony_ci depth+1, 6507db96d56Sopenharmony_ci ) 6517db96d56Sopenharmony_ci else: 6527db96d56Sopenharmony_ci self.emit("%s = 0;" % field.name, depth+1) 6537db96d56Sopenharmony_ci elif not self.isSimpleType(field): 6547db96d56Sopenharmony_ci self.emit("%s = NULL;" % field.name, depth+1) 6557db96d56Sopenharmony_ci else: 6567db96d56Sopenharmony_ci raise TypeError("could not determine the default value for %s" % field.name) 6577db96d56Sopenharmony_ci self.emit("}", depth) 6587db96d56Sopenharmony_ci self.emit("else {", depth) 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci self.emit("int res;", depth+1) 6617db96d56Sopenharmony_ci if field.seq: 6627db96d56Sopenharmony_ci self.emit("Py_ssize_t len;", depth+1) 6637db96d56Sopenharmony_ci self.emit("Py_ssize_t i;", depth+1) 6647db96d56Sopenharmony_ci self.emit("if (!PyList_Check(tmp)) {", depth+1) 6657db96d56Sopenharmony_ci self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must " 6667db96d56Sopenharmony_ci "be a list, not a %%.200s\", _PyType_Name(Py_TYPE(tmp)));" % 6677db96d56Sopenharmony_ci (name, field.name), 6687db96d56Sopenharmony_ci depth+2, reflow=False) 6697db96d56Sopenharmony_ci self.emit("goto failed;", depth+2) 6707db96d56Sopenharmony_ci self.emit("}", depth+1) 6717db96d56Sopenharmony_ci self.emit("len = PyList_GET_SIZE(tmp);", depth+1) 6727db96d56Sopenharmony_ci if self.isSimpleType(field): 6737db96d56Sopenharmony_ci self.emit("%s = _Py_asdl_int_seq_new(len, arena);" % field.name, depth+1) 6747db96d56Sopenharmony_ci else: 6757db96d56Sopenharmony_ci self.emit("%s = _Py_asdl_%s_seq_new(len, arena);" % (field.name, field.type), depth+1) 6767db96d56Sopenharmony_ci self.emit("if (%s == NULL) goto failed;" % field.name, depth+1) 6777db96d56Sopenharmony_ci self.emit("for (i = 0; i < len; i++) {", depth+1) 6787db96d56Sopenharmony_ci self.emit("%s val;" % ctype, depth+2) 6797db96d56Sopenharmony_ci self.emit("PyObject *tmp2 = PyList_GET_ITEM(tmp, i);", depth+2) 6807db96d56Sopenharmony_ci self.emit("Py_INCREF(tmp2);", depth+2) 6817db96d56Sopenharmony_ci with self.recursive_call(name, depth+2): 6827db96d56Sopenharmony_ci self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % 6837db96d56Sopenharmony_ci field.type, depth+2, reflow=False) 6847db96d56Sopenharmony_ci self.emit("Py_DECREF(tmp2);", depth+2) 6857db96d56Sopenharmony_ci self.emit("if (res != 0) goto failed;", depth+2) 6867db96d56Sopenharmony_ci self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2) 6877db96d56Sopenharmony_ci self.emit("PyErr_SetString(PyExc_RuntimeError, \"%s field \\\"%s\\\" " 6887db96d56Sopenharmony_ci "changed size during iteration\");" % 6897db96d56Sopenharmony_ci (name, field.name), 6907db96d56Sopenharmony_ci depth+3, reflow=False) 6917db96d56Sopenharmony_ci self.emit("goto failed;", depth+3) 6927db96d56Sopenharmony_ci self.emit("}", depth+2) 6937db96d56Sopenharmony_ci self.emit("asdl_seq_SET(%s, i, val);" % field.name, depth+2) 6947db96d56Sopenharmony_ci self.emit("}", depth+1) 6957db96d56Sopenharmony_ci else: 6967db96d56Sopenharmony_ci with self.recursive_call(name, depth+1): 6977db96d56Sopenharmony_ci self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % 6987db96d56Sopenharmony_ci (field.type, field.name), depth+1) 6997db96d56Sopenharmony_ci self.emit("if (res != 0) goto failed;", depth+1) 7007db96d56Sopenharmony_ci 7017db96d56Sopenharmony_ci self.emit("Py_CLEAR(tmp);", depth+1) 7027db96d56Sopenharmony_ci self.emit("}", depth) 7037db96d56Sopenharmony_ci 7047db96d56Sopenharmony_ci 7057db96d56Sopenharmony_ciclass SequenceConstructorVisitor(EmitVisitor): 7067db96d56Sopenharmony_ci def visitModule(self, mod): 7077db96d56Sopenharmony_ci for dfn in mod.dfns: 7087db96d56Sopenharmony_ci self.visit(dfn) 7097db96d56Sopenharmony_ci 7107db96d56Sopenharmony_ci def visitType(self, type): 7117db96d56Sopenharmony_ci self.visit(type.value, type.name) 7127db96d56Sopenharmony_ci 7137db96d56Sopenharmony_ci def visitProduct(self, prod, name): 7147db96d56Sopenharmony_ci self.emit_sequence_constructor(name, get_c_type(name)) 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_ci def visitSum(self, sum, name): 7177db96d56Sopenharmony_ci if not is_simple(sum): 7187db96d56Sopenharmony_ci self.emit_sequence_constructor(name, get_c_type(name)) 7197db96d56Sopenharmony_ci 7207db96d56Sopenharmony_ci def emit_sequence_constructor(self, name, type): 7217db96d56Sopenharmony_ci self.emit(f"GENERATE_ASDL_SEQ_CONSTRUCTOR({name}, {type})", depth=0) 7227db96d56Sopenharmony_ci 7237db96d56Sopenharmony_ciclass PyTypesDeclareVisitor(PickleVisitor): 7247db96d56Sopenharmony_ci 7257db96d56Sopenharmony_ci def visitProduct(self, prod, name): 7267db96d56Sopenharmony_ci self.emit("static PyObject* ast2obj_%s(struct ast_state *state, void*);" % name, 0) 7277db96d56Sopenharmony_ci if prod.attributes: 7287db96d56Sopenharmony_ci self.emit("static const char * const %s_attributes[] = {" % name, 0) 7297db96d56Sopenharmony_ci for a in prod.attributes: 7307db96d56Sopenharmony_ci self.emit('"%s",' % a.name, 1) 7317db96d56Sopenharmony_ci self.emit("};", 0) 7327db96d56Sopenharmony_ci if prod.fields: 7337db96d56Sopenharmony_ci self.emit("static const char * const %s_fields[]={" % name,0) 7347db96d56Sopenharmony_ci for f in prod.fields: 7357db96d56Sopenharmony_ci self.emit('"%s",' % f.name, 1) 7367db96d56Sopenharmony_ci self.emit("};", 0) 7377db96d56Sopenharmony_ci 7387db96d56Sopenharmony_ci def visitSum(self, sum, name): 7397db96d56Sopenharmony_ci if sum.attributes: 7407db96d56Sopenharmony_ci self.emit("static const char * const %s_attributes[] = {" % name, 0) 7417db96d56Sopenharmony_ci for a in sum.attributes: 7427db96d56Sopenharmony_ci self.emit('"%s",' % a.name, 1) 7437db96d56Sopenharmony_ci self.emit("};", 0) 7447db96d56Sopenharmony_ci ptype = "void*" 7457db96d56Sopenharmony_ci if is_simple(sum): 7467db96d56Sopenharmony_ci ptype = get_c_type(name) 7477db96d56Sopenharmony_ci self.emit("static PyObject* ast2obj_%s(struct ast_state *state, %s);" % (name, ptype), 0) 7487db96d56Sopenharmony_ci for t in sum.types: 7497db96d56Sopenharmony_ci self.visitConstructor(t, name) 7507db96d56Sopenharmony_ci 7517db96d56Sopenharmony_ci def visitConstructor(self, cons, name): 7527db96d56Sopenharmony_ci if cons.fields: 7537db96d56Sopenharmony_ci self.emit("static const char * const %s_fields[]={" % cons.name, 0) 7547db96d56Sopenharmony_ci for t in cons.fields: 7557db96d56Sopenharmony_ci self.emit('"%s",' % t.name, 1) 7567db96d56Sopenharmony_ci self.emit("};",0) 7577db96d56Sopenharmony_ci 7587db96d56Sopenharmony_ci 7597db96d56Sopenharmony_ciclass PyTypesVisitor(PickleVisitor): 7607db96d56Sopenharmony_ci 7617db96d56Sopenharmony_ci def visitModule(self, mod): 7627db96d56Sopenharmony_ci self.emit(""" 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_citypedef struct { 7657db96d56Sopenharmony_ci PyObject_HEAD 7667db96d56Sopenharmony_ci PyObject *dict; 7677db96d56Sopenharmony_ci} AST_object; 7687db96d56Sopenharmony_ci 7697db96d56Sopenharmony_cistatic void 7707db96d56Sopenharmony_ciast_dealloc(AST_object *self) 7717db96d56Sopenharmony_ci{ 7727db96d56Sopenharmony_ci /* bpo-31095: UnTrack is needed before calling any callbacks */ 7737db96d56Sopenharmony_ci PyTypeObject *tp = Py_TYPE(self); 7747db96d56Sopenharmony_ci PyObject_GC_UnTrack(self); 7757db96d56Sopenharmony_ci Py_CLEAR(self->dict); 7767db96d56Sopenharmony_ci freefunc free_func = PyType_GetSlot(tp, Py_tp_free); 7777db96d56Sopenharmony_ci assert(free_func != NULL); 7787db96d56Sopenharmony_ci free_func(self); 7797db96d56Sopenharmony_ci Py_DECREF(tp); 7807db96d56Sopenharmony_ci} 7817db96d56Sopenharmony_ci 7827db96d56Sopenharmony_cistatic int 7837db96d56Sopenharmony_ciast_traverse(AST_object *self, visitproc visit, void *arg) 7847db96d56Sopenharmony_ci{ 7857db96d56Sopenharmony_ci Py_VISIT(Py_TYPE(self)); 7867db96d56Sopenharmony_ci Py_VISIT(self->dict); 7877db96d56Sopenharmony_ci return 0; 7887db96d56Sopenharmony_ci} 7897db96d56Sopenharmony_ci 7907db96d56Sopenharmony_cistatic int 7917db96d56Sopenharmony_ciast_clear(AST_object *self) 7927db96d56Sopenharmony_ci{ 7937db96d56Sopenharmony_ci Py_CLEAR(self->dict); 7947db96d56Sopenharmony_ci return 0; 7957db96d56Sopenharmony_ci} 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_cistatic int 7987db96d56Sopenharmony_ciast_type_init(PyObject *self, PyObject *args, PyObject *kw) 7997db96d56Sopenharmony_ci{ 8007db96d56Sopenharmony_ci struct ast_state *state = get_ast_state(); 8017db96d56Sopenharmony_ci if (state == NULL) { 8027db96d56Sopenharmony_ci return -1; 8037db96d56Sopenharmony_ci } 8047db96d56Sopenharmony_ci 8057db96d56Sopenharmony_ci Py_ssize_t i, numfields = 0; 8067db96d56Sopenharmony_ci int res = -1; 8077db96d56Sopenharmony_ci PyObject *key, *value, *fields; 8087db96d56Sopenharmony_ci if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { 8097db96d56Sopenharmony_ci goto cleanup; 8107db96d56Sopenharmony_ci } 8117db96d56Sopenharmony_ci if (fields) { 8127db96d56Sopenharmony_ci numfields = PySequence_Size(fields); 8137db96d56Sopenharmony_ci if (numfields == -1) { 8147db96d56Sopenharmony_ci goto cleanup; 8157db96d56Sopenharmony_ci } 8167db96d56Sopenharmony_ci } 8177db96d56Sopenharmony_ci 8187db96d56Sopenharmony_ci res = 0; /* if no error occurs, this stays 0 to the end */ 8197db96d56Sopenharmony_ci if (numfields < PyTuple_GET_SIZE(args)) { 8207db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "%.400s constructor takes at most " 8217db96d56Sopenharmony_ci "%zd positional argument%s", 8227db96d56Sopenharmony_ci _PyType_Name(Py_TYPE(self)), 8237db96d56Sopenharmony_ci numfields, numfields == 1 ? "" : "s"); 8247db96d56Sopenharmony_ci res = -1; 8257db96d56Sopenharmony_ci goto cleanup; 8267db96d56Sopenharmony_ci } 8277db96d56Sopenharmony_ci for (i = 0; i < PyTuple_GET_SIZE(args); i++) { 8287db96d56Sopenharmony_ci /* cannot be reached when fields is NULL */ 8297db96d56Sopenharmony_ci PyObject *name = PySequence_GetItem(fields, i); 8307db96d56Sopenharmony_ci if (!name) { 8317db96d56Sopenharmony_ci res = -1; 8327db96d56Sopenharmony_ci goto cleanup; 8337db96d56Sopenharmony_ci } 8347db96d56Sopenharmony_ci res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i)); 8357db96d56Sopenharmony_ci Py_DECREF(name); 8367db96d56Sopenharmony_ci if (res < 0) { 8377db96d56Sopenharmony_ci goto cleanup; 8387db96d56Sopenharmony_ci } 8397db96d56Sopenharmony_ci } 8407db96d56Sopenharmony_ci if (kw) { 8417db96d56Sopenharmony_ci i = 0; /* needed by PyDict_Next */ 8427db96d56Sopenharmony_ci while (PyDict_Next(kw, &i, &key, &value)) { 8437db96d56Sopenharmony_ci int contains = PySequence_Contains(fields, key); 8447db96d56Sopenharmony_ci if (contains == -1) { 8457db96d56Sopenharmony_ci res = -1; 8467db96d56Sopenharmony_ci goto cleanup; 8477db96d56Sopenharmony_ci } else if (contains == 1) { 8487db96d56Sopenharmony_ci Py_ssize_t p = PySequence_Index(fields, key); 8497db96d56Sopenharmony_ci if (p == -1) { 8507db96d56Sopenharmony_ci res = -1; 8517db96d56Sopenharmony_ci goto cleanup; 8527db96d56Sopenharmony_ci } 8537db96d56Sopenharmony_ci if (p < PyTuple_GET_SIZE(args)) { 8547db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 8557db96d56Sopenharmony_ci "%.400s got multiple values for argument '%U'", 8567db96d56Sopenharmony_ci Py_TYPE(self)->tp_name, key); 8577db96d56Sopenharmony_ci res = -1; 8587db96d56Sopenharmony_ci goto cleanup; 8597db96d56Sopenharmony_ci } 8607db96d56Sopenharmony_ci } 8617db96d56Sopenharmony_ci res = PyObject_SetAttr(self, key, value); 8627db96d56Sopenharmony_ci if (res < 0) { 8637db96d56Sopenharmony_ci goto cleanup; 8647db96d56Sopenharmony_ci } 8657db96d56Sopenharmony_ci } 8667db96d56Sopenharmony_ci } 8677db96d56Sopenharmony_ci cleanup: 8687db96d56Sopenharmony_ci Py_XDECREF(fields); 8697db96d56Sopenharmony_ci return res; 8707db96d56Sopenharmony_ci} 8717db96d56Sopenharmony_ci 8727db96d56Sopenharmony_ci/* Pickling support */ 8737db96d56Sopenharmony_cistatic PyObject * 8747db96d56Sopenharmony_ciast_type_reduce(PyObject *self, PyObject *unused) 8757db96d56Sopenharmony_ci{ 8767db96d56Sopenharmony_ci struct ast_state *state = get_ast_state(); 8777db96d56Sopenharmony_ci if (state == NULL) { 8787db96d56Sopenharmony_ci return NULL; 8797db96d56Sopenharmony_ci } 8807db96d56Sopenharmony_ci 8817db96d56Sopenharmony_ci PyObject *dict; 8827db96d56Sopenharmony_ci if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) { 8837db96d56Sopenharmony_ci return NULL; 8847db96d56Sopenharmony_ci } 8857db96d56Sopenharmony_ci if (dict) { 8867db96d56Sopenharmony_ci return Py_BuildValue("O()N", Py_TYPE(self), dict); 8877db96d56Sopenharmony_ci } 8887db96d56Sopenharmony_ci return Py_BuildValue("O()", Py_TYPE(self)); 8897db96d56Sopenharmony_ci} 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_cistatic PyMemberDef ast_type_members[] = { 8927db96d56Sopenharmony_ci {"__dictoffset__", T_PYSSIZET, offsetof(AST_object, dict), READONLY}, 8937db96d56Sopenharmony_ci {NULL} /* Sentinel */ 8947db96d56Sopenharmony_ci}; 8957db96d56Sopenharmony_ci 8967db96d56Sopenharmony_cistatic PyMethodDef ast_type_methods[] = { 8977db96d56Sopenharmony_ci {"__reduce__", ast_type_reduce, METH_NOARGS, NULL}, 8987db96d56Sopenharmony_ci {NULL} 8997db96d56Sopenharmony_ci}; 9007db96d56Sopenharmony_ci 9017db96d56Sopenharmony_cistatic PyGetSetDef ast_type_getsets[] = { 9027db96d56Sopenharmony_ci {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, 9037db96d56Sopenharmony_ci {NULL} 9047db96d56Sopenharmony_ci}; 9057db96d56Sopenharmony_ci 9067db96d56Sopenharmony_cistatic PyType_Slot AST_type_slots[] = { 9077db96d56Sopenharmony_ci {Py_tp_dealloc, ast_dealloc}, 9087db96d56Sopenharmony_ci {Py_tp_getattro, PyObject_GenericGetAttr}, 9097db96d56Sopenharmony_ci {Py_tp_setattro, PyObject_GenericSetAttr}, 9107db96d56Sopenharmony_ci {Py_tp_traverse, ast_traverse}, 9117db96d56Sopenharmony_ci {Py_tp_clear, ast_clear}, 9127db96d56Sopenharmony_ci {Py_tp_members, ast_type_members}, 9137db96d56Sopenharmony_ci {Py_tp_methods, ast_type_methods}, 9147db96d56Sopenharmony_ci {Py_tp_getset, ast_type_getsets}, 9157db96d56Sopenharmony_ci {Py_tp_init, ast_type_init}, 9167db96d56Sopenharmony_ci {Py_tp_alloc, PyType_GenericAlloc}, 9177db96d56Sopenharmony_ci {Py_tp_new, PyType_GenericNew}, 9187db96d56Sopenharmony_ci {Py_tp_free, PyObject_GC_Del}, 9197db96d56Sopenharmony_ci {0, 0}, 9207db96d56Sopenharmony_ci}; 9217db96d56Sopenharmony_ci 9227db96d56Sopenharmony_cistatic PyType_Spec AST_type_spec = { 9237db96d56Sopenharmony_ci "ast.AST", 9247db96d56Sopenharmony_ci sizeof(AST_object), 9257db96d56Sopenharmony_ci 0, 9267db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, 9277db96d56Sopenharmony_ci AST_type_slots 9287db96d56Sopenharmony_ci}; 9297db96d56Sopenharmony_ci 9307db96d56Sopenharmony_cistatic PyObject * 9317db96d56Sopenharmony_cimake_type(struct ast_state *state, const char *type, PyObject* base, 9327db96d56Sopenharmony_ci const char* const* fields, int num_fields, const char *doc) 9337db96d56Sopenharmony_ci{ 9347db96d56Sopenharmony_ci PyObject *fnames, *result; 9357db96d56Sopenharmony_ci int i; 9367db96d56Sopenharmony_ci fnames = PyTuple_New(num_fields); 9377db96d56Sopenharmony_ci if (!fnames) return NULL; 9387db96d56Sopenharmony_ci for (i = 0; i < num_fields; i++) { 9397db96d56Sopenharmony_ci PyObject *field = PyUnicode_InternFromString(fields[i]); 9407db96d56Sopenharmony_ci if (!field) { 9417db96d56Sopenharmony_ci Py_DECREF(fnames); 9427db96d56Sopenharmony_ci return NULL; 9437db96d56Sopenharmony_ci } 9447db96d56Sopenharmony_ci PyTuple_SET_ITEM(fnames, i, field); 9457db96d56Sopenharmony_ci } 9467db96d56Sopenharmony_ci result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOOOOOs}", 9477db96d56Sopenharmony_ci type, base, 9487db96d56Sopenharmony_ci state->_fields, fnames, 9497db96d56Sopenharmony_ci state->__match_args__, fnames, 9507db96d56Sopenharmony_ci state->__module__, 9517db96d56Sopenharmony_ci state->ast, 9527db96d56Sopenharmony_ci state->__doc__, doc); 9537db96d56Sopenharmony_ci Py_DECREF(fnames); 9547db96d56Sopenharmony_ci return result; 9557db96d56Sopenharmony_ci} 9567db96d56Sopenharmony_ci 9577db96d56Sopenharmony_cistatic int 9587db96d56Sopenharmony_ciadd_attributes(struct ast_state *state, PyObject *type, const char * const *attrs, int num_fields) 9597db96d56Sopenharmony_ci{ 9607db96d56Sopenharmony_ci int i, result; 9617db96d56Sopenharmony_ci PyObject *s, *l = PyTuple_New(num_fields); 9627db96d56Sopenharmony_ci if (!l) 9637db96d56Sopenharmony_ci return 0; 9647db96d56Sopenharmony_ci for (i = 0; i < num_fields; i++) { 9657db96d56Sopenharmony_ci s = PyUnicode_InternFromString(attrs[i]); 9667db96d56Sopenharmony_ci if (!s) { 9677db96d56Sopenharmony_ci Py_DECREF(l); 9687db96d56Sopenharmony_ci return 0; 9697db96d56Sopenharmony_ci } 9707db96d56Sopenharmony_ci PyTuple_SET_ITEM(l, i, s); 9717db96d56Sopenharmony_ci } 9727db96d56Sopenharmony_ci result = PyObject_SetAttr(type, state->_attributes, l) >= 0; 9737db96d56Sopenharmony_ci Py_DECREF(l); 9747db96d56Sopenharmony_ci return result; 9757db96d56Sopenharmony_ci} 9767db96d56Sopenharmony_ci 9777db96d56Sopenharmony_ci/* Conversion AST -> Python */ 9787db96d56Sopenharmony_ci 9797db96d56Sopenharmony_cistatic PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* (*func)(struct ast_state *state, void*)) 9807db96d56Sopenharmony_ci{ 9817db96d56Sopenharmony_ci Py_ssize_t i, n = asdl_seq_LEN(seq); 9827db96d56Sopenharmony_ci PyObject *result = PyList_New(n); 9837db96d56Sopenharmony_ci PyObject *value; 9847db96d56Sopenharmony_ci if (!result) 9857db96d56Sopenharmony_ci return NULL; 9867db96d56Sopenharmony_ci for (i = 0; i < n; i++) { 9877db96d56Sopenharmony_ci value = func(state, asdl_seq_GET_UNTYPED(seq, i)); 9887db96d56Sopenharmony_ci if (!value) { 9897db96d56Sopenharmony_ci Py_DECREF(result); 9907db96d56Sopenharmony_ci return NULL; 9917db96d56Sopenharmony_ci } 9927db96d56Sopenharmony_ci PyList_SET_ITEM(result, i, value); 9937db96d56Sopenharmony_ci } 9947db96d56Sopenharmony_ci return result; 9957db96d56Sopenharmony_ci} 9967db96d56Sopenharmony_ci 9977db96d56Sopenharmony_cistatic PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o) 9987db96d56Sopenharmony_ci{ 9997db96d56Sopenharmony_ci if (!o) 10007db96d56Sopenharmony_ci o = Py_None; 10017db96d56Sopenharmony_ci Py_INCREF((PyObject*)o); 10027db96d56Sopenharmony_ci return (PyObject*)o; 10037db96d56Sopenharmony_ci} 10047db96d56Sopenharmony_ci#define ast2obj_constant ast2obj_object 10057db96d56Sopenharmony_ci#define ast2obj_identifier ast2obj_object 10067db96d56Sopenharmony_ci#define ast2obj_string ast2obj_object 10077db96d56Sopenharmony_ci 10087db96d56Sopenharmony_cistatic PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) 10097db96d56Sopenharmony_ci{ 10107db96d56Sopenharmony_ci return PyLong_FromLong(b); 10117db96d56Sopenharmony_ci} 10127db96d56Sopenharmony_ci 10137db96d56Sopenharmony_ci/* Conversion Python -> AST */ 10147db96d56Sopenharmony_ci 10157db96d56Sopenharmony_cistatic int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) 10167db96d56Sopenharmony_ci{ 10177db96d56Sopenharmony_ci if (obj == Py_None) 10187db96d56Sopenharmony_ci obj = NULL; 10197db96d56Sopenharmony_ci if (obj) { 10207db96d56Sopenharmony_ci if (_PyArena_AddPyObject(arena, obj) < 0) { 10217db96d56Sopenharmony_ci *out = NULL; 10227db96d56Sopenharmony_ci return -1; 10237db96d56Sopenharmony_ci } 10247db96d56Sopenharmony_ci Py_INCREF(obj); 10257db96d56Sopenharmony_ci } 10267db96d56Sopenharmony_ci *out = obj; 10277db96d56Sopenharmony_ci return 0; 10287db96d56Sopenharmony_ci} 10297db96d56Sopenharmony_ci 10307db96d56Sopenharmony_cistatic int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) 10317db96d56Sopenharmony_ci{ 10327db96d56Sopenharmony_ci if (_PyArena_AddPyObject(arena, obj) < 0) { 10337db96d56Sopenharmony_ci *out = NULL; 10347db96d56Sopenharmony_ci return -1; 10357db96d56Sopenharmony_ci } 10367db96d56Sopenharmony_ci Py_INCREF(obj); 10377db96d56Sopenharmony_ci *out = obj; 10387db96d56Sopenharmony_ci return 0; 10397db96d56Sopenharmony_ci} 10407db96d56Sopenharmony_ci 10417db96d56Sopenharmony_cistatic int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) 10427db96d56Sopenharmony_ci{ 10437db96d56Sopenharmony_ci if (!PyUnicode_CheckExact(obj) && obj != Py_None) { 10447db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); 10457db96d56Sopenharmony_ci return 1; 10467db96d56Sopenharmony_ci } 10477db96d56Sopenharmony_ci return obj2ast_object(state, obj, out, arena); 10487db96d56Sopenharmony_ci} 10497db96d56Sopenharmony_ci 10507db96d56Sopenharmony_cistatic int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) 10517db96d56Sopenharmony_ci{ 10527db96d56Sopenharmony_ci if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { 10537db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); 10547db96d56Sopenharmony_ci return 1; 10557db96d56Sopenharmony_ci } 10567db96d56Sopenharmony_ci return obj2ast_object(state, obj, out, arena); 10577db96d56Sopenharmony_ci} 10587db96d56Sopenharmony_ci 10597db96d56Sopenharmony_cistatic int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) 10607db96d56Sopenharmony_ci{ 10617db96d56Sopenharmony_ci int i; 10627db96d56Sopenharmony_ci if (!PyLong_Check(obj)) { 10637db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); 10647db96d56Sopenharmony_ci return 1; 10657db96d56Sopenharmony_ci } 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ci i = _PyLong_AsInt(obj); 10687db96d56Sopenharmony_ci if (i == -1 && PyErr_Occurred()) 10697db96d56Sopenharmony_ci return 1; 10707db96d56Sopenharmony_ci *out = i; 10717db96d56Sopenharmony_ci return 0; 10727db96d56Sopenharmony_ci} 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_cistatic int add_ast_fields(struct ast_state *state) 10757db96d56Sopenharmony_ci{ 10767db96d56Sopenharmony_ci PyObject *empty_tuple; 10777db96d56Sopenharmony_ci empty_tuple = PyTuple_New(0); 10787db96d56Sopenharmony_ci if (!empty_tuple || 10797db96d56Sopenharmony_ci PyObject_SetAttrString(state->AST_type, "_fields", empty_tuple) < 0 || 10807db96d56Sopenharmony_ci PyObject_SetAttrString(state->AST_type, "__match_args__", empty_tuple) < 0 || 10817db96d56Sopenharmony_ci PyObject_SetAttrString(state->AST_type, "_attributes", empty_tuple) < 0) { 10827db96d56Sopenharmony_ci Py_XDECREF(empty_tuple); 10837db96d56Sopenharmony_ci return -1; 10847db96d56Sopenharmony_ci } 10857db96d56Sopenharmony_ci Py_DECREF(empty_tuple); 10867db96d56Sopenharmony_ci return 0; 10877db96d56Sopenharmony_ci} 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_ci""", 0, reflow=False) 10907db96d56Sopenharmony_ci 10917db96d56Sopenharmony_ci self.file.write(textwrap.dedent(''' 10927db96d56Sopenharmony_ci static int 10937db96d56Sopenharmony_ci init_types(struct ast_state *state) 10947db96d56Sopenharmony_ci { 10957db96d56Sopenharmony_ci // init_types() must not be called after _PyAST_Fini() 10967db96d56Sopenharmony_ci // has been called 10977db96d56Sopenharmony_ci assert(state->initialized >= 0); 10987db96d56Sopenharmony_ci 10997db96d56Sopenharmony_ci if (state->initialized) { 11007db96d56Sopenharmony_ci return 1; 11017db96d56Sopenharmony_ci } 11027db96d56Sopenharmony_ci if (init_identifiers(state) < 0) { 11037db96d56Sopenharmony_ci return 0; 11047db96d56Sopenharmony_ci } 11057db96d56Sopenharmony_ci state->AST_type = PyType_FromSpec(&AST_type_spec); 11067db96d56Sopenharmony_ci if (!state->AST_type) { 11077db96d56Sopenharmony_ci return 0; 11087db96d56Sopenharmony_ci } 11097db96d56Sopenharmony_ci if (add_ast_fields(state) < 0) { 11107db96d56Sopenharmony_ci return 0; 11117db96d56Sopenharmony_ci } 11127db96d56Sopenharmony_ci ''')) 11137db96d56Sopenharmony_ci for dfn in mod.dfns: 11147db96d56Sopenharmony_ci self.visit(dfn) 11157db96d56Sopenharmony_ci self.file.write(textwrap.dedent(''' 11167db96d56Sopenharmony_ci state->recursion_depth = 0; 11177db96d56Sopenharmony_ci state->recursion_limit = 0; 11187db96d56Sopenharmony_ci state->initialized = 1; 11197db96d56Sopenharmony_ci return 1; 11207db96d56Sopenharmony_ci } 11217db96d56Sopenharmony_ci ''')) 11227db96d56Sopenharmony_ci 11237db96d56Sopenharmony_ci def visitProduct(self, prod, name): 11247db96d56Sopenharmony_ci if prod.fields: 11257db96d56Sopenharmony_ci fields = name+"_fields" 11267db96d56Sopenharmony_ci else: 11277db96d56Sopenharmony_ci fields = "NULL" 11287db96d56Sopenharmony_ci self.emit('state->%s_type = make_type(state, "%s", state->AST_type, %s, %d,' % 11297db96d56Sopenharmony_ci (name, name, fields, len(prod.fields)), 1) 11307db96d56Sopenharmony_ci self.emit('%s);' % reflow_c_string(asdl_of(name, prod), 2), 2, reflow=False) 11317db96d56Sopenharmony_ci self.emit("if (!state->%s_type) return 0;" % name, 1) 11327db96d56Sopenharmony_ci if prod.attributes: 11337db96d56Sopenharmony_ci self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % 11347db96d56Sopenharmony_ci (name, name, len(prod.attributes)), 1) 11357db96d56Sopenharmony_ci else: 11367db96d56Sopenharmony_ci self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) 11377db96d56Sopenharmony_ci self.emit_defaults(name, prod.fields, 1) 11387db96d56Sopenharmony_ci self.emit_defaults(name, prod.attributes, 1) 11397db96d56Sopenharmony_ci 11407db96d56Sopenharmony_ci def visitSum(self, sum, name): 11417db96d56Sopenharmony_ci self.emit('state->%s_type = make_type(state, "%s", state->AST_type, NULL, 0,' % 11427db96d56Sopenharmony_ci (name, name), 1) 11437db96d56Sopenharmony_ci self.emit('%s);' % reflow_c_string(asdl_of(name, sum), 2), 2, reflow=False) 11447db96d56Sopenharmony_ci self.emit("if (!state->%s_type) return 0;" % name, 1) 11457db96d56Sopenharmony_ci if sum.attributes: 11467db96d56Sopenharmony_ci self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % 11477db96d56Sopenharmony_ci (name, name, len(sum.attributes)), 1) 11487db96d56Sopenharmony_ci else: 11497db96d56Sopenharmony_ci self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) 11507db96d56Sopenharmony_ci self.emit_defaults(name, sum.attributes, 1) 11517db96d56Sopenharmony_ci simple = is_simple(sum) 11527db96d56Sopenharmony_ci for t in sum.types: 11537db96d56Sopenharmony_ci self.visitConstructor(t, name, simple) 11547db96d56Sopenharmony_ci 11557db96d56Sopenharmony_ci def visitConstructor(self, cons, name, simple): 11567db96d56Sopenharmony_ci if cons.fields: 11577db96d56Sopenharmony_ci fields = cons.name+"_fields" 11587db96d56Sopenharmony_ci else: 11597db96d56Sopenharmony_ci fields = "NULL" 11607db96d56Sopenharmony_ci self.emit('state->%s_type = make_type(state, "%s", state->%s_type, %s, %d,' % 11617db96d56Sopenharmony_ci (cons.name, cons.name, name, fields, len(cons.fields)), 1) 11627db96d56Sopenharmony_ci self.emit('%s);' % reflow_c_string(asdl_of(cons.name, cons), 2), 2, reflow=False) 11637db96d56Sopenharmony_ci self.emit("if (!state->%s_type) return 0;" % cons.name, 1) 11647db96d56Sopenharmony_ci self.emit_defaults(cons.name, cons.fields, 1) 11657db96d56Sopenharmony_ci if simple: 11667db96d56Sopenharmony_ci self.emit("state->%s_singleton = PyType_GenericNew((PyTypeObject *)" 11677db96d56Sopenharmony_ci "state->%s_type, NULL, NULL);" % 11687db96d56Sopenharmony_ci (cons.name, cons.name), 1) 11697db96d56Sopenharmony_ci self.emit("if (!state->%s_singleton) return 0;" % cons.name, 1) 11707db96d56Sopenharmony_ci 11717db96d56Sopenharmony_ci def emit_defaults(self, name, fields, depth): 11727db96d56Sopenharmony_ci for field in fields: 11737db96d56Sopenharmony_ci if field.opt: 11747db96d56Sopenharmony_ci self.emit('if (PyObject_SetAttr(state->%s_type, state->%s, Py_None) == -1)' % 11757db96d56Sopenharmony_ci (name, field.name), depth) 11767db96d56Sopenharmony_ci self.emit("return 0;", depth+1) 11777db96d56Sopenharmony_ci 11787db96d56Sopenharmony_ci 11797db96d56Sopenharmony_ciclass ASTModuleVisitor(PickleVisitor): 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_ci def visitModule(self, mod): 11827db96d56Sopenharmony_ci self.emit("static int", 0) 11837db96d56Sopenharmony_ci self.emit("astmodule_exec(PyObject *m)", 0) 11847db96d56Sopenharmony_ci self.emit("{", 0) 11857db96d56Sopenharmony_ci self.emit('struct ast_state *state = get_ast_state();', 1) 11867db96d56Sopenharmony_ci self.emit('if (state == NULL) {', 1) 11877db96d56Sopenharmony_ci self.emit('return -1;', 2) 11887db96d56Sopenharmony_ci self.emit('}', 1) 11897db96d56Sopenharmony_ci self.emit('if (PyModule_AddObjectRef(m, "AST", state->AST_type) < 0) {', 1) 11907db96d56Sopenharmony_ci self.emit('return -1;', 2) 11917db96d56Sopenharmony_ci self.emit('}', 1) 11927db96d56Sopenharmony_ci self.emit('if (PyModule_AddIntMacro(m, PyCF_ALLOW_TOP_LEVEL_AWAIT) < 0) {', 1) 11937db96d56Sopenharmony_ci self.emit("return -1;", 2) 11947db96d56Sopenharmony_ci self.emit('}', 1) 11957db96d56Sopenharmony_ci self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0) {', 1) 11967db96d56Sopenharmony_ci self.emit("return -1;", 2) 11977db96d56Sopenharmony_ci self.emit('}', 1) 11987db96d56Sopenharmony_ci self.emit('if (PyModule_AddIntMacro(m, PyCF_TYPE_COMMENTS) < 0) {', 1) 11997db96d56Sopenharmony_ci self.emit("return -1;", 2) 12007db96d56Sopenharmony_ci self.emit('}', 1) 12017db96d56Sopenharmony_ci for dfn in mod.dfns: 12027db96d56Sopenharmony_ci self.visit(dfn) 12037db96d56Sopenharmony_ci self.emit("return 0;", 1) 12047db96d56Sopenharmony_ci self.emit("}", 0) 12057db96d56Sopenharmony_ci self.emit("", 0) 12067db96d56Sopenharmony_ci self.emit(""" 12077db96d56Sopenharmony_cistatic PyModuleDef_Slot astmodule_slots[] = { 12087db96d56Sopenharmony_ci {Py_mod_exec, astmodule_exec}, 12097db96d56Sopenharmony_ci {0, NULL} 12107db96d56Sopenharmony_ci}; 12117db96d56Sopenharmony_ci 12127db96d56Sopenharmony_cistatic struct PyModuleDef _astmodule = { 12137db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 12147db96d56Sopenharmony_ci .m_name = "_ast", 12157db96d56Sopenharmony_ci // The _ast module uses a per-interpreter state (PyInterpreterState.ast) 12167db96d56Sopenharmony_ci .m_size = 0, 12177db96d56Sopenharmony_ci .m_slots = astmodule_slots, 12187db96d56Sopenharmony_ci}; 12197db96d56Sopenharmony_ci 12207db96d56Sopenharmony_ciPyMODINIT_FUNC 12217db96d56Sopenharmony_ciPyInit__ast(void) 12227db96d56Sopenharmony_ci{ 12237db96d56Sopenharmony_ci return PyModuleDef_Init(&_astmodule); 12247db96d56Sopenharmony_ci} 12257db96d56Sopenharmony_ci""".strip(), 0, reflow=False) 12267db96d56Sopenharmony_ci 12277db96d56Sopenharmony_ci def visitProduct(self, prod, name): 12287db96d56Sopenharmony_ci self.addObj(name) 12297db96d56Sopenharmony_ci 12307db96d56Sopenharmony_ci def visitSum(self, sum, name): 12317db96d56Sopenharmony_ci self.addObj(name) 12327db96d56Sopenharmony_ci for t in sum.types: 12337db96d56Sopenharmony_ci self.visitConstructor(t, name) 12347db96d56Sopenharmony_ci 12357db96d56Sopenharmony_ci def visitConstructor(self, cons, name): 12367db96d56Sopenharmony_ci self.addObj(cons.name) 12377db96d56Sopenharmony_ci 12387db96d56Sopenharmony_ci def addObj(self, name): 12397db96d56Sopenharmony_ci self.emit("if (PyModule_AddObjectRef(m, \"%s\", " 12407db96d56Sopenharmony_ci "state->%s_type) < 0) {" % (name, name), 1) 12417db96d56Sopenharmony_ci self.emit("return -1;", 2) 12427db96d56Sopenharmony_ci self.emit('}', 1) 12437db96d56Sopenharmony_ci 12447db96d56Sopenharmony_ci 12457db96d56Sopenharmony_ciclass StaticVisitor(PickleVisitor): 12467db96d56Sopenharmony_ci CODE = '''Very simple, always emit this static code. Override CODE''' 12477db96d56Sopenharmony_ci 12487db96d56Sopenharmony_ci def visit(self, object): 12497db96d56Sopenharmony_ci self.emit(self.CODE, 0, reflow=False) 12507db96d56Sopenharmony_ci 12517db96d56Sopenharmony_ci 12527db96d56Sopenharmony_ciclass ObjVisitor(PickleVisitor): 12537db96d56Sopenharmony_ci 12547db96d56Sopenharmony_ci def func_begin(self, name): 12557db96d56Sopenharmony_ci ctype = get_c_type(name) 12567db96d56Sopenharmony_ci self.emit("PyObject*", 0) 12577db96d56Sopenharmony_ci self.emit("ast2obj_%s(struct ast_state *state, void* _o)" % (name), 0) 12587db96d56Sopenharmony_ci self.emit("{", 0) 12597db96d56Sopenharmony_ci self.emit("%s o = (%s)_o;" % (ctype, ctype), 1) 12607db96d56Sopenharmony_ci self.emit("PyObject *result = NULL, *value = NULL;", 1) 12617db96d56Sopenharmony_ci self.emit("PyTypeObject *tp;", 1) 12627db96d56Sopenharmony_ci self.emit('if (!o) {', 1) 12637db96d56Sopenharmony_ci self.emit("Py_RETURN_NONE;", 2) 12647db96d56Sopenharmony_ci self.emit("}", 1) 12657db96d56Sopenharmony_ci self.emit("if (++state->recursion_depth > state->recursion_limit) {", 1) 12667db96d56Sopenharmony_ci self.emit("PyErr_SetString(PyExc_RecursionError,", 2) 12677db96d56Sopenharmony_ci self.emit('"maximum recursion depth exceeded during ast construction");', 3) 12687db96d56Sopenharmony_ci self.emit("return 0;", 2) 12697db96d56Sopenharmony_ci self.emit("}", 1) 12707db96d56Sopenharmony_ci 12717db96d56Sopenharmony_ci def func_end(self): 12727db96d56Sopenharmony_ci self.emit("state->recursion_depth--;", 1) 12737db96d56Sopenharmony_ci self.emit("return result;", 1) 12747db96d56Sopenharmony_ci self.emit("failed:", 0) 12757db96d56Sopenharmony_ci self.emit("Py_XDECREF(value);", 1) 12767db96d56Sopenharmony_ci self.emit("Py_XDECREF(result);", 1) 12777db96d56Sopenharmony_ci self.emit("return NULL;", 1) 12787db96d56Sopenharmony_ci self.emit("}", 0) 12797db96d56Sopenharmony_ci self.emit("", 0) 12807db96d56Sopenharmony_ci 12817db96d56Sopenharmony_ci def visitSum(self, sum, name): 12827db96d56Sopenharmony_ci if is_simple(sum): 12837db96d56Sopenharmony_ci self.simpleSum(sum, name) 12847db96d56Sopenharmony_ci return 12857db96d56Sopenharmony_ci self.func_begin(name) 12867db96d56Sopenharmony_ci self.emit("switch (o->kind) {", 1) 12877db96d56Sopenharmony_ci for i in range(len(sum.types)): 12887db96d56Sopenharmony_ci t = sum.types[i] 12897db96d56Sopenharmony_ci self.visitConstructor(t, i + 1, name) 12907db96d56Sopenharmony_ci self.emit("}", 1) 12917db96d56Sopenharmony_ci for a in sum.attributes: 12927db96d56Sopenharmony_ci self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) 12937db96d56Sopenharmony_ci self.emit("if (!value) goto failed;", 1) 12947db96d56Sopenharmony_ci self.emit('if (PyObject_SetAttr(result, state->%s, value) < 0)' % a.name, 1) 12957db96d56Sopenharmony_ci self.emit('goto failed;', 2) 12967db96d56Sopenharmony_ci self.emit('Py_DECREF(value);', 1) 12977db96d56Sopenharmony_ci self.func_end() 12987db96d56Sopenharmony_ci 12997db96d56Sopenharmony_ci def simpleSum(self, sum, name): 13007db96d56Sopenharmony_ci self.emit("PyObject* ast2obj_%s(struct ast_state *state, %s_ty o)" % (name, name), 0) 13017db96d56Sopenharmony_ci self.emit("{", 0) 13027db96d56Sopenharmony_ci self.emit("switch(o) {", 1) 13037db96d56Sopenharmony_ci for t in sum.types: 13047db96d56Sopenharmony_ci self.emit("case %s:" % t.name, 2) 13057db96d56Sopenharmony_ci self.emit("Py_INCREF(state->%s_singleton);" % t.name, 3) 13067db96d56Sopenharmony_ci self.emit("return state->%s_singleton;" % t.name, 3) 13077db96d56Sopenharmony_ci self.emit("}", 1) 13087db96d56Sopenharmony_ci self.emit("Py_UNREACHABLE();", 1); 13097db96d56Sopenharmony_ci self.emit("}", 0) 13107db96d56Sopenharmony_ci 13117db96d56Sopenharmony_ci def visitProduct(self, prod, name): 13127db96d56Sopenharmony_ci self.func_begin(name) 13137db96d56Sopenharmony_ci self.emit("tp = (PyTypeObject *)state->%s_type;" % name, 1) 13147db96d56Sopenharmony_ci self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 1); 13157db96d56Sopenharmony_ci self.emit("if (!result) return NULL;", 1) 13167db96d56Sopenharmony_ci for field in prod.fields: 13177db96d56Sopenharmony_ci self.visitField(field, name, 1, True) 13187db96d56Sopenharmony_ci for a in prod.attributes: 13197db96d56Sopenharmony_ci self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) 13207db96d56Sopenharmony_ci self.emit("if (!value) goto failed;", 1) 13217db96d56Sopenharmony_ci self.emit("if (PyObject_SetAttr(result, state->%s, value) < 0)" % a.name, 1) 13227db96d56Sopenharmony_ci self.emit('goto failed;', 2) 13237db96d56Sopenharmony_ci self.emit('Py_DECREF(value);', 1) 13247db96d56Sopenharmony_ci self.func_end() 13257db96d56Sopenharmony_ci 13267db96d56Sopenharmony_ci def visitConstructor(self, cons, enum, name): 13277db96d56Sopenharmony_ci self.emit("case %s_kind:" % cons.name, 1) 13287db96d56Sopenharmony_ci self.emit("tp = (PyTypeObject *)state->%s_type;" % cons.name, 2) 13297db96d56Sopenharmony_ci self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 2); 13307db96d56Sopenharmony_ci self.emit("if (!result) goto failed;", 2) 13317db96d56Sopenharmony_ci for f in cons.fields: 13327db96d56Sopenharmony_ci self.visitField(f, cons.name, 2, False) 13337db96d56Sopenharmony_ci self.emit("break;", 2) 13347db96d56Sopenharmony_ci 13357db96d56Sopenharmony_ci def visitField(self, field, name, depth, product): 13367db96d56Sopenharmony_ci def emit(s, d): 13377db96d56Sopenharmony_ci self.emit(s, depth + d) 13387db96d56Sopenharmony_ci if product: 13397db96d56Sopenharmony_ci value = "o->%s" % field.name 13407db96d56Sopenharmony_ci else: 13417db96d56Sopenharmony_ci value = "o->v.%s.%s" % (name, field.name) 13427db96d56Sopenharmony_ci self.set(field, value, depth) 13437db96d56Sopenharmony_ci emit("if (!value) goto failed;", 0) 13447db96d56Sopenharmony_ci emit("if (PyObject_SetAttr(result, state->%s, value) == -1)" % field.name, 0) 13457db96d56Sopenharmony_ci emit("goto failed;", 1) 13467db96d56Sopenharmony_ci emit("Py_DECREF(value);", 0) 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ci def set(self, field, value, depth): 13497db96d56Sopenharmony_ci if field.seq: 13507db96d56Sopenharmony_ci if field.type in self.metadata.simple_sums: 13517db96d56Sopenharmony_ci # While the sequence elements are stored as void*, 13527db96d56Sopenharmony_ci # simple sums expects an enum 13537db96d56Sopenharmony_ci self.emit("{", depth) 13547db96d56Sopenharmony_ci self.emit("Py_ssize_t i, n = asdl_seq_LEN(%s);" % value, depth+1) 13557db96d56Sopenharmony_ci self.emit("value = PyList_New(n);", depth+1) 13567db96d56Sopenharmony_ci self.emit("if (!value) goto failed;", depth+1) 13577db96d56Sopenharmony_ci self.emit("for(i = 0; i < n; i++)", depth+1) 13587db96d56Sopenharmony_ci # This cannot fail, so no need for error handling 13597db96d56Sopenharmony_ci self.emit( 13607db96d56Sopenharmony_ci "PyList_SET_ITEM(value, i, ast2obj_{0}(state, ({0}_ty)asdl_seq_GET({1}, i)));".format( 13617db96d56Sopenharmony_ci field.type, 13627db96d56Sopenharmony_ci value 13637db96d56Sopenharmony_ci ), 13647db96d56Sopenharmony_ci depth + 2, 13657db96d56Sopenharmony_ci reflow=False, 13667db96d56Sopenharmony_ci ) 13677db96d56Sopenharmony_ci self.emit("}", depth) 13687db96d56Sopenharmony_ci else: 13697db96d56Sopenharmony_ci self.emit("value = ast2obj_list(state, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth) 13707db96d56Sopenharmony_ci else: 13717db96d56Sopenharmony_ci self.emit("value = ast2obj_%s(state, %s);" % (field.type, value), depth, reflow=False) 13727db96d56Sopenharmony_ci 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ciclass PartingShots(StaticVisitor): 13757db96d56Sopenharmony_ci 13767db96d56Sopenharmony_ci CODE = """ 13777db96d56Sopenharmony_ciPyObject* PyAST_mod2obj(mod_ty t) 13787db96d56Sopenharmony_ci{ 13797db96d56Sopenharmony_ci struct ast_state *state = get_ast_state(); 13807db96d56Sopenharmony_ci if (state == NULL) { 13817db96d56Sopenharmony_ci return NULL; 13827db96d56Sopenharmony_ci } 13837db96d56Sopenharmony_ci 13847db96d56Sopenharmony_ci int recursion_limit = Py_GetRecursionLimit(); 13857db96d56Sopenharmony_ci int starting_recursion_depth; 13867db96d56Sopenharmony_ci /* Be careful here to prevent overflow. */ 13877db96d56Sopenharmony_ci int COMPILER_STACK_FRAME_SCALE = 3; 13887db96d56Sopenharmony_ci PyThreadState *tstate = _PyThreadState_GET(); 13897db96d56Sopenharmony_ci if (!tstate) { 13907db96d56Sopenharmony_ci return 0; 13917db96d56Sopenharmony_ci } 13927db96d56Sopenharmony_ci state->recursion_limit = (recursion_limit < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? 13937db96d56Sopenharmony_ci recursion_limit * COMPILER_STACK_FRAME_SCALE : recursion_limit; 13947db96d56Sopenharmony_ci int recursion_depth = tstate->recursion_limit - tstate->recursion_remaining; 13957db96d56Sopenharmony_ci starting_recursion_depth = (recursion_depth < INT_MAX / COMPILER_STACK_FRAME_SCALE) ? 13967db96d56Sopenharmony_ci recursion_depth * COMPILER_STACK_FRAME_SCALE : recursion_depth; 13977db96d56Sopenharmony_ci state->recursion_depth = starting_recursion_depth; 13987db96d56Sopenharmony_ci 13997db96d56Sopenharmony_ci PyObject *result = ast2obj_mod(state, t); 14007db96d56Sopenharmony_ci 14017db96d56Sopenharmony_ci /* Check that the recursion depth counting balanced correctly */ 14027db96d56Sopenharmony_ci if (result && state->recursion_depth != starting_recursion_depth) { 14037db96d56Sopenharmony_ci PyErr_Format(PyExc_SystemError, 14047db96d56Sopenharmony_ci "AST constructor recursion depth mismatch (before=%d, after=%d)", 14057db96d56Sopenharmony_ci starting_recursion_depth, state->recursion_depth); 14067db96d56Sopenharmony_ci return 0; 14077db96d56Sopenharmony_ci } 14087db96d56Sopenharmony_ci return result; 14097db96d56Sopenharmony_ci} 14107db96d56Sopenharmony_ci 14117db96d56Sopenharmony_ci/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */ 14127db96d56Sopenharmony_cimod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) 14137db96d56Sopenharmony_ci{ 14147db96d56Sopenharmony_ci const char * const req_name[] = {"Module", "Expression", "Interactive"}; 14157db96d56Sopenharmony_ci int isinstance; 14167db96d56Sopenharmony_ci 14177db96d56Sopenharmony_ci if (PySys_Audit("compile", "OO", ast, Py_None) < 0) { 14187db96d56Sopenharmony_ci return NULL; 14197db96d56Sopenharmony_ci } 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci struct ast_state *state = get_ast_state(); 14227db96d56Sopenharmony_ci if (state == NULL) { 14237db96d56Sopenharmony_ci return NULL; 14247db96d56Sopenharmony_ci } 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci PyObject *req_type[3]; 14277db96d56Sopenharmony_ci req_type[0] = state->Module_type; 14287db96d56Sopenharmony_ci req_type[1] = state->Expression_type; 14297db96d56Sopenharmony_ci req_type[2] = state->Interactive_type; 14307db96d56Sopenharmony_ci 14317db96d56Sopenharmony_ci assert(0 <= mode && mode <= 2); 14327db96d56Sopenharmony_ci 14337db96d56Sopenharmony_ci isinstance = PyObject_IsInstance(ast, req_type[mode]); 14347db96d56Sopenharmony_ci if (isinstance == -1) 14357db96d56Sopenharmony_ci return NULL; 14367db96d56Sopenharmony_ci if (!isinstance) { 14377db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s", 14387db96d56Sopenharmony_ci req_name[mode], _PyType_Name(Py_TYPE(ast))); 14397db96d56Sopenharmony_ci return NULL; 14407db96d56Sopenharmony_ci } 14417db96d56Sopenharmony_ci 14427db96d56Sopenharmony_ci mod_ty res = NULL; 14437db96d56Sopenharmony_ci if (obj2ast_mod(state, ast, &res, arena) != 0) 14447db96d56Sopenharmony_ci return NULL; 14457db96d56Sopenharmony_ci else 14467db96d56Sopenharmony_ci return res; 14477db96d56Sopenharmony_ci} 14487db96d56Sopenharmony_ci 14497db96d56Sopenharmony_ciint PyAST_Check(PyObject* obj) 14507db96d56Sopenharmony_ci{ 14517db96d56Sopenharmony_ci struct ast_state *state = get_ast_state(); 14527db96d56Sopenharmony_ci if (state == NULL) { 14537db96d56Sopenharmony_ci return -1; 14547db96d56Sopenharmony_ci } 14557db96d56Sopenharmony_ci return PyObject_IsInstance(obj, state->AST_type); 14567db96d56Sopenharmony_ci} 14577db96d56Sopenharmony_ci""" 14587db96d56Sopenharmony_ci 14597db96d56Sopenharmony_ciclass ChainOfVisitors: 14607db96d56Sopenharmony_ci def __init__(self, *visitors, metadata = None): 14617db96d56Sopenharmony_ci self.visitors = visitors 14627db96d56Sopenharmony_ci self.metadata = metadata 14637db96d56Sopenharmony_ci 14647db96d56Sopenharmony_ci def visit(self, object): 14657db96d56Sopenharmony_ci for v in self.visitors: 14667db96d56Sopenharmony_ci v.metadata = self.metadata 14677db96d56Sopenharmony_ci v.visit(object) 14687db96d56Sopenharmony_ci v.emit("", 0) 14697db96d56Sopenharmony_ci 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_cidef generate_ast_state(module_state, f): 14727db96d56Sopenharmony_ci f.write('struct ast_state {\n') 14737db96d56Sopenharmony_ci f.write(' int initialized;\n') 14747db96d56Sopenharmony_ci f.write(' int recursion_depth;\n') 14757db96d56Sopenharmony_ci f.write(' int recursion_limit;\n') 14767db96d56Sopenharmony_ci for s in module_state: 14777db96d56Sopenharmony_ci f.write(' PyObject *' + s + ';\n') 14787db96d56Sopenharmony_ci f.write('};') 14797db96d56Sopenharmony_ci 14807db96d56Sopenharmony_ci 14817db96d56Sopenharmony_cidef generate_ast_fini(module_state, f): 14827db96d56Sopenharmony_ci f.write(textwrap.dedent(""" 14837db96d56Sopenharmony_ci void _PyAST_Fini(PyInterpreterState *interp) 14847db96d56Sopenharmony_ci { 14857db96d56Sopenharmony_ci struct ast_state *state = &interp->ast; 14867db96d56Sopenharmony_ci 14877db96d56Sopenharmony_ci """)) 14887db96d56Sopenharmony_ci for s in module_state: 14897db96d56Sopenharmony_ci f.write(" Py_CLEAR(state->" + s + ');\n') 14907db96d56Sopenharmony_ci f.write(textwrap.dedent(""" 14917db96d56Sopenharmony_ci #if !defined(NDEBUG) 14927db96d56Sopenharmony_ci state->initialized = -1; 14937db96d56Sopenharmony_ci #else 14947db96d56Sopenharmony_ci state->initialized = 0; 14957db96d56Sopenharmony_ci #endif 14967db96d56Sopenharmony_ci } 14977db96d56Sopenharmony_ci 14987db96d56Sopenharmony_ci """)) 14997db96d56Sopenharmony_ci 15007db96d56Sopenharmony_ci 15017db96d56Sopenharmony_cidef generate_module_def(mod, metadata, f, internal_h): 15027db96d56Sopenharmony_ci # Gather all the data needed for ModuleSpec 15037db96d56Sopenharmony_ci state_strings = { 15047db96d56Sopenharmony_ci "ast", 15057db96d56Sopenharmony_ci "_fields", 15067db96d56Sopenharmony_ci "__match_args__", 15077db96d56Sopenharmony_ci "__doc__", 15087db96d56Sopenharmony_ci "__dict__", 15097db96d56Sopenharmony_ci "__module__", 15107db96d56Sopenharmony_ci "_attributes", 15117db96d56Sopenharmony_ci *metadata.identifiers 15127db96d56Sopenharmony_ci } 15137db96d56Sopenharmony_ci 15147db96d56Sopenharmony_ci module_state = state_strings.copy() 15157db96d56Sopenharmony_ci module_state.update( 15167db96d56Sopenharmony_ci "%s_singleton" % singleton 15177db96d56Sopenharmony_ci for singleton in metadata.singletons 15187db96d56Sopenharmony_ci ) 15197db96d56Sopenharmony_ci module_state.update( 15207db96d56Sopenharmony_ci "%s_type" % type 15217db96d56Sopenharmony_ci for type in metadata.types 15227db96d56Sopenharmony_ci ) 15237db96d56Sopenharmony_ci 15247db96d56Sopenharmony_ci state_strings = sorted(state_strings) 15257db96d56Sopenharmony_ci module_state = sorted(module_state) 15267db96d56Sopenharmony_ci 15277db96d56Sopenharmony_ci generate_ast_state(module_state, internal_h) 15287db96d56Sopenharmony_ci 15297db96d56Sopenharmony_ci print(textwrap.dedent(""" 15307db96d56Sopenharmony_ci #include "Python.h" 15317db96d56Sopenharmony_ci #include "pycore_ast.h" 15327db96d56Sopenharmony_ci #include "pycore_ast_state.h" // struct ast_state 15337db96d56Sopenharmony_ci #include "pycore_ceval.h" // _Py_EnterRecursiveCall 15347db96d56Sopenharmony_ci #include "pycore_interp.h" // _PyInterpreterState.ast 15357db96d56Sopenharmony_ci #include "pycore_pystate.h" // _PyInterpreterState_GET() 15367db96d56Sopenharmony_ci #include "structmember.h" 15377db96d56Sopenharmony_ci #include <stddef.h> 15387db96d56Sopenharmony_ci 15397db96d56Sopenharmony_ci // Forward declaration 15407db96d56Sopenharmony_ci static int init_types(struct ast_state *state); 15417db96d56Sopenharmony_ci 15427db96d56Sopenharmony_ci static struct ast_state* 15437db96d56Sopenharmony_ci get_ast_state(void) 15447db96d56Sopenharmony_ci { 15457db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterState_GET(); 15467db96d56Sopenharmony_ci struct ast_state *state = &interp->ast; 15477db96d56Sopenharmony_ci if (!init_types(state)) { 15487db96d56Sopenharmony_ci return NULL; 15497db96d56Sopenharmony_ci } 15507db96d56Sopenharmony_ci return state; 15517db96d56Sopenharmony_ci } 15527db96d56Sopenharmony_ci """).strip(), file=f) 15537db96d56Sopenharmony_ci 15547db96d56Sopenharmony_ci generate_ast_fini(module_state, f) 15557db96d56Sopenharmony_ci 15567db96d56Sopenharmony_ci f.write('static int init_identifiers(struct ast_state *state)\n') 15577db96d56Sopenharmony_ci f.write('{\n') 15587db96d56Sopenharmony_ci for identifier in state_strings: 15597db96d56Sopenharmony_ci f.write(' if ((state->' + identifier) 15607db96d56Sopenharmony_ci f.write(' = PyUnicode_InternFromString("') 15617db96d56Sopenharmony_ci f.write(identifier + '")) == NULL) return 0;\n') 15627db96d56Sopenharmony_ci f.write(' return 1;\n') 15637db96d56Sopenharmony_ci f.write('};\n\n') 15647db96d56Sopenharmony_ci 15657db96d56Sopenharmony_cidef write_header(mod, metadata, f): 15667db96d56Sopenharmony_ci f.write(textwrap.dedent(""" 15677db96d56Sopenharmony_ci #ifndef Py_INTERNAL_AST_H 15687db96d56Sopenharmony_ci #define Py_INTERNAL_AST_H 15697db96d56Sopenharmony_ci #ifdef __cplusplus 15707db96d56Sopenharmony_ci extern "C" { 15717db96d56Sopenharmony_ci #endif 15727db96d56Sopenharmony_ci 15737db96d56Sopenharmony_ci #ifndef Py_BUILD_CORE 15747db96d56Sopenharmony_ci # error "this header requires Py_BUILD_CORE define" 15757db96d56Sopenharmony_ci #endif 15767db96d56Sopenharmony_ci 15777db96d56Sopenharmony_ci #include "pycore_asdl.h" 15787db96d56Sopenharmony_ci 15797db96d56Sopenharmony_ci """).lstrip()) 15807db96d56Sopenharmony_ci 15817db96d56Sopenharmony_ci c = ChainOfVisitors( 15827db96d56Sopenharmony_ci TypeDefVisitor(f), 15837db96d56Sopenharmony_ci SequenceDefVisitor(f), 15847db96d56Sopenharmony_ci StructVisitor(f), 15857db96d56Sopenharmony_ci metadata=metadata 15867db96d56Sopenharmony_ci ) 15877db96d56Sopenharmony_ci c.visit(mod) 15887db96d56Sopenharmony_ci 15897db96d56Sopenharmony_ci f.write("// Note: these macros affect function definitions, not only call sites.\n") 15907db96d56Sopenharmony_ci prototype_visitor = PrototypeVisitor(f, metadata=metadata) 15917db96d56Sopenharmony_ci prototype_visitor.visit(mod) 15927db96d56Sopenharmony_ci 15937db96d56Sopenharmony_ci f.write(textwrap.dedent(""" 15947db96d56Sopenharmony_ci 15957db96d56Sopenharmony_ci PyObject* PyAST_mod2obj(mod_ty t); 15967db96d56Sopenharmony_ci mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode); 15977db96d56Sopenharmony_ci int PyAST_Check(PyObject* obj); 15987db96d56Sopenharmony_ci 15997db96d56Sopenharmony_ci extern int _PyAST_Validate(mod_ty); 16007db96d56Sopenharmony_ci 16017db96d56Sopenharmony_ci /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ 16027db96d56Sopenharmony_ci extern PyObject* _PyAST_ExprAsUnicode(expr_ty); 16037db96d56Sopenharmony_ci 16047db96d56Sopenharmony_ci /* Return the borrowed reference to the first literal string in the 16057db96d56Sopenharmony_ci sequence of statements or NULL if it doesn't start from a literal string. 16067db96d56Sopenharmony_ci Doesn't set exception. */ 16077db96d56Sopenharmony_ci extern PyObject* _PyAST_GetDocString(asdl_stmt_seq *); 16087db96d56Sopenharmony_ci 16097db96d56Sopenharmony_ci #ifdef __cplusplus 16107db96d56Sopenharmony_ci } 16117db96d56Sopenharmony_ci #endif 16127db96d56Sopenharmony_ci #endif /* !Py_INTERNAL_AST_H */ 16137db96d56Sopenharmony_ci """)) 16147db96d56Sopenharmony_ci 16157db96d56Sopenharmony_ci 16167db96d56Sopenharmony_cidef write_internal_h_header(mod, f): 16177db96d56Sopenharmony_ci print(textwrap.dedent(""" 16187db96d56Sopenharmony_ci #ifndef Py_INTERNAL_AST_STATE_H 16197db96d56Sopenharmony_ci #define Py_INTERNAL_AST_STATE_H 16207db96d56Sopenharmony_ci #ifdef __cplusplus 16217db96d56Sopenharmony_ci extern "C" { 16227db96d56Sopenharmony_ci #endif 16237db96d56Sopenharmony_ci 16247db96d56Sopenharmony_ci #ifndef Py_BUILD_CORE 16257db96d56Sopenharmony_ci # error "this header requires Py_BUILD_CORE define" 16267db96d56Sopenharmony_ci #endif 16277db96d56Sopenharmony_ci """).lstrip(), file=f) 16287db96d56Sopenharmony_ci 16297db96d56Sopenharmony_ci 16307db96d56Sopenharmony_cidef write_internal_h_footer(mod, f): 16317db96d56Sopenharmony_ci print(textwrap.dedent(""" 16327db96d56Sopenharmony_ci 16337db96d56Sopenharmony_ci #ifdef __cplusplus 16347db96d56Sopenharmony_ci } 16357db96d56Sopenharmony_ci #endif 16367db96d56Sopenharmony_ci #endif /* !Py_INTERNAL_AST_STATE_H */ 16377db96d56Sopenharmony_ci """), file=f) 16387db96d56Sopenharmony_ci 16397db96d56Sopenharmony_cidef write_source(mod, metadata, f, internal_h_file): 16407db96d56Sopenharmony_ci generate_module_def(mod, metadata, f, internal_h_file) 16417db96d56Sopenharmony_ci 16427db96d56Sopenharmony_ci v = ChainOfVisitors( 16437db96d56Sopenharmony_ci SequenceConstructorVisitor(f), 16447db96d56Sopenharmony_ci PyTypesDeclareVisitor(f), 16457db96d56Sopenharmony_ci PyTypesVisitor(f), 16467db96d56Sopenharmony_ci Obj2ModPrototypeVisitor(f), 16477db96d56Sopenharmony_ci FunctionVisitor(f), 16487db96d56Sopenharmony_ci ObjVisitor(f), 16497db96d56Sopenharmony_ci Obj2ModVisitor(f), 16507db96d56Sopenharmony_ci ASTModuleVisitor(f), 16517db96d56Sopenharmony_ci PartingShots(f), 16527db96d56Sopenharmony_ci metadata=metadata 16537db96d56Sopenharmony_ci ) 16547db96d56Sopenharmony_ci v.visit(mod) 16557db96d56Sopenharmony_ci 16567db96d56Sopenharmony_cidef main(input_filename, c_filename, h_filename, internal_h_filename, dump_module=False): 16577db96d56Sopenharmony_ci auto_gen_msg = AUTOGEN_MESSAGE.format("/".join(Path(__file__).parts[-2:])) 16587db96d56Sopenharmony_ci mod = asdl.parse(input_filename) 16597db96d56Sopenharmony_ci if dump_module: 16607db96d56Sopenharmony_ci print('Parsed Module:') 16617db96d56Sopenharmony_ci print(mod) 16627db96d56Sopenharmony_ci if not asdl.check(mod): 16637db96d56Sopenharmony_ci sys.exit(1) 16647db96d56Sopenharmony_ci 16657db96d56Sopenharmony_ci metadata_visitor = MetadataVisitor() 16667db96d56Sopenharmony_ci metadata_visitor.visit(mod) 16677db96d56Sopenharmony_ci metadata = metadata_visitor.metadata 16687db96d56Sopenharmony_ci 16697db96d56Sopenharmony_ci with c_filename.open("w") as c_file, \ 16707db96d56Sopenharmony_ci h_filename.open("w") as h_file, \ 16717db96d56Sopenharmony_ci internal_h_filename.open("w") as internal_h_file: 16727db96d56Sopenharmony_ci c_file.write(auto_gen_msg) 16737db96d56Sopenharmony_ci h_file.write(auto_gen_msg) 16747db96d56Sopenharmony_ci internal_h_file.write(auto_gen_msg) 16757db96d56Sopenharmony_ci 16767db96d56Sopenharmony_ci write_internal_h_header(mod, internal_h_file) 16777db96d56Sopenharmony_ci write_source(mod, metadata, c_file, internal_h_file) 16787db96d56Sopenharmony_ci write_header(mod, metadata, h_file) 16797db96d56Sopenharmony_ci write_internal_h_footer(mod, internal_h_file) 16807db96d56Sopenharmony_ci 16817db96d56Sopenharmony_ci print(f"{c_filename}, {h_filename}, {internal_h_filename} regenerated.") 16827db96d56Sopenharmony_ci 16837db96d56Sopenharmony_ciif __name__ == "__main__": 16847db96d56Sopenharmony_ci parser = ArgumentParser() 16857db96d56Sopenharmony_ci parser.add_argument("input_file", type=Path) 16867db96d56Sopenharmony_ci parser.add_argument("-C", "--c-file", type=Path, required=True) 16877db96d56Sopenharmony_ci parser.add_argument("-H", "--h-file", type=Path, required=True) 16887db96d56Sopenharmony_ci parser.add_argument("-I", "--internal-h-file", type=Path, required=True) 16897db96d56Sopenharmony_ci parser.add_argument("-d", "--dump-module", action="store_true") 16907db96d56Sopenharmony_ci 16917db96d56Sopenharmony_ci args = parser.parse_args() 16927db96d56Sopenharmony_ci main(args.input_file, args.c_file, args.h_file, 16937db96d56Sopenharmony_ci args.internal_h_file, args.dump_module) 1694