def testWriteExceptDispatcherBareExceptionNotLast(self): visitor = stmt.StatementVisitor(_MakeModuleBlock()) handlers = [ast.ExceptHandler(type=None), ast.ExceptHandler(type=ast.Name(id='foo'))] self.assertRaisesRegexp(util.ParseError, r"default 'except:' must be last", visitor._write_except_dispatcher, # pylint: disable=protected-access 'exc', 'tb', handlers)
def _ParseAndVisit(source): mod = pythonparser.parse(source) future_features = stmt.visit_future(mod) b = block.ModuleBlock('__main__', '<test>', source, future_features) visitor = stmt.StatementVisitor(b) visitor.visit(mod) return visitor
def _ParseAndVisit(source): mod = ast.parse(source) future_features = stmt.visit_future(mod) b = block.ModuleBlock('__main__', 'grumpy', 'grumpy/lib', '<test>', source.split('\n'), future_features) visitor = stmt.StatementVisitor(b) visitor.visit(mod) return visitor
def _ParseAndVisit(source): mod = pythonparser.parse(source) _, future_features = imputil.parse_future_features(mod) importer = imputil.Importer(None, 'foo', 'foo.py', False) b = block.ModuleBlock(importer, '__main__', '<test>', source, future_features) visitor = stmt.StatementVisitor(b) visitor.visit(mod) return visitor
def testWriteExceptDispatcherBareExcept(self): visitor = stmt.StatementVisitor(_MakeModuleBlock()) handlers = [ast.ExceptHandler(type=ast.Name(id='foo')), ast.ExceptHandler(type=None)] self.assertEqual(visitor._write_except_dispatcher( # pylint: disable=protected-access 'exc', 'tb', handlers), [1, 2]) expected = re.compile(r'ResolveGlobal\(.*foo.*\bIsInstance\(.*' r'goto Label1.*goto Label2', re.DOTALL) self.assertRegexpMatches(visitor.writer.getvalue(), expected)
def testWriteExceptDispatcherMultipleExcept(self): visitor = stmt.StatementVisitor(_MakeModuleBlock()) handlers = [ast.ExceptHandler(type=ast.Name(id='foo')), ast.ExceptHandler(type=ast.Name(id='bar'))] self.assertEqual(visitor._write_except_dispatcher( # pylint: disable=protected-access 'exc', 'tb', handlers), [1, 2]) expected = re.compile( r'ResolveGlobal\(.*foo.*\bif .*\bIsInstance\(.*\{.*goto Label1.*' r'ResolveGlobal\(.*bar.*\bif .*\bIsInstance\(.*\{.*goto Label2.*' r'\bRaise\(exc\.ToObject\(\), nil, tb\.ToObject\(\)\)', re.DOTALL) self.assertRegexpMatches(visitor.writer.getvalue(), expected)
def visit_function_inline(self, node): """Returns an GeneratedExpr for a function with the given body.""" # First pass collects the names of locals used in this function. Do this in # a separate pass so that we know whether to resolve a name as a local or a # global during the second pass. func_visitor = block.FunctionBlockVisitor(node) for child in node.body: func_visitor.visit(child) func_block = block.FunctionBlock(self.block, node.name, func_visitor.vars, func_visitor.is_generator) # TODO: Find a better way to reduce coupling between ExprVisitor and # StatementVisitor. from grumpy.compiler import stmt # pylint: disable=g-import-not-at-top visitor = stmt.StatementVisitor(func_block) # Indent so that the function body is aligned with the goto labels. with visitor.writer.indent_block(): visitor._visit_each(node.body) # pylint: disable=protected-access result = self.block.alloc_temp() with self.block.alloc_temp('[]πg.Param') as func_args: args = node.args argc = len(args.args) self.writer.write('{} = make([]πg.Param, {})'.format( func_args.expr, argc)) # The list of defaults only contains args for which a default value is # specified so pad it with None to make it the same length as args. defaults = [None] * (argc - len(args.defaults)) + args.defaults for i, (a, d) in enumerate(zip(args.args, defaults)): with self.visit(d) if d else expr.nil_expr as default: tmpl = '$args[$i] = πg.Param{Name: $name, Def: $default}' self.writer.write_tmpl(tmpl, args=func_args.expr, i=i, name=util.go_str(a.id), default=default.expr) flags = [] if args.vararg: flags.append('πg.CodeFlagVarArg') if args.kwarg: flags.append('πg.CodeFlagKWArg') # The function object gets written to a temporary writer because we need # it as an expression that we subsequently bind to some variable. self.writer.write_tmpl( '$result = πg.NewFunction(πg.NewCode($name, $filename, $args, ' '$flags, func(πF *πg.Frame, πArgs []*πg.Object) ' '(*πg.Object, *πg.BaseException) {', result=result.name, name=util.go_str(node.name), filename=util.go_str(self.block.filename), args=func_args.expr, flags=' | '.join(flags) if flags else 0) with self.writer.indent_block(): for var in func_block.vars.values(): if var.type != block.Var.TYPE_GLOBAL: fmt = 'var {0} *πg.Object = {1}; _ = {0}' self.writer.write(fmt.format( util.adjust_local_name(var.name), var.init_expr)) self.writer.write_temp_decls(func_block) if func_block.is_generator: self.writer.write('return πg.NewGenerator(πF, func(πSent *πg.Object) ' '(*πg.Object, *πg.BaseException) {') with self.writer.indent_block(): self.writer.write_block(func_block, visitor.writer.out.getvalue()) self.writer.write('}).ToObject(), nil') else: self.writer.write_block(func_block, visitor.writer.out.getvalue()) self.writer.write('}), πF.Globals()).ToObject()') return result
def _ParseAndVisitExpr(expr): visitor = stmt.StatementVisitor(_MakeModuleBlock()) visitor.visit_expr(_ParseExpr(expr)) return visitor.writer.getvalue()
def _ParseAndVisit(source): b = block.ModuleBlock('__main__', 'grumpy', 'grumpy/lib', '<test>', source.split('\n')) visitor = stmt.StatementVisitor(b) visitor.visit(ast.parse(source)) return visitor
def main(script=None, modname=None): assert script and modname, 'Script "%s" or Modname "%s" is empty' % ( script, modname) gopath = os.getenv('GOPATH', None) if not gopath: print >> sys.stderr, 'GOPATH not set' return 1 with open(script) as py_file: py_contents = py_file.read() try: mod = pythonparser.parse(py_contents) except SyntaxError as e: print >> sys.stderr, '{}: line {}: invalid syntax: {}'.format( e.filename, e.lineno, e.text) return 2 # Do a pass for compiler directives from `from __future__ import *` statements try: future_node, future_features = imputil.parse_future_features(mod) except util.CompileError as e: print >> sys.stderr, str(e) return 2 importer = imputil.Importer(gopath, modname, script, future_features.absolute_import) full_package_name = modname.replace('.', '/') mod_block = block.ModuleBlock(importer, full_package_name, script, py_contents, future_features) visitor = stmt.StatementVisitor(mod_block, future_node) # Indent so that the module body is aligned with the goto labels. with visitor.writer.indent_block(): try: visitor.visit(mod) except util.ParseError as e: print >> sys.stderr, str(e) return 2 writer = util.Writer(sys.stdout) tmpl = textwrap.dedent("""\ package $package import πg "grumpy" var Code *πg.Code func init() { \tCode = πg.NewCode("<module>", $script, nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) { \t\tvar πR *πg.Object; _ = πR \t\tvar πE *πg.BaseException; _ = πE""") writer.write_tmpl(tmpl, package=modname.split('.')[-1], script=util.go_str(script)) with writer.indent_block(2): for s in sorted(mod_block.strings): writer.write('ß{} := πg.InternStr({})'.format(s, util.go_str(s))) writer.write_temp_decls(mod_block) writer.write_block(mod_block, visitor.writer.getvalue()) writer.write_tmpl(textwrap.dedent("""\ \t\treturn nil, πE \t}) \tπg.RegisterModule($modname, Code) }"""), modname=util.go_str(modname)) return 0