def visit_ClassDef(self, node): node = self.generic_visit(node) # free variables of the class block become parameters of the function scopes = getattr(node, "scopes", {}) free = [var for var, scope in scopes.iteritems() if scope == scoping.Scope.FREE] free_param = [ast.Name(id=var, ctx=ast.Param()) for var in free] free_args = [ast.Name(id=var, ctx=ast.Load()) for var in free] # free variables of sub-blocks. Those need name mangling to avoid # collisions with variables local to the class block. passthrough = self.find_passthrough_vars(node) pt_param = [ast.Name(id=naming.passthrough_var(var), ctx=ast.Param()) for var in passthrough] pt_args = [ast.Name(id=var, ctx=ast.Load()) for var in passthrough] # function to execute the class body and collect the attributes func = ast.FunctionDef() func.name = self.id_factory("class_" + node.name) func.args = ast.arguments(args=free_param + pt_param, vararg=None, kwarg=None, defaults=[]) func.body = node.body + [ast.Return(value=mk_name("__pydron_members__"))] func.decorator_list = [] # replicate name mangling of `LocalizeFreeVariables` all_args = free_args + pt_args if self._inside_class(): for arg in all_args: arg.id = naming.passthrough_var(arg.id) # create the class typefunc = mk_call("__pydron_read_global__", [mk_str("type")]) class_expr = mk_call_expr(typefunc, [mk_str(node.name), mk_tuple(node.bases), mk_call(func.name, all_args)]) for decorator in reversed(node.decorator_list): class_expr = mk_call_expr(decorator, [class_expr]) stmt = mk_assign(node.name, class_expr) return [func, stmt]
def visit_ClassDef(self, node): node = self.generic_visit(node) # free variables of the class block become parameters of the function scopes = getattr(node, 'scopes', {}) free = [var for var,scope in scopes.iteritems() if scope == scoping.Scope.FREE] free_param = [ast.Name(id=var, ctx=ast.Param()) for var in free] free_args = [ast.Name(id=var, ctx=ast.Load()) for var in free] # free variables of sub-blocks. Those need name mangling to avoid # collisions with variables local to the class block. passthrough = self.find_passthrough_vars(node) pt_param = [ast.Name(id=naming.passthrough_var(var), ctx=ast.Param()) for var in passthrough] pt_args = [ast.Name(id=var, ctx=ast.Load()) for var in passthrough] # function to execute the class body and collect the attributes func = ast.FunctionDef() func.name = self.id_factory("class_" + node.name) func.args = ast.arguments(args=free_param + pt_param, vararg=None, kwarg=None, defaults=[]) func.body = node.body + [ast.Return(value=mk_name('__pydron_members__')) ] func.decorator_list = [] # replicate name mangling of `LocalizeFreeVariables` all_args = free_args + pt_args if self._inside_class(): for arg in all_args: arg.id = naming.passthrough_var(arg.id) # create the class typefunc = mk_call('__pydron_read_global__', [mk_str('type')]) class_expr = mk_call_expr(typefunc, [mk_str(node.name), mk_tuple(node.bases), mk_call(func.name, all_args)]) for decorator in reversed(node.decorator_list): class_expr = mk_call_expr(decorator, [class_expr]) stmt = mk_assign(node.name, class_expr) return [func, stmt]
def _dedecorate(self, node): if not node.decorator_list: return node # use a temporary name orig_id = node.name node.name = self.id_factory(orig_id) # call the decorators obj = mk_name(node.name) for decorator_expr in reversed(node.decorator_list): obj = mk_call_expr(decorator_expr, [obj]) # assign to the original name assignment_stmt = mk_assign(orig_id, obj) node.decorator_list = [] return [node, assignment_stmt]
def visit_With(self, node): node = self.generic_visit(node) # Build equivalent code with try catch finally. # PEP-0343 provides the equivalent code for us. statements = [] # mgr = node.expr mgr_id = self.id_factory("mgr") s = mk_assign(mgr_id, node.context_expr) statements.append(s) # exit = type(msg).__exit__ exit_id = self.id_factory("exit") s = mk_assign(exit_id, mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__")) statements.append(s) # value = type(msg).__enter__(mgr) value_id = self.id_factory("value") s = mk_assign( value_id, mk_call_expr( mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"), [mk_name(mgr_id)])) statements.append(s) # exc = True exc_id = self.id_factory("exc") s = mk_assign(exc_id, mk_name("True")) statements.append(s) # try: tryfinally_body = [] tryfinally_finalbody = [] s = ast.TryFinally(body=tryfinally_body, finalbody=tryfinally_finalbody) statements.append(s) # try: tryexcept_body = [] tryexcept_except = [] expt_handler = ast.ExceptHandler(type=None, name=None, body=tryexcept_except) s = ast.TryExcept(body=tryexcept_body, handlers=[expt_handler], orelse=[]) tryfinally_body.append(s) # node.optional_vars = value if node.optional_vars: s = ast.Assign(targets=[node.optional_vars], value=mk_name(value_id)) tryexcept_body.append(s) # body tryexcept_body.extend(node.body) # except: # exc = False s = mk_assign(exc_id, mk_name("False")) tryexcept_except.append(s) # sys.exc_info() sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), []) # exit(mgr, *sys.exc_info()) exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info) # not exit(mgr, *sys.exc_info()) test = ast.UnaryOp(op=ast.Not(), operand=exit_call) # if not exit(mgr, *sys.exc_info()): # raise s = ast.If(test=test, body=[ast.Raise(type=None, inst=None, tback=None)], orelse=[]) tryexcept_except.append(s) # finally: # if exc: # exit(mgr, None, None, None) exit_call = mk_call(exit_id, [ mk_name(mgr_id), mk_name("None"), mk_name("None"), mk_name("None") ]) s = ast.If(test=mk_name(exc_id), body=[ast.Expr(value=exit_call)], orelse=[]) tryfinally_finalbody.append(s) return statements
def visit_With(self, node): node = self.generic_visit(node) # Build equivalent code with try catch finally. # PEP-0343 provides the equivalent code for us. statements = [] # mgr = node.expr mgr_id = self.id_factory("mgr") s = mk_assign(mgr_id, node.context_expr) statements.append(s) # exit = type(msg).__exit__ exit_id = self.id_factory("exit") s = mk_assign(exit_id, mk_attr(mk_call('type', [mk_name(mgr_id)]), "__exit__")) statements.append(s) # value = type(msg).__enter__(mgr) value_id = self.id_factory("value") s = mk_assign(value_id, mk_call_expr(mk_attr(mk_call('type', [mk_name(mgr_id)]), "__enter__"), [mk_name(mgr_id)])) statements.append(s) # exc = True exc_id = self.id_factory("exc") s = mk_assign(exc_id, mk_name("True")) statements.append(s) # try: tryfinally_body = [] tryfinally_finalbody = [] s = ast.TryFinally(body=tryfinally_body, finalbody=tryfinally_finalbody) statements.append(s) # try: tryexcept_body = [] tryexcept_except = [] expt_handler = ast.ExceptHandler(type=None,name=None,body=tryexcept_except) s = ast.TryExcept(body=tryexcept_body, handlers=[expt_handler], orelse=[]) tryfinally_body.append(s) # node.optional_vars = value if node.optional_vars: s = ast.Assign(targets=[node.optional_vars], value=mk_name(value_id)) tryexcept_body.append(s) # body tryexcept_body.extend(node.body) # except: # exc = False s = mk_assign(exc_id, mk_name("False")) tryexcept_except.append(s) # sys.exc_info() sys_exc_info = mk_call_expr(mk_attr(mk_name('sys'), "exc_info"), []) # exit(mgr, *sys.exc_info()) exit_call = mk_call(exit_id, [mk_name(mgr_id)], vararg=sys_exc_info) # not exit(mgr, *sys.exc_info()) test = ast.UnaryOp(op=ast.Not(), operand=exit_call) # if not exit(mgr, *sys.exc_info()): # raise s = ast.If(test=test, body=[ast.Raise(type=None, inst=None, tback=None)], orelse=[]) tryexcept_except.append(s) # finally: # if exc: # exit(mgr, None, None, None) exit_call = mk_call(exit_id, [mk_name(mgr_id), mk_name("None"), mk_name("None"), mk_name("None")]) s = ast.If(test=mk_name(exc_id), body=[ast.Expr(value=exit_call)], orelse=[]) tryfinally_finalbody.append(s) return statements