Beispiel #1
0
 def _import_native(self, name, values):
     reflect_package = self.block.add_native_import('reflect')
     package_name = name[len(_NATIVE_MODULE_PREFIX):].replace('.', '/')
     package = self.block.add_native_import(package_name)
     mod = self.block.alloc_temp()
     with self.block.alloc_temp('map[string]*πg.Object') as members:
         self.writer.write_tmpl('$members = map[string]*πg.Object{}',
                                members=members.name)
         for v in values:
             module_attr = v
             with self.block.alloc_temp() as wrapped:
                 if v.startswith(_NATIVE_TYPE_PREFIX):
                     module_attr = v[len(_NATIVE_TYPE_PREFIX):]
                     with self.block.alloc_temp('{}.{}'.format(
                             package.alias, module_attr)) as type_:
                         self.writer.write_checked_call2(
                             wrapped, 'πg.WrapNative(πF, {}.ValueOf({}))',
                             reflect_package.alias, type_.expr)
                         self.writer.write(
                             '{} = {}.Type().ToObject()'.format(
                                 wrapped.name, wrapped.expr))
                 else:
                     self.writer.write_checked_call2(
                         wrapped, 'πg.WrapNative(πF, {}.ValueOf({}.{}))',
                         reflect_package.alias, package.alias, v)
                 self.writer.write('{}[{}] = {}'.format(
                     members.name, util.go_str(module_attr), wrapped.expr))
         self.writer.write_checked_call2(
             mod, 'πg.ImportNativeModule(πF, {}, {})', util.go_str(name),
             members.expr)
     return mod
Beispiel #2
0
  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)
    visitor = StatementVisitor(func_block, self.future_node)
    # 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_expr(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.arg), 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.root.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.getvalue())
          self.writer.write('}).ToObject(), nil')
        else:
          self.writer.write_block(func_block, visitor.writer.getvalue())
      self.writer.write('}), πF.Globals()).ToObject()')
    return result
Beispiel #3
0
  def _import_and_bind(self, imp):
    """Generates code that imports a module and binds it to a variable.

    Args:
      imp: Import object representing an import of the form "import x.y.z" or
          "from x.y import z". Expects only a single binding.
    """
    # Acquire handles to the Code objects in each Go package and call
    # ImportModule to initialize all modules.
    with self.block.alloc_temp() as mod, \
        self.block.alloc_temp('[]*πg.Object') as mod_slice:
      self.writer.write_checked_call2(
          mod_slice, 'πg.ImportModule(πF, {})', util.go_str(imp.name))

      # Bind the imported modules or members to variables in the current scope.
      for binding in imp.bindings:
        if binding.bind_type == imputil.Import.MODULE:
          self.writer.write('{} = {}[{}]'.format(
              mod.name, mod_slice.expr, binding.value))
          self.block.bind_var(self.writer, binding.alias, mod.expr)
        else:
          self.writer.write('{} = {}[{}]'.format(
              mod.name, mod_slice.expr, imp.name.count('.')))
          # Binding a member of the imported module.
          with self.block.alloc_temp() as member:
            self.writer.write_checked_call2(
                member, 'πg.GetAttr(πF, {}, {}, nil)',
                mod.expr, self.block.root.intern(binding.value))
            self.block.bind_var(self.writer, binding.alias, member.expr)
Beispiel #4
0
  def _import_and_bind(self, imp):
    """Generates code that imports a module and binds it to a variable.

    Args:
      imp: Import object representing an import of the form "import x.y.z" or
          "from x.y import z". Expects only a single binding.
    """
    parts = imp.name.split('.')
    code_objs = []
    for i in xrange(len(parts)):
      package_name = '/'.join(parts[:i + 1])
      if package_name != self.block.root.full_package_name:
        package = self.block.root.add_import(package_name)
        code_objs.append('{}.Code'.format(package.alias))
      else:
        code_objs.append('Code')
    with self.block.alloc_temp() as mod, \
        self.block.alloc_temp('[]*πg.Object') as mod_slice:
      handles_expr = '[]*πg.Code{' + ', '.join(code_objs) + '}'
      self.writer.write_checked_call2(
          mod_slice, 'πg.ImportModule(πF, {}, {})',
          util.go_str(imp.name), handles_expr)
      # This method only handles simple module imports (i.e. not member
      # imports) which always have a single binding.
      binding = imp.bindings[0]
      if binding.value == util.Import.ROOT:
        index = 0
      else:
        index = len(parts) - 1
      self.writer.write('{} = {}[{}]'.format(mod.name, mod_slice.expr, index))
      self.block.bind_var(self.writer, binding.alias, mod.expr)
Beispiel #5
0
  def _import_and_bind(self, imp):
    """Generates code that imports a module and binds it to a variable.

    Args:
      imp: Import object representing an import of the form "import x.y.z" or
          "from x.y import z". Expects only a single binding.
    """
    # Acquire handles to the Code objects in each Go package and call
    # ImportModule to initialize all modules.
    with self.block.alloc_temp() as mod, \
        self.block.alloc_temp('[]*πg.Object') as mod_slice:
      self.writer.write_checked_call2(
          mod_slice, 'πg.ImportModule(πF, {})', util.go_str(imp.name))

      # Bind the imported modules or members to variables in the current scope.
      for binding in imp.bindings:
        if binding.bind_type == imputil.Import.MODULE:
          self.writer.write('{} = {}[{}]'.format(
              mod.name, mod_slice.expr, binding.value))
          self.block.bind_var(self.writer, binding.alias, mod.expr)
        else:
          self.writer.write('{} = {}[{}]'.format(
              mod.name, mod_slice.expr, imp.name.count('.')))
          # Binding a member of the imported module.
          with self.block.alloc_temp() as member:
            self.writer.write_checked_call2(
                member, 'πg.GetAttr(πF, {}, {}, nil)',
                mod.expr, self.block.root.intern(binding.value))
            self.block.bind_var(self.writer, binding.alias, member.expr)
Beispiel #6
0
 def visit_Str(self, node):
   if isinstance(node.s, unicode):
     expr_str = 'πg.NewUnicode({}).ToObject()'.format(
         util.go_str(node.s.encode('utf-8')))
   else:
     expr_str = '{}.ToObject()'.format(self.block.intern(node.s))
   return expr.GeneratedLiteral(expr_str)
Beispiel #7
0
 def visit_Str(self, node):
   if isinstance(node.s, unicode):
     expr_str = 'πg.NewUnicode({}).ToObject()'.format(
         util.go_str(node.s.encode('utf-8')))
   else:
     expr_str = '{}.ToObject()'.format(self.block.root.intern(node.s))
   return expr.GeneratedLiteral(expr_str)
Beispiel #8
0
  def _import(self, name, index):
    """Returns an expression for a Module object returned from ImportModule.

    Args:
      name: The fully qualified Python module name, e.g. foo.bar.
      index: The element in the list of modules that this expression should
          select. E.g. for 'foo.bar', 0 corresponds to the package foo and 1
          corresponds to the module bar.
    Returns:
      A Go expression evaluating to an *Object (upcast from a *Module.)
    """
    parts = name.split('.')
    code_objs = []
    for i in xrange(len(parts)):
      package_name = '/'.join(parts[:i + 1])
      if package_name != self.block.full_package_name:
        package = self.block.add_import(package_name)
        code_objs.append('{}.Code'.format(package.alias))
      else:
        code_objs.append('Code')
    mod = self.block.alloc_temp()
    with self.block.alloc_temp('[]*πg.Object') as mod_slice:
      handles_expr = '[]*πg.Code{' + ', '.join(code_objs) + '}'
      self.writer.write_checked_call2(
          mod_slice, 'πg.ImportModule(πF, {}, {})',
          util.go_str(name), handles_expr)
      self.writer.write('{} = {}[{}]'.format(mod.name, mod_slice.expr, index))
    return mod
Beispiel #9
0
    def _import(self, name, index):
        """Returns an expression for a Module object returned from ImportModule.

    Args:
      name: The fully qualified Python module name, e.g. foo.bar.
      index: The element in the list of modules that this expression should
          select. E.g. for 'foo.bar', 0 corresponds to the package foo and 1
          corresponds to the module bar.
    Returns:
      A Go expression evaluating to an *Object (upcast from a *Module.)
    """
        parts = name.split('.')
        code_objs = []
        for i in xrange(len(parts)):
            package_name = '/'.join(parts[:i + 1])
            if package_name != self.block.full_package_name:
                package = self.block.add_import(package_name)
                code_objs.append('{}.Code'.format(package.alias))
            else:
                code_objs.append('Code')
        mod = self.block.alloc_temp()
        with self.block.alloc_temp('[]*πg.Object') as mod_slice:
            handles_expr = '[]*πg.Code{' + ', '.join(code_objs) + '}'
            self.writer.write_checked_call2(mod_slice,
                                            'πg.ImportModule(πF, {}, {})',
                                            util.go_str(name), handles_expr)
            self.writer.write('{} = {}[{}]'.format(mod.name, mod_slice.expr,
                                                   index))
        return mod
Beispiel #10
0
    def _import_native(self, name, values):
        reflect_package = self.block.add_native_import('reflect')
        import_name = name[len(_NATIVE_MODULE_PREFIX):]
        # Work-around for importing go module from VCS
        # TODO: support bzr|git|hg|svn from any server
        package_name = None
        for x in _KNOWN_VCS:
            if import_name.startswith(x):
                package_name = x + import_name[len(x):].replace('.', '/')
                break
        if not package_name:
            package_name = import_name.replace('.', '/')

        package = self.block.add_native_import(package_name)
        mod = self.block.alloc_temp()
        with self.block.alloc_temp('map[string]*πg.Object') as members:
            self.writer.write_tmpl('$members = map[string]*πg.Object{}',
                                   members=members.name)
            for v in values:
                module_attr = v
                with self.block.alloc_temp() as wrapped:
                    if v.startswith(_NATIVE_TYPE_PREFIX):
                        module_attr = v[len(_NATIVE_TYPE_PREFIX):]
                        with self.block.alloc_temp('{}.{}'.format(
                                package.alias, module_attr)) as type_:
                            self.writer.write_checked_call2(
                                wrapped, 'πg.WrapNative(πF, {}.ValueOf({}))',
                                reflect_package.alias, type_.expr)
                            self.writer.write(
                                '{} = {}.Type().ToObject()'.format(
                                    wrapped.name, wrapped.expr))
                    else:
                        self.writer.write_checked_call2(
                            wrapped, 'πg.WrapNative(πF, {}.ValueOf({}.{}))',
                            reflect_package.alias, package.alias, v)
                    self.writer.write('{}[{}] = {}'.format(
                        members.name, util.go_str(module_attr), wrapped.expr))
            self.writer.write_checked_call2(
                mod, 'πg.ImportNativeModule(πF, {}, {})', util.go_str(name),
                members.expr)
        return mod
Beispiel #11
0
 def del_var(self, writer, name):
   var = self.vars.get(name)
   if not var:
     raise util.ParseError(
         None, 'cannot delete nonexistent local: {}'.format(name))
   if var.type == Var.TYPE_GLOBAL:
     return self._module_block.del_var(writer, name)
   adjusted_name = util.adjust_local_name(name)
   # Resolve local first to ensure the variable is already bound.
   writer.write_checked_call1('πg.CheckLocal(πF, {}, {})',
                              adjusted_name, util.go_str(name))
   writer.write('{} = πg.UnboundLocal'.format(adjusted_name))
Beispiel #12
0
 def del_var(self, writer, name):
   var = self.vars.get(name)
   if not var:
     raise util.ParseError(
         None, 'cannot delete nonexistent local: {}'.format(name))
   if var.type == Var.TYPE_GLOBAL:
     return self._module_block.del_var(writer, name)
   adjusted_name = util.adjust_local_name(name)
   # Resolve local first to ensure the variable is already bound.
   writer.write_checked_call1('πg.CheckLocal(πF, {}, {})',
                              adjusted_name, util.go_str(name))
   writer.write('{} = πg.UnboundLocal'.format(adjusted_name))
Beispiel #13
0
  def _import_native(self, name, values):
    reflect_package = self.block.add_native_import('reflect')
    import_name = name[len(_NATIVE_MODULE_PREFIX):]
    # Work-around for importing go module from VCS
    # TODO: support bzr|git|hg|svn from any server
    package_name = None
    for x in _KNOWN_VCS:
      if import_name.startswith(x):
        package_name = x + import_name[len(x):].replace('.', '/')
        break
    if not package_name:
      package_name = import_name.replace('.', '/')

    package = self.block.add_native_import(package_name)
    mod = self.block.alloc_temp()
    with self.block.alloc_temp('map[string]*πg.Object') as members:
      self.writer.write_tmpl('$members = map[string]*πg.Object{}',
                             members=members.name)
      for v in values:
        module_attr = v
        with self.block.alloc_temp() as wrapped:
          if v.startswith(_NATIVE_TYPE_PREFIX):
            module_attr = v[len(_NATIVE_TYPE_PREFIX):]
            with self.block.alloc_temp(
                '{}.{}'.format(package.alias, module_attr)) as type_:
              self.writer.write_checked_call2(
                  wrapped, 'πg.WrapNative(πF, {}.ValueOf({}))',
                  reflect_package.alias, type_.expr)
              self.writer.write('{} = {}.Type().ToObject()'.format(
                  wrapped.name, wrapped.expr))
          else:
            self.writer.write_checked_call2(
                wrapped, 'πg.WrapNative(πF, {}.ValueOf({}.{}))',
                reflect_package.alias, package.alias, v)
          self.writer.write('{}[{}] = {}'.format(
              members.name, util.go_str(module_attr), wrapped.expr))
      self.writer.write_checked_call2(mod, 'πg.ImportNativeModule(πF, {}, {})',
                                      util.go_str(name), members.expr)
    return mod
Beispiel #14
0
 def resolve_name(self, writer, name):
   block = self
   while not isinstance(block, ModuleBlock):
     if isinstance(block, FunctionBlock):
       var = block.vars.get(name)
       if var:
         if var.type == Var.TYPE_GLOBAL:
           return self._resolve_global(writer, name)
         writer.write_checked_call1('πg.CheckLocal(πF, {}, {})',
                                    util.adjust_local_name(name),
                                    util.go_str(name))
         return expr.GeneratedLocalVar(name)
     block = block.parent_block
   return self._resolve_global(writer, name)
Beispiel #15
0
 def resolve_name(self, writer, name):
   block = self
   while not isinstance(block, ModuleBlock):
     if isinstance(block, FunctionBlock):
       var = block.vars.get(name)
       if var:
         if var.type == Var.TYPE_GLOBAL:
           return self._resolve_global(writer, name)
         writer.write_checked_call1('πg.CheckLocal(πF, {}, {})',
                                    util.adjust_local_name(name),
                                    util.go_str(name))
         return expr.GeneratedLocalVar(name)
     block = block.parent_block
   return self._resolve_global(writer, name)
Beispiel #16
0
 def visit_Call(self, node):
     # Build positional arguments.
     args = expr.nil_expr
     if node.args:
         args = self.block.alloc_temp('[]*πg.Object')
         self.writer.write('{} = πF.MakeArgs({})'.format(
             args.expr, len(node.args)))
         for i, n in enumerate(node.args):
             with self.visit(n) as a:
                 self.writer.write('{}[{}] = {}'.format(
                     args.expr, i, a.expr))
     varg = expr.nil_expr
     if node.starargs:
         varg = self.visit(node.starargs)
     # Build keyword arguments
     keywords = expr.nil_expr
     if node.keywords:
         values = []
         for k in node.keywords:
             values.append((util.go_str(k.arg), self.visit(k.value)))
         keywords = self.block.alloc_temp('πg.KWArgs')
         self.writer.write_tmpl('$keywords = πg.KWArgs{',
                                keywords=keywords.name)
         with self.writer.indent_block():
             for k, v in values:
                 with v:
                     self.writer.write_tmpl('{$name, $value},',
                                            name=k,
                                            value=v.expr)
         self.writer.write('}')
     kwargs = expr.nil_expr
     if node.kwargs:
         kwargs = self.visit(node.kwargs)
     # Invoke function with all parameters.
     with args, varg, keywords, kwargs, self.visit(node.func) as func:
         result = self.block.alloc_temp()
         if varg is expr.nil_expr and kwargs is expr.nil_expr:
             self.writer.write_checked_call2(result, '{}.Call(πF, {}, {})',
                                             func.expr, args.expr,
                                             keywords.expr)
         else:
             self.writer.write_checked_call2(
                 result, 'πg.Invoke(πF, {}, {}, {}, {}, {})', func.expr,
                 args.expr, varg.expr, keywords.expr, kwargs.expr)
         if node.args:
             self.writer.write('πF.FreeArgs({})'.format(args.expr))
     return result
Beispiel #17
0
 def visit_Call(self, node):
   # Build positional arguments.
   args = expr.nil_expr
   if node.args:
     args = self.block.alloc_temp('[]*πg.Object')
     self.writer.write('{} = πF.MakeArgs({})'.format(args.expr,
                                                     len(node.args)))
     for i, n in enumerate(node.args):
       with self.visit(n) as a:
         self.writer.write('{}[{}] = {}'.format(args.expr, i, a.expr))
   varg = expr.nil_expr
   if node.starargs:
     varg = self.visit(node.starargs)
   # Build keyword arguments
   keywords = expr.nil_expr
   if node.keywords:
     values = []
     for k in node.keywords:
       values.append((util.go_str(k.arg), self.visit(k.value)))
     keywords = self.block.alloc_temp('πg.KWArgs')
     self.writer.write_tmpl('$keywords = πg.KWArgs{', keywords=keywords.name)
     with self.writer.indent_block():
       for k, v in values:
         with v:
           self.writer.write_tmpl('{$name, $value},', name=k, value=v.expr)
     self.writer.write('}')
   kwargs = expr.nil_expr
   if node.kwargs:
     kwargs = self.visit(node.kwargs)
   # Invoke function with all parameters.
   with args, varg, keywords, kwargs, self.visit(node.func) as func:
     result = self.block.alloc_temp()
     if varg is expr.nil_expr and kwargs is expr.nil_expr:
       self.writer.write_checked_call2(result, '{}.Call(πF, {}, {})',
                                       func.expr, args.expr, keywords.expr)
     else:
       self.writer.write_checked_call2(result,
                                       'πg.Invoke(πF, {}, {}, {}, {}, {})',
                                       func.expr, args.expr, varg.expr,
                                       keywords.expr, kwargs.expr)
     if node.args:
       self.writer.write('πF.FreeArgs({})'.format(args.expr))
   return result
Beispiel #18
0
    def _import_and_bind(self, imp):
        """Generates code that imports a module and binds it to a variable.

    Args:
      imp: Import object representing an import of the form "import x.y.z" or
          "from x.y import z". Expects only a single binding.
    """
        # Acquire handles to the Code objects in each Go package and call
        # ImportModule to initialize all modules.
        parts = imp.name.split('.')
        code_objs = []
        for i in xrange(len(parts)):
            package_name = '/'.join(parts[:i + 1])
            if package_name != self.block.root.full_package_name:
                package = self.block.root.add_import(package_name)
                code_objs.append('{}.Code'.format(package.alias))
            else:
                code_objs.append('Code')
        with self.block.alloc_temp() as mod, \
            self.block.alloc_temp('[]*πg.Object') as mod_slice:
            handles_expr = '[]*πg.Code{' + ', '.join(code_objs) + '}'
            self.writer.write_checked_call2(mod_slice,
                                            'πg.ImportModule(πF, {}, {})',
                                            util.go_str(imp.name),
                                            handles_expr)

            # Bind the imported modules or members to variables in the current scope.
            for binding in imp.bindings:
                if binding.bind_type == imputil.Import.MODULE:
                    self.writer.write('{} = {}[{}]'.format(
                        mod.name, mod_slice.expr, binding.value))
                    self.block.bind_var(self.writer, binding.alias, mod.expr)
                else:
                    self.writer.write('{} = {}[{}]'.format(
                        mod.name, mod_slice.expr, imp.name.count('.')))
                    # Binding a member of the imported module.
                    with self.block.alloc_temp() as member:
                        self.writer.write_checked_call2(
                            member, 'πg.GetAttr(πF, {}, {}, nil)', mod.expr,
                            self.block.root.intern(binding.value))
                        self.block.bind_var(self.writer, binding.alias,
                                            member.expr)
Beispiel #19
0
  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)
    visitor = StatementVisitor(func_block, self.future_node)
    # 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_expr(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.arg), 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.root.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)
        self.writer.write('var πR *πg.Object; _ = πR')
        self.writer.write('var πE *πg.BaseException; _ = πE')
        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.getvalue())
            self.writer.write('return nil, πE')
          self.writer.write('}).ToObject(), nil')
        else:
          self.writer.write_block(func_block, visitor.writer.getvalue())
          self.writer.write(textwrap.dedent("""\
              if πE != nil {
              \tπR = nil
              } else if πR == nil {
              \tπR = πg.None
              }
              return πR, πE"""))
      self.writer.write('}), πF.Globals()).ToObject()')
    return result
Beispiel #20
0
  def visit_ClassDef(self, node):
    # Since we only care about global vars, we end up throwing away the locals
    # collected by BlockVisitor. But use it anyway since it buys us detection of
    # assignment to vars that are later declared global.
    block_visitor = block.BlockVisitor()
    for child in node.body:
      block_visitor.visit(child)
    global_vars = {v.name for v in block_visitor.vars.values()
                   if v.type == block.Var.TYPE_GLOBAL}
    # Visit all the statements inside body of the class definition.
    body_visitor = StatementVisitor(block.ClassBlock(
        self.block, node.name, global_vars))
    # Indent so that the function body is aligned with the goto labels.
    with body_visitor.writer.indent_block():
      body_visitor._visit_each(node.body)  # pylint: disable=protected-access

    self._write_py_context(node.lineno)
    with self.block.alloc_temp('*πg.Dict') as cls, \
        self.block.alloc_temp() as mod_name, \
        self.block.alloc_temp('[]*πg.Object') as bases, \
        self.block.alloc_temp() as meta:
      self.writer.write('{} = make([]*πg.Object, {})'.format(
          bases.expr, len(node.bases)))
      for i, b in enumerate(node.bases):
        with self.expr_visitor.visit(b) as b:
          self.writer.write('{}[{}] = {}'.format(bases.expr, i, b.expr))
      self.writer.write('{} = πg.NewDict()'.format(cls.name))
      self.writer.write_checked_call2(
          mod_name, 'πF.Globals().GetItem(πF, {}.ToObject())',
          self.block.intern('__name__'))
      self.writer.write_checked_call1(
          '{}.SetItem(πF, {}.ToObject(), {})',
          cls.expr, self.block.intern('__module__'), mod_name.expr)
      tmpl = textwrap.dedent("""
          _, πE = πg.NewCode($name, $filename, nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) {
          \tπClass := $cls
          \t_ = πClass""")
      self.writer.write_tmpl(tmpl, name=util.go_str(node.name),
                             filename=util.go_str(self.block.filename),
                             cls=cls.expr)
      with self.writer.indent_block():
        self.writer.write_temp_decls(body_visitor.block)
        self.writer.write_block(body_visitor.block,
                                body_visitor.writer.out.getvalue())
      tmpl = textwrap.dedent("""\
          }).Eval(πF, πF.Globals(), nil, nil)
          if πE != nil {
          \treturn nil, πE
          }
          if $meta, πE = $cls.GetItem(πF, $metaclass_str.ToObject()); πE != nil {
          \treturn nil, πE
          }
          if $meta == nil {
          \t$meta = πg.TypeType.ToObject()
          }""")
      self.writer.write_tmpl(tmpl, meta=meta.name, cls=cls.expr,
                             metaclass_str=self.block.intern('__metaclass__'))
      with self.block.alloc_temp() as type_:
        type_expr = ('{}.Call(πF, []*πg.Object{{πg.NewStr({}).ToObject(), '
                     'πg.NewTuple({}...).ToObject(), {}.ToObject()}}, nil)')
        self.writer.write_checked_call2(
            type_, type_expr, meta.expr,
            util.go_str(node.name), bases.expr, cls.expr)
        self.block.bind_var(self.writer, node.name, type_.expr)
Beispiel #21
0
 def intern(self, s):
   if len(s) > 64 or _non_word_re.search(s):
     return 'πg.NewStr({})'.format(util.go_str(s))
   self.strings.add(s)
   return 'ß' + s
Beispiel #22
0
 def intern(self, s):
   if len(s) > 64 or _non_word_re.search(s):
     return 'πg.NewStr({})'.format(util.go_str(s))
   self.strings.add(s)
   return 'ß' + s
Beispiel #23
0
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
Beispiel #24
0
  def visit_ClassDef(self, node):
    # Since we only care about global vars, we end up throwing away the locals
    # collected by BlockVisitor. But use it anyway since it buys us detection of
    # assignment to vars that are later declared global.
    block_visitor = block.BlockVisitor()
    for child in node.body:
      block_visitor.visit(child)
    global_vars = {v.name for v in block_visitor.vars.values()
                   if v.type == block.Var.TYPE_GLOBAL}
    # Visit all the statements inside body of the class definition.
    body_visitor = StatementVisitor(block.ClassBlock(
        self.block, node.name, global_vars))
    # Indent so that the function body is aligned with the goto labels.
    with body_visitor.writer.indent_block():
      body_visitor._visit_each(node.body)  # pylint: disable=protected-access

    self._write_py_context(node.lineno)
    with self.block.alloc_temp('*πg.Dict') as cls, \
        self.block.alloc_temp() as mod_name, \
        self.block.alloc_temp('[]*πg.Object') as bases, \
        self.block.alloc_temp() as meta:
      self.writer.write('{} = make([]*πg.Object, {})'.format(
          bases.expr, len(node.bases)))
      for i, b in enumerate(node.bases):
        with self.expr_visitor.visit(b) as b:
          self.writer.write('{}[{}] = {}'.format(bases.expr, i, b.expr))
      self.writer.write('{} = πg.NewDict()'.format(cls.name))
      self.writer.write_checked_call2(
          mod_name, 'πF.Globals().GetItem(πF, {}.ToObject())',
          self.block.root.intern('__name__'))
      self.writer.write_checked_call1(
          '{}.SetItem(πF, {}.ToObject(), {})',
          cls.expr, self.block.root.intern('__module__'), mod_name.expr)
      tmpl = textwrap.dedent("""
          _, πE = πg.NewCode($name, $filename, nil, 0, func(πF *πg.Frame, _ []*πg.Object) (*πg.Object, *πg.BaseException) {
          \tπClass := $cls
          \t_ = πClass""")
      self.writer.write_tmpl(tmpl, name=util.go_str(node.name),
                             filename=util.go_str(self.block.root.filename),
                             cls=cls.expr)
      with self.writer.indent_block():
        self.writer.write_temp_decls(body_visitor.block)
        self.writer.write_block(body_visitor.block,
                                body_visitor.writer.getvalue())
      tmpl = textwrap.dedent("""\
          }).Eval(πF, πF.Globals(), nil, nil)
          if πE != nil {
          \tcontinue
          }
          if $meta, πE = $cls.GetItem(πF, $metaclass_str.ToObject()); πE != nil {
          \tcontinue
          }
          if $meta == nil {
          \t$meta = πg.TypeType.ToObject()
          }""")
      self.writer.write_tmpl(
          tmpl, meta=meta.name, cls=cls.expr,
          metaclass_str=self.block.root.intern('__metaclass__'))
      with self.block.alloc_temp() as type_:
        type_expr = ('{}.Call(πF, []*πg.Object{{πg.NewStr({}).ToObject(), '
                     'πg.NewTuple({}...).ToObject(), {}.ToObject()}}, nil)')
        self.writer.write_checked_call2(
            type_, type_expr, meta.expr,
            util.go_str(node.name), bases.expr, cls.expr)
        self.block.bind_var(self.writer, node.name, type_.expr)