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