From b76a0284c499247f96c2ea14cdc14891d802224f Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Sun, 10 Jan 2021 16:32:10 -0600 Subject: [PATCH] Implement ast->obj functionality of the ast module --- ast/asdl_rs.py | 1420 ++++------------------------- ast/src/constant.rs | 18 +- scripts/update_asdl.sh | 8 + vm/src/iterator.rs | 13 +- vm/src/stdlib/ast.rs | 762 +++------------- vm/src/stdlib/ast/gen.rs | 1825 ++++++++++++++++++++++++++++++++++++++ vm/src/vm.rs | 15 +- 7 files changed, 2127 insertions(+), 1934 deletions(-) create mode 100755 scripts/update_asdl.sh create mode 100644 vm/src/stdlib/ast/gen.rs diff --git a/ast/asdl_rs.py b/ast/asdl_rs.py index 737d1e44b..e09bbf14a 100755 --- a/ast/asdl_rs.py +++ b/ast/asdl_rs.py @@ -5,6 +5,8 @@ import os import sys import textwrap +import json + from argparse import ArgumentParser from pathlib import Path @@ -145,7 +147,13 @@ class FindUserdataTypesVisitor(asdl.VisitorBase): def add_children(self, name, fields): self.typeinfo[name].children.update((field.type, field.seq) for field in fields) - + +def rust_field(field_name): + if field_name == 'type': + return 'type_' + else: + return field_name + class StructVisitor(EmitVisitor): """Visitor to generate typedefs for AST.""" @@ -216,9 +224,7 @@ class StructVisitor(EmitVisitor): typ = f"Option<{typ}>" if field.seq: typ = f"Vec<{typ}>" - name = field.name - if name == 'type': - name = 'type_' + name = rust_field(field.name) self.emit(f"{vis}{name}: {typ},", depth) def visitProduct(self, product, name, depth): @@ -243,1241 +249,154 @@ class StructVisitor(EmitVisitor): else: return "", "" -class PrototypeVisitor(EmitVisitor): - """Generate function prototypes for the .h file""" +class ClassDefVisitor(EmitVisitor): def visitModule(self, mod): for dfn in mod.dfns: self.visit(dfn) - def visitType(self, type): - self.visit(type.value, type.name) + def visitType(self, type, depth=0): + self.visit(type.value, type.name, depth) - def visitSum(self, sum, name): - if is_simple(sum): - pass # XXX - else: - for t in sum.types: - self.visit(t, name, sum.attributes) + def visitSum(self, sum, name, depth): + for cons in sum.types: + self.visit(cons, sum.attributes, depth) - def get_args(self, fields): - """Return list of C argument into, one for each field. + def visitConstructor(self, cons, attrs, depth): + self.gen_classdef(cons.name, cons.fields, attrs, depth) - Argument info is 3-tuple of a C type, variable name, and flag - that is true if type can be NULL. - """ - args = [] - unnamed = {} + def visitProduct(self, product, name, depth): + self.gen_classdef(name, product.fields, product.attributes, depth) + + def gen_classdef(self, name, fields, attrs, depth): + structname = "Node" + name + self.emit(f'#[pyclass(module = "_ast", name = {json.dumps(name)}, base = "AstNode")]', depth) + self.emit(f"struct {structname};", depth) + self.emit("#[pyimpl(flags(HAS_DICT))]", depth) + self.emit(f"impl {structname} {{", depth) + self.emit(f"#[extend_class]", depth + 1) + self.emit("fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) {", depth + 1) + fields = ",".join(f"ctx.new_str({json.dumps(f.name)})" for f in fields) + self.emit(f'class.set_str_attr("_fields", ctx.new_list(vec![{fields}]));', depth + 2) + attrs = ",".join(f"ctx.new_str({json.dumps(attr.name)})" for attr in attrs) + self.emit(f'class.set_str_attr("_attributes", ctx.new_list(vec![{fields}]));', depth + 2) + self.emit("}", depth + 1) + self.emit("}", depth) + +class ExtendModuleVisitor(EmitVisitor): + + def visitModule(self, mod): + depth = 0 + self.emit("pub fn extend_module_nodes(vm: &VirtualMachine, module: &PyObjectRef) {", depth) + self.emit("extend_module!(vm, module, {", depth + 1) + for dfn in mod.dfns: + self.visit(dfn, depth + 2) + self.emit("})", depth + 1) + self.emit("}", depth) + + def visitType(self, type, depth): + self.visit(type.value, type.name, depth) + + def visitSum(self, sum, name, depth): + for cons in sum.types: + self.visit(cons, depth) + + def visitConstructor(self, cons, depth): + self.gen_extension(cons.name, depth) + + def visitProduct(self, product, name, depth): + self.gen_extension(name, depth) + + def gen_extension(self, name, depth): + self.emit(f"{json.dumps(name)} => Node{name}::make_class(&vm.ctx),", depth) + + +class TraitImplVisitor(EmitVisitor): + def __init__(self, file, typeinfo): + self.typeinfo = typeinfo + super().__init__(file) + + def visitModule(self, mod): + for dfn in mod.dfns: + self.visit(dfn) + + def visitType(self, type, depth=0): + self.visit(type.value, type.name, depth) + + def visitSum(self, sum, name, depth): + rustname = enumname = get_rust_type(name) + node = "self" + if sum.attributes: + enumname = rustname + "Kind" + node = "self.node" + + self.emit(f"impl Node for ast::{rustname} {{", depth) + self.emit("fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {", depth + 1) + self.emit(f"let node = match {node} {{", depth + 2) + for variant in sum.types: + self.constructor_to_object(variant, enumname, depth + 3) + self.emit("};", depth + 2) + if sum.attributes: + self.add_location(depth + 2) + self.emit("node.into_object()", depth + 2) + self.emit("}", depth + 1) + self.emit("fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult {", depth + 1) + self.emit("todo!()", depth + 2) + self.emit("}", depth + 1) + self.emit("}", depth) + + def constructor_to_object(self, cons, enumname, depth): + fields_pattern = self.make_pattern(cons.fields) + self.emit(f"ast::{enumname}::{cons.name} {{ {fields_pattern} }} => {{", depth) + self.make_node(cons.name, cons.fields, depth + 1) + self.emit("}", depth) + + def visitProduct(self, product, name, depth): + rustname = structname = get_rust_type(name) + node = "self" + if product.attributes: + structname = rustname + "Data" + node = "self.node" + + self.emit(f"impl Node for ast::{rustname} {{", depth) + self.emit("fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef {", depth + 1) + fields_pattern = self.make_pattern(product.fields) + self.emit("let node = {", depth + 2) + self.emit(f"let ast::{structname} {{ {fields_pattern} }} = {node};", depth + 3) + self.make_node(name, product.fields, depth + 3) + self.emit("};", depth + 2) + if product.attributes: + self.add_location(depth + 2) + self.emit("node.into_object()", depth + 2) + self.emit("}", depth + 1) + self.emit("fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult {", depth + 1) + self.emit("todo!()", depth + 2) + self.emit("}", depth + 1) + self.emit("}", depth) + + def make_node(self, variant, fields, depth): + lines = [] + self.emit(f"let _node = AstNode.into_ref_with_type(_vm, Node{variant}::static_type().clone()).unwrap();", depth) + if fields: + self.emit("let _dict = _node.as_object().dict().unwrap();", depth) for f in fields: - if f.name is None: - name = f.type - c = unnamed[name] = unnamed.get(name, 0) + 1 - if c > 1: - name = "name%d" % (c - 1) - else: - name = f.name - # XXX should extend get_c_type() to handle this - if f.seq: - if f.type == 'cmpop': - ctype = "asdl_int_seq *" - else: - ctype = f"asdl_{f.type}_seq *" - else: - ctype = get_c_type(f.type) - args.append((ctype, name, f.opt or f.seq)) - return args + self.emit(f"_dict.set_item({json.dumps(f.name)}, {rust_field(f.name)}.ast_to_object(_vm), _vm).unwrap();", depth) + self.emit("_node", depth) - def visitConstructor(self, cons, type, attrs): - args = self.get_args(cons.fields) - attrs = self.get_args(attrs) - ctype = get_c_type(type) - self.emit_function(cons.name, ctype, args, attrs) + def make_pattern(self, fields): + return ",".join(rust_field(f.name) for f in fields) - def emit_function(self, name, ctype, args, attrs, union=True): - args = args + attrs - if args: - argstr = ", ".join(["%s %s" % (atype, aname) - for atype, aname, opt in args]) - argstr += ", PyArena *arena" - else: - argstr = "PyArena *arena" - margs = "a0" - for i in range(1, len(args)+1): - margs += ", a%d" % i - self.emit("#define %s(%s) _Py_%s(%s)" % (name, margs, name, margs), 0, - reflow=False) - self.emit("%s _Py_%s(%s);" % (ctype, name, argstr), False) + def add_location(self, depth): + self.emit(f"node_add_location(&node, self.location, _vm);", depth) - def visitProduct(self, prod, name): - self.emit_function(name, get_c_type(name), - self.get_args(prod.fields), - self.get_args(prod.attributes), - union=False) - -class FunctionVisitor(PrototypeVisitor): - """Visitor to generate constructor functions for AST.""" - - def emit_function(self, name, ctype, args, attrs, union=True): - def emit(s, depth=0, reflow=True): - self.emit(s, depth, reflow) - argstr = ", ".join(["%s %s" % (atype, aname) - for atype, aname, opt in args + attrs]) - if argstr: - argstr += ", PyArena *arena" - else: - argstr = "PyArena *arena" - self.emit("%s" % ctype, 0) - emit("%s(%s)" % (name, argstr)) - emit("{") - emit("%s p;" % ctype, 1) - for argtype, argname, opt in args: - if not opt and argtype != "int": - emit("if (!%s) {" % argname, 1) - emit("PyErr_SetString(PyExc_ValueError,", 2) - msg = "field '%s' is required for %s" % (argname, name) - emit(' "%s");' % msg, - 2, reflow=False) - emit('return NULL;', 2) - emit('}', 1) - - emit("p = (%s)PyArena_Malloc(arena, sizeof(*p));" % ctype, 1); - emit("if (!p)", 1) - emit("return NULL;", 2) - if union: - self.emit_body_union(name, args, attrs) - else: - self.emit_body_struct(name, args, attrs) - emit("return p;", 1) - emit("}") - emit("") - - def emit_body_union(self, name, args, attrs): - def emit(s, depth=0, reflow=True): - self.emit(s, depth, reflow) - emit("p->kind = %s_kind;" % name, 1) - for argtype, argname, opt in args: - emit("p->v.%s.%s = %s;" % (name, argname, argname), 1) - for argtype, argname, opt in attrs: - emit("p->%s = %s;" % (argname, argname), 1) - - def emit_body_struct(self, name, args, attrs): - def emit(s, depth=0, reflow=True): - self.emit(s, depth, reflow) - for argtype, argname, opt in args: - emit("p->%s = %s;" % (argname, argname), 1) - for argtype, argname, opt in attrs: - emit("p->%s = %s;" % (argname, argname), 1) - - -class PickleVisitor(EmitVisitor): - - def visitModule(self, mod): - for dfn in mod.dfns: - self.visit(dfn) - - def visitType(self, type): - self.visit(type.value, type.name) - - def visitSum(self, sum, name): - pass - - def visitProduct(self, sum, name): - pass - - def visitConstructor(self, cons, name): - pass - - def visitField(self, sum): - pass - - -class Obj2ModPrototypeVisitor(PickleVisitor): - def visitProduct(self, prod, name): - code = "static int obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena);" - self.emit(code % (name, get_c_type(name)), 0) - - visitSum = visitProduct - - -class Obj2ModVisitor(PickleVisitor): - def funcHeader(self, name): - ctype = get_c_type(name) - self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) - self.emit("{", 0) - self.emit("int isinstance;", 1) - self.emit("", 0) - - def sumTrailer(self, name, add_label=False): - self.emit("", 0) - # there's really nothing more we can do if this fails ... - error = "expected some sort of %s, but got %%R" % name - format = "PyErr_Format(PyExc_TypeError, \"%s\", obj);" - self.emit(format % error, 1, reflow=False) - if add_label: - self.emit("failed:", 1) - self.emit("Py_XDECREF(tmp);", 1) - self.emit("return 1;", 1) - self.emit("}", 0) - self.emit("", 0) - - def simpleSum(self, sum, name): - self.funcHeader(name) - for t in sum.types: - line = ("isinstance = PyObject_IsInstance(obj, " - "state->%s_type);") - self.emit(line % (t.name,), 1) - self.emit("if (isinstance == -1) {", 1) - self.emit("return 1;", 2) - self.emit("}", 1) - self.emit("if (isinstance) {", 1) - self.emit("*out = %s;" % t.name, 2) - self.emit("return 0;", 2) - self.emit("}", 1) - self.sumTrailer(name) - - def buildArgs(self, fields): - return ", ".join(fields + ["arena"]) - - def complexSum(self, sum, name): - self.funcHeader(name) - self.emit("PyObject *tmp = NULL;", 1) - self.emit("PyObject *tp;", 1) - for a in sum.attributes: - self.visitAttributeDeclaration(a, name, sum=sum) - self.emit("", 0) - # XXX: should we only do this for 'expr'? - self.emit("if (obj == Py_None) {", 1) - self.emit("*out = NULL;", 2) - self.emit("return 0;", 2) - self.emit("}", 1) - for a in sum.attributes: - self.visitField(a, name, sum=sum, depth=1) - for t in sum.types: - self.emit("tp = state->%s_type;" % (t.name,), 1) - self.emit("isinstance = PyObject_IsInstance(obj, tp);", 1) - self.emit("if (isinstance == -1) {", 1) - self.emit("return 1;", 2) - self.emit("}", 1) - self.emit("if (isinstance) {", 1) - for f in t.fields: - self.visitFieldDeclaration(f, t.name, sum=sum, depth=2) - self.emit("", 0) - for f in t.fields: - self.visitField(f, t.name, sum=sum, depth=2) - args = [f.name for f in t.fields] + [a.name for a in sum.attributes] - self.emit("*out = %s(%s);" % (t.name, self.buildArgs(args)), 2) - self.emit("if (*out == NULL) goto failed;", 2) - self.emit("return 0;", 2) - self.emit("}", 1) - self.sumTrailer(name, True) - - def visitAttributeDeclaration(self, a, name, sum=sum): - ctype = get_c_type(a.type) - self.emit("%s %s;" % (ctype, a.name), 1) - - def visitSum(self, sum, name): - if is_simple(sum): - self.simpleSum(sum, name) - else: - self.complexSum(sum, name) - - def visitProduct(self, prod, name): - ctype = get_c_type(name) - self.emit("int", 0) - self.emit("obj2ast_%s(struct ast_state *state, PyObject* obj, %s* out, PyArena* arena)" % (name, ctype), 0) - self.emit("{", 0) - self.emit("PyObject* tmp = NULL;", 1) - for f in prod.fields: - self.visitFieldDeclaration(f, name, prod=prod, depth=1) - for a in prod.attributes: - self.visitFieldDeclaration(a, name, prod=prod, depth=1) - self.emit("", 0) - for f in prod.fields: - self.visitField(f, name, prod=prod, depth=1) - for a in prod.attributes: - self.visitField(a, name, prod=prod, depth=1) - args = [f.name for f in prod.fields] - args.extend([a.name for a in prod.attributes]) - self.emit("*out = %s(%s);" % (name, self.buildArgs(args)), 1) - self.emit("return 0;", 1) - self.emit("failed:", 0) - self.emit("Py_XDECREF(tmp);", 1) - self.emit("return 1;", 1) - self.emit("}", 0) - self.emit("", 0) - - def visitFieldDeclaration(self, field, name, sum=None, prod=None, depth=0): - ctype = get_c_type(field.type) - if field.seq: - if self.isSimpleType(field): - self.emit("asdl_int_seq* %s;" % field.name, depth) - else: - _type = field.type - self.emit(f"asdl_{field.type}_seq* {field.name};", depth) - else: - ctype = get_c_type(field.type) - self.emit("%s %s;" % (ctype, field.name), depth) - - def isSimpleSum(self, field): - # XXX can the members of this list be determined automatically? - return field.type in ('expr_context', 'boolop', 'operator', - 'unaryop', 'cmpop') - - def isNumeric(self, field): - return get_c_type(field.type) in ("int", "bool") - - def isSimpleType(self, field): - return self.isSimpleSum(field) or self.isNumeric(field) - - def visitField(self, field, name, sum=None, prod=None, depth=0): - ctype = get_c_type(field.type) - line = "if (_PyObject_LookupAttr(obj, state->%s, &tmp) < 0) {" - self.emit(line % field.name, depth) - self.emit("return 1;", depth+1) - self.emit("}", depth) - if not field.opt: - self.emit("if (tmp == NULL) {", depth) - message = "required field \\\"%s\\\" missing from %s" % (field.name, name) - format = "PyErr_SetString(PyExc_TypeError, \"%s\");" - self.emit(format % message, depth+1, reflow=False) - self.emit("return 1;", depth+1) - else: - self.emit("if (tmp == NULL || tmp == Py_None) {", depth) - self.emit("Py_CLEAR(tmp);", depth+1) - if self.isNumeric(field): - self.emit("%s = 0;" % field.name, depth+1) - elif not self.isSimpleType(field): - self.emit("%s = NULL;" % field.name, depth+1) - else: - raise TypeError("could not determine the default value for %s" % field.name) - self.emit("}", depth) - self.emit("else {", depth) - - self.emit("int res;", depth+1) - if field.seq: - self.emit("Py_ssize_t len;", depth+1) - self.emit("Py_ssize_t i;", depth+1) - self.emit("if (!PyList_Check(tmp)) {", depth+1) - self.emit("PyErr_Format(PyExc_TypeError, \"%s field \\\"%s\\\" must " - "be a list, not a %%.200s\", _PyType_Name(Py_TYPE(tmp)));" % - (name, field.name), - depth+2, reflow=False) - self.emit("goto failed;", depth+2) - self.emit("}", depth+1) - self.emit("len = PyList_GET_SIZE(tmp);", depth+1) - if self.isSimpleType(field): - self.emit("%s = _Py_asdl_int_seq_new(len, arena);" % field.name, depth+1) - else: - self.emit("%s = _Py_asdl_%s_seq_new(len, arena);" % (field.name, field.type), depth+1) - self.emit("if (%s == NULL) goto failed;" % field.name, depth+1) - self.emit("for (i = 0; i < len; i++) {", depth+1) - self.emit("%s val;" % ctype, depth+2) - self.emit("PyObject *tmp2 = PyList_GET_ITEM(tmp, i);", depth+2) - self.emit("Py_INCREF(tmp2);", depth+2) - self.emit("res = obj2ast_%s(state, tmp2, &val, arena);" % - field.type, depth+2, reflow=False) - self.emit("Py_DECREF(tmp2);", depth+2) - self.emit("if (res != 0) goto failed;", depth+2) - self.emit("if (len != PyList_GET_SIZE(tmp)) {", depth+2) - self.emit("PyErr_SetString(PyExc_RuntimeError, \"%s field \\\"%s\\\" " - "changed size during iteration\");" % - (name, field.name), - depth+3, reflow=False) - self.emit("goto failed;", depth+3) - self.emit("}", depth+2) - self.emit("asdl_seq_SET(%s, i, val);" % field.name, depth+2) - self.emit("}", depth+1) - else: - self.emit("res = obj2ast_%s(state, tmp, &%s, arena);" % - (field.type, field.name), depth+1) - self.emit("if (res != 0) goto failed;", depth+1) - - self.emit("Py_CLEAR(tmp);", depth+1) - self.emit("}", depth) - - -class SequenceConstructorVisitor(EmitVisitor): - def visitModule(self, mod): - for dfn in mod.dfns: - self.visit(dfn) - - def visitType(self, type): - self.visit(type.value, type.name) - - def visitProduct(self, prod, name): - self.emit_sequence_constructor(name, get_c_type(name)) - - def visitSum(self, sum, name): - if not is_simple(sum): - self.emit_sequence_constructor(name, get_c_type(name)) - - def emit_sequence_constructor(self, name, type): - self.emit(f"GENERATE_ASDL_SEQ_CONSTRUCTOR({name}, {type})", depth=0) - -class PyTypesDeclareVisitor(PickleVisitor): - - def visitProduct(self, prod, name): - self.emit_type("%s_type" % name) - self.emit("static PyObject* ast2obj_%s(struct ast_state *state, void*);" % name, 0) - if prod.attributes: - for a in prod.attributes: - self.emit_identifier(a.name) - self.emit("static const char * const %s_attributes[] = {" % name, 0) - for a in prod.attributes: - self.emit('"%s",' % a.name, 1) - self.emit("};", 0) - if prod.fields: - for f in prod.fields: - self.emit_identifier(f.name) - self.emit("static const char * const %s_fields[]={" % name,0) - for f in prod.fields: - self.emit('"%s",' % f.name, 1) - self.emit("};", 0) - - def visitSum(self, sum, name): - self.emit_type("%s_type" % name) - if sum.attributes: - for a in sum.attributes: - self.emit_identifier(a.name) - self.emit("static const char * const %s_attributes[] = {" % name, 0) - for a in sum.attributes: - self.emit('"%s",' % a.name, 1) - self.emit("};", 0) - ptype = "void*" - if is_simple(sum): - ptype = get_c_type(name) - for t in sum.types: - self.emit_singleton("%s_singleton" % t.name) - self.emit("static PyObject* ast2obj_%s(struct ast_state *state, %s);" % (name, ptype), 0) - for t in sum.types: - self.visitConstructor(t, name) - - def visitConstructor(self, cons, name): - if cons.fields: - for t in cons.fields: - self.emit_identifier(t.name) - self.emit("static const char * const %s_fields[]={" % cons.name, 0) - for t in cons.fields: - self.emit('"%s",' % t.name, 1) - self.emit("};",0) - - -class PyTypesVisitor(PickleVisitor): - - def visitModule(self, mod): - self.emit(""" -_Py_IDENTIFIER(_fields); -_Py_IDENTIFIER(_attributes); - -typedef struct { - PyObject_HEAD - PyObject *dict; -} AST_object; - -static void -ast_dealloc(AST_object *self) -{ - /* bpo-31095: UnTrack is needed before calling any callbacks */ - PyTypeObject *tp = Py_TYPE(self); - PyObject_GC_UnTrack(self); - Py_CLEAR(self->dict); - freefunc free_func = PyType_GetSlot(tp, Py_tp_free); - assert(free_func != NULL); - free_func(self); - Py_DECREF(tp); -} - -static int -ast_traverse(AST_object *self, visitproc visit, void *arg) -{ - Py_VISIT(Py_TYPE(self)); - Py_VISIT(self->dict); - return 0; -} - -static int -ast_clear(AST_object *self) -{ - Py_CLEAR(self->dict); - return 0; -} - -static int -ast_type_init(PyObject *self, PyObject *args, PyObject *kw) -{ - struct ast_state *state = get_ast_state(); - if (state == NULL) { - return -1; - } - - Py_ssize_t i, numfields = 0; - int res = -1; - PyObject *key, *value, *fields; - if (_PyObject_LookupAttr((PyObject*)Py_TYPE(self), state->_fields, &fields) < 0) { - goto cleanup; - } - if (fields) { - numfields = PySequence_Size(fields); - if (numfields == -1) { - goto cleanup; - } - } - - res = 0; /* if no error occurs, this stays 0 to the end */ - if (numfields < PyTuple_GET_SIZE(args)) { - PyErr_Format(PyExc_TypeError, "%.400s constructor takes at most " - "%zd positional argument%s", - _PyType_Name(Py_TYPE(self)), - numfields, numfields == 1 ? "" : "s"); - res = -1; - goto cleanup; - } - for (i = 0; i < PyTuple_GET_SIZE(args); i++) { - /* cannot be reached when fields is NULL */ - PyObject *name = PySequence_GetItem(fields, i); - if (!name) { - res = -1; - goto cleanup; - } - res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i)); - Py_DECREF(name); - if (res < 0) { - goto cleanup; - } - } - if (kw) { - i = 0; /* needed by PyDict_Next */ - while (PyDict_Next(kw, &i, &key, &value)) { - int contains = PySequence_Contains(fields, key); - if (contains == -1) { - res = -1; - goto cleanup; - } else if (contains == 1) { - Py_ssize_t p = PySequence_Index(fields, key); - if (p == -1) { - res = -1; - goto cleanup; - } - if (p < PyTuple_GET_SIZE(args)) { - PyErr_Format(PyExc_TypeError, - "%.400s got multiple values for argument '%U'", - Py_TYPE(self)->tp_name, key); - res = -1; - goto cleanup; - } - } - res = PyObject_SetAttr(self, key, value); - if (res < 0) { - goto cleanup; - } - } - } - cleanup: - Py_XDECREF(fields); - return res; -} - -/* Pickling support */ -static PyObject * -ast_type_reduce(PyObject *self, PyObject *unused) -{ - struct ast_state *state = get_ast_state(); - if (state == NULL) { - return NULL; - } - - PyObject *dict; - if (_PyObject_LookupAttr(self, state->__dict__, &dict) < 0) { - return NULL; - } - if (dict) { - return Py_BuildValue("O()N", Py_TYPE(self), dict); - } - return Py_BuildValue("O()", Py_TYPE(self)); -} - -static PyMemberDef ast_type_members[] = { - {"__dictoffset__", T_PYSSIZET, offsetof(AST_object, dict), READONLY}, - {NULL} /* Sentinel */ -}; - -static PyMethodDef ast_type_methods[] = { - {"__reduce__", ast_type_reduce, METH_NOARGS, NULL}, - {NULL} -}; - -static PyGetSetDef ast_type_getsets[] = { - {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, - {NULL} -}; - -static PyType_Slot AST_type_slots[] = { - {Py_tp_dealloc, ast_dealloc}, - {Py_tp_getattro, PyObject_GenericGetAttr}, - {Py_tp_setattro, PyObject_GenericSetAttr}, - {Py_tp_traverse, ast_traverse}, - {Py_tp_clear, ast_clear}, - {Py_tp_members, ast_type_members}, - {Py_tp_methods, ast_type_methods}, - {Py_tp_getset, ast_type_getsets}, - {Py_tp_init, ast_type_init}, - {Py_tp_alloc, PyType_GenericAlloc}, - {Py_tp_new, PyType_GenericNew}, - {Py_tp_free, PyObject_GC_Del}, - {0, 0}, -}; - -static PyType_Spec AST_type_spec = { - "ast.AST", - sizeof(AST_object), - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - AST_type_slots -}; - -static PyObject * -make_type(struct ast_state *state, const char *type, PyObject* base, - const char* const* fields, int num_fields, const char *doc) -{ - PyObject *fnames, *result; - int i; - fnames = PyTuple_New(num_fields); - if (!fnames) return NULL; - for (i = 0; i < num_fields; i++) { - PyObject *field = PyUnicode_InternFromString(fields[i]); - if (!field) { - Py_DECREF(fnames); - return NULL; - } - PyTuple_SET_ITEM(fnames, i, field); - } - result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOOOs}", - type, base, - state->_fields, fnames, - state->__module__, - state->ast, - state->__doc__, doc); - Py_DECREF(fnames); - return result; -} - -static int -add_attributes(struct ast_state *state, PyObject *type, const char * const *attrs, int num_fields) -{ - int i, result; - PyObject *s, *l = PyTuple_New(num_fields); - if (!l) - return 0; - for (i = 0; i < num_fields; i++) { - s = PyUnicode_InternFromString(attrs[i]); - if (!s) { - Py_DECREF(l); - return 0; - } - PyTuple_SET_ITEM(l, i, s); - } - result = PyObject_SetAttr(type, state->_attributes, l) >= 0; - Py_DECREF(l); - return result; -} - -/* Conversion AST -> Python */ - -static PyObject* ast2obj_list(struct ast_state *state, asdl_seq *seq, PyObject* (*func)(struct ast_state *state, void*)) -{ - Py_ssize_t i, n = asdl_seq_LEN(seq); - PyObject *result = PyList_New(n); - PyObject *value; - if (!result) - return NULL; - for (i = 0; i < n; i++) { - value = func(state, asdl_seq_GET_UNTYPED(seq, i)); - if (!value) { - Py_DECREF(result); - return NULL; - } - PyList_SET_ITEM(result, i, value); - } - return result; -} - -static PyObject* ast2obj_object(struct ast_state *Py_UNUSED(state), void *o) -{ - if (!o) - o = Py_None; - Py_INCREF((PyObject*)o); - return (PyObject*)o; -} -#define ast2obj_constant ast2obj_object -#define ast2obj_identifier ast2obj_object -#define ast2obj_string ast2obj_object - -static PyObject* ast2obj_int(struct ast_state *Py_UNUSED(state), long b) -{ - return PyLong_FromLong(b); -} - -/* Conversion Python -> AST */ - -static int obj2ast_object(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) -{ - if (obj == Py_None) - obj = NULL; - if (obj) { - if (PyArena_AddPyObject(arena, obj) < 0) { - *out = NULL; - return -1; - } - Py_INCREF(obj); - } - *out = obj; - return 0; -} - -static int obj2ast_constant(struct ast_state *Py_UNUSED(state), PyObject* obj, PyObject** out, PyArena* arena) -{ - if (PyArena_AddPyObject(arena, obj) < 0) { - *out = NULL; - return -1; - } - Py_INCREF(obj); - *out = obj; - return 0; -} - -static int obj2ast_identifier(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) -{ - if (!PyUnicode_CheckExact(obj) && obj != Py_None) { - PyErr_SetString(PyExc_TypeError, "AST identifier must be of type str"); - return 1; - } - return obj2ast_object(state, obj, out, arena); -} - -static int obj2ast_string(struct ast_state *state, PyObject* obj, PyObject** out, PyArena* arena) -{ - if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) { - PyErr_SetString(PyExc_TypeError, "AST string must be of type str"); - return 1; - } - return obj2ast_object(state, obj, out, arena); -} - -static int obj2ast_int(struct ast_state* Py_UNUSED(state), PyObject* obj, int* out, PyArena* arena) -{ - int i; - if (!PyLong_Check(obj)) { - PyErr_Format(PyExc_ValueError, "invalid integer value: %R", obj); - return 1; - } - - i = _PyLong_AsInt(obj); - if (i == -1 && PyErr_Occurred()) - return 1; - *out = i; - return 0; -} - -static int add_ast_fields(struct ast_state *state) -{ - PyObject *empty_tuple; - empty_tuple = PyTuple_New(0); - if (!empty_tuple || - PyObject_SetAttrString(state->AST_type, "_fields", empty_tuple) < 0 || - PyObject_SetAttrString(state->AST_type, "_attributes", empty_tuple) < 0) { - Py_XDECREF(empty_tuple); - return -1; - } - Py_DECREF(empty_tuple); - return 0; -} - -""", 0, reflow=False) - - self.file.write(textwrap.dedent(''' - static int - init_types(struct ast_state *state) - { - // init_types() must not be called after _PyAST_Fini() - // has been called - assert(state->initialized >= 0); - - if (state->initialized) { - return 1; - } - if (init_identifiers(state) < 0) { - return 0; - } - state->AST_type = PyType_FromSpec(&AST_type_spec); - if (!state->AST_type) { - return 0; - } - if (add_ast_fields(state) < 0) { - return 0; - } - ''')) - for dfn in mod.dfns: - self.visit(dfn) - self.file.write(textwrap.dedent(''' - state->initialized = 1; - return 1; - } - ''')) - - def visitProduct(self, prod, name): - if prod.fields: - fields = name+"_fields" - else: - fields = "NULL" - self.emit('state->%s_type = make_type(state, "%s", state->AST_type, %s, %d,' % - (name, name, fields, len(prod.fields)), 1) - self.emit('%s);' % reflow_c_string(asdl_of(name, prod), 2), 2, reflow=False) - self.emit("if (!state->%s_type) return 0;" % name, 1) - self.emit_type("AST_type") - self.emit_type("%s_type" % name) - if prod.attributes: - self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % - (name, name, len(prod.attributes)), 1) - else: - self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) - self.emit_defaults(name, prod.fields, 1) - self.emit_defaults(name, prod.attributes, 1) - - def visitSum(self, sum, name): - self.emit('state->%s_type = make_type(state, "%s", state->AST_type, NULL, 0,' % - (name, name), 1) - self.emit('%s);' % reflow_c_string(asdl_of(name, sum), 2), 2, reflow=False) - self.emit_type("%s_type" % name) - self.emit("if (!state->%s_type) return 0;" % name, 1) - if sum.attributes: - self.emit("if (!add_attributes(state, state->%s_type, %s_attributes, %d)) return 0;" % - (name, name, len(sum.attributes)), 1) - else: - self.emit("if (!add_attributes(state, state->%s_type, NULL, 0)) return 0;" % name, 1) - self.emit_defaults(name, sum.attributes, 1) - simple = is_simple(sum) - for t in sum.types: - self.visitConstructor(t, name, simple) - - def visitConstructor(self, cons, name, simple): - if cons.fields: - fields = cons.name+"_fields" - else: - fields = "NULL" - self.emit('state->%s_type = make_type(state, "%s", state->%s_type, %s, %d,' % - (cons.name, cons.name, name, fields, len(cons.fields)), 1) - self.emit('%s);' % reflow_c_string(asdl_of(cons.name, cons), 2), 2, reflow=False) - self.emit("if (!state->%s_type) return 0;" % cons.name, 1) - self.emit_type("%s_type" % cons.name) - self.emit_defaults(cons.name, cons.fields, 1) - if simple: - self.emit("state->%s_singleton = PyType_GenericNew((PyTypeObject *)" - "state->%s_type, NULL, NULL);" % - (cons.name, cons.name), 1) - self.emit("if (!state->%s_singleton) return 0;" % cons.name, 1) - - def emit_defaults(self, name, fields, depth): - for field in fields: - if field.opt: - self.emit('if (PyObject_SetAttr(state->%s_type, state->%s, Py_None) == -1)' % - (name, field.name), depth) - self.emit("return 0;", depth+1) - - -class ASTModuleVisitor(PickleVisitor): - - def visitModule(self, mod): - self.emit("static int", 0) - self.emit("astmodule_exec(PyObject *m)", 0) - self.emit("{", 0) - self.emit('struct ast_state *state = get_ast_state();', 1) - self.emit('if (state == NULL) {', 1) - self.emit('return -1;', 2) - self.emit('}', 1) - self.emit('if (PyModule_AddObjectRef(m, "AST", state->AST_type) < 0) {', 1) - self.emit('return -1;', 2) - self.emit('}', 1) - self.emit('if (PyModule_AddIntMacro(m, PyCF_ALLOW_TOP_LEVEL_AWAIT) < 0) {', 1) - self.emit("return -1;", 2) - self.emit('}', 1) - self.emit('if (PyModule_AddIntMacro(m, PyCF_ONLY_AST) < 0) {', 1) - self.emit("return -1;", 2) - self.emit('}', 1) - self.emit('if (PyModule_AddIntMacro(m, PyCF_TYPE_COMMENTS) < 0) {', 1) - self.emit("return -1;", 2) - self.emit('}', 1) - for dfn in mod.dfns: - self.visit(dfn) - self.emit("return 0;", 1) - self.emit("}", 0) - self.emit("", 0) - self.emit(""" -static PyModuleDef_Slot astmodule_slots[] = { - {Py_mod_exec, astmodule_exec}, - {0, NULL} -}; - -static struct PyModuleDef _astmodule = { - PyModuleDef_HEAD_INIT, - .m_name = "_ast", - // The _ast module uses a per-interpreter state (PyInterpreterState.ast) - .m_size = 0, - .m_slots = astmodule_slots, -}; - -PyMODINIT_FUNC -PyInit__ast(void) -{ - return PyModuleDef_Init(&_astmodule); -} -""".strip(), 0, reflow=False) - - def visitProduct(self, prod, name): - self.addObj(name) - - def visitSum(self, sum, name): - self.addObj(name) - for t in sum.types: - self.visitConstructor(t, name) - - def visitConstructor(self, cons, name): - self.addObj(cons.name) - - def addObj(self, name): - self.emit("if (PyModule_AddObjectRef(m, \"%s\", " - "state->%s_type) < 0) {" % (name, name), 1) - self.emit("return -1;", 2) - self.emit('}', 1) - - -class StaticVisitor(PickleVisitor): - CODE = '''Very simple, always emit this static code. Override CODE''' - - def visit(self, object): - self.emit(self.CODE, 0, reflow=False) - - -class ObjVisitor(PickleVisitor): - - def func_begin(self, name): - ctype = get_rust_type(name) - self.emit("PyObject*", 0) - self.emit("ast2obj_%s(void* _o)" % (name), 0) - self.emit("{", 0) - self.emit("%s o = (%s)_o;" % (ctype, ctype), 1) - self.emit("PyObject *result = NULL, *value = NULL;", 1) - self.emit('if (!o) {', 1) - self.emit("Py_RETURN_NONE;", 2) - self.emit("}", 1) - self.emit('', 0) - - def func_end(self): - self.emit("return result;", 1) - self.emit("failed:", 0) - self.emit("Py_XDECREF(value);", 1) - self.emit("Py_XDECREF(result);", 1) - self.emit("return NULL;", 1) - self.emit("}", 0) - self.emit("", 0) - - def visitSum(self, sum, name): - if is_simple(sum): - self.simpleSum(sum, name) - return - self.func_begin(name) - self.emit("switch (o->kind) {", 1) - for i in range(len(sum.types)): - t = sum.types[i] - self.visitConstructor(t, i + 1, name) - self.emit("}", 1) - for a in sum.attributes: - self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) - self.emit("if (!value) goto failed;", 1) - self.emit('if (PyObject_SetAttr(result, state->%s, value) < 0)' % a.name, 1) - self.emit('goto failed;', 2) - self.emit('Py_DECREF(value);', 1) - self.func_end() - - def simpleSum(self, sum, name): - self.emit("PyObject* ast2obj_%s(struct ast_state *state, %s_ty o)" % (name, name), 0) - self.emit("{", 0) - self.emit("switch(o) {", 1) - for t in sum.types: - self.emit("case %s:" % t.name, 2) - self.emit("Py_INCREF(state->%s_singleton);" % t.name, 3) - self.emit("return state->%s_singleton;" % t.name, 3) - self.emit("}", 1) - self.emit("Py_UNREACHABLE();", 1); - self.emit("}", 0) - - def visitProduct(self, prod, name): - self.func_begin(name) - self.emit("tp = (PyTypeObject *)state->%s_type;" % name, 1) - self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 1); - self.emit("if (!result) return NULL;", 1) - for field in prod.fields: - self.visitField(field, name, 1, True) - for a in prod.attributes: - self.emit("value = ast2obj_%s(state, o->%s);" % (a.type, a.name), 1) - self.emit("if (!value) goto failed;", 1) - self.emit("if (PyObject_SetAttr(result, state->%s, value) < 0)" % a.name, 1) - self.emit('goto failed;', 2) - self.emit('Py_DECREF(value);', 1) - self.func_end() - - def visitConstructor(self, cons, enum, name): - self.emit("case %s_kind:" % cons.name, 1) - self.emit("tp = (PyTypeObject *)state->%s_type;" % cons.name, 2) - self.emit("result = PyType_GenericNew(tp, NULL, NULL);", 2); - self.emit("if (!result) goto failed;", 2) - for f in cons.fields: - self.visitField(f, cons.name, 2, False) - self.emit("break;", 2) - - def visitField(self, field, name, depth, product): - def emit(s, d): - self.emit(s, depth + d) - if product: - value = "o->%s" % field.name - else: - value = "o->v.%s.%s" % (name, field.name) - self.set(field, value, depth) - emit("if (!value) goto failed;", 0) - emit("if (PyObject_SetAttr(result, state->%s, value) == -1)" % field.name, 0) - emit("goto failed;", 1) - emit("Py_DECREF(value);", 0) - - def set(self, field, value, depth): - if field.seq: - # XXX should really check for is_simple, but that requires a symbol table - if field.type == "cmpop": - # While the sequence elements are stored as void*, - # ast2obj_cmpop expects an enum - self.emit("{", depth) - self.emit("Py_ssize_t i, n = asdl_seq_LEN(%s);" % value, depth+1) - self.emit("value = PyList_New(n);", depth+1) - self.emit("if (!value) goto failed;", depth+1) - self.emit("for(i = 0; i < n; i++)", depth+1) - # This cannot fail, so no need for error handling - self.emit("PyList_SET_ITEM(value, i, ast2obj_cmpop(state, (cmpop_ty)asdl_seq_GET(%s, i)));" % value, - depth+2, reflow=False) - self.emit("}", depth) - else: - self.emit("value = ast2obj_list(state, (asdl_seq*)%s, ast2obj_%s);" % (value, field.type), depth) - else: - self.emit("value = ast2obj_%s(state, %s);" % (field.type, value), depth, reflow=False) - - -class PartingShots(StaticVisitor): - - CODE = """ -PyObject* PyAST_mod2obj(mod_ty t) -{ - struct ast_state *state = get_ast_state(); - if (state == NULL) { - return NULL; - } - return ast2obj_mod(state, t); - if (!init_types()) - return NULL; - return ast2obj_mod(t); -} - -/* mode is 0 for "exec", 1 for "eval" and 2 for "single" input */ -mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) -{ - const char * const req_name[] = {"Module", "Expression", "Interactive"}; - int isinstance; - - if (PySys_Audit("compile", "OO", ast, Py_None) < 0) { - return NULL; - } - - struct ast_state *state = get_ast_state(); - if (state == NULL) { - return NULL; - } - - PyObject *req_type[3]; - req_type[0] = state->Module_type; - req_type[1] = state->Expression_type; - req_type[2] = state->Interactive_type; - - assert(0 <= mode && mode <= 2); - - isinstance = PyObject_IsInstance(ast, req_type[mode]); - if (isinstance == -1) - return NULL; - if (!isinstance) { - PyErr_Format(PyExc_TypeError, "expected %s node, got %.400s", - req_name[mode], _PyType_Name(Py_TYPE(ast))); - return NULL; - } - - mod_ty res = NULL; - if (obj2ast_mod(state, ast, &res, arena) != 0) - return NULL; - else - return res; -} - -int PyAST_Check(PyObject* obj) -{ - struct ast_state *state = get_ast_state(); - if (state == NULL) { - return -1; - } - return PyObject_IsInstance(obj, state->AST_type); -} -""" - -class ChainOfVisitors: - def __init__(self, *visitors): - self.visitors = visitors - - def visit(self, object): - for v in self.visitors: - v.visit(object) - v.emit("", 0) - - -def generate_ast_state(module_state, f): - f.write('struct ast_state {\n') - f.write(' int initialized;\n') - for s in module_state: - f.write(' PyObject *' + s + ';\n') - f.write('};') - - -def generate_ast_fini(module_state, f): - f.write(textwrap.dedent(""" - void _PyAST_Fini(PyInterpreterState *interp) - { - #ifdef Py_BUILD_CORE - struct ast_state *state = &interp->ast; - #else - struct ast_state *state = &global_ast_state; - #endif - - """)) - for s in module_state: - f.write(" Py_CLEAR(state->" + s + ');\n') - f.write(textwrap.dedent(""" - #if defined(Py_BUILD_CORE) && !defined(NDEBUG) - state->initialized = -1; - #else - state->initialized = 0; - #endif - } - - """)) - - -def generate_module_def(mod, f, internal_h): - # Gather all the data needed for ModuleSpec - visitor_list = set() - with open(os.devnull, "w") as devnull: - visitor = PyTypesDeclareVisitor(devnull) - visitor.visit(mod) - visitor_list.add(visitor) - visitor = PyTypesVisitor(devnull) - visitor.visit(mod) - visitor_list.add(visitor) - - state_strings = { - "ast", - "_fields", - "__doc__", - "__dict__", - "__module__", - "_attributes", - } - module_state = state_strings.copy() - for visitor in visitor_list: - for identifier in visitor.identifiers: - module_state.add(identifier) - state_strings.add(identifier) - for singleton in visitor.singletons: - module_state.add(singleton) - for tp in visitor.types: - module_state.add(tp) - state_strings = sorted(state_strings) - module_state = sorted(module_state) - - generate_ast_state(module_state, internal_h) - - print(textwrap.dedent(f""" - #ifdef Py_BUILD_CORE - # include "pycore_ast.h" // struct ast_state - # include "pycore_interp.h" // _PyInterpreterState.ast - # include "pycore_pystate.h" // _PyInterpreterState_GET() - #else - """).strip(), file=f) - - generate_ast_state(module_state, f) - - print(textwrap.dedent(f""" - #endif // Py_BUILD_CORE - """).rstrip(), file=f) - - f.write(""" -// Forward declaration -static int init_types(struct ast_state *state); - -#ifdef Py_BUILD_CORE -static struct ast_state* -get_ast_state(void) -{ - PyInterpreterState *interp = _PyInterpreterState_GET(); - struct ast_state *state = &interp->ast; - if (!init_types(state)) { - return NULL; - } - return state; -} -#else -static struct ast_state global_ast_state; - -static struct ast_state* -get_ast_state(void) -{ - struct ast_state *state = &global_ast_state; - if (!init_types(state)) { - return NULL; - } - return state; -} -#endif // Py_BUILD_CORE -""") - - # f-string for {mod.name} - f.write(f""" -// Include {mod.name}-ast.h after pycore_interp.h to avoid conflicts -// with the Yield macro redefined by -#include "{mod.name}-ast.h" -#include "structmember.h" -""") - - generate_ast_fini(module_state, f) - - f.write('static int init_identifiers(struct ast_state *state)\n') - f.write('{\n') - for identifier in state_strings: - f.write(' if ((state->' + identifier) - f.write(' = PyUnicode_InternFromString("') - f.write(identifier + '")) == NULL) return 0;\n') - f.write(' return 1;\n') - f.write('};\n\n') - -def write_ast_def(mod, f): +def write_ast_def(mod, typeinfo, f): f.write('pub use crate::location::Location;\n') f.write('pub use crate::constant::*;\n') f.write('\n') f.write('type Ident = String;\n') f.write('\n') - StructVisitor(f, {}).emit_attrs(0) + StructVisitor(f, typeinfo).emit_attrs(0) f.write('pub struct Located {\n') f.write(' pub location: Location,\n') f.write(' pub custom: U,\n') @@ -1491,57 +410,22 @@ def write_ast_def(mod, f): f.write('}\n') f.write('\n') - typeinfo = {} - FindUserdataTypesVisitor(typeinfo).visit(mod) - StructVisitor(f, typeinfo).visit(mod) -def write_internal_h_header(mod, f): - print(textwrap.dedent(""" - #ifndef Py_INTERNAL_AST_H - #define Py_INTERNAL_AST_H - #ifdef __cplusplus - extern "C" { - #endif +def write_ast_mod(mod, typeinfo, f): + f.write('use super::*;\n') + f.write('\n') - #ifndef Py_BUILD_CORE - # error "this header requires Py_BUILD_CORE define" - #endif - """).lstrip(), file=f) + ClassDefVisitor(f).visit(mod) + f.write('\n') -def write_internal_h_footer(mod, f): - print(textwrap.dedent(""" + TraitImplVisitor(f, typeinfo).visit(mod) - #ifdef __cplusplus - } - #endif - #endif /* !Py_INTERNAL_AST_H */ - """), file=f) + f.write('\n') - -def write_source(mod, f, internal_h_file): - print(textwrap.dedent(f""" - #include - - #include "Python.h" - """), file=f) - - generate_module_def(mod, f, internal_h_file) - - v = ChainOfVisitors( - SequenceConstructorVisitor(f), - PyTypesDeclareVisitor(f), - PyTypesVisitor(f), - Obj2ModPrototypeVisitor(f), - FunctionVisitor(f), - ObjVisitor(f), - Obj2ModVisitor(f), - ASTModuleVisitor(f), - PartingShots(f), - ) - v.visit(mod) + ExtendModuleVisitor(f).visit(mod) def main(input_filename, ast_mod_filename, ast_def_filename, dump_module=False): auto_gen_msg = AUTOGEN_MESSAGE.format("/".join(Path(__file__).parts[-2:])) @@ -1552,12 +436,16 @@ def main(input_filename, ast_mod_filename, ast_def_filename, dump_module=False): if not asdl.check(mod): sys.exit(1) + typeinfo = {} + FindUserdataTypesVisitor(typeinfo).visit(mod) + with ast_def_filename.open("w") as def_file, \ ast_mod_filename.open("w") as mod_file: def_file.write(auto_gen_msg) - mod_file.write(auto_gen_msg) + write_ast_def(mod, typeinfo, def_file) - write_ast_def(mod, def_file) + mod_file.write(auto_gen_msg) + write_ast_mod(mod, typeinfo, mod_file) print(f"{ast_def_filename}, {ast_mod_filename} regenerated.") diff --git a/ast/src/constant.rs b/ast/src/constant.rs index f6c523c4c..579fd47bc 100644 --- a/ast/src/constant.rs +++ b/ast/src/constant.rs @@ -31,11 +31,23 @@ impl From for Constant { /// Transforms a value prior to formatting it. #[derive(Copy, Clone, Debug, PartialEq)] +#[repr(u8)] pub enum ConversionFlag { /// Converts by calling `str()`. - Str, + Str = b's', /// Converts by calling `ascii()`. - Ascii, + Ascii = b'a', /// Converts by calling `repr()`. - Repr, + Repr = b'r', +} + +impl ConversionFlag { + pub fn try_from_byte(b: u8) -> Option { + match b { + b's' => Some(Self::Str), + b'a' => Some(Self::Ascii), + b'r' => Some(Self::Repr), + _ => None, + } + } } diff --git a/scripts/update_asdl.sh b/scripts/update_asdl.sh new file mode 100755 index 000000000..148e5ca60 --- /dev/null +++ b/scripts/update_asdl.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +cd "$(dirname "$(dirname "$0")")" + +python ast/asdl_rs.py -D ast/src/ast_gen.rs -M vm/src/stdlib/ast/gen.rs ast/Python.asdl + +cargo fmt diff --git a/vm/src/iterator.rs b/vm/src/iterator.rs index 0eb9265f4..740308353 100644 --- a/vm/src/iterator.rs +++ b/vm/src/iterator.rs @@ -75,18 +75,7 @@ pub fn get_next_object( /* Retrieve all elements from an iterator */ pub fn get_all(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult> { - let cap = length_hint(vm, iter_obj.clone())?.unwrap_or(0); - // TODO: fix extend to do this check (?), see test_extend in Lib/test/list_tests.py, - // https://github.com/python/cpython/blob/master/Objects/listobject.c#L934-L940 - if cap >= isize::max_value() as usize { - return Ok(Vec::new()); - } - let mut elements = Vec::with_capacity(cap); - while let Some(element) = get_next_object(vm, iter_obj)? { - elements.push(T::try_from_object(vm, element)?); - } - elements.shrink_to_fit(); - Ok(elements) + try_map(vm, iter_obj, |obj| T::try_from_object(vm, obj)) } pub fn try_map(vm: &VirtualMachine, iter_obj: &PyObjectRef, mut f: F) -> PyResult> diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 5a9065f31..e90f02b69 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -3,19 +3,29 @@ //! This module makes use of the parser logic, and translates all ast nodes //! into python ast.AST objects. -use std::ops::Deref; - use num_complex::Complex64; +use num_traits::ToPrimitive; use rustpython_parser::{ast, mode::Mode, parser}; -use crate::builtins::list::PyListRef; -use crate::builtins::pytype::PyTypeRef; +use crate::builtins::{PyStrRef, PyTypeRef}; use crate::pyobject::{ - IntoPyObject, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, StaticType, + BorrowValue, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + StaticType, TryFromObject, }; use crate::vm::VirtualMachine; +#[rustfmt::skip] +mod gen; + +fn node_add_location(node: &AstNodeRef, location: ast::Location, vm: &VirtualMachine) { + let dict = node.as_object().dict().unwrap(); + dict.set_item("lineno", vm.ctx.new_int(location.row()), vm) + .unwrap(); + dict.set_item("col_offset", vm.ctx.new_int(location.column()), vm) + .unwrap(); +} + #[pyclass(module = "_ast", name = "AST")] #[derive(Debug)] struct AstNode; @@ -33,678 +43,132 @@ impl PyValue for AstNode { } } -macro_rules! node { - ( $vm: expr, $node_name:ident, { $($attr_name:ident => $attr_value:expr),* $(,)* }) => { - { - let node = create_node($vm, stringify!($node_name))?; - let mut field_names = vec![]; - $( - let field_name = stringify!($attr_name); - $vm.set_attr(node.as_object(), field_name, $attr_value)?; - field_names.push($vm.ctx.new_str(field_name)); - )* - $vm.set_attr(node.as_object(), "_fields", $vm.ctx.new_tuple(field_names))?; - node +trait Node: Sized { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef; + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult; +} + +impl Node for Vec { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_list( + self.into_iter() + .map(|node| node.ast_to_object(vm)) + .collect(), + ) + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + vm.extract_elements_func(&object, |obj| Node::ast_from_object(vm, obj)) + } +} + +impl Node for Box { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + (*self).ast_to_object(vm) + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + T::ast_from_object(vm, object).map(Box::new) + } +} + +impl Node for Option { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + match self { + Some(node) => node.ast_to_object(vm), + None => vm.ctx.none(), } - }; - ( $vm: expr, $node_name:ident) => { - { - let node = create_node($vm, stringify!($node_name))?; - $vm.set_attr(node.as_object(), "_fields", $vm.ctx.new_tuple(vec![]))?; - node + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + if vm.is_none(&object) { + Ok(None) + } else { + Ok(Some(T::ast_from_object(vm, object)?)) } } } -fn top_to_ast(vm: &VirtualMachine, top: &ast::Top) -> PyResult { - match top { - ast::Top::Program(program) => statements_to_ast(vm, &program.statements), - ast::Top::Statement(statements) => statements_to_ast(vm, statements), - ast::Top::Expression(_) => unimplemented!("top_to_ast unimplemented ast::Top::Expression"), +impl Node for String { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_str(self) + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + PyStrRef::try_from_object(vm, object).map(|s| s.borrow_value().to_owned()) } } -// Create a node class instance -fn create_node(vm: &VirtualMachine, name: &str) -> PyResult { - AstNode.into_ref_with_type(vm, vm.class(MODULE_NAME, name)) +impl Node for usize { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_int(self) + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + Self::try_from_object(vm, object) + } } -fn statements_to_ast(vm: &VirtualMachine, statements: &[ast::Statement]) -> PyResult { - let body: PyResult> = statements - .iter() - .map(|statement| Ok(statement_to_ast(&vm, statement)?.into_object())) - .collect(); - Ok(vm.ctx.new_list(body?).downcast().unwrap()) +impl Node for bool { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_int(self as u8) + } + + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + i32::try_from_object(vm, object).map(|i| i != 0) + } } -fn statement_to_ast(vm: &VirtualMachine, statement: &ast::Statement) -> PyResult { - use ast::StatementType::*; - let node = match &statement.node { - ClassDef { - name, - body, - keywords, - decorator_list, - .. - } => node!(vm, ClassDef, { - name => vm.ctx.new_str(name), - keywords => map_ast(keyword_to_ast, vm, keywords)?, - body => statements_to_ast(vm, body)?, - decorator_list => expressions_to_ast(vm, decorator_list)?, - }), - FunctionDef { - is_async, - name, - args, - body, - decorator_list, - returns, - } => { - if *is_async { - node!(vm, AsyncFunctionDef, { - name => vm.ctx.new_str(name), - args => parameters_to_ast(vm, args)?, - body => statements_to_ast(vm, body)?, - decorator_list => expressions_to_ast(vm, decorator_list)?, - returns => optional_expression_to_ast(vm, returns)? - }) - } else { - node!(vm, FunctionDef, { - name => vm.ctx.new_str(name), - args => parameters_to_ast(vm, args)?, - body => statements_to_ast(vm, body)?, - decorator_list => expressions_to_ast(vm, decorator_list)?, - returns => optional_expression_to_ast(vm, returns)? - }) - } - } - Continue => node!(vm, Continue), - Break => node!(vm, Break), - Pass => node!(vm, Pass), - Assert { test, msg } => node!(vm, Assert, { - test => expression_to_ast(vm, test)?, - msg => optional_expression_to_ast(vm, msg)? - }), - Delete { targets } => { - let targets: PyResult<_> = targets - .iter() - .map(|v| Ok(expression_to_ast(vm, v)?.into_object())) - .collect(); - let py_targets = vm.ctx.new_tuple(targets?); - node!(vm, Delete, { targets => py_targets }) - } - Return { value } => node!(vm, Return, { - value => optional_expression_to_ast(vm, value)? - }), - If { test, body, orelse } => node!(vm, If, { - test => expression_to_ast(vm, test)?, - body => statements_to_ast(vm, body)?, - orelse => optional_statements_to_ast(vm, orelse)? - }), - For { - is_async, - target, - iter, - body, - orelse, - } => { - if *is_async { - node!(vm, AsyncFor, { - target => expression_to_ast(vm, target)?, - iter => expression_to_ast(vm, iter)?, - body => statements_to_ast(vm, body)?, - orelse => optional_statements_to_ast(vm, orelse)? - }) - } else { - node!(vm, For, { - target => expression_to_ast(vm, target)?, - iter => expression_to_ast(vm, iter)?, - body => statements_to_ast(vm, body)?, - orelse => optional_statements_to_ast(vm, orelse)? - }) - } - } - While { test, body, orelse } => node!(vm, While, { - test => expression_to_ast(vm, test)?, - body => statements_to_ast(vm, body)?, - orelse => optional_statements_to_ast(vm, orelse)? - }), - With { - is_async, - items, - body, - } => { - if *is_async { - node!(vm, AsyncWith, { - items => map_ast(with_item_to_ast, vm, items)?, - body => statements_to_ast(vm, body)? - }) - } else { - node!(vm, With, { - items => map_ast(with_item_to_ast, vm, items)?, - body => statements_to_ast(vm, body)? - }) - } - } - Try { - body, - handlers, - orelse, - finalbody, - } => node!(vm, Try, { - body => statements_to_ast(vm, body)?, - handlers => map_ast(handler_to_ast, vm, handlers)?, - orelse => optional_statements_to_ast(vm, orelse)?, - finalbody => optional_statements_to_ast(vm, finalbody)? - }), - Expression { expression } => node!(vm, Expr, { - value => expression_to_ast(vm, expression)? - }), - Import { names } => node!(vm, Import, { - names => map_ast(alias_to_ast, vm, names)? - }), - ImportFrom { - level, - module, - names, - } => node!(vm, ImportFrom, { - level => vm.ctx.new_int(*level), - module => module.as_ref().into_pyobject(vm), - names => map_ast(alias_to_ast, vm, names)? - }), - Nonlocal { names } => node!(vm, Nonlocal, { - names => make_string_list(vm, names) - }), - Global { names } => node!(vm, Global, { - names => make_string_list(vm, names) - }), - Assign { targets, value } => node!(vm, Assign, { - targets => expressions_to_ast(vm, targets)?, - value => expression_to_ast(vm, value)?, - }), - AugAssign { target, op, value } => node!(vm, AugAssign, { - target => expression_to_ast(vm, target)?, - op => vm.ctx.new_str(operator_string(op)), - value => expression_to_ast(vm, value)?, - }), - AnnAssign { - target, - annotation, - value, - } => node!(vm, AnnAssign, { - target => expression_to_ast(vm, target)?, - annotation => expression_to_ast(vm, annotation)?, - value => optional_expression_to_ast(vm, value)?, - }), - Raise { exception, cause } => node!(vm, Raise, { - exc => optional_expression_to_ast(vm, exception)?, - cause => optional_expression_to_ast(vm, cause)?, - }), - }; - - // set lineno on node: - let lineno = vm.ctx.new_int(statement.location.row()); - vm.set_attr(node.as_object(), "lineno", lineno).unwrap(); - - Ok(node) -} - -fn alias_to_ast(vm: &VirtualMachine, alias: &ast::ImportSymbol) -> PyResult { - Ok(node!(vm, alias, { - name => vm.ctx.new_str(&alias.symbol), - asname => alias.alias.as_ref().into_pyobject(vm), - })) -} - -fn optional_statements_to_ast( - vm: &VirtualMachine, - statements: &Option>, -) -> PyResult { - let statements = if let Some(statements) = statements { - statements_to_ast(vm, statements)?.into_object() - } else { - vm.ctx.new_list(vec![]) - }; - Ok(statements) -} - -fn with_item_to_ast(vm: &VirtualMachine, with_item: &ast::WithItem) -> PyResult { - let node = node!(vm, withitem, { - context_expr => expression_to_ast(vm, &with_item.context_expr)?, - optional_vars => optional_expression_to_ast(vm, &with_item.optional_vars)? - }); - Ok(node) -} - -fn handler_to_ast(vm: &VirtualMachine, handler: &ast::ExceptHandler) -> PyResult { - let node = node!(vm, ExceptHandler, { - typ => optional_expression_to_ast(vm, &handler.typ)?, - name => handler.name.as_ref().into_pyobject(vm), - body => statements_to_ast(vm, &handler.body)?, - }); - Ok(node) -} - -fn make_string_list(vm: &VirtualMachine, names: &[String]) -> PyObjectRef { - vm.ctx - .new_list(names.iter().map(|x| vm.ctx.new_str(x)).collect()) -} - -fn optional_expressions_to_ast( - vm: &VirtualMachine, - expressions: &[Option], -) -> PyResult { - let py_expression_nodes: PyResult<_> = expressions - .iter() - .map(|expression| Ok(optional_expression_to_ast(vm, expression)?)) - .collect(); - Ok(vm.ctx.new_list(py_expression_nodes?).downcast().unwrap()) -} - -fn optional_expression_to_ast(vm: &VirtualMachine, value: &Option) -> PyResult { - let ast = value - .as_ref() - .map(|expr| expression_to_ast(vm, expr)) - .transpose()?; - Ok(ast.into_pyobject(vm)) -} - -fn expressions_to_ast(vm: &VirtualMachine, expressions: &[ast::Expression]) -> PyResult { - let py_expression_nodes: PyResult<_> = expressions - .iter() - .map(|expression| Ok(expression_to_ast(vm, expression)?.into_object())) - .collect(); - Ok(vm.ctx.new_list(py_expression_nodes?).downcast().unwrap()) -} - -fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyResult { - use ast::ExpressionType::*; - let node = match &expression.node { - Call { - function, - args, - keywords, - } => node!(vm, Call, { - func => expression_to_ast(vm, function)?, - args => expressions_to_ast(vm, args)?, - keywords => map_ast(keyword_to_ast, vm, keywords)?, - }), - Binop { a, op, b } => { - // Operator: - node!(vm, BinOp, { - left => expression_to_ast(vm, a)?, - op => vm.ctx.new_str(operator_string(op)), - right => expression_to_ast(vm, b)?, - }) - } - Unop { op, a } => { - let op = match op { - ast::UnaryOperator::Not => "Not", - ast::UnaryOperator::Inv => "Invert", - ast::UnaryOperator::Neg => "USub", - ast::UnaryOperator::Pos => "UAdd", - }; - node!(vm, UnaryOp, { - op => vm.ctx.new_str(op), - operand => expression_to_ast(vm, a)?, - }) - } - BoolOp { op, values } => { - let py_values = expressions_to_ast(vm, values)?; - - let str_op = match op { - ast::BooleanOperator::And => "And", - ast::BooleanOperator::Or => "Or", - }; - let py_op = vm.ctx.new_str(str_op); - - node!(vm, BoolOp, { - op => py_op, - values => py_values, - }) - } - Compare { vals, ops } => { - let left = expression_to_ast(vm, &vals[0])?; - - // Operator: - let to_operator = |op: &ast::Comparison| match op { - ast::Comparison::Equal => "Eq", - ast::Comparison::NotEqual => "NotEq", - ast::Comparison::Less => "Lt", - ast::Comparison::LessOrEqual => "LtE", - ast::Comparison::Greater => "Gt", - ast::Comparison::GreaterOrEqual => "GtE", - ast::Comparison::In => "In", - ast::Comparison::NotIn => "NotIn", - ast::Comparison::Is => "Is", - ast::Comparison::IsNot => "IsNot", - }; - let ops = vm +impl Node for ast::Constant { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + match self { + ast::Constant::None => vm.ctx.none(), + ast::Constant::Bool(b) => vm.ctx.new_bool(b), + ast::Constant::Str(s) => vm.ctx.new_str(s), + ast::Constant::Bytes(b) => vm.ctx.new_bytes(b), + ast::Constant::Int(i) => vm.ctx.new_int(i), + ast::Constant::Tuple(t) => vm .ctx - .new_list(ops.iter().map(|x| vm.ctx.new_str(to_operator(x))).collect()); - - let comparators: PyResult<_> = vals - .iter() - .skip(1) - .map(|x| Ok(expression_to_ast(vm, x)?.into_object())) - .collect(); - let comparators = vm.ctx.new_list(comparators?); - node!(vm, Compare, { - left => left, - ops => ops, - comparators => comparators, - }) + .new_tuple(t.into_iter().map(|c| c.ast_to_object(vm)).collect()), + ast::Constant::Float(f) => vm.ctx.new_float(f), + ast::Constant::Complex { real, imag } => vm.ctx.new_complex(Complex64::new(real, imag)), + ast::Constant::Ellipsis => vm.ctx.ellipsis(), } - Identifier { name } => node!(vm, Name, { - id => vm.ctx.new_str(name), - ctx => vm.ctx.none() // TODO: add context. - }), - Lambda { args, body } => node!(vm, Lambda, { - args => parameters_to_ast(vm, args)?, - body => expression_to_ast(vm, body)?, - }), - IfExpression { test, body, orelse } => node!(vm, IfExp, { - text => expression_to_ast(vm, test)?, - body => expression_to_ast(vm, body)?, - or_else => expression_to_ast(vm, orelse)?, - }), - Number { value } => { - let py_n = match value { - ast::Number::Integer { value } => vm.ctx.new_bigint(value), - ast::Number::Float { value } => vm.ctx.new_float(*value), - ast::Number::Complex { real, imag } => { - vm.ctx.new_complex(Complex64::new(*real, *imag)) - } - }; - node!(vm, Num, { - n => py_n - }) - } - True => node!(vm, NameConstant, { - value => vm.ctx.new_bool(true) - }), - False => node!(vm, NameConstant, { - value => vm.ctx.new_bool(false) - }), - None => node!(vm, NameConstant, { - value => vm.ctx.none() - }), - Ellipsis => node!(vm, Ellipsis), - List { elements } => node!(vm, List, { - elts => expressions_to_ast(vm, &elements)? - }), - Tuple { elements } => node!(vm, Tuple, { - elts => expressions_to_ast(vm, &elements)? - }), - Set { elements } => node!(vm, Set, { - elts => expressions_to_ast(vm, &elements)? - }), - Dict { elements } => { - let mut keys = Vec::new(); - let mut values = Vec::new(); - for (k, v) in elements { - let k = k.as_ref().map(|k| expression_to_ast(vm, k)).transpose()?; - keys.push(k.into_pyobject(vm)); - values.push(expression_to_ast(vm, v)?.into_object()); - } - - node!(vm, Dict, { - keys => vm.ctx.new_list(keys), - values => vm.ctx.new_list(values), - }) - } - Comprehension { kind, generators } => { - let py_generators = map_ast(comprehension_to_ast, vm, generators)?; - - match kind.deref() { - ast::ComprehensionKind::GeneratorExpression { element } => { - node!(vm, GeneratorExp, { - elt => expression_to_ast(vm, element)?, - generators => py_generators - }) - } - ast::ComprehensionKind::List { element } => node!(vm, ListComp, { - elt => expression_to_ast(vm, element)?, - generators => py_generators - }), - ast::ComprehensionKind::Set { element } => node!(vm, SetComp, { - elt => expression_to_ast(vm, element)?, - generators => py_generators - }), - ast::ComprehensionKind::Dict { key, value } => node!(vm, DictComp, { - key => expression_to_ast(vm, key)?, - value => expression_to_ast(vm, value)?, - generators => py_generators - }), - } - } - Await { value } => { - let py_value = expression_to_ast(vm, value)?; - node!(vm, Await, { - value => py_value - }) - } - Yield { value } => { - let py_value = value - .as_ref() - .map(|v| expression_to_ast(vm, v)) - .transpose()?; - node!(vm, Yield, { - value => py_value.into_pyobject(vm) - }) - } - YieldFrom { value } => { - let py_value = expression_to_ast(vm, value)?; - node!(vm, YieldFrom, { - value => py_value - }) - } - Subscript { a, b } => node!(vm, Subscript, { - value => expression_to_ast(vm, a)?, - slice => expression_to_ast(vm, b)?, - }), - Attribute { value, name } => node!(vm, Attribute, { - value => expression_to_ast(vm, value)?, - attr => vm.ctx.new_str(name), - ctx => vm.ctx.none() - }), - Starred { value } => node!(vm, Starred, { - value => expression_to_ast(vm, value)? - }), - Slice { elements } => node!(vm, Slice, { - bounds => expressions_to_ast(vm, elements)? - }), - String { value } => string_to_ast(vm, value)?, - Bytes { value } => node!(vm, Bytes, { s => vm.ctx.new_bytes(value.clone()) }), - NamedExpression { left, right } => { - node!(vm, NamedExpression, { left => expression_to_ast(vm, left)?, right => expression_to_ast(vm, right)? }) - } - }; - - let lineno = vm.ctx.new_int(expression.location.row()); - vm.set_attr(node.as_object(), "lineno", lineno).unwrap(); - Ok(node) -} - -fn operator_string(op: &ast::Operator) -> String { - use ast::Operator::*; - match op { - Add => "Add", - Sub => "Sub", - Mult => "Mult", - MatMult => "MatMult", - Div => "Div", - Mod => "Mod", - Pow => "Pow", - LShift => "LShift", - RShift => "RShift", - BitOr => "BitOr", - BitXor => "BitXor", - BitAnd => "BitAnd", - FloorDiv => "FloorDiv", } - .to_owned() + + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } } -fn parameters_to_ast(vm: &VirtualMachine, args: &ast::Parameters) -> PyResult { - Ok(node!(vm, arguments, { - args => map_ast(parameter_to_ast, vm, &args.args)?, - vararg => vararg_to_ast(vm, &args.vararg)?, - kwonlyargs => map_ast(parameter_to_ast, vm, &args.kwonlyargs)?, - kw_defaults => optional_expressions_to_ast(vm, &args.kw_defaults)?, - kwarg => vararg_to_ast(vm, &args.kwarg)?, - defaults => expressions_to_ast(vm, &args.defaults)? - })) -} +impl Node for ast::ConversionFlag { + fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_int(self as u8) + } -fn vararg_to_ast(vm: &VirtualMachine, vararg: &ast::Varargs) -> PyResult { - let py_node = match vararg { - ast::Varargs::None => vm.ctx.none(), - ast::Varargs::Unnamed => vm.ctx.none(), - ast::Varargs::Named(parameter) => parameter_to_ast(vm, parameter)?.into_object(), - }; - Ok(py_node) -} - -fn parameter_to_ast(vm: &VirtualMachine, parameter: &ast::Parameter) -> PyResult { - let py_annotation = parameter - .annotation - .as_ref() - .map(|expr| expression_to_ast(vm, expr)) - .transpose()? - .into_pyobject(vm); - let py_node = node!(vm, arg, { - arg => vm.ctx.new_str(¶meter.arg), - annotation => py_annotation - }); - - let lineno = vm.ctx.new_int(parameter.location.row()); - vm.set_attr(py_node.as_object(), "lineno", lineno)?; - - Ok(py_node) -} - -fn keyword_to_ast(vm: &VirtualMachine, keyword: &ast::Keyword) -> PyResult { - Ok(node!(vm, keyword, { - arg => keyword.name.as_ref().into_pyobject(vm), - value => expression_to_ast(vm, &keyword.value)? - })) -} - -fn map_ast( - f: fn(vm: &VirtualMachine, &T) -> PyResult, - vm: &VirtualMachine, - items: &[T], -) -> PyResult { - let list: PyResult> = - items.iter().map(|x| Ok(f(vm, x)?.into_object())).collect(); - Ok(vm.ctx.new_list(list?)) -} - -fn comprehension_to_ast( - vm: &VirtualMachine, - comprehension: &ast::Comprehension, -) -> PyResult { - Ok(node!(vm, comprehension, { - target => expression_to_ast(vm, &comprehension.target)?, - iter => expression_to_ast(vm, &comprehension.iter)?, - ifs => expressions_to_ast(vm, &comprehension.ifs)?, - is_async => vm.ctx.new_bool(comprehension.is_async), - })) -} - -fn string_to_ast(vm: &VirtualMachine, string: &ast::StringGroup) -> PyResult { - let string = match string { - ast::StringGroup::Constant { value } => node!(vm, Str, { s => vm.ctx.new_str(value) }), - ast::StringGroup::FormattedValue { value, .. } => { - node!(vm, FormattedValue, { value => expression_to_ast(vm, value)? }) - } - ast::StringGroup::Joined { values } => { - let py_values = map_ast(string_to_ast, vm, &values)?; - node!(vm, JoinedStr, { values => py_values }) - } - }; - Ok(string) + fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { + i32::try_from_object(vm, object)? + .to_u8() + .and_then(ast::ConversionFlag::try_from_byte) + .ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned())) + } } pub(crate) fn parse(vm: &VirtualMachine, source: &str, mode: Mode) -> PyResult { - let ast = parser::parse(source, mode).map_err(|err| vm.new_value_error(format!("{}", err)))?; - let py_body = top_to_ast(vm, &ast)?; - Ok(node!(vm, Module, { body => py_body }).into_object()) + // TODO: use vm.new_syntax_error() + let top = parser::parse(source, mode).map_err(|err| vm.new_value_error(format!("{}", err)))?; + Ok(top.ast_to_object(vm)) } pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; let ast_base = AstNode::make_class(ctx); - py_module!(vm, MODULE_NAME, { + let module = py_module!(vm, MODULE_NAME, { // TODO: There's got to be a better way! - "alias" => py_class!(ctx, "alias", &ast_base, {}), - "arg" => py_class!(ctx, "arg", &ast_base, {}), - "arguments" => py_class!(ctx, "arguments", &ast_base, {}), - "AnnAssign" => py_class!(ctx, "AnnAssign", &ast_base, {}), - "Assign" => py_class!(ctx, "Assign", &ast_base, {}), - "AugAssign" => py_class!(ctx, "AugAssign", &ast_base, {}), - "AsyncFor" => py_class!(ctx, "AsyncFor", &ast_base, {}), - "AsyncFunctionDef" => py_class!(ctx, "AsyncFunctionDef", &ast_base, {}), - "AsyncWith" => py_class!(ctx, "AsyncWith", &ast_base, {}), - "Assert" => py_class!(ctx, "Assert", &ast_base, {}), - "Attribute" => py_class!(ctx, "Attribute", &ast_base, {}), - "Await" => py_class!(ctx, "Await", &ast_base, {}), - "BinOp" => py_class!(ctx, "BinOp", &ast_base, {}), - "BoolOp" => py_class!(ctx, "BoolOp", &ast_base, {}), - "Break" => py_class!(ctx, "Break", &ast_base, {}), - "Bytes" => py_class!(ctx, "Bytes", &ast_base, {}), - "Call" => py_class!(ctx, "Call", &ast_base, {}), - "ClassDef" => py_class!(ctx, "ClassDef", &ast_base, {}), - "Compare" => py_class!(ctx, "Compare", &ast_base, {}), - "comprehension" => py_class!(ctx, "comprehension", &ast_base, {}), - "Continue" => py_class!(ctx, "Continue", &ast_base, {}), - "Delete" => py_class!(ctx, "Delete", &ast_base, {}), - "Dict" => py_class!(ctx, "Dict", &ast_base, {}), - "DictComp" => py_class!(ctx, "DictComp", &ast_base, {}), - "Ellipsis" => py_class!(ctx, "Ellipsis", &ast_base, {}), - "Expr" => py_class!(ctx, "Expr", &ast_base, {}), - "ExceptHandler" => py_class!(ctx, "ExceptHandler", &ast_base, {}), - "For" => py_class!(ctx, "For", &ast_base, {}), - "FormattedValue" => py_class!(ctx, "FormattedValue", &ast_base, {}), - "FunctionDef" => py_class!(ctx, "FunctionDef", &ast_base, {}), - "GeneratorExp" => py_class!(ctx, "GeneratorExp", &ast_base, {}), - "Global" => py_class!(ctx, "Global", &ast_base, {}), - "If" => py_class!(ctx, "If", &ast_base, {}), - "IfExp" => py_class!(ctx, "IfExp", &ast_base, {}), - "Import" => py_class!(ctx, "Import", &ast_base, {}), - "ImportFrom" => py_class!(ctx, "ImportFrom", &ast_base, {}), - "JoinedStr" => py_class!(ctx, "JoinedStr", &ast_base, {}), - "keyword" => py_class!(ctx, "keyword", &ast_base, {}), - "Lambda" => py_class!(ctx, "Lambda", &ast_base, {}), - "List" => py_class!(ctx, "List", &ast_base, {}), - "ListComp" => py_class!(ctx, "ListComp", &ast_base, {}), - "Module" => py_class!(ctx, "Module", &ast_base, {}), - "Name" => py_class!(ctx, "Name", &ast_base, {}), - "NameConstant" => py_class!(ctx, "NameConstant", &ast_base, {}), - "NamedExpression" => py_class!(ctx, "NamedExpression", &ast_base, {}), - "Nonlocal" => py_class!(ctx, "Nonlocal", &ast_base, {}), - "Num" => py_class!(ctx, "Num", &ast_base, {}), - "Pass" => py_class!(ctx, "Pass", &ast_base, {}), - "Raise" => py_class!(ctx, "Raise", &ast_base, {}), - "Return" => py_class!(ctx, "Return", &ast_base, {}), - "Set" => py_class!(ctx, "Set", &ast_base, {}), - "SetComp" => py_class!(ctx, "SetComp", &ast_base, {}), - "Slice" => py_class!(ctx, "Slice", &ast_base, {}), - "Starred" => py_class!(ctx, "Starred", &ast_base, {}), - "Starred" => py_class!(ctx, "Starred", &ast_base, {}), - "Str" => py_class!(ctx, "Str", &ast_base, {}), - "Subscript" => py_class!(ctx, "Subscript", &ast_base, {}), - "Try" => py_class!(ctx, "Try", &ast_base, {}), - "Tuple" => py_class!(ctx, "Tuple", &ast_base, {}), - "UnaryOp" => py_class!(ctx, "UnaryOp", &ast_base, {}), - "While" => py_class!(ctx, "While", &ast_base, {}), - "With" => py_class!(ctx, "With", &ast_base, {}), - "withitem" => py_class!(ctx, "withitem", &ast_base, {}), - "Yield" => py_class!(ctx, "Yield", &ast_base, {}), - "YieldFrom" => py_class!(ctx, "YieldFrom", &ast_base, {}), "AST" => ast_base, "PyCF_ONLY_AST" => ctx.new_int(PY_COMPILE_FLAG_AST_ONLY), - }) + }); + gen::extend_module_nodes(vm, &module); + module } diff --git a/vm/src/stdlib/ast/gen.rs b/vm/src/stdlib/ast/gen.rs new file mode 100644 index 000000000..f6df6461c --- /dev/null +++ b/vm/src/stdlib/ast/gen.rs @@ -0,0 +1,1825 @@ +// File automatically generated by ast/asdl_rs.py. + +use super::*; + +#[pyclass(module = "_ast", name = "Module", base = "AstNode")] +struct NodeModule; +#[pyimpl(flags(HAS_DICT))] +impl NodeModule { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("body"),ctx.new_str("type_ignores")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("body"),ctx.new_str("type_ignores")])); + } +} +#[pyclass(module = "_ast", name = "Interactive", base = "AstNode")] +struct NodeInteractive; +#[pyimpl(flags(HAS_DICT))] +impl NodeInteractive { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("body")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("body")])); + } +} +#[pyclass(module = "_ast", name = "Expression", base = "AstNode")] +struct NodeExpression; +#[pyimpl(flags(HAS_DICT))] +impl NodeExpression { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("body")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("body")])); + } +} +#[pyclass(module = "_ast", name = "FunctionType", base = "AstNode")] +struct NodeFunctionType; +#[pyimpl(flags(HAS_DICT))] +impl NodeFunctionType { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("argtypes"),ctx.new_str("returns")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("argtypes"),ctx.new_str("returns")])); + } +} +#[pyclass(module = "_ast", name = "FunctionDef", base = "AstNode")] +struct NodeFunctionDef; +#[pyimpl(flags(HAS_DICT))] +impl NodeFunctionDef { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("args"),ctx.new_str("body"),ctx.new_str("decorator_list"),ctx.new_str("returns"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("args"),ctx.new_str("body"),ctx.new_str("decorator_list"),ctx.new_str("returns"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = "AstNode")] +struct NodeAsyncFunctionDef; +#[pyimpl(flags(HAS_DICT))] +impl NodeAsyncFunctionDef { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("args"),ctx.new_str("body"),ctx.new_str("decorator_list"),ctx.new_str("returns"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("args"),ctx.new_str("body"),ctx.new_str("decorator_list"),ctx.new_str("returns"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "ClassDef", base = "AstNode")] +struct NodeClassDef; +#[pyimpl(flags(HAS_DICT))] +impl NodeClassDef { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("bases"),ctx.new_str("keywords"),ctx.new_str("body"),ctx.new_str("decorator_list")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("bases"),ctx.new_str("keywords"),ctx.new_str("body"),ctx.new_str("decorator_list")])); + } +} +#[pyclass(module = "_ast", name = "Return", base = "AstNode")] +struct NodeReturn; +#[pyimpl(flags(HAS_DICT))] +impl NodeReturn { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "Delete", base = "AstNode")] +struct NodeDelete; +#[pyimpl(flags(HAS_DICT))] +impl NodeDelete { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("targets")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("targets")])); + } +} +#[pyclass(module = "_ast", name = "Assign", base = "AstNode")] +struct NodeAssign; +#[pyimpl(flags(HAS_DICT))] +impl NodeAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("targets"),ctx.new_str("value"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("targets"),ctx.new_str("value"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "AugAssign", base = "AstNode")] +struct NodeAugAssign; +#[pyimpl(flags(HAS_DICT))] +impl NodeAugAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("op"),ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("op"),ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "AnnAssign", base = "AstNode")] +struct NodeAnnAssign; +#[pyimpl(flags(HAS_DICT))] +impl NodeAnnAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("annotation"),ctx.new_str("value"),ctx.new_str("simple")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("annotation"),ctx.new_str("value"),ctx.new_str("simple")])); + } +} +#[pyclass(module = "_ast", name = "For", base = "AstNode")] +struct NodeFor; +#[pyimpl(flags(HAS_DICT))] +impl NodeFor { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("body"),ctx.new_str("orelse"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("body"),ctx.new_str("orelse"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "AsyncFor", base = "AstNode")] +struct NodeAsyncFor; +#[pyimpl(flags(HAS_DICT))] +impl NodeAsyncFor { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("body"),ctx.new_str("orelse"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("body"),ctx.new_str("orelse"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "While", base = "AstNode")] +struct NodeWhile; +#[pyimpl(flags(HAS_DICT))] +impl NodeWhile { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + } +} +#[pyclass(module = "_ast", name = "If", base = "AstNode")] +struct NodeIf; +#[pyimpl(flags(HAS_DICT))] +impl NodeIf { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + } +} +#[pyclass(module = "_ast", name = "With", base = "AstNode")] +struct NodeWith; +#[pyimpl(flags(HAS_DICT))] +impl NodeWith { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("items"),ctx.new_str("body"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("items"),ctx.new_str("body"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "AsyncWith", base = "AstNode")] +struct NodeAsyncWith; +#[pyimpl(flags(HAS_DICT))] +impl NodeAsyncWith { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("items"),ctx.new_str("body"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("items"),ctx.new_str("body"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "Raise", base = "AstNode")] +struct NodeRaise; +#[pyimpl(flags(HAS_DICT))] +impl NodeRaise { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("exc"),ctx.new_str("cause")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("exc"),ctx.new_str("cause")])); + } +} +#[pyclass(module = "_ast", name = "Try", base = "AstNode")] +struct NodeTry; +#[pyimpl(flags(HAS_DICT))] +impl NodeTry { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("body"),ctx.new_str("handlers"),ctx.new_str("orelse"),ctx.new_str("finalbody")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("body"),ctx.new_str("handlers"),ctx.new_str("orelse"),ctx.new_str("finalbody")])); + } +} +#[pyclass(module = "_ast", name = "Assert", base = "AstNode")] +struct NodeAssert; +#[pyimpl(flags(HAS_DICT))] +impl NodeAssert { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("msg")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("msg")])); + } +} +#[pyclass(module = "_ast", name = "Import", base = "AstNode")] +struct NodeImport; +#[pyimpl(flags(HAS_DICT))] +impl NodeImport { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("names")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("names")])); + } +} +#[pyclass(module = "_ast", name = "ImportFrom", base = "AstNode")] +struct NodeImportFrom; +#[pyimpl(flags(HAS_DICT))] +impl NodeImportFrom { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("module"),ctx.new_str("names"),ctx.new_str("level")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("module"),ctx.new_str("names"),ctx.new_str("level")])); + } +} +#[pyclass(module = "_ast", name = "Global", base = "AstNode")] +struct NodeGlobal; +#[pyimpl(flags(HAS_DICT))] +impl NodeGlobal { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("names")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("names")])); + } +} +#[pyclass(module = "_ast", name = "Nonlocal", base = "AstNode")] +struct NodeNonlocal; +#[pyimpl(flags(HAS_DICT))] +impl NodeNonlocal { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("names")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("names")])); + } +} +#[pyclass(module = "_ast", name = "Expr", base = "AstNode")] +struct NodeExpr; +#[pyimpl(flags(HAS_DICT))] +impl NodeExpr { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "Pass", base = "AstNode")] +struct NodePass; +#[pyimpl(flags(HAS_DICT))] +impl NodePass { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Break", base = "AstNode")] +struct NodeBreak; +#[pyimpl(flags(HAS_DICT))] +impl NodeBreak { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Continue", base = "AstNode")] +struct NodeContinue; +#[pyimpl(flags(HAS_DICT))] +impl NodeContinue { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "BoolOp", base = "AstNode")] +struct NodeBoolOp; +#[pyimpl(flags(HAS_DICT))] +impl NodeBoolOp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("op"),ctx.new_str("values")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("op"),ctx.new_str("values")])); + } +} +#[pyclass(module = "_ast", name = "NamedExpr", base = "AstNode")] +struct NodeNamedExpr; +#[pyimpl(flags(HAS_DICT))] +impl NodeNamedExpr { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "BinOp", base = "AstNode")] +struct NodeBinOp; +#[pyimpl(flags(HAS_DICT))] +impl NodeBinOp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("left"),ctx.new_str("op"),ctx.new_str("right")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("left"),ctx.new_str("op"),ctx.new_str("right")])); + } +} +#[pyclass(module = "_ast", name = "UnaryOp", base = "AstNode")] +struct NodeUnaryOp; +#[pyimpl(flags(HAS_DICT))] +impl NodeUnaryOp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("op"),ctx.new_str("operand")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("op"),ctx.new_str("operand")])); + } +} +#[pyclass(module = "_ast", name = "Lambda", base = "AstNode")] +struct NodeLambda; +#[pyimpl(flags(HAS_DICT))] +impl NodeLambda { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("args"),ctx.new_str("body")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("args"),ctx.new_str("body")])); + } +} +#[pyclass(module = "_ast", name = "IfExp", base = "AstNode")] +struct NodeIfExp; +#[pyimpl(flags(HAS_DICT))] +impl NodeIfExp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("test"),ctx.new_str("body"),ctx.new_str("orelse")])); + } +} +#[pyclass(module = "_ast", name = "Dict", base = "AstNode")] +struct NodeDict; +#[pyimpl(flags(HAS_DICT))] +impl NodeDict { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("keys"),ctx.new_str("values")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("keys"),ctx.new_str("values")])); + } +} +#[pyclass(module = "_ast", name = "Set", base = "AstNode")] +struct NodeSet; +#[pyimpl(flags(HAS_DICT))] +impl NodeSet { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elts")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elts")])); + } +} +#[pyclass(module = "_ast", name = "ListComp", base = "AstNode")] +struct NodeListComp; +#[pyimpl(flags(HAS_DICT))] +impl NodeListComp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + } +} +#[pyclass(module = "_ast", name = "SetComp", base = "AstNode")] +struct NodeSetComp; +#[pyimpl(flags(HAS_DICT))] +impl NodeSetComp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + } +} +#[pyclass(module = "_ast", name = "DictComp", base = "AstNode")] +struct NodeDictComp; +#[pyimpl(flags(HAS_DICT))] +impl NodeDictComp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("key"),ctx.new_str("value"),ctx.new_str("generators")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("key"),ctx.new_str("value"),ctx.new_str("generators")])); + } +} +#[pyclass(module = "_ast", name = "GeneratorExp", base = "AstNode")] +struct NodeGeneratorExp; +#[pyimpl(flags(HAS_DICT))] +impl NodeGeneratorExp { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elt"),ctx.new_str("generators")])); + } +} +#[pyclass(module = "_ast", name = "Await", base = "AstNode")] +struct NodeAwait; +#[pyimpl(flags(HAS_DICT))] +impl NodeAwait { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "Yield", base = "AstNode")] +struct NodeYield; +#[pyimpl(flags(HAS_DICT))] +impl NodeYield { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "YieldFrom", base = "AstNode")] +struct NodeYieldFrom; +#[pyimpl(flags(HAS_DICT))] +impl NodeYieldFrom { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "Compare", base = "AstNode")] +struct NodeCompare; +#[pyimpl(flags(HAS_DICT))] +impl NodeCompare { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("left"),ctx.new_str("ops"),ctx.new_str("comparators")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("left"),ctx.new_str("ops"),ctx.new_str("comparators")])); + } +} +#[pyclass(module = "_ast", name = "Call", base = "AstNode")] +struct NodeCall; +#[pyimpl(flags(HAS_DICT))] +impl NodeCall { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("func"),ctx.new_str("args"),ctx.new_str("keywords")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("func"),ctx.new_str("args"),ctx.new_str("keywords")])); + } +} +#[pyclass(module = "_ast", name = "FormattedValue", base = "AstNode")] +struct NodeFormattedValue; +#[pyimpl(flags(HAS_DICT))] +impl NodeFormattedValue { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("conversion"),ctx.new_str("format_spec")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("conversion"),ctx.new_str("format_spec")])); + } +} +#[pyclass(module = "_ast", name = "JoinedStr", base = "AstNode")] +struct NodeJoinedStr; +#[pyimpl(flags(HAS_DICT))] +impl NodeJoinedStr { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("values")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("values")])); + } +} +#[pyclass(module = "_ast", name = "Constant", base = "AstNode")] +struct NodeConstant; +#[pyimpl(flags(HAS_DICT))] +impl NodeConstant { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("kind")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("kind")])); + } +} +#[pyclass(module = "_ast", name = "Attribute", base = "AstNode")] +struct NodeAttribute; +#[pyimpl(flags(HAS_DICT))] +impl NodeAttribute { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("attr"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("attr"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "Subscript", base = "AstNode")] +struct NodeSubscript; +#[pyimpl(flags(HAS_DICT))] +impl NodeSubscript { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("slice"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("slice"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "Starred", base = "AstNode")] +struct NodeStarred; +#[pyimpl(flags(HAS_DICT))] +impl NodeStarred { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("value"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "Name", base = "AstNode")] +struct NodeName; +#[pyimpl(flags(HAS_DICT))] +impl NodeName { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("id"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("id"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "List", base = "AstNode")] +struct NodeList; +#[pyimpl(flags(HAS_DICT))] +impl NodeList { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elts"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elts"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "Tuple", base = "AstNode")] +struct NodeTuple; +#[pyimpl(flags(HAS_DICT))] +impl NodeTuple { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("elts"),ctx.new_str("ctx")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("elts"),ctx.new_str("ctx")])); + } +} +#[pyclass(module = "_ast", name = "Slice", base = "AstNode")] +struct NodeSlice; +#[pyimpl(flags(HAS_DICT))] +impl NodeSlice { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("lower"),ctx.new_str("upper"),ctx.new_str("step")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("lower"),ctx.new_str("upper"),ctx.new_str("step")])); + } +} +#[pyclass(module = "_ast", name = "Load", base = "AstNode")] +struct NodeLoad; +#[pyimpl(flags(HAS_DICT))] +impl NodeLoad { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Store", base = "AstNode")] +struct NodeStore; +#[pyimpl(flags(HAS_DICT))] +impl NodeStore { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Del", base = "AstNode")] +struct NodeDel; +#[pyimpl(flags(HAS_DICT))] +impl NodeDel { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "And", base = "AstNode")] +struct NodeAnd; +#[pyimpl(flags(HAS_DICT))] +impl NodeAnd { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Or", base = "AstNode")] +struct NodeOr; +#[pyimpl(flags(HAS_DICT))] +impl NodeOr { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Add", base = "AstNode")] +struct NodeAdd; +#[pyimpl(flags(HAS_DICT))] +impl NodeAdd { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Sub", base = "AstNode")] +struct NodeSub; +#[pyimpl(flags(HAS_DICT))] +impl NodeSub { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Mult", base = "AstNode")] +struct NodeMult; +#[pyimpl(flags(HAS_DICT))] +impl NodeMult { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "MatMult", base = "AstNode")] +struct NodeMatMult; +#[pyimpl(flags(HAS_DICT))] +impl NodeMatMult { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Div", base = "AstNode")] +struct NodeDiv; +#[pyimpl(flags(HAS_DICT))] +impl NodeDiv { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Mod", base = "AstNode")] +struct NodeMod; +#[pyimpl(flags(HAS_DICT))] +impl NodeMod { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Pow", base = "AstNode")] +struct NodePow; +#[pyimpl(flags(HAS_DICT))] +impl NodePow { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "LShift", base = "AstNode")] +struct NodeLShift; +#[pyimpl(flags(HAS_DICT))] +impl NodeLShift { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "RShift", base = "AstNode")] +struct NodeRShift; +#[pyimpl(flags(HAS_DICT))] +impl NodeRShift { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "BitOr", base = "AstNode")] +struct NodeBitOr; +#[pyimpl(flags(HAS_DICT))] +impl NodeBitOr { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "BitXor", base = "AstNode")] +struct NodeBitXor; +#[pyimpl(flags(HAS_DICT))] +impl NodeBitXor { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "BitAnd", base = "AstNode")] +struct NodeBitAnd; +#[pyimpl(flags(HAS_DICT))] +impl NodeBitAnd { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "FloorDiv", base = "AstNode")] +struct NodeFloorDiv; +#[pyimpl(flags(HAS_DICT))] +impl NodeFloorDiv { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Invert", base = "AstNode")] +struct NodeInvert; +#[pyimpl(flags(HAS_DICT))] +impl NodeInvert { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Not", base = "AstNode")] +struct NodeNot; +#[pyimpl(flags(HAS_DICT))] +impl NodeNot { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "UAdd", base = "AstNode")] +struct NodeUAdd; +#[pyimpl(flags(HAS_DICT))] +impl NodeUAdd { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "USub", base = "AstNode")] +struct NodeUSub; +#[pyimpl(flags(HAS_DICT))] +impl NodeUSub { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Eq", base = "AstNode")] +struct NodeEq; +#[pyimpl(flags(HAS_DICT))] +impl NodeEq { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "NotEq", base = "AstNode")] +struct NodeNotEq; +#[pyimpl(flags(HAS_DICT))] +impl NodeNotEq { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Lt", base = "AstNode")] +struct NodeLt; +#[pyimpl(flags(HAS_DICT))] +impl NodeLt { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "LtE", base = "AstNode")] +struct NodeLtE; +#[pyimpl(flags(HAS_DICT))] +impl NodeLtE { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Gt", base = "AstNode")] +struct NodeGt; +#[pyimpl(flags(HAS_DICT))] +impl NodeGt { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "GtE", base = "AstNode")] +struct NodeGtE; +#[pyimpl(flags(HAS_DICT))] +impl NodeGtE { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "Is", base = "AstNode")] +struct NodeIs; +#[pyimpl(flags(HAS_DICT))] +impl NodeIs { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "IsNot", base = "AstNode")] +struct NodeIsNot; +#[pyimpl(flags(HAS_DICT))] +impl NodeIsNot { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "In", base = "AstNode")] +struct NodeIn; +#[pyimpl(flags(HAS_DICT))] +impl NodeIn { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "NotIn", base = "AstNode")] +struct NodeNotIn; +#[pyimpl(flags(HAS_DICT))] +impl NodeNotIn { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![])); + class.set_str_attr("_attributes", ctx.new_list(vec![])); + } +} +#[pyclass(module = "_ast", name = "comprehension", base = "AstNode")] +struct Nodecomprehension; +#[pyimpl(flags(HAS_DICT))] +impl Nodecomprehension { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("ifs"),ctx.new_str("is_async")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("target"),ctx.new_str("iter"),ctx.new_str("ifs"),ctx.new_str("is_async")])); + } +} +#[pyclass(module = "_ast", name = "ExceptHandler", base = "AstNode")] +struct NodeExceptHandler; +#[pyimpl(flags(HAS_DICT))] +impl NodeExceptHandler { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("type"),ctx.new_str("name"),ctx.new_str("body")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("type"),ctx.new_str("name"),ctx.new_str("body")])); + } +} +#[pyclass(module = "_ast", name = "arguments", base = "AstNode")] +struct Nodearguments; +#[pyimpl(flags(HAS_DICT))] +impl Nodearguments { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("posonlyargs"),ctx.new_str("args"),ctx.new_str("vararg"),ctx.new_str("kwonlyargs"),ctx.new_str("kw_defaults"),ctx.new_str("kwarg"),ctx.new_str("defaults")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("posonlyargs"),ctx.new_str("args"),ctx.new_str("vararg"),ctx.new_str("kwonlyargs"),ctx.new_str("kw_defaults"),ctx.new_str("kwarg"),ctx.new_str("defaults")])); + } +} +#[pyclass(module = "_ast", name = "arg", base = "AstNode")] +struct Nodearg; +#[pyimpl(flags(HAS_DICT))] +impl Nodearg { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("arg"),ctx.new_str("annotation"),ctx.new_str("type_comment")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("arg"),ctx.new_str("annotation"),ctx.new_str("type_comment")])); + } +} +#[pyclass(module = "_ast", name = "keyword", base = "AstNode")] +struct Nodekeyword; +#[pyimpl(flags(HAS_DICT))] +impl Nodekeyword { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("arg"),ctx.new_str("value")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("arg"),ctx.new_str("value")])); + } +} +#[pyclass(module = "_ast", name = "alias", base = "AstNode")] +struct Nodealias; +#[pyimpl(flags(HAS_DICT))] +impl Nodealias { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("asname")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("name"),ctx.new_str("asname")])); + } +} +#[pyclass(module = "_ast", name = "withitem", base = "AstNode")] +struct Nodewithitem; +#[pyimpl(flags(HAS_DICT))] +impl Nodewithitem { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("context_expr"),ctx.new_str("optional_vars")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("context_expr"),ctx.new_str("optional_vars")])); + } +} +#[pyclass(module = "_ast", name = "TypeIgnore", base = "AstNode")] +struct NodeTypeIgnore; +#[pyimpl(flags(HAS_DICT))] +impl NodeTypeIgnore { + #[extend_class] + fn extend_class_with_fields(ctx: &PyContext, class: &PyTypeRef) { + class.set_str_attr("_fields", ctx.new_list(vec![ctx.new_str("lineno"),ctx.new_str("tag")])); + class.set_str_attr("_attributes", ctx.new_list(vec![ctx.new_str("lineno"),ctx.new_str("tag")])); + } +} + +impl Node for ast::Mod { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::Mod::Module { body,type_ignores } => { + let _node = AstNode.into_ref_with_type(_vm, NodeModule::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_ignores", type_ignores.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::Mod::Interactive { body } => { + let _node = AstNode.into_ref_with_type(_vm, NodeInteractive::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::Mod::Expression { body } => { + let _node = AstNode.into_ref_with_type(_vm, NodeExpression::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::Mod::FunctionType { argtypes,returns } => { + let _node = AstNode.into_ref_with_type(_vm, NodeFunctionType::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("argtypes", argtypes.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("returns", returns.ast_to_object(_vm), _vm).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Stmt { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self.node { + ast::StmtKind::FunctionDef { name,args,body,decorator_list,returns,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeFunctionDef::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("returns", returns.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::AsyncFunctionDef { name,args,body,decorator_list,returns,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAsyncFunctionDef::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("returns", returns.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::ClassDef { name,bases,keywords,body,decorator_list } => { + let _node = AstNode.into_ref_with_type(_vm, NodeClassDef::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("bases", bases.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("keywords", keywords.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Return { value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeReturn::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Delete { targets } => { + let _node = AstNode.into_ref_with_type(_vm, NodeDelete::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("targets", targets.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Assign { targets,value,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAssign::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("targets", targets.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::AugAssign { target,op,value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAugAssign::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::AnnAssign { target,annotation,value,simple } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAnnAssign::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("annotation", annotation.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("simple", simple.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::For { target,iter,body,orelse,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeFor::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::AsyncFor { target,iter,body,orelse,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAsyncFor::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::While { test,body,orelse } => { + let _node = AstNode.into_ref_with_type(_vm, NodeWhile::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::If { test,body,orelse } => { + let _node = AstNode.into_ref_with_type(_vm, NodeIf::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::With { items,body,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeWith::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("items", items.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::AsyncWith { items,body,type_comment } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAsyncWith::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("items", items.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Raise { exc,cause } => { + let _node = AstNode.into_ref_with_type(_vm, NodeRaise::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("exc", exc.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("cause", cause.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Try { body,handlers,orelse,finalbody } => { + let _node = AstNode.into_ref_with_type(_vm, NodeTry::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("handlers", handlers.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("finalbody", finalbody.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Assert { test,msg } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAssert::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("msg", msg.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Import { names } => { + let _node = AstNode.into_ref_with_type(_vm, NodeImport::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("names", names.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::ImportFrom { module,names,level } => { + let _node = AstNode.into_ref_with_type(_vm, NodeImportFrom::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("module", module.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("names", names.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("level", level.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Global { names } => { + let _node = AstNode.into_ref_with_type(_vm, NodeGlobal::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("names", names.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Nonlocal { names } => { + let _node = AstNode.into_ref_with_type(_vm, NodeNonlocal::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("names", names.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Expr { value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeExpr::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::StmtKind::Pass { } => { + let _node = AstNode.into_ref_with_type(_vm, NodePass::static_type().clone()).unwrap(); + _node + } + ast::StmtKind::Break { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBreak::static_type().clone()).unwrap(); + _node + } + ast::StmtKind::Continue { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeContinue::static_type().clone()).unwrap(); + _node + } + }; + node_add_location(&node, self.location, _vm); + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Expr { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self.node { + ast::ExprKind::BoolOp { op,values } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBoolOp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("values", values.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::NamedExpr { target,value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeNamedExpr::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::BinOp { left,op,right } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBinOp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("left", left.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("right", right.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::UnaryOp { op,operand } => { + let _node = AstNode.into_ref_with_type(_vm, NodeUnaryOp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("operand", operand.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Lambda { args,body } => { + let _node = AstNode.into_ref_with_type(_vm, NodeLambda::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::IfExp { test,body,orelse } => { + let _node = AstNode.into_ref_with_type(_vm, NodeIfExp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("orelse", orelse.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Dict { keys,values } => { + let _node = AstNode.into_ref_with_type(_vm, NodeDict::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("keys", keys.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("values", values.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Set { elts } => { + let _node = AstNode.into_ref_with_type(_vm, NodeSet::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::ListComp { elt,generators } => { + let _node = AstNode.into_ref_with_type(_vm, NodeListComp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("generators", generators.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::SetComp { elt,generators } => { + let _node = AstNode.into_ref_with_type(_vm, NodeSetComp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("generators", generators.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::DictComp { key,value,generators } => { + let _node = AstNode.into_ref_with_type(_vm, NodeDictComp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("key", key.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("generators", generators.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::GeneratorExp { elt,generators } => { + let _node = AstNode.into_ref_with_type(_vm, NodeGeneratorExp::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("generators", generators.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Await { value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAwait::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Yield { value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeYield::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::YieldFrom { value } => { + let _node = AstNode.into_ref_with_type(_vm, NodeYieldFrom::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Compare { left,ops,comparators } => { + let _node = AstNode.into_ref_with_type(_vm, NodeCompare::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("left", left.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ops", ops.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("comparators", comparators.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Call { func,args,keywords } => { + let _node = AstNode.into_ref_with_type(_vm, NodeCall::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("func", func.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("keywords", keywords.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::FormattedValue { value,conversion,format_spec } => { + let _node = AstNode.into_ref_with_type(_vm, NodeFormattedValue::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("conversion", conversion.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("format_spec", format_spec.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::JoinedStr { values } => { + let _node = AstNode.into_ref_with_type(_vm, NodeJoinedStr::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("values", values.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Constant { value,kind } => { + let _node = AstNode.into_ref_with_type(_vm, NodeConstant::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("kind", kind.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Attribute { value,attr,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAttribute::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("attr", attr.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Subscript { value,slice,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeSubscript::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("slice", slice.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Starred { value,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeStarred::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Name { id,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeName::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("id", id.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::List { elts,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeList::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Tuple { elts,ctx } => { + let _node = AstNode.into_ref_with_type(_vm, NodeTuple::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); + _node + } + ast::ExprKind::Slice { lower,upper,step } => { + let _node = AstNode.into_ref_with_type(_vm, NodeSlice::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("lower", lower.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("upper", upper.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("step", step.ast_to_object(_vm), _vm).unwrap(); + _node + } + }; + node_add_location(&node, self.location, _vm); + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::ExprContext { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::ExprContext::Load { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeLoad::static_type().clone()).unwrap(); + _node + } + ast::ExprContext::Store { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeStore::static_type().clone()).unwrap(); + _node + } + ast::ExprContext::Del { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeDel::static_type().clone()).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Boolop { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::Boolop::And { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAnd::static_type().clone()).unwrap(); + _node + } + ast::Boolop::Or { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeOr::static_type().clone()).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Operator { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::Operator::Add { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeAdd::static_type().clone()).unwrap(); + _node + } + ast::Operator::Sub { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeSub::static_type().clone()).unwrap(); + _node + } + ast::Operator::Mult { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeMult::static_type().clone()).unwrap(); + _node + } + ast::Operator::MatMult { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeMatMult::static_type().clone()).unwrap(); + _node + } + ast::Operator::Div { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeDiv::static_type().clone()).unwrap(); + _node + } + ast::Operator::Mod { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeMod::static_type().clone()).unwrap(); + _node + } + ast::Operator::Pow { } => { + let _node = AstNode.into_ref_with_type(_vm, NodePow::static_type().clone()).unwrap(); + _node + } + ast::Operator::LShift { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeLShift::static_type().clone()).unwrap(); + _node + } + ast::Operator::RShift { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeRShift::static_type().clone()).unwrap(); + _node + } + ast::Operator::BitOr { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBitOr::static_type().clone()).unwrap(); + _node + } + ast::Operator::BitXor { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBitXor::static_type().clone()).unwrap(); + _node + } + ast::Operator::BitAnd { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeBitAnd::static_type().clone()).unwrap(); + _node + } + ast::Operator::FloorDiv { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeFloorDiv::static_type().clone()).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Unaryop { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::Unaryop::Invert { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeInvert::static_type().clone()).unwrap(); + _node + } + ast::Unaryop::Not { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeNot::static_type().clone()).unwrap(); + _node + } + ast::Unaryop::UAdd { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeUAdd::static_type().clone()).unwrap(); + _node + } + ast::Unaryop::USub { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeUSub::static_type().clone()).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Cmpop { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::Cmpop::Eq { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeEq::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::NotEq { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeNotEq::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::Lt { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeLt::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::LtE { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeLtE::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::Gt { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeGt::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::GtE { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeGtE::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::Is { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeIs::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::IsNot { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeIsNot::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::In { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeIn::static_type().clone()).unwrap(); + _node + } + ast::Cmpop::NotIn { } => { + let _node = AstNode.into_ref_with_type(_vm, NodeNotIn::static_type().clone()).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Comprehension { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::Comprehension { target,iter,ifs,is_async } = self; + let _node = AstNode.into_ref_with_type(_vm, Nodecomprehension::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("target", target.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("ifs", ifs.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("is_async", is_async.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Excepthandler { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self.node { + ast::ExcepthandlerKind::ExceptHandler { type_,name,body } => { + let _node = AstNode.into_ref_with_type(_vm, NodeExceptHandler::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("type", type_.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); + _node + } + }; + node_add_location(&node, self.location, _vm); + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Arguments { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::Arguments { posonlyargs,args,vararg,kwonlyargs,kw_defaults,kwarg,defaults } = self; + let _node = AstNode.into_ref_with_type(_vm, Nodearguments::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("posonlyargs", posonlyargs.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("vararg", vararg.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("kwonlyargs", kwonlyargs.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("kw_defaults", kw_defaults.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("kwarg", kwarg.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("defaults", defaults.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Arg { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::ArgData { arg,annotation,type_comment } = self.node; + let _node = AstNode.into_ref_with_type(_vm, Nodearg::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("annotation", annotation.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node_add_location(&node, self.location, _vm); + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Keyword { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::KeywordData { arg,value } = self.node; + let _node = AstNode.into_ref_with_type(_vm, Nodekeyword::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("value", value.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node_add_location(&node, self.location, _vm); + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Alias { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::Alias { name,asname } = self; + let _node = AstNode.into_ref_with_type(_vm, Nodealias::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("asname", asname.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::Withitem { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = { + let ast::Withitem { context_expr,optional_vars } = self; + let _node = AstNode.into_ref_with_type(_vm, Nodewithitem::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("context_expr", context_expr.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("optional_vars", optional_vars.ast_to_object(_vm), _vm).unwrap(); + _node + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} +impl Node for ast::TypeIgnore { + fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { + let node = match self { + ast::TypeIgnore::TypeIgnore { lineno,tag } => { + let _node = AstNode.into_ref_with_type(_vm, NodeTypeIgnore::static_type().clone()).unwrap(); + let _dict = _node.as_object().dict().unwrap(); + _dict.set_item("lineno", lineno.ast_to_object(_vm), _vm).unwrap(); + _dict.set_item("tag", tag.ast_to_object(_vm), _vm).unwrap(); + _node + } + }; + node.into_object() + } + fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { + todo!() + } +} + +pub fn extend_module_nodes(vm: &VirtualMachine, module: &PyObjectRef) { + extend_module!(vm, module, { + "Module" => NodeModule::make_class(&vm.ctx), + "Interactive" => NodeInteractive::make_class(&vm.ctx), + "Expression" => NodeExpression::make_class(&vm.ctx), + "FunctionType" => NodeFunctionType::make_class(&vm.ctx), + "FunctionDef" => NodeFunctionDef::make_class(&vm.ctx), + "AsyncFunctionDef" => NodeAsyncFunctionDef::make_class(&vm.ctx), + "ClassDef" => NodeClassDef::make_class(&vm.ctx), + "Return" => NodeReturn::make_class(&vm.ctx), + "Delete" => NodeDelete::make_class(&vm.ctx), + "Assign" => NodeAssign::make_class(&vm.ctx), + "AugAssign" => NodeAugAssign::make_class(&vm.ctx), + "AnnAssign" => NodeAnnAssign::make_class(&vm.ctx), + "For" => NodeFor::make_class(&vm.ctx), + "AsyncFor" => NodeAsyncFor::make_class(&vm.ctx), + "While" => NodeWhile::make_class(&vm.ctx), + "If" => NodeIf::make_class(&vm.ctx), + "With" => NodeWith::make_class(&vm.ctx), + "AsyncWith" => NodeAsyncWith::make_class(&vm.ctx), + "Raise" => NodeRaise::make_class(&vm.ctx), + "Try" => NodeTry::make_class(&vm.ctx), + "Assert" => NodeAssert::make_class(&vm.ctx), + "Import" => NodeImport::make_class(&vm.ctx), + "ImportFrom" => NodeImportFrom::make_class(&vm.ctx), + "Global" => NodeGlobal::make_class(&vm.ctx), + "Nonlocal" => NodeNonlocal::make_class(&vm.ctx), + "Expr" => NodeExpr::make_class(&vm.ctx), + "Pass" => NodePass::make_class(&vm.ctx), + "Break" => NodeBreak::make_class(&vm.ctx), + "Continue" => NodeContinue::make_class(&vm.ctx), + "BoolOp" => NodeBoolOp::make_class(&vm.ctx), + "NamedExpr" => NodeNamedExpr::make_class(&vm.ctx), + "BinOp" => NodeBinOp::make_class(&vm.ctx), + "UnaryOp" => NodeUnaryOp::make_class(&vm.ctx), + "Lambda" => NodeLambda::make_class(&vm.ctx), + "IfExp" => NodeIfExp::make_class(&vm.ctx), + "Dict" => NodeDict::make_class(&vm.ctx), + "Set" => NodeSet::make_class(&vm.ctx), + "ListComp" => NodeListComp::make_class(&vm.ctx), + "SetComp" => NodeSetComp::make_class(&vm.ctx), + "DictComp" => NodeDictComp::make_class(&vm.ctx), + "GeneratorExp" => NodeGeneratorExp::make_class(&vm.ctx), + "Await" => NodeAwait::make_class(&vm.ctx), + "Yield" => NodeYield::make_class(&vm.ctx), + "YieldFrom" => NodeYieldFrom::make_class(&vm.ctx), + "Compare" => NodeCompare::make_class(&vm.ctx), + "Call" => NodeCall::make_class(&vm.ctx), + "FormattedValue" => NodeFormattedValue::make_class(&vm.ctx), + "JoinedStr" => NodeJoinedStr::make_class(&vm.ctx), + "Constant" => NodeConstant::make_class(&vm.ctx), + "Attribute" => NodeAttribute::make_class(&vm.ctx), + "Subscript" => NodeSubscript::make_class(&vm.ctx), + "Starred" => NodeStarred::make_class(&vm.ctx), + "Name" => NodeName::make_class(&vm.ctx), + "List" => NodeList::make_class(&vm.ctx), + "Tuple" => NodeTuple::make_class(&vm.ctx), + "Slice" => NodeSlice::make_class(&vm.ctx), + "Load" => NodeLoad::make_class(&vm.ctx), + "Store" => NodeStore::make_class(&vm.ctx), + "Del" => NodeDel::make_class(&vm.ctx), + "And" => NodeAnd::make_class(&vm.ctx), + "Or" => NodeOr::make_class(&vm.ctx), + "Add" => NodeAdd::make_class(&vm.ctx), + "Sub" => NodeSub::make_class(&vm.ctx), + "Mult" => NodeMult::make_class(&vm.ctx), + "MatMult" => NodeMatMult::make_class(&vm.ctx), + "Div" => NodeDiv::make_class(&vm.ctx), + "Mod" => NodeMod::make_class(&vm.ctx), + "Pow" => NodePow::make_class(&vm.ctx), + "LShift" => NodeLShift::make_class(&vm.ctx), + "RShift" => NodeRShift::make_class(&vm.ctx), + "BitOr" => NodeBitOr::make_class(&vm.ctx), + "BitXor" => NodeBitXor::make_class(&vm.ctx), + "BitAnd" => NodeBitAnd::make_class(&vm.ctx), + "FloorDiv" => NodeFloorDiv::make_class(&vm.ctx), + "Invert" => NodeInvert::make_class(&vm.ctx), + "Not" => NodeNot::make_class(&vm.ctx), + "UAdd" => NodeUAdd::make_class(&vm.ctx), + "USub" => NodeUSub::make_class(&vm.ctx), + "Eq" => NodeEq::make_class(&vm.ctx), + "NotEq" => NodeNotEq::make_class(&vm.ctx), + "Lt" => NodeLt::make_class(&vm.ctx), + "LtE" => NodeLtE::make_class(&vm.ctx), + "Gt" => NodeGt::make_class(&vm.ctx), + "GtE" => NodeGtE::make_class(&vm.ctx), + "Is" => NodeIs::make_class(&vm.ctx), + "IsNot" => NodeIsNot::make_class(&vm.ctx), + "In" => NodeIn::make_class(&vm.ctx), + "NotIn" => NodeNotIn::make_class(&vm.ctx), + "comprehension" => Nodecomprehension::make_class(&vm.ctx), + "ExceptHandler" => NodeExceptHandler::make_class(&vm.ctx), + "arguments" => Nodearguments::make_class(&vm.ctx), + "arg" => Nodearg::make_class(&vm.ctx), + "keyword" => Nodekeyword::make_class(&vm.ctx), + "alias" => Nodealias::make_class(&vm.ctx), + "withitem" => Nodewithitem::make_class(&vm.ctx), + "TypeIgnore" => NodeTypeIgnore::make_class(&vm.ctx), + }) +} diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 77e51b3cf..fb223d093 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -1034,7 +1034,10 @@ impl VirtualMachine { Ok(()) } - pub fn extract_elements(&self, value: &PyObjectRef) -> PyResult> { + pub fn extract_elements_func(&self, value: &PyObjectRef, func: F) -> PyResult> + where + F: Fn(PyObjectRef) -> PyResult, + { // Extract elements from item, if possible: let cls = value.class(); if cls.is(&self.ctx.types.tuple_type) { @@ -1043,7 +1046,7 @@ impl VirtualMachine { .unwrap() .borrow_value() .iter() - .map(|obj| T::try_from_object(self, obj.clone())) + .map(|obj| func(obj.clone())) .collect() } else if cls.is(&self.ctx.types.list_type) { value @@ -1051,14 +1054,18 @@ impl VirtualMachine { .unwrap() .borrow_value() .iter() - .map(|obj| T::try_from_object(self, obj.clone())) + .map(|obj| func(obj.clone())) .collect() } else { let iter = iterator::get_iter(self, value.clone())?; - iterator::get_all(self, &iter) + iterator::try_map(self, &iter, |obj| func(obj)) } } + pub fn extract_elements(&self, value: &PyObjectRef) -> PyResult> { + self.extract_elements_func(value, |obj| T::try_from_object(self, obj)) + } + pub fn map_iterable_object( &self, obj: &PyObjectRef,