예제 #1
0
파일: stmt.py 프로젝트: liangfeixu/grumpy
  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
예제 #2
0
파일: block.py 프로젝트: slox3r/grumpy
 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))
예제 #3
0
파일: block.py 프로젝트: zofuthan/grumpy
 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))
예제 #4
0
파일: block.py 프로젝트: slox3r/grumpy
 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)
예제 #5
0
파일: block.py 프로젝트: zofuthan/grumpy
 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)
예제 #6
0
파일: block.py 프로젝트: slox3r/grumpy
 def resolve_name(self, writer, name):
   local = 'nil'
   if name not in self.global_vars:
     # Only look for a local in an outer block when name hasn't been declared
     # global in this block. If it has been declared global then we fallback
     # straight to the global dict.
     block = self.parent_block
     while not isinstance(block, ModuleBlock):
       if isinstance(block, FunctionBlock) and name in block.vars:
         var = block.vars[name]
         if var.type != Var.TYPE_GLOBAL:
           local = util.adjust_local_name(name)
         # When it is declared global, prefer it to anything in outer blocks.
         break
       block = block.parent_block
   result = self.alloc_temp()
   writer.write_checked_call2(
       result, 'πg.ResolveClass(πF, πClass, {}, {})',
       local, self.intern(name))
   return result
예제 #7
0
파일: block.py 프로젝트: zofuthan/grumpy
 def resolve_name(self, writer, name):
   local = 'nil'
   if name not in self.global_vars:
     # Only look for a local in an outer block when name hasn't been declared
     # global in this block. If it has been declared global then we fallback
     # straight to the global dict.
     block = self.parent_block
     while not isinstance(block, ModuleBlock):
       if isinstance(block, FunctionBlock) and name in block.vars:
         var = block.vars[name]
         if var.type != Var.TYPE_GLOBAL:
           local = util.adjust_local_name(name)
         # When it is declared global, prefer it to anything in outer blocks.
         break
       block = block.parent_block
   result = self.alloc_temp()
   writer.write_checked_call2(
       result, 'πg.ResolveClass(πF, πClass, {}, {})',
       local, self.intern(name))
   return result
예제 #8
0
파일: block.py 프로젝트: slox3r/grumpy
 def bind_var(self, writer, name, value):
   if self.vars[name].type == Var.TYPE_GLOBAL:
     return self._module_block.bind_var(writer, name, value)
   writer.write('{} = {}'.format(util.adjust_local_name(name), value))
예제 #9
0
파일: expr.py 프로젝트: 0xBADCA7/grumpy
 def expr(self):
   return util.adjust_local_name(self._name)
예제 #10
0
파일: block.py 프로젝트: zofuthan/grumpy
 def bind_var(self, writer, name, value):
   if self.vars[name].type == Var.TYPE_GLOBAL:
     return self._module_block.bind_var(writer, name, value)
   writer.write('{} = {}'.format(util.adjust_local_name(name), value))
예제 #11
0
 def expr(self):
     return util.adjust_local_name(self._name)
예제 #12
0
파일: stmt.py 프로젝트: 0xBADCA7/grumpy
  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