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()))