| 772 | |
| 773 | |
| 774 | class AnnotationsVisitor(PickleVisitor): |
| 775 | def visitModule(self, mod): |
| 776 | self.file.write(textwrap.dedent(''' |
| 777 | static int |
| 778 | add_ast_annotations(struct ast_state *state) |
| 779 | { |
| 780 | bool cond; |
| 781 | ''')) |
| 782 | for dfn in mod.dfns: |
| 783 | self.visit(dfn) |
| 784 | self.file.write(textwrap.dedent(''' |
| 785 | return 1; |
| 786 | } |
| 787 | ''')) |
| 788 | |
| 789 | def visitProduct(self, prod, name): |
| 790 | self.emit_annotations(name, prod.fields) |
| 791 | |
| 792 | def visitSum(self, sum, name): |
| 793 | for t in sum.types: |
| 794 | self.visitConstructor(t, name) |
| 795 | |
| 796 | def visitConstructor(self, cons, name): |
| 797 | self.emit_annotations(cons.name, cons.fields) |
| 798 | |
| 799 | def emit_annotations(self, name, fields): |
| 800 | self.emit(f"PyObject *{name}_annotations = PyDict_New();", 1) |
| 801 | self.emit(f"if (!{name}_annotations) return 0;", 1) |
| 802 | for field in fields: |
| 803 | self.emit("{", 1) |
| 804 | if field.type in builtin_type_to_c_type: |
| 805 | self.emit(f"PyObject *type = (PyObject *)&{builtin_type_to_c_type[field.type]};", 2) |
| 806 | else: |
| 807 | self.emit(f"PyObject *type = state->{field.type}_type;", 2) |
| 808 | if field.opt: |
| 809 | self.emit("type = _Py_union_type_or(type, Py_None);", 2) |
| 810 | self.emit("cond = type != NULL;", 2) |
| 811 | self.emit_annotations_error(name, 2) |
| 812 | elif field.seq: |
| 813 | self.emit("type = Py_GenericAlias((PyObject *)&PyList_Type, type);", 2) |
| 814 | self.emit("cond = type != NULL;", 2) |
| 815 | self.emit_annotations_error(name, 2) |
| 816 | else: |
| 817 | self.emit("Py_INCREF(type);", 2) |
| 818 | self.emit(f"cond = PyDict_SetItemString({name}_annotations, \"{field.name}\", type) == 0;", 2) |
| 819 | self.emit("Py_DECREF(type);", 2) |
| 820 | self.emit_annotations_error(name, 2) |
| 821 | self.emit("}", 1) |
| 822 | self.emit(f'cond = PyObject_SetAttrString(state->{name}_type, "_field_types", {name}_annotations) == 0;', 1) |
| 823 | self.emit_annotations_error(name, 1) |
| 824 | self.emit(f'cond = PyObject_SetAttrString(state->{name}_type, "__annotations__", {name}_annotations) == 0;', 1) |
| 825 | self.emit_annotations_error(name, 1) |
| 826 | self.emit(f"Py_DECREF({name}_annotations);", 1) |
| 827 | |
| 828 | def emit_annotations_error(self, name, depth): |
| 829 | self.emit("if (!cond) {", depth) |
| 830 | self.emit(f"Py_DECREF({name}_annotations);", depth + 1) |
| 831 | self.emit("return 0;", depth + 1) |
no outgoing calls
no test coverage detected
searching dependent graphs…