github.com/google/grumpy@v0.0.0-20171122020858-3ec87959189c/tools/grumpc (about) 1 #!/usr/bin/env python 2 # coding=utf-8 3 4 # Copyright 2016 Google Inc. All Rights Reserved. 5 # 6 # Licensed under the Apache License, Version 2.0 (the "License"); 7 # you may not use this file except in compliance with the License. 8 # You may obtain a copy of the License at 9 # 10 # http://www.apache.org/licenses/LICENSE-2.0 11 # 12 # Unless required by applicable law or agreed to in writing, software 13 # distributed under the License is distributed on an "AS IS" BASIS, 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 # See the License for the specific language governing permissions and 16 # limitations under the License. 17 18 """A Python -> Go transcompiler.""" 19 20 from __future__ import unicode_literals 21 22 import argparse 23 import os 24 import sys 25 import textwrap 26 27 from grumpy.compiler import block 28 from grumpy.compiler import imputil 29 from grumpy.compiler import stmt 30 from grumpy.compiler import util 31 from grumpy import pythonparser 32 33 34 parser = argparse.ArgumentParser() 35 parser.add_argument('script', help='Python source filename') 36 parser.add_argument('-modname', default='__main__', help='Python module name') 37 38 39 def main(args): 40 for arg in ('script', 'modname'): 41 if not getattr(args, arg, None): 42 print >> sys.stderr, '{} arg must not be empty'.format(arg) 43 return 1 44 45 gopath = os.getenv('GOPATH', None) 46 if not gopath: 47 print >> sys.stderr, 'GOPATH not set' 48 return 1 49 50 with open(args.script) as py_file: 51 py_contents = py_file.read() 52 try: 53 mod = pythonparser.parse(py_contents) 54 except SyntaxError as e: 55 print >> sys.stderr, '{}: line {}: invalid syntax: {}'.format( 56 e.filename, e.lineno, e.text) 57 return 2 58 59 # Do a pass for compiler directives from `from __future__ import *` statements 60 try: 61 future_node, future_features = imputil.parse_future_features(mod) 62 except util.CompileError as e: 63 print >> sys.stderr, str(e) 64 return 2 65 66 importer = imputil.Importer(gopath, args.modname, args.script, 67 future_features.absolute_import) 68 full_package_name = args.modname.replace('.', '/') 69 mod_block = block.ModuleBlock(importer, full_package_name, args.script, 70 py_contents, future_features) 71 72 visitor = stmt.StatementVisitor(mod_block, future_node) 73 # Indent so that the module body is aligned with the goto labels. 74 with visitor.writer.indent_block(): 75 try: 76 visitor.visit(mod) 77 except util.ParseError as e: 78 print >> sys.stderr, str(e) 79 return 2 80 81 writer = util.Writer(sys.stdout) 82 tmpl = textwrap.dedent("""\ 83 package $package 84 import πg "grumpy" 85 var Code *πg.Code 86 func init() { 87 \tCode = πg.NewCode("<module>", $script, nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) { 88 \t\tvar πR *πg.Object; _ = πR 89 \t\tvar πE *πg.BaseException; _ = πE""") 90 writer.write_tmpl(tmpl, package=args.modname.split('.')[-1], 91 script=util.go_str(args.script)) 92 with writer.indent_block(2): 93 for s in sorted(mod_block.strings): 94 writer.write('ß{} := πg.InternStr({})'.format(s, util.go_str(s))) 95 writer.write_temp_decls(mod_block) 96 writer.write_block(mod_block, visitor.writer.getvalue()) 97 writer.write_tmpl(textwrap.dedent("""\ 98 \t\treturn nil, πE 99 \t}) 100 \tπg.RegisterModule($modname, Code) 101 }"""), modname=util.go_str(args.modname)) 102 return 0 103 104 105 if __name__ == '__main__': 106 sys.exit(main(parser.parse_args()))