[pypy-commit] pypy py3k: merge heads
antocuni
noreply at buildbot.pypy.org
Thu Mar 15 18:39:21 CET 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r53684:8930822eca5b
Date: 2012-03-15 18:38 +0100
http://bitbucket.org/pypy/pypy/changeset/8930822eca5b/
Log: merge heads
diff --git a/lib_pypy/_functools.py b/lib_pypy/_functools.py
--- a/lib_pypy/_functools.py
+++ b/lib_pypy/_functools.py
@@ -1,7 +1,27 @@
""" Supplies the internal functions for functools.py in the standard library """
-# reduce() has moved to _functools in Python 2.6+.
-reduce = reduce
+sentinel = object()
+
+def reduce(func, sequence, initial=sentinel):
+ """reduce(function, sequence[, initial]) -> value
+
+Apply a function of two arguments cumulatively to the items of a sequence,
+from left to right, so as to reduce the sequence to a single value.
+For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
+((((1+2)+3)+4)+5). If initial is present, it is placed before the items
+of the sequence in the calculation, and serves as a default when the
+sequence is empty."""
+ iterator = iter(sequence)
+ if initial is sentinel:
+ try:
+ initial = next(iterator)
+ except StopIteration:
+ raise TypeError("reduce() of empty sequence with no initial value")
+ result = initial
+ for item in iterator:
+ result = func(result, item)
+ return result
+
class partial(object):
"""
diff --git a/pypy/bin/rpython b/pypy/bin/rpython
new file mode 100755
--- /dev/null
+++ b/pypy/bin/rpython
@@ -0,0 +1,18 @@
+#!/usr/bin/env pypy
+
+"""RPython translation usage:
+
+rpython <translation options> target <targetoptions>
+
+run with --help for more information
+"""
+
+import sys
+from pypy.translator.goal.translate import main
+
+# no implicit targets
+if len(sys.argv) == 1:
+ print __doc__
+ sys.exit(1)
+
+main()
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -182,9 +182,6 @@
cmdline="--translationmodules",
suggests=[("objspace.allworkingmodules", False)]),
- BoolOption("geninterp", "specify whether geninterp should be used",
- default=False),
-
BoolOption("logbytecodes",
"keep track of bytecode usage",
default=False),
@@ -391,10 +388,6 @@
config.objspace.std.suggest(withsmalllong=True)
# xxx other options? ropes maybe?
- # completely disable geninterp in a level 0 translation
- if level == '0':
- config.objspace.suggest(geninterp=False)
-
# some optimizations have different effects depending on the typesystem
if type_system == 'ootype':
config.objspace.std.suggest(multimethods="doubledispatch")
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -182,11 +182,6 @@
# Flags of the TranslationContext:
BoolOption("simplifying", "Simplify flow graphs", default=True),
- BoolOption("builtins_can_raise_exceptions",
- "When true, assume any call to a 'simple' builtin such as "
- "'hex' can raise an arbitrary exception",
- default=False,
- cmdline=None),
BoolOption("list_comprehension_operations",
"When true, look for and special-case the sequence of "
"operations that results from a list comprehension and "
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -262,7 +262,7 @@
# XXX: this should be @jit.look_inside_iff, but we need key word arguments,
# and it doesn't support them for now.
def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
- blindargs=0):
+ w_kw_defs=None, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
Return the number of arguments filled in.
@@ -270,19 +270,19 @@
if jit.we_are_jitted() and self._dont_jit:
return self._match_signature_jit_opaque(w_firstarg, scope_w,
signature, defaults_w,
- blindargs)
+ w_kw_defs, blindargs)
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults_w, blindargs)
+ defaults_w, w_kw_defs, blindargs)
@jit.dont_look_inside
def _match_signature_jit_opaque(self, w_firstarg, scope_w, signature,
- defaults_w, blindargs):
+ defaults_w, w_kw_defs, blindargs):
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults_w, blindargs)
+ defaults_w, w_kw_defs, blindargs)
@jit.unroll_safe
def _really_match_signature(self, w_firstarg, scope_w, signature,
- defaults_w=None, blindargs=0):
+ defaults_w=None, w_kw_defs=None, blindargs=0):
#
# args_w = list of the normal actual parameters, wrapped
# kwds_w = real dictionary {'keyword': wrapped parameter}
@@ -346,11 +346,12 @@
starargs_w = args_w[args_left:]
else:
starargs_w = []
- scope_w[co_argcount] = self.space.newtuple(starargs_w)
+ loc = co_argcount + co_kwonlyargcount
+ scope_w[loc] = self.space.newtuple(starargs_w)
elif avail > co_argcount:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults_w, 0)
+ defaults_w, w_kw_defs, 0)
# the code assumes that keywords can potentially be large, but that
# argnames is typically not too large
@@ -384,8 +385,8 @@
num_remainingkwds -= 1
missing = 0
if input_argcount < co_argcount + co_kwonlyargcount:
- def_first = co_argcount + co_kwonlyargcount - (0 if defaults_w is None else len(defaults_w))
- for i in range(input_argcount, co_argcount + co_kwonlyargcount):
+ def_first = co_argcount - (0 if defaults_w is None else len(defaults_w))
+ for i in range(input_argcount, co_argcount):
if scope_w[i] is not None:
continue
defnum = i - def_first
@@ -396,6 +397,19 @@
# because it might be related to a problem with */** or
# keyword arguments, which will be checked for below.
missing += 1
+ for i in range(co_argcount, co_argcount + co_kwonlyargcount):
+ if scope_w[i] is not None:
+ continue
+ elif w_kw_defs is None:
+ missing += 1
+ continue
+ name = signature.kwonlyargnames[i - co_argcount]
+ w_name = self.space.wrap(name)
+ w_def = self.space.finditem(w_kw_defs, w_name)
+ if w_def is not None:
+ scope_w[i] = w_def
+ else:
+ missing += 1
# TODO: Put a nice error message
#if co_kwonlyargcount:
@@ -417,26 +431,27 @@
w_key = self.keyword_names_w[i - limit]
self.space.setitem(w_kwds, w_key, keywords_w[i])
#
- scope_w[co_argcount + has_vararg] = w_kwds
+ scope_w[co_argcount + co_kwonlyargcount + has_vararg] = w_kwds
elif num_remainingkwds:
if co_argcount == 0:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults_w, missing)
+ defaults_w, w_kw_defs, missing)
raise ArgErrUnknownKwds(self.space, num_remainingkwds, keywords,
used_keywords, self.keyword_names_w)
if missing:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults_w, missing)
+ defaults_w, w_kw_defs, missing)
return co_argcount + has_vararg + has_kwarg + co_kwonlyargcount
def parse_into_scope(self, w_firstarg,
- scope_w, fnname, signature, defaults_w=None):
+ scope_w, fnname, signature, defaults_w=None,
+ w_kw_defs=None):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
Store the argumentvalues into scope_w.
@@ -444,29 +459,32 @@
"""
try:
return self._match_signature(w_firstarg,
- scope_w, signature, defaults_w, 0)
+ scope_w, signature, defaults_w,
+ w_kw_defs, 0)
except ArgErr, e:
raise operationerrfmt(self.space.w_TypeError,
"%s() %s", fnname, e.getmsg())
- def _parse(self, w_firstarg, signature, defaults_w, blindargs=0):
+ def _parse(self, w_firstarg, signature, defaults_w, w_kw_defs, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
scopelen = signature.scope_length()
scope_w = [None] * scopelen
self._match_signature(w_firstarg, scope_w, signature, defaults_w,
- blindargs)
+ w_kw_defs, blindargs)
return scope_w
def parse_obj(self, w_firstarg,
- fnname, signature, defaults_w=None, blindargs=0):
+ fnname, signature, defaults_w=None, w_kw_defs=None,
+ blindargs=0):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
"""
try:
- return self._parse(w_firstarg, signature, defaults_w, blindargs)
+ return self._parse(w_firstarg, signature, defaults_w, w_kw_defs,
+ blindargs)
except ArgErr, e:
raise operationerrfmt(self.space.w_TypeError,
"%s() %s", fnname, e.getmsg())
@@ -522,22 +540,22 @@
def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
- blindargs=0):
+ w_kw_defs=None, blindargs=0):
self.combine_if_necessary()
# _match_signature is destructive
return Arguments._match_signature(
self, w_firstarg, scope_w, signature,
- defaults_w, blindargs)
+ defaults_w, w_kw_defs, blindargs)
def unpack(self):
self.combine_if_necessary()
return Arguments.unpack(self)
- def match_signature(self, signature, defaults_w):
+ def match_signature(self, signature, defaults_w, w_kw_defs=None):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
- return self._parse(None, signature, defaults_w)
+ return self._parse(None, signature, defaults_w, w_kw_defs)
def unmatch_signature(self, signature, data_w):
"""kind of inverse of match_signature"""
@@ -650,7 +668,7 @@
class ArgErrCount(ArgErr):
def __init__(self, got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
- defaults_w, missing_args):
+ defaults_w, w_kw_defs, missing_args):
self.expected_nargs = expected_nargs
self.has_vararg = has_vararg
self.has_kwarg = has_kwarg
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -602,7 +602,7 @@
return arg + 1
def _compute_UNPACK_EX(arg):
- return (arg % 256) + (arg // 256)
+ return (arg & 0xFF) + (arg >> 8)
def _compute_BUILD_TUPLE(arg):
return 1 - arg
@@ -611,10 +611,10 @@
return 1 - arg
def _compute_MAKE_CLOSURE(arg):
- return -arg - 1
+ return -1 - _num_args(arg) - ((arg >> 16) & 0xFFFF)
def _compute_MAKE_FUNCTION(arg):
- return -arg
+ return -_num_args(arg) - ((arg >> 16) & 0xFFFF)
def _compute_BUILD_SLICE(arg):
if arg == 3:
@@ -626,7 +626,7 @@
return -arg
def _num_args(oparg):
- return (oparg % 256) + 2 * (oparg / 256)
+ return (oparg % 256) + 2 * ((oparg // 256) % 256)
def _compute_CALL_FUNCTION(arg):
return -_num_args(arg)
diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -242,15 +242,16 @@
class FunctionDef(stmt):
- def __init__(self, name, args, body, decorator_list, lineno, col_offset):
+ def __init__(self, name, args, body, decorator_list, returns, lineno, col_offset):
self.name = name
self.args = args
self.body = body
self.w_body = None
self.decorator_list = decorator_list
self.w_decorator_list = None
+ self.returns = returns
stmt.__init__(self, lineno, col_offset)
- self.initialization_state = 63
+ self.initialization_state = 127
def walkabout(self, visitor):
visitor.visit_FunctionDef(self)
@@ -261,13 +262,16 @@
visitor._mutate_sequence(self.body)
if self.decorator_list:
visitor._mutate_sequence(self.decorator_list)
+ if self.returns:
+ self.returns = self.returns.mutate_over(visitor)
return visitor.visit_FunctionDef(self)
def sync_app_attrs(self, space):
- if (self.initialization_state & ~0) ^ 63:
- self.missing_field(space, ['lineno', 'col_offset', 'name', 'args', 'body', 'decorator_list'], 'FunctionDef')
+ if (self.initialization_state & ~64) ^ 63:
+ self.missing_field(space, ['lineno', 'col_offset', 'name', 'args', 'body', 'decorator_list', None], 'FunctionDef')
else:
- pass
+ if not self.initialization_state & 64:
+ self.returns = None
self.args.sync_app_attrs(space)
w_list = self.w_body
if w_list is not None:
@@ -289,6 +293,8 @@
if self.decorator_list is not None:
for node in self.decorator_list:
node.sync_app_attrs(space)
+ if self.returns:
+ self.returns.sync_app_attrs(space)
class ClassDef(stmt):
@@ -1631,6 +1637,25 @@
pass
+class Ellipsis(expr):
+
+ def __init__(self, lineno, col_offset):
+ expr.__init__(self, lineno, col_offset)
+ self.initialization_state = 3
+
+ def walkabout(self, visitor):
+ visitor.visit_Ellipsis(self)
+
+ def mutate_over(self, visitor):
+ return visitor.visit_Ellipsis(self)
+
+ def sync_app_attrs(self, space):
+ if (self.initialization_state & ~0) ^ 3:
+ self.missing_field(space, ['lineno', 'col_offset'], 'Ellipsis')
+ else:
+ pass
+
+
class Attribute(expr):
def __init__(self, value, attr, ctx, lineno, col_offset):
@@ -1868,24 +1893,6 @@
class slice(AST):
pass
-class Ellipsis(slice):
-
- def __init__(self):
- self.initialization_state = 0
-
- def walkabout(self, visitor):
- visitor.visit_Ellipsis(self)
-
- def mutate_over(self, visitor):
- return visitor.visit_Ellipsis(self)
-
- def sync_app_attrs(self, space):
- if (self.initialization_state & ~0) ^ 0:
- self.missing_field(space, [], 'Ellipsis')
- else:
- pass
-
-
class Slice(slice):
def __init__(self, lower, upper, step):
@@ -2300,57 +2307,75 @@
class arguments(AST):
- def __init__(self, args, vararg, kwonlyargs, kwarg, defaults):
+ def __init__(self, args, vararg, varargannotation, kwonlyargs, kwarg, kwargannotation, defaults, kw_defaults):
self.args = args
self.w_args = None
self.vararg = vararg
+ self.varargannotation = varargannotation
self.kwonlyargs = kwonlyargs
self.w_kwonlyargs = None
self.kwarg = kwarg
+ self.kwargannotation = kwargannotation
self.defaults = defaults
self.w_defaults = None
- self.initialization_state = 31
+ self.kw_defaults = kw_defaults
+ self.w_kw_defaults = None
+ self.initialization_state = 255
def mutate_over(self, visitor):
if self.args:
visitor._mutate_sequence(self.args)
+ if self.varargannotation:
+ self.varargannotation = self.varargannotation.mutate_over(visitor)
if self.kwonlyargs:
visitor._mutate_sequence(self.kwonlyargs)
+ if self.kwargannotation:
+ self.kwargannotation = self.kwargannotation.mutate_over(visitor)
if self.defaults:
visitor._mutate_sequence(self.defaults)
+ if self.kw_defaults:
+ visitor._mutate_sequence(self.kw_defaults)
return visitor.visit_arguments(self)
def walkabout(self, visitor):
visitor.visit_arguments(self)
def sync_app_attrs(self, space):
- if (self.initialization_state & ~10) ^ 21:
- self.missing_field(space, ['args', None, 'kwonlyargs', None, 'defaults'], 'arguments')
+ if (self.initialization_state & ~54) ^ 201:
+ self.missing_field(space, ['args', None, None, 'kwonlyargs', None, None, 'defaults', 'kw_defaults'], 'arguments')
else:
if not self.initialization_state & 2:
self.vararg = None
- if not self.initialization_state & 8:
+ if not self.initialization_state & 4:
+ self.varargannotation = None
+ if not self.initialization_state & 16:
self.kwarg = None
+ if not self.initialization_state & 32:
+ self.kwargannotation = None
w_list = self.w_args
if w_list is not None:
list_w = space.listview(w_list)
if list_w:
- self.args = [space.interp_w(expr, w_obj) for w_obj in list_w]
+ self.args = [space.interp_w(arg, w_obj) for w_obj in list_w]
else:
self.args = None
if self.args is not None:
for node in self.args:
node.sync_app_attrs(space)
+ if self.varargannotation:
+ self.varargannotation.sync_app_attrs(space)
w_list = self.w_kwonlyargs
if w_list is not None:
list_w = space.listview(w_list)
if list_w:
- self.kwonlyargs = [space.interp_w(expr, w_obj) for w_obj in list_w]
+ self.kwonlyargs = [space.interp_w(arg, w_obj) for w_obj in list_w]
else:
self.kwonlyargs = None
if self.kwonlyargs is not None:
for node in self.kwonlyargs:
node.sync_app_attrs(space)
+ if self.kwargannotation:
+ self.kwargannotation.sync_app_attrs(space)
w_list = self.w_defaults
if w_list is not None:
list_w = space.listview(w_list)
@@ -2361,6 +2386,40 @@
if self.defaults is not None:
for node in self.defaults:
node.sync_app_attrs(space)
+ w_list = self.w_kw_defaults
+ if w_list is not None:
+ list_w = space.listview(w_list)
+ if list_w:
+ self.kw_defaults = [space.interp_w(expr, w_obj) for w_obj in list_w]
+ else:
+ self.kw_defaults = None
+ if self.kw_defaults is not None:
+ for node in self.kw_defaults:
+ node.sync_app_attrs(space)
+
+class arg(AST):
+
+ def __init__(self, arg, annotation):
+ self.arg = arg
+ self.annotation = annotation
+ self.initialization_state = 3
+
+ def mutate_over(self, visitor):
+ if self.annotation:
+ self.annotation = self.annotation.mutate_over(visitor)
+ return visitor.visit_arg(self)
+
+ def walkabout(self, visitor):
+ visitor.visit_arg(self)
+
+ def sync_app_attrs(self, space):
+ if (self.initialization_state & ~2) ^ 1:
+ self.missing_field(space, ['arg', None], 'arg')
+ else:
+ if not self.initialization_state & 2:
+ self.annotation = None
+ if self.annotation:
+ self.annotation.sync_app_attrs(space)
class keyword(AST):
@@ -2415,7 +2474,8 @@
def _mutate_sequence(self, seq):
for i in range(len(seq)):
- seq[i] = seq[i].mutate_over(self)
+ if seq[i] is not None:
+ seq[i] = seq[i].mutate_over(self)
def visit_Module(self, node):
return self.default_visitor(node)
@@ -2503,6 +2563,8 @@
return self.default_visitor(node)
def visit_Bytes(self, node):
return self.default_visitor(node)
+ def visit_Ellipsis(self, node):
+ return self.default_visitor(node)
def visit_Attribute(self, node):
return self.default_visitor(node)
def visit_Subscript(self, node):
@@ -2517,8 +2579,6 @@
return self.default_visitor(node)
def visit_Const(self, node):
return self.default_visitor(node)
- def visit_Ellipsis(self, node):
- return self.default_visitor(node)
def visit_Slice(self, node):
return self.default_visitor(node)
def visit_ExtSlice(self, node):
@@ -2531,6 +2591,8 @@
return self.default_visitor(node)
def visit_arguments(self, node):
return self.default_visitor(node)
+ def visit_arg(self, node):
+ return self.default_visitor(node)
def visit_keyword(self, node):
return self.default_visitor(node)
def visit_alias(self, node):
@@ -2554,6 +2616,8 @@
node.args.walkabout(self)
self.visit_sequence(node.body)
self.visit_sequence(node.decorator_list)
+ if node.returns:
+ node.returns.walkabout(self)
def visit_ClassDef(self, node):
self.visit_sequence(node.bases)
@@ -2715,6 +2779,9 @@
def visit_Bytes(self, node):
pass
+ def visit_Ellipsis(self, node):
+ pass
+
def visit_Attribute(self, node):
node.value.walkabout(self)
@@ -2737,9 +2804,6 @@
def visit_Const(self, node):
pass
- def visit_Ellipsis(self, node):
- pass
-
def visit_Slice(self, node):
if node.lower:
node.lower.walkabout(self)
@@ -2766,8 +2830,17 @@
def visit_arguments(self, node):
self.visit_sequence(node.args)
+ if node.varargannotation:
+ node.varargannotation.walkabout(self)
self.visit_sequence(node.kwonlyargs)
+ if node.kwargannotation:
+ node.kwargannotation.walkabout(self)
self.visit_sequence(node.defaults)
+ self.visit_sequence(node.kw_defaults)
+
+ def visit_arg(self, node):
+ if node.annotation:
+ node.annotation.walkabout(self)
def visit_keyword(self, node):
node.value.walkabout(self)
@@ -3083,15 +3156,38 @@
w_self.w_decorator_list = w_new_value
w_self.initialization_state |= 32
-_FunctionDef_field_unroller = unrolling_iterable(['name', 'args', 'body', 'decorator_list'])
+def FunctionDef_get_returns(space, w_self):
+ if w_self.w_dict is not None:
+ w_obj = w_self.getdictvalue(space, 'returns')
+ if w_obj is not None:
+ return w_obj
+ if not w_self.initialization_state & 64:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'returns')
+ return space.wrap(w_self.returns)
+
+def FunctionDef_set_returns(space, w_self, w_new_value):
+ try:
+ w_self.returns = space.interp_w(expr, w_new_value, True)
+ if type(w_self.returns) is expr:
+ raise OperationError(space.w_TypeError, space.w_None)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ w_self.setdictvalue(space, 'returns', w_new_value)
+ return
+ w_self.deldictvalue(space, 'returns')
+ w_self.initialization_state |= 64
+
+_FunctionDef_field_unroller = unrolling_iterable(['name', 'args', 'body', 'decorator_list', 'returns'])
def FunctionDef_init(space, w_self, __args__):
w_self = space.descr_self_interp_w(FunctionDef, w_self)
w_self.w_body = None
w_self.w_decorator_list = None
args_w, kwargs_w = __args__.unpack()
if args_w:
- if len(args_w) != 4:
- w_err = space.wrap("FunctionDef constructor takes either 0 or 4 positional arguments")
+ if len(args_w) != 5:
+ w_err = space.wrap("FunctionDef constructor takes either 0 or 5 positional arguments")
raise OperationError(space.w_TypeError, w_err)
i = 0
for field in _FunctionDef_field_unroller:
@@ -3103,11 +3199,12 @@
FunctionDef.typedef = typedef.TypeDef("FunctionDef",
stmt.typedef,
__module__='_ast',
- _fields=_FieldsWrapper(['name', 'args', 'body', 'decorator_list']),
+ _fields=_FieldsWrapper(['name', 'args', 'body', 'decorator_list', 'returns']),
name=typedef.GetSetProperty(FunctionDef_get_name, FunctionDef_set_name, cls=FunctionDef),
args=typedef.GetSetProperty(FunctionDef_get_args, FunctionDef_set_args, cls=FunctionDef),
body=typedef.GetSetProperty(FunctionDef_get_body, FunctionDef_set_body, cls=FunctionDef),
decorator_list=typedef.GetSetProperty(FunctionDef_get_decorator_list, FunctionDef_set_decorator_list, cls=FunctionDef),
+ returns=typedef.GetSetProperty(FunctionDef_get_returns, FunctionDef_set_returns, cls=FunctionDef),
__new__=interp2app(get_AST_new(FunctionDef)),
__init__=interp2app(FunctionDef_init),
)
@@ -5734,6 +5831,23 @@
__init__=interp2app(Bytes_init),
)
+def Ellipsis_init(space, w_self, __args__):
+ w_self = space.descr_self_interp_w(Ellipsis, w_self)
+ args_w, kwargs_w = __args__.unpack()
+ if args_w:
+ w_err = space.wrap("Ellipsis constructor takes no arguments")
+ raise OperationError(space.w_TypeError, w_err)
+ for field, w_value in kwargs_w.iteritems():
+ space.setattr(w_self, space.wrap(field), w_value)
+
+Ellipsis.typedef = typedef.TypeDef("Ellipsis",
+ expr.typedef,
+ __module__='_ast',
+ _fields=_FieldsWrapper([]),
+ __new__=interp2app(get_AST_new(Ellipsis)),
+ __init__=interp2app(Ellipsis_init),
+)
+
def Attribute_get_value(space, w_self):
if w_self.w_dict is not None:
w_obj = w_self.getdictvalue(space, 'value')
@@ -6295,23 +6409,6 @@
__new__=interp2app(get_AST_new(slice)),
)
-def Ellipsis_init(space, w_self, __args__):
- w_self = space.descr_self_interp_w(Ellipsis, w_self)
- args_w, kwargs_w = __args__.unpack()
- if args_w:
- w_err = space.wrap("Ellipsis constructor takes no arguments")
- raise OperationError(space.w_TypeError, w_err)
- for field, w_value in kwargs_w.iteritems():
- space.setattr(w_self, space.wrap(field), w_value)
-
-Ellipsis.typedef = typedef.TypeDef("Ellipsis",
- slice.typedef,
- __module__='_ast',
- _fields=_FieldsWrapper([]),
- __new__=interp2app(get_AST_new(Ellipsis)),
- __init__=interp2app(Ellipsis_init),
-)
-
def Slice_get_lower(space, w_self):
if w_self.w_dict is not None:
w_obj = w_self.getdictvalue(space, 'lower')
@@ -6993,8 +7090,31 @@
w_self.deldictvalue(space, 'vararg')
w_self.initialization_state |= 2
+def arguments_get_varargannotation(space, w_self):
+ if w_self.w_dict is not None:
+ w_obj = w_self.getdictvalue(space, 'varargannotation')
+ if w_obj is not None:
+ return w_obj
+ if not w_self.initialization_state & 4:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'varargannotation')
+ return space.wrap(w_self.varargannotation)
+
+def arguments_set_varargannotation(space, w_self, w_new_value):
+ try:
+ w_self.varargannotation = space.interp_w(expr, w_new_value, True)
+ if type(w_self.varargannotation) is expr:
+ raise OperationError(space.w_TypeError, space.w_None)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ w_self.setdictvalue(space, 'varargannotation', w_new_value)
+ return
+ w_self.deldictvalue(space, 'varargannotation')
+ w_self.initialization_state |= 4
+
def arguments_get_kwonlyargs(space, w_self):
- if not w_self.initialization_state & 4:
+ if not w_self.initialization_state & 8:
typename = space.type(w_self).getname(space)
raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kwonlyargs')
if w_self.w_kwonlyargs is None:
@@ -7008,14 +7128,14 @@
def arguments_set_kwonlyargs(space, w_self, w_new_value):
w_self.w_kwonlyargs = w_new_value
- w_self.initialization_state |= 4
+ w_self.initialization_state |= 8
def arguments_get_kwarg(space, w_self):
if w_self.w_dict is not None:
w_obj = w_self.getdictvalue(space, 'kwarg')
if w_obj is not None:
return w_obj
- if not w_self.initialization_state & 8:
+ if not w_self.initialization_state & 16:
typename = space.type(w_self).getname(space)
raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kwarg')
return space.wrap(w_self.kwarg)
@@ -7032,10 +7152,33 @@
w_self.setdictvalue(space, 'kwarg', w_new_value)
return
w_self.deldictvalue(space, 'kwarg')
- w_self.initialization_state |= 8
+ w_self.initialization_state |= 16
+
+def arguments_get_kwargannotation(space, w_self):
+ if w_self.w_dict is not None:
+ w_obj = w_self.getdictvalue(space, 'kwargannotation')
+ if w_obj is not None:
+ return w_obj
+ if not w_self.initialization_state & 32:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kwargannotation')
+ return space.wrap(w_self.kwargannotation)
+
+def arguments_set_kwargannotation(space, w_self, w_new_value):
+ try:
+ w_self.kwargannotation = space.interp_w(expr, w_new_value, True)
+ if type(w_self.kwargannotation) is expr:
+ raise OperationError(space.w_TypeError, space.w_None)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ w_self.setdictvalue(space, 'kwargannotation', w_new_value)
+ return
+ w_self.deldictvalue(space, 'kwargannotation')
+ w_self.initialization_state |= 32
def arguments_get_defaults(space, w_self):
- if not w_self.initialization_state & 16:
+ if not w_self.initialization_state & 64:
typename = space.type(w_self).getname(space)
raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'defaults')
if w_self.w_defaults is None:
@@ -7049,18 +7192,36 @@
def arguments_set_defaults(space, w_self, w_new_value):
w_self.w_defaults = w_new_value
- w_self.initialization_state |= 16
-
-_arguments_field_unroller = unrolling_iterable(['args', 'vararg', 'kwonlyargs', 'kwarg', 'defaults'])
+ w_self.initialization_state |= 64
+
+def arguments_get_kw_defaults(space, w_self):
+ if not w_self.initialization_state & 128:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'kw_defaults')
+ if w_self.w_kw_defaults is None:
+ if w_self.kw_defaults is None:
+ list_w = []
+ else:
+ list_w = [space.wrap(node) for node in w_self.kw_defaults]
+ w_list = space.newlist(list_w)
+ w_self.w_kw_defaults = w_list
+ return w_self.w_kw_defaults
+
+def arguments_set_kw_defaults(space, w_self, w_new_value):
+ w_self.w_kw_defaults = w_new_value
+ w_self.initialization_state |= 128
+
+_arguments_field_unroller = unrolling_iterable(['args', 'vararg', 'varargannotation', 'kwonlyargs', 'kwarg', 'kwargannotation', 'defaults', 'kw_defaults'])
def arguments_init(space, w_self, __args__):
w_self = space.descr_self_interp_w(arguments, w_self)
w_self.w_args = None
w_self.w_kwonlyargs = None
w_self.w_defaults = None
+ w_self.w_kw_defaults = None
args_w, kwargs_w = __args__.unpack()
if args_w:
- if len(args_w) != 5:
- w_err = space.wrap("arguments constructor takes either 0 or 5 positional arguments")
+ if len(args_w) != 8:
+ w_err = space.wrap("arguments constructor takes either 0 or 8 positional arguments")
raise OperationError(space.w_TypeError, w_err)
i = 0
for field in _arguments_field_unroller:
@@ -7072,16 +7233,88 @@
arguments.typedef = typedef.TypeDef("arguments",
AST.typedef,
__module__='_ast',
- _fields=_FieldsWrapper(['args', 'vararg', 'kwonlyargs', 'kwarg', 'defaults']),
+ _fields=_FieldsWrapper(['args', 'vararg', 'varargannotation', 'kwonlyargs', 'kwarg', 'kwargannotation', 'defaults', 'kw_defaults']),
args=typedef.GetSetProperty(arguments_get_args, arguments_set_args, cls=arguments),
vararg=typedef.GetSetProperty(arguments_get_vararg, arguments_set_vararg, cls=arguments),
+ varargannotation=typedef.GetSetProperty(arguments_get_varargannotation, arguments_set_varargannotation, cls=arguments),
kwonlyargs=typedef.GetSetProperty(arguments_get_kwonlyargs, arguments_set_kwonlyargs, cls=arguments),
kwarg=typedef.GetSetProperty(arguments_get_kwarg, arguments_set_kwarg, cls=arguments),
+ kwargannotation=typedef.GetSetProperty(arguments_get_kwargannotation, arguments_set_kwargannotation, cls=arguments),
defaults=typedef.GetSetProperty(arguments_get_defaults, arguments_set_defaults, cls=arguments),
+ kw_defaults=typedef.GetSetProperty(arguments_get_kw_defaults, arguments_set_kw_defaults, cls=arguments),
__new__=interp2app(get_AST_new(arguments)),
__init__=interp2app(arguments_init),
)
+def arg_get_arg(space, w_self):
+ if w_self.w_dict is not None:
+ w_obj = w_self.getdictvalue(space, 'arg')
+ if w_obj is not None:
+ return w_obj
+ if not w_self.initialization_state & 1:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'arg')
+ return space.wrap(w_self.arg)
+
+def arg_set_arg(space, w_self, w_new_value):
+ try:
+ w_self.arg = space.str_w(w_new_value)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ w_self.setdictvalue(space, 'arg', w_new_value)
+ return
+ w_self.deldictvalue(space, 'arg')
+ w_self.initialization_state |= 1
+
+def arg_get_annotation(space, w_self):
+ if w_self.w_dict is not None:
+ w_obj = w_self.getdictvalue(space, 'annotation')
+ if w_obj is not None:
+ return w_obj
+ if not w_self.initialization_state & 2:
+ typename = space.type(w_self).getname(space)
+ raise operationerrfmt(space.w_AttributeError, "'%s' object has no attribute '%s'", typename, 'annotation')
+ return space.wrap(w_self.annotation)
+
+def arg_set_annotation(space, w_self, w_new_value):
+ try:
+ w_self.annotation = space.interp_w(expr, w_new_value, True)
+ if type(w_self.annotation) is expr:
+ raise OperationError(space.w_TypeError, space.w_None)
+ except OperationError, e:
+ if not e.match(space, space.w_TypeError):
+ raise
+ w_self.setdictvalue(space, 'annotation', w_new_value)
+ return
+ w_self.deldictvalue(space, 'annotation')
+ w_self.initialization_state |= 2
+
+_arg_field_unroller = unrolling_iterable(['arg', 'annotation'])
+def arg_init(space, w_self, __args__):
+ w_self = space.descr_self_interp_w(arg, w_self)
+ args_w, kwargs_w = __args__.unpack()
+ if args_w:
+ if len(args_w) != 2:
+ w_err = space.wrap("arg constructor takes either 0 or 2 positional arguments")
+ raise OperationError(space.w_TypeError, w_err)
+ i = 0
+ for field in _arg_field_unroller:
+ space.setattr(w_self, space.wrap(field), args_w[i])
+ i += 1
+ for field, w_value in kwargs_w.iteritems():
+ space.setattr(w_self, space.wrap(field), w_value)
+
+arg.typedef = typedef.TypeDef("arg",
+ AST.typedef,
+ __module__='_ast',
+ _fields=_FieldsWrapper(['arg', 'annotation']),
+ arg=typedef.GetSetProperty(arg_get_arg, arg_set_arg, cls=arg),
+ annotation=typedef.GetSetProperty(arg_get_annotation, arg_set_annotation, cls=arg),
+ __new__=interp2app(get_AST_new(arg)),
+ __init__=interp2app(arg_init),
+)
+
def keyword_get_arg(space, w_self):
if w_self.w_dict is not None:
w_obj = w_self.getdictvalue(space, 'arg')
diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -211,11 +211,15 @@
dot_count = 0
while i < child_count:
child = import_node.children[i]
- if child.type == syms.dotted_name:
+ child_type = child.type
+ if child_type == syms.dotted_name:
module = self.alias_for_import_name(child, False)
i += 1
break
- elif child.type != tokens.DOT:
+ elif child_type == tokens.ELLIPSIS:
+ # Special case for tokenization.
+ dot_count += 2
+ elif child_type != tokens.DOT:
break
i += 1
dot_count += 1
@@ -462,8 +466,13 @@
name = name_node.value
self.check_forbidden_name(name, name_node)
args = self.handle_arguments(funcdef_node.children[2])
- body = self.handle_suite(funcdef_node.children[4])
- return ast.FunctionDef(name, args, body, decorators,
+ suite = 4
+ returns = None
+ if funcdef_node.children[3].type == tokens.RARROW:
+ returns = self.handle_expr(funcdef_node.children[4])
+ suite += 2
+ body = self.handle_suite(funcdef_node.children[suite])
+ return ast.FunctionDef(name, args, body, decorators, returns,
funcdef_node.lineno, funcdef_node.column)
def handle_decorated(self, decorated_node):
@@ -508,99 +517,136 @@
# and varargslist (lambda definition).
if arguments_node.type == syms.parameters:
if len(arguments_node.children) == 2:
- return ast.arguments(None, None, None, None, None)
+ return ast.arguments(None, None, None, None, None, None, None,
+ None)
arguments_node = arguments_node.children[1]
i = 0
child_count = len(arguments_node.children)
- defaults = []
- args = []
- variable_arg = None
- keywordonly_args = None
- keywords_arg = None
+ n_pos = 0
+ n_pos_def = 0
+ n_kwdonly = 0
+ # scan args
+ while i < child_count:
+ arg_type = arguments_node.children[i].type
+ if arg_type == tokens.STAR:
+ i += 1
+ if i < child_count:
+ next_arg_type = arguments_node.children[i].type
+ if (next_arg_type == syms.tfpdef or
+ next_arg_type == syms.vfpdef):
+ i += 1
+ break
+ if arg_type == tokens.DOUBLESTAR:
+ break
+ if arg_type == syms.vfpdef or arg_type == syms.tfpdef:
+ n_pos += 1
+ if arg_type == tokens.EQUAL:
+ n_pos_def += 1
+ i += 1
+ while i < child_count:
+ arg_type = arguments_node.children[i].type
+ if arg_type == tokens.DOUBLESTAR:
+ break
+ if arg_type == syms.vfpdef or arg_type == syms.tfpdef:
+ n_kwdonly += 1
+ i += 1
+ pos = []
+ posdefaults = []
+ kwonly = [] if n_kwdonly else None
+ kwdefaults = []
+ kwarg = None
+ kwargann = None
+ vararg = None
+ varargann = None
+ if n_pos + n_kwdonly > 255:
+ self.error("more than 255 arguments", arguments_node)
+ # process args
+ i = 0
have_default = False
while i < child_count:
- argument = arguments_node.children[i]
- arg_type = argument.type
+ arg = arguments_node.children[i]
+ arg_type = arg.type
if arg_type == syms.tfpdef or arg_type == syms.vfpdef:
- parenthesized = False
- complex_args = False
- while True:
- if i + 1 < child_count and \
- arguments_node.children[i + 1].type == tokens.EQUAL:
- default_node = arguments_node.children[i + 2]
- defaults.append(self.handle_expr(default_node))
- i += 2
- have_default = True
- elif have_default:
- if parenthesized and not complex_args:
- msg = "parenthesized arg with default"
- else:
- msg = ("non-default argument follows default "
- "argument")
- self.error(msg, arguments_node)
- if len(argument.children) == 3:
- sub_arg = argument.children[1]
- if len(sub_arg.children) != 1:
- complex_args = True
- args.append(self.handle_arg_unpacking(sub_arg))
- else:
- parenthesized = True
- argument = sub_arg.children[0]
- continue
- if argument.children[0].type == tokens.NAME:
- name_node = argument.children[0]
- arg_name = name_node.value
- self.check_forbidden_name(arg_name, name_node)
- name = ast.Name(arg_name, ast.Param, name_node.lineno,
- name_node.column)
- if keywordonly_args is None:
- args.append(name)
- else:
- keywordonly_args.append(name)
+ if i + 1 < child_count and \
+ arguments_node.children[i + 1].type == tokens.EQUAL:
+ default_node = arguments_node.children[i + 2]
+ posdefaults.append(self.handle_expr(default_node))
i += 2
- break
+ have_default = True
+ elif have_default:
+ msg = "non-default argument follows default argument"
+ self.error(msg, arguments_node)
+ pos.append(self.handle_arg(arg))
+ i += 2
elif arg_type == tokens.STAR:
+ if i + 1 >= child_count:
+ self.error("named arguments must follow bare *",
+ arguments_node)
name_node = arguments_node.children[i + 1]
keywordonly_args = []
if name_node.type == tokens.COMMA:
i += 2
+ i = self.handle_keywordonly_args(arguments_node, i, kwonly,
+ kwdefaults)
else:
- variable_arg = name_node.children[0].value
- self.check_forbidden_name(variable_arg, name_node)
+ vararg = name_node.children[0].value
+ self.check_forbidden_name(vararg, name_node)
+ if len(name_node.children) > 1:
+ varargann = self.handle_expr(name_node.children[2])
i += 3
+ if i < child_count:
+ next_arg_type = arguments_node.children[i].type
+ if (next_arg_type == syms.tfpdef or
+ next_arg_type == syms.vfpdef):
+ i = self.handle_keywordonly_args(arguments_node, i,
+ kwonly, kwdefaults)
elif arg_type == tokens.DOUBLESTAR:
name_node = arguments_node.children[i + 1]
- keywords_arg = name_node.children[0].value
- self.check_forbidden_name(keywords_arg, name_node)
+ kwarg = name_node.children[0].value
+ self.check_forbidden_name(kwarg, name_node)
+ if len(name_node.children) > 1:
+ kwargann = self.handle_expr(name_node.children[2])
i += 3
else:
raise AssertionError("unknown node in argument list")
- if not defaults:
- defaults = None
- if not args:
- args = None
- return ast.arguments(args, variable_arg, keywordonly_args, keywords_arg, defaults)
+ return ast.arguments(pos, vararg, varargann, kwonly, kwarg,
+ kwargann, posdefaults, kwdefaults)
- def handle_arg_unpacking(self, fplist_node):
- args = []
- for i in range((len(fplist_node.children) + 1) / 2):
- fpdef_node = fplist_node.children[i * 2]
- while True:
- child = fpdef_node.children[0]
- if child.type == tokens.NAME:
- arg = ast.Name(child.value, ast.Store, child.lineno,
- child.column)
- args.append(arg)
+ def handle_keywordonly_args(self, arguments_node, i, kwonly, kwdefaults):
+ if kwonly is None:
+ self.error("named arguments must follows bare *",
+ arguments_node.children[i])
+ child_count = len(arguments_node.children)
+ while i < child_count:
+ arg = arguments_node.children[i]
+ arg_type = arg.type
+ if arg_type == syms.vfpdef or arg_type == syms.tfpdef:
+ if (i + 1 < child_count and
+ arguments_node.children[i + 1].type == tokens.EQUAL):
+ expr = self.handle_expr(arguments_node.children[i + 2])
+ kwdefaults.append(expr)
+ i += 2
else:
- child = fpdef_node.children[1]
- if len(child.children) == 1:
- fpdef_node = child.children[0]
- continue
- args.append(self.handle_arg_unpacking(child))
- break
- tup = ast.Tuple(args, ast.Store, fplist_node.lineno, fplist_node.column)
- self.set_context(tup, ast.Store)
- return tup
+ kwdefaults.append(None)
+ ann = None
+ if len(arg.children) == 3:
+ ann = self.handle_expr(arg.children[2])
+ name_node = arg.children[0]
+ argname = name_node.value
+ self.check_forbidden_name(argname, name_node)
+ kwonly.append(ast.arg(argname, ann))
+ i += 2
+ elif arg_type == tokens.DOUBLESTAR:
+ return i
+ return i
+
+ def handle_arg(self, arg_node):
+ name_node = arg_node.children[0]
+ self.check_forbidden_name(name_node.value, arg_node)
+ ann = None
+ if len(arg_node.children) == 3:
+ ann = self.handle_expr(arg_node.children[2])
+ return ast.arg(name_node.value, ann)
def handle_stmt(self, stmt):
stmt_type = stmt.type
@@ -705,9 +751,9 @@
# Loop until we return something.
while True:
expr_node_type = expr_node.type
- if expr_node_type == syms.test or expr_node_type == syms.old_test:
+ if expr_node_type == syms.test or expr_node_type == syms.test_nocond:
first_child = expr_node.children[0]
- if first_child.type in (syms.lambdef, syms.old_lambdef):
+ if first_child.type in (syms.lambdef, syms.lambdef_nocond):
return self.handle_lambdef(first_child)
elif len(expr_node.children) > 1:
return self.handle_ifexp(expr_node)
@@ -774,12 +820,13 @@
def handle_star_expr(self, star_expr_node):
expr = self.handle_expr(star_expr_node.children[1])
- return ast.Starred(expr, ast.Load, star_expr_node.lineno, star_expr_node.column)
+ return ast.Starred(expr, ast.Load, star_expr_node.lineno,
+ star_expr_node.column)
def handle_lambdef(self, lambdef_node):
expr = self.handle_expr(lambdef_node.children[-1])
if len(lambdef_node.children) == 3:
- args = ast.arguments(None, None, None, None, None)
+ args = ast.arguments(None, None, None, None, None, None, None, None)
else:
args = self.handle_arguments(lambdef_node.children[1])
return ast.Lambda(args, expr, lambdef_node.lineno, lambdef_node.column)
@@ -885,8 +932,6 @@
def handle_slice(self, slice_node):
first_child = slice_node.children[0]
- if first_child.type == tokens.DOT:
- return ast.Ellipsis()
if len(slice_node.children) == 1 and first_child.type == syms.test:
index = self.handle_expr(first_child)
return ast.Index(index)
@@ -1100,6 +1145,8 @@
elif first_child_type == tokens.NUMBER:
num_value = self.parse_number(first_child.value)
return ast.Num(num_value, atom_node.lineno, atom_node.column)
+ elif first_child_type == tokens.ELLIPSIS:
+ return ast.Ellipsis(atom_node.lineno, atom_node.column)
elif first_child_type == tokens.LPAR:
second_child = atom_node.children[1]
if second_child.type == tokens.RPAR:
diff --git a/pypy/interpreter/astcompiler/asthelpers.py b/pypy/interpreter/astcompiler/asthelpers.py
--- a/pypy/interpreter/astcompiler/asthelpers.py
+++ b/pypy/interpreter/astcompiler/asthelpers.py
@@ -168,3 +168,9 @@
class __extend__(ast.Num):
constant = True
+
+
+class __extend__(ast.Ellipsis):
+
+ _description = "Ellipsis"
+ constant = True
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -286,17 +286,64 @@
self.emit_op_arg(ops.LOAD_CONST, code_index)
self.emit_op_arg(ops.MAKE_FUNCTION, num_defaults)
+ def _visit_kwonlydefaults(self, args):
+ defaults = 0
+ for kwonly, default in zip(args.kwonlyargs, args.kw_defaults):
+ if default:
+ self.load_const(self.space.wrap(kwonly.arg))
+ default.walkabout(self)
+ defaults += 1
+ return defaults
+
+ def _visit_arg_annotation(self, name, ann, names):
+ if ann:
+ ann.walkabout(self)
+ names.append(name)
+
+ def _visit_arg_annotations(self, args, names):
+ if args:
+ for arg in args:
+ self._visit_arg_annotation(arg.arg, arg.annotation, names)
+
+ def _visit_annotations(self, func, args, returns):
+ space = self.space
+ names = []
+ self._visit_arg_annotations(args.args, names)
+ if args.varargannotation:
+ self._visit_arg_annotation(args.vararg, args.varargannotation,
+ names)
+ self._visit_arg_annotations(args.kwonlyargs, names)
+ if args.kwargannotation:
+ self._visit_arg_annotation(args.kwarg, args.kwargannotation,
+ names)
+ self._visit_arg_annotation("return", returns, names)
+ l = len(names)
+ if l:
+ if l > 65534:
+ self.error("too many annotations", func)
+ w_tup = space.newtuple([space.wrap(name) for name in names])
+ self.load_const(w_tup)
+ l += 1
+ return l
+
def visit_FunctionDef(self, func):
self.update_position(func.lineno, True)
# Load decorators first, but apply them after the function is created.
self.visit_sequence(func.decorator_list)
args = func.args
assert isinstance(args, ast.arguments)
+ kw_default_count = 0
+ if args.kwonlyargs:
+ kw_default_count = self._visit_kwonlydefaults(args)
self.visit_sequence(args.defaults)
+ num_annotations = self._visit_annotations(func, args, func.returns)
num_defaults = len(args.defaults) if args.defaults is not None else 0
+ oparg = num_defaults
+ oparg |= kw_default_count << 8
+ oparg |= num_annotations << 16
code = self.sub_scope(FunctionCodeGenerator, func.name, func,
func.lineno)
- self._make_function(code, num_defaults)
+ self._make_function(code, oparg)
# Apply decorators.
if func.decorator_list:
for i in range(len(func.decorator_list)):
@@ -307,10 +354,15 @@
self.update_position(lam.lineno)
args = lam.args
assert isinstance(args, ast.arguments)
+ kw_default_count = 0
+ if args.kwonlyargs:
+ kw_default_count = self._visit_kwonlydefaults(args)
self.visit_sequence(args.defaults)
default_count = len(args.defaults) if args.defaults is not None else 0
code = self.sub_scope(LambdaCodeGenerator, "<lambda>", lam, lam.lineno)
- self._make_function(code, default_count)
+ oparg = default_count
+ oparg |= kw_default_count << 8
+ self._make_function(code, oparg)
def visit_ClassDef(self, cls):
self.update_position(cls.lineno, True)
@@ -371,9 +423,8 @@
self.emit_op_name(ops.LOAD_GLOBAL, self.names, "AssertionError")
if asrt.msg:
asrt.msg.walkabout(self)
- self.emit_op_arg(ops.RAISE_VARARGS, 2)
- else:
- self.emit_op_arg(ops.RAISE_VARARGS, 1)
+ self.emit_op_arg(ops.CALL_FUNCTION, 1)
+ self.emit_op_arg(ops.RAISE_VARARGS, 1)
self.use_next_block(end)
def _binop(self, op):
@@ -778,6 +829,9 @@
space = self.space
self.load_const(const.value)
+ def visit_Ellipsis(self, e):
+ self.load_const(self.space.w_Ellipsis)
+
def visit_UnaryOp(self, op):
self.update_position(op.lineno)
op.operand.walkabout(self)
@@ -834,36 +888,46 @@
ifexp.orelse.walkabout(self)
self.use_next_block(end)
- def visit_Tuple(self, tup):
- self.update_position(tup.lineno)
- elt_count = len(tup.elts) if tup.elts is not None else 0
- if tup.ctx == ast.Store:
- star_pos = -1
+ def _visit_list_or_tuple(self, node, elts, ctx, op):
+ elt_count = len(elts) if elts else 0
+ star_pos = -1
+ if ctx == ast.Store:
if elt_count > 0:
- for i, elt in enumerate(tup.elts):
+ for i, elt in enumerate(elts):
if isinstance(elt, ast.Starred):
if star_pos != -1:
- self.error("two starred expressions in assignment", tup)
+ msg = "too many starred expressions in assignment"
+ self.error(msg, node)
star_pos = i
- if star_pos > -1:
+ if star_pos != -1:
self.emit_op_arg(ops.UNPACK_EX, star_pos | (elt_count-star_pos-1)<<8)
else:
self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
- self.visit_sequence(tup.elts)
- if tup.ctx == ast.Load:
- self.emit_op_arg(ops.BUILD_TUPLE, elt_count)
+ if elt_count > 0:
+ if star_pos != -1:
+ for elt in elts:
+ if isinstance(elt, ast.Starred):
+ elt.value.walkabout(self)
+ else:
+ elt.walkabout(self)
+ else:
+ self.visit_sequence(elts)
+ if ctx == ast.Load:
+ self.emit_op_arg(op, elt_count)
def visit_Starred(self, star):
- star.value.walkabout(self)
+ if star.ctx != ast.Store:
+ self.error("can use starred expression only as assignment target",
+ star)
+ self.error("starred assignment must be in list or tuple", star)
+
+ def visit_Tuple(self, tup):
+ self.update_position(tup.lineno)
+ self._visit_list_or_tuple(tup, tup.elts, tup.ctx, ops.BUILD_TUPLE)
def visit_List(self, l):
self.update_position(l.lineno)
- elt_count = len(l.elts) if l.elts is not None else 0
- if l.ctx == ast.Store:
- self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
- self.visit_sequence(l.elts)
- if l.ctx == ast.Load:
- self.emit_op_arg(ops.BUILD_LIST, elt_count)
+ self._visit_list_or_tuple(l, l.elts, l.ctx, ops.BUILD_LIST)
def visit_Dict(self, d):
self.update_position(d.lineno)
@@ -1079,9 +1143,7 @@
self.emit_op_arg(ops.BUILD_SLICE, arg)
def _nested_slice(self, slc, ctx):
- if isinstance(slc, ast.Ellipsis):
- self.load_const(self.space.w_Ellipsis)
- elif isinstance(slc, ast.Slice):
+ if isinstance(slc, ast.Slice):
self._complex_slice(slc, ctx)
elif isinstance(slc, ast.Index):
slc.value.walkabout(self)
@@ -1093,10 +1155,6 @@
kind = "index"
if ctx != ast.AugStore:
slc.value.walkabout(self)
- elif isinstance(slc, ast.Ellipsis):
- kind = "ellipsis"
- if ctx != ast.AugStore:
- self.load_const(self.space.w_Ellipsis)
elif isinstance(slc, ast.Slice):
kind = "slice"
if ctx != ast.AugStore:
@@ -1190,6 +1248,8 @@
assert isinstance(args, ast.arguments)
if args.args:
self.argcount = len(args.args)
+ if args.kwonlyargs:
+ self.kwonlyargcount = len(args.kwonlyargs)
# Prevent a string from being the first constant and thus a docstring.
self.add_const(self.space.w_None)
lam.body.walkabout(self)
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -62,6 +62,12 @@
return self.s
+class __extend__(ast.Ellipsis):
+
+ def as_constant_truth(self, space):
+ return True
+
+
class __extend__(ast.Const):
def as_constant(self):
@@ -255,11 +261,18 @@
return rep
def visit_Name(self, name):
- # Turn loading None into a constant lookup. Eventaully, we can do this
- # for True and False, too.
- if name.id == "None":
- assert name.ctx == ast.Load
- return ast.Const(self.space.w_None, name.lineno, name.col_offset)
+ """Turn loading None, True, and False into a constant lookup."""
+ space = self.space
+ iden = name.id
+ w_const = None
+ if iden == "None":
+ w_const = space.w_None
+ elif iden == "True":
+ w_const = space.w_True
+ elif iden == "False":
+ w_const = space.w_False
+ if w_const is not None:
+ return ast.Const(w_const, name.lineno, name.col_offset)
return name
def visit_Tuple(self, tup):
diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -356,6 +356,11 @@
args = func.args
assert isinstance(args, ast.arguments)
self.visit_sequence(args.defaults)
+ if args.kw_defaults:
+ for arg in args.kw_defaults:
+ if arg:
+ arg.walkabout(self)
+ self._visit_annotations(func)
self.visit_sequence(func.decorator_list)
new_scope = FunctionScope(func.name, func.lineno, func.col_offset)
self.push_scope(new_scope, func)
@@ -443,7 +448,6 @@
misc.syntax_warning(self.space, msg, self.compile_info.filename,
nonl.lineno, nonl.col_offset)
self.note_symbol(name, SYM_NONLOCAL)
-
def visit_Lambda(self, lamb):
args = lamb.args
@@ -501,11 +505,26 @@
def _handle_params(self, params, is_toplevel):
for i in range(len(params)):
- arg = params[i]
- if isinstance(arg, ast.Name):
- self.note_symbol(arg.id, SYM_PARAM)
- else:
- raise AssertionError("unknown parameter type")
+ arg = params[i].arg
+ self.note_symbol(arg, SYM_PARAM)
+
+ def _visit_annotations(self, func):
+ args = func.args
+ if args.args:
+ self._visit_arg_annotations(args.args)
+ if args.varargannotation:
+ args.varargannotation.walkabout(self)
+ if args.kwargannotation:
+ args.kwargannotation.walkabout(self)
+ if args.kwonlyargs:
+ self._visit_arg_annotations(args.kwonlyargs)
+ if func.returns:
+ func.returns.walkabout(self)
+
+ def _visit_arg_annotations(self, args):
+ for arg in args:
+ if arg.annotation:
+ arg.annotation.walkabout(self)
def visit_Name(self, name):
if name.ctx == ast.Load:
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -478,43 +478,40 @@
assert args.defaults is None
assert args.kwarg is None
assert args.vararg is None
+ assert func.returns is None
args = self.get_first_stmt("def f(a, b): pass").args
assert len(args.args) == 2
a1, a2 = args.args
- assert isinstance(a1, ast.Name)
- assert a1.id == "a"
- assert a1.ctx == ast.Param
- assert isinstance(a2, ast.Name)
- assert a2.id == "b"
- assert a2.ctx == ast.Param
+ assert isinstance(a1, ast.arg)
+ assert a1.arg == "a"
+ assert isinstance(a2, ast.arg)
+ assert a2.arg == "b"
assert args.vararg is None
assert args.kwarg is None
args = self.get_first_stmt("def f(a=b): pass").args
assert len(args.args) == 1
arg = args.args[0]
- assert isinstance(arg, ast.Name)
- assert arg.id == "a"
- assert arg.ctx == ast.Param
+ assert isinstance(arg, ast.arg)
+ assert arg.arg == "a"
assert len(args.defaults) == 1
default = args.defaults[0]
assert isinstance(default, ast.Name)
assert default.id == "b"
assert default.ctx == ast.Load
args = self.get_first_stmt("def f(*a): pass").args
- assert args.args is None
- assert args.defaults is None
+ assert not args.args
+ assert not args.defaults
assert args.kwarg is None
assert args.vararg == "a"
args = self.get_first_stmt("def f(**a): pass").args
- assert args.args is None
- assert args.defaults is None
+ assert not args.args
+ assert not args.defaults
assert args.vararg is None
assert args.kwarg == "a"
args = self.get_first_stmt("def f(a, b, c=d, *e, **f): pass").args
assert len(args.args) == 3
for arg in args.args:
- assert isinstance(arg, ast.Name)
- assert arg.ctx == ast.Param
+ assert isinstance(arg, ast.arg)
assert len(args.defaults) == 1
assert isinstance(args.defaults[0], ast.Name)
assert args.defaults[0].ctx == ast.Load
@@ -524,6 +521,65 @@
exc = py.test.raises(SyntaxError, self.get_ast, input).value
assert exc.msg == "non-default argument follows default argument"
+ def test_kwonly_arguments(self):
+ fn = self.get_first_stmt("def f(a, b, c, *, kwarg): pass")
+ assert isinstance(fn, ast.FunctionDef)
+ assert len(fn.args.kwonlyargs) == 1
+ assert isinstance(fn.args.kwonlyargs[0], ast.arg)
+ assert fn.args.kwonlyargs[0].arg == "kwarg"
+ assert fn.args.kw_defaults == [None]
+ fn = self.get_first_stmt("def f(a, b, c, *args, kwarg): pass")
+ assert isinstance(fn, ast.FunctionDef)
+ assert len(fn.args.kwonlyargs) == 1
+ assert isinstance(fn.args.kwonlyargs[0], ast.arg)
+ assert fn.args.kwonlyargs[0].arg == "kwarg"
+ assert fn.args.kw_defaults == [None]
+ fn = self.get_first_stmt("def f(a, b, c, *, kwarg=2): pass")
+ assert isinstance(fn, ast.FunctionDef)
+ assert len(fn.args.kwonlyargs) == 1
+ assert isinstance(fn.args.kwonlyargs[0], ast.arg)
+ assert fn.args.kwonlyargs[0].arg == "kwarg"
+ assert len(fn.args.kw_defaults) == 1
+ assert isinstance(fn.args.kw_defaults[0], ast.Num)
+ input = "def f(p1, *, **k1): pass"
+ exc = py.test.raises(SyntaxError, self.get_ast, input).value
+ assert exc.msg == "named arguments must follows bare *"
+
+ def test_function_annotation(self):
+ func = self.get_first_stmt("def f() -> X: pass")
+ assert isinstance(func.returns, ast.Name)
+ assert func.returns.id == "X"
+ assert func.returns.ctx == ast.Load
+ for stmt in "def f(x : 42): pass", "def f(x : 42=a): pass":
+ func = self.get_first_stmt(stmt)
+ assert isinstance(func.args.args[0].annotation, ast.Num)
+ assert isinstance(func.args.defaults[0], ast.Name)
+ func = self.get_first_stmt("def f(*x : 42): pass")
+ assert isinstance(func.args.varargannotation, ast.Num)
+ func = self.get_first_stmt("def f(**kw : 42): pass")
+ assert isinstance(func.args.kwargannotation, ast.Num)
+ func = self.get_first_stmt("def f(*, kw : 42=a): pass")
+ assert isinstance(func.args.kwonlyargs[0].annotation, ast.Num)
+
+ def test_lots_of_kwonly_arguments(self):
+ fundef = "def f("
+ for i in range(255):
+ fundef += "i%d, "%i
+ fundef += "*, key=100):\n pass\n"
+ py.test.raises(SyntaxError, self.get_first_stmt, fundef)
+
+ fundef2 = "def foo(i,*,"
+ for i in range(255):
+ fundef2 += "i%d, "%i
+ fundef2 += "lastarg):\n pass\n"
+ py.test.raises(SyntaxError, self.get_first_stmt, fundef)
+
+ fundef3 = "def f(i,*,"
+ for i in range(253):
+ fundef3 += "i%d, "%i
+ fundef3 += "lastarg):\n pass\n"
+ self.get_first_stmt(fundef3)
+
def test_decorators(self):
to_examine = (("def f(): pass", ast.FunctionDef),
("class x: pass", ast.ClassDef))
@@ -712,6 +768,7 @@
("{1, 2, 3}", "literal"),
("(x > 4)", "comparison"),
("(x if y else a)", "conditional expression"),
+ ("...", "Ellipsis"),
)
test_contexts = (
("assign to", "%s = 23"),
@@ -741,15 +798,11 @@
"from x import y as %s",
"for %s in x: pass",
)
- for name in ("None", "__debug__"):
+ for name in "__debug__",:
for template in invalid:
input = template % (name,)
exc = py.test.raises(SyntaxError, self.get_ast, input).value
assert exc.msg == "cannot assign to %s" % (name,)
- # This is ok.
- self.get_ast("from None import x")
- self.get_ast("from x import None as y")
- self.get_ast("import None as x")
def test_lambda(self):
lam = self.get_first_expr("lambda x: expr")
@@ -758,13 +811,13 @@
assert isinstance(args, ast.arguments)
assert args.vararg is None
assert args.kwarg is None
- assert args.defaults is None
+ assert not args.defaults
assert len(args.args) == 1
- assert isinstance(args.args[0], ast.Name)
+ assert isinstance(args.args[0], ast.arg)
assert isinstance(lam.body, ast.Name)
lam = self.get_first_expr("lambda: True")
args = lam.args
- assert args.args is None
+ assert not args.args
lam = self.get_first_expr("lambda x=x: y")
assert len(lam.args.args) == 1
assert len(lam.args.defaults) == 1
@@ -1023,8 +1076,6 @@
slc = self.get_first_expr("x[1:2:3]").slice
for field in (slc.lower, slc.upper, slc.step):
assert isinstance(field, ast.Num)
- sub = self.get_first_expr("x[...]")
- assert isinstance(sub.slice, ast.Ellipsis)
sub = self.get_first_expr("x[1,2,3]")
slc = sub.slice
assert isinstance(slc, ast.Index)
@@ -1040,6 +1091,12 @@
assert isinstance(complex_slc.upper, ast.Num)
assert complex_slc.step is None
+ def test_ellipsis(self):
+ e = self.get_first_expr("...")
+ assert isinstance(e, ast.Ellipsis)
+ sub = self.get_first_expr("x[...]")
+ assert isinstance(sub.slice.value, ast.Ellipsis)
+
def test_string(self):
space = self.space
s = self.get_first_expr("'hi'")
@@ -1199,17 +1256,3 @@
if1, if2 = comps[0].ifs
assert isinstance(if1, ast.Name)
assert isinstance(if2, ast.Name)
-
- def test_kwonly_arguments(self):
- fn = self.get_first_stmt("def f(a, b, c, *, kwarg): pass")
- assert isinstance(fn, ast.FunctionDef)
- assert len(fn.args.kwonlyargs) == 1
- assert isinstance(fn.args.kwonlyargs[0], ast.expr)
- assert fn.args.kwonlyargs[0].id == "kwarg"
-
- def test_kwonly_arguments_2(self):
- fn = self.get_first_stmt("def f(a, b, c, *args, kwarg): pass")
- assert isinstance(fn, ast.FunctionDef)
- assert len(fn.args.kwonlyargs) == 1
- assert isinstance(fn.args.kwonlyargs[0], ast.expr)
- assert fn.args.kwonlyargs[0].id == "kwarg"
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -716,6 +716,15 @@
decl = str(decl) + '\n'
yield self.simple_test, decl, 'r', None
+ def test_assert(self):
+ decl = py.code.Source("""
+ try:
+ assert 0, 'hi'
+ except AssertionError as e:
+ msg = str(e)
+ """)
+ yield self.simple_test, decl, 'msg', 'hi'
+
def test_indentation_error(self):
source = py.code.Source("""
x
@@ -818,12 +827,34 @@
yield self.st, test, "f()", 42
# This line is needed for py.code to find the source.
- def test_tuple_unpacking(self):
+ def test_extended_unpacking(self):
func = """def f():
(a, *b, c) = 1, 2, 3, 4, 5
return a, b, c
"""
yield self.st, func, "f()", (1, [2, 3, 4], 5)
+ func = """def f():
+ [a, *b, c] = 1, 2, 3, 4, 5
+ return a, b, c
+ """
+ yield self.st, func, "f()", (1, [2, 3, 4], 5)
+ func = """def f():
+ *a, = [1, 2, 3]
+ return a
+ """
+ yield self.st, func, "f()", [1, 2, 3]
+ func = """def f():
+ for a, *b, c in [(1, 2, 3, 4)]:
+ return a, b, c
+ """
+ yield self.st, func, "f()", (1, [2, 3], 4)
+ py.test.raises(SyntaxError, self.simple_test, "*a, *b = [1, 2]",
+ None, None)
+ py.test.raises(SyntaxError, self.simple_test, "a = [*b, c]",
+ None, None)
+ py.test.raises(SyntaxError, self.simple_test, "for *a in x: pass",
+ None, None)
+
class AppTestCompiler:
diff --git a/pypy/interpreter/astcompiler/test/test_symtable.py b/pypy/interpreter/astcompiler/test/test_symtable.py
--- a/pypy/interpreter/astcompiler/test/test_symtable.py
+++ b/pypy/interpreter/astcompiler/test/test_symtable.py
@@ -68,12 +68,24 @@
assert exc.msg == "duplicate argument 'x' in function definition"
def test_function_defaults(self):
- scp = self.mod_scope("y = 4\ndef f(x=y): return x")
+ scp = self.mod_scope("y = w = 4\ndef f(x=y, *, z=w): return x")
self.check_unknown(scp, "x")
+ self.check_unknown(scp, "z")
assert scp.lookup("y") == symtable.SCOPE_LOCAL
+ assert scp.lookup("w") == symtable.SCOPE_LOCAL
scp = scp.children[0]
assert scp.lookup("x") == symtable.SCOPE_LOCAL
+ assert scp.lookup("z") == symtable.SCOPE_LOCAL
self.check_unknown(scp, "y")
+ self.check_unknown(scp, "w")
+
+ def test_function_annotations(self):
+ scp = self.mod_scope("def f(x : X) -> Y: pass")
+ assert scp.lookup("X") == symtable.SCOPE_GLOBAL_IMPLICIT
+ assert scp.lookup("Y") == symtable.SCOPE_GLOBAL_IMPLICIT
+ scp = scp.children[0]
+ self.check_unknown(scp, "X")
+ self.check_unknown(scp, "Y")
def check_comprehension(self, template):
def brack(s):
@@ -126,9 +138,13 @@
assert scp.lookup("x") == symtable.SCOPE_LOCAL
def test_arguments_kwonly(self):
- scp = self.func_scope("def f(a, *, b): pass")
- for name in ("a", "b"):
+ scp = self.func_scope("def f(a, *b, c, **d): pass")
+ varnames = ["a", "c", "b", "d"]
+ for name in varnames:
assert scp.lookup(name) == symtable.SCOPE_LOCAL
+ assert scp.varnames == varnames
+ scp = self.func_scope("def f(a, b=0, *args, k1, k2=0): pass")
+ assert scp.varnames == ["a", "b", "k1", "k2", "args"]
def test_function(self):
scp = self.func_scope("def f(): x = 4")
diff --git a/pypy/interpreter/astcompiler/tools/Python.asdl b/pypy/interpreter/astcompiler/tools/Python.asdl
--- a/pypy/interpreter/astcompiler/tools/Python.asdl
+++ b/pypy/interpreter/astcompiler/tools/Python.asdl
@@ -1,6 +1,6 @@
-- ASDL's four builtin types are identifier, int, string, object
-module Python version "$Revision: 43614 $"
+module Python version "$Revision$"
{
mod = Module(stmt* body)
| Interactive(stmt* body)
@@ -10,7 +10,7 @@
| Suite(stmt* body)
stmt = FunctionDef(identifier name, arguments args,
- stmt* body, expr* decorator_list)
+ stmt* body, expr* decorator_list, expr? returns)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
@@ -68,7 +68,8 @@
expr? starargs, expr? kwargs)
| Num(object n) -- a number as a PyObject.
| Str(string s) -- need to specify raw, unicode, etc?
- | Bytes(string s)
+ | Bytes(string s)
+ | Ellipsis
-- other literals? bools?
-- the following expression can appear in assignment context
@@ -79,15 +80,15 @@
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
- -- PyPy modification
- | Const(object value)
+ -- PyPy modification
+ | Const(object value)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset)
expr_context = Load | Store | Del | AugLoad | AugStore | Param
- slice = Ellipsis | Slice(expr? lower, expr? upper, expr? step)
+ slice = Slice(expr? lower, expr? upper, expr? step)
| ExtSlice(slice* dims)
| Index(expr value)
@@ -106,8 +107,11 @@
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset)
- arguments = (expr* args, identifier? vararg, expr* kwonlyargs,
- identifier? kwarg, expr* defaults)
+ arguments = (arg* args, identifier? vararg, expr? varargannotation,
+ arg* kwonlyargs, identifier? kwarg,
+ expr? kwargannotation, expr* defaults,
+ expr* kw_defaults)
+ arg = (identifier arg, expr? annotation)
-- keyword arguments supplied to call
keyword = (identifier arg, expr value)
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -227,7 +227,8 @@
self.emit("")
self.emit("def _mutate_sequence(self, seq):", 1)
self.emit("for i in range(len(seq)):", 2)
- self.emit("seq[i] = seq[i].mutate_over(self)", 3)
+ self.emit("if seq[i] is not None:", 3)
+ self.emit("seq[i] = seq[i].mutate_over(self)", 4)
self.emit("")
super(ASTVisitorVisitor, self).visitModule(mod)
self.emit("")
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -34,8 +34,8 @@
'defs_w?[*]',
'name?']
- def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
- forcename=None):
+ def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
+ closure=None, w_ann=None, forcename=None):
self.space = space
self.name = forcename or code.co_name
self.w_doc = None # lazily read from code.getdocstring()
@@ -43,8 +43,10 @@
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
self.defs_w = defs_w
+ self.w_kw_defs = w_kw_defs
self.w_func_dict = None # filled out below if needed
self.w_module = None
+ self.w_ann = w_ann
def __repr__(self):
# return "function %s.%s" % (self.space, self.name)
@@ -223,7 +225,8 @@
raise OperationError(space.w_ValueError, space.wrap("closure is wrong size"))
closure = [space.interp_w(Cell, w_cell) for w_cell in closure_w]
func = space.allocate_instance(Function, w_subtype)
- Function.__init__(func, space, code, w_globals, defs_w, closure, name)
+ Function.__init__(func, space, code, w_globals, defs_w, None, closure,
+ None,name)
return space.wrap(func)
def descr_function_call(self, __args__):
@@ -352,6 +355,22 @@
def fdel_func_defaults(self, space):
self.defs_w = []
+ def fget_func_kwdefaults(self, space):
+ if self.w_kw_defs is None:
+ return space.w_None
+ return self.w_kw_defs
+
+ def fset_func_kwdefaults(self, space, w_new):
+ if space.is_w(w_new, space.w_None):
+ w_new = None
+ elif not space.isinstance_w(w_new, space.w_dict):
+ msg = "__kwdefaults__ must be a dict"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ self.w_kw_defs = w_new
+
+ def fdel_func_kwdefaults(self, space):
+ self.w_kw_defs = None
+
def fget_func_doc(self, space):
if self.w_doc is None:
self.w_doc = self.code.getdocstring(space)
@@ -416,6 +435,22 @@
w_res = space.w_None
return w_res
+ def fget_func_annotations(self, space):
+ if self.w_ann is None:
+ self.w_ann = space.newdict()
+ return self.w_ann
+
+ def fset_func_annotations(self, space, w_new):
+ if space.is_w(w_new, space.w_None):
+ w_new = None
+ elif not space.isinstance_w(w_new, space.w_dict):
+ msg = "__annotations__ must be a dict"
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ self.w_ann = w_new
+
+ def fdel_func_annotations(self, space):
+ self.w_ann = None
+
def descr_function_get(space, w_function, w_obj, w_cls=None):
"""functionobject.__get__(obj[, type]) -> method"""
# this is not defined as a method on Function because it's generally
@@ -552,7 +587,7 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs_w, func.closure, func.name)
+ func.defs_w, None, func.closure, None, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -617,7 +617,7 @@
space = func.space
activation = self.activation
scope_w = args.parse_obj(w_obj, func.name, self.sig,
- func.defs_w, self.minargs)
+ func.defs_w, func.w_kw_defs, self.minargs)
try:
w_result = activation._run(space, scope_w)
except DescrMismatch:
@@ -913,18 +913,12 @@
self.filename = filename
self.source = str(py.code.Source(source).deindent())
self.modname = modname
- # look at the first three lines for a NOT_RPYTHON tag
- first = "\n".join(source.split("\n", 3)[:3])
- if "NOT_RPYTHON" in first:
- self.can_use_geninterp = False
- else:
- self.can_use_geninterp = True
# make source code available for tracebacks
lines = [x + "\n" for x in source.split("\n")]
py.std.linecache.cache[filename] = (1, None, lines, filename)
def __repr__(self):
- return "<ApplevelClass filename=%r can_use_geninterp=%r>" % (self.filename, self.can_use_geninterp)
+ return "<ApplevelClass filename=%r>" % (self.filename,)
def getwdict(self, space):
return space.fromcache(ApplevelCache).getorbuild(self)
@@ -985,10 +979,7 @@
def build(self, app):
"NOT_RPYTHON. Called indirectly by Applevel.getwdict()."
- if self.space.config.objspace.geninterp and app.can_use_geninterp:
- return PyPyCacheDir.build_applevelinterp_dict(app, self.space)
- else:
- return build_applevel_dict(app, self.space)
+ return build_applevel_dict(app, self.space)
# __________ pure applevel version __________
@@ -1002,157 +993,6 @@
filename=self.filename)
return w_glob
-# __________ geninterplevel version __________
-
-class PyPyCacheDir:
- "NOT_RPYTHON"
- # similar to applevel, but using translation to interp-level.
- # This version maintains a cache folder with single files.
-
- def build_applevelinterp_dict(cls, self, space):
- "NOT_RPYTHON"
- # N.B. 'self' is the ApplevelInterp; this is a class method,
- # just so that we have a convenient place to store the global state.
- if not cls._setup_done:
- cls._setup()
-
- from pypy.translator.geninterplevel import translate_as_module
- import marshal
- scramble = md5(cls.seed)
- scramble.update(marshal.dumps(self.source))
- key = scramble.hexdigest()
- initfunc = cls.known_code.get(key)
- if not initfunc:
- # try to get it from file
- name = key
- if self.filename:
- prename = os.path.splitext(os.path.basename(self.filename))[0]
- else:
- prename = 'zznoname'
- name = "%s_%s" % (prename, name)
- try:
- __import__("pypy._cache."+name)
- except ImportError, x:
- # print x
- pass
- else:
- initfunc = cls.known_code[key]
- if not initfunc:
- # build it and put it into a file
- initfunc, newsrc = translate_as_module(
- self.source, self.filename, self.modname)
- fname = cls.cache_path.join(name+".py").strpath
- f = file(get_tmp_file_name(fname), "w")
- print >> f, """\
-# self-destruct on double-click:
-if __name__ == "__main__":
- from pypy import _cache
- import os
- namestart = os.path.join(os.path.split(_cache.__file__)[0], '%s')
- for ending in ('.py', '.pyc', '.pyo'):
- try:
- os.unlink(namestart+ending)
- except os.error:
- pass""" % name
- print >> f
- print >> f, newsrc
- print >> f, "from pypy._cache import known_code"
- print >> f, "known_code[%r] = %s" % (key, initfunc.__name__)
- f.close()
- rename_tmp_to_eventual_file_name(fname)
- w_glob = initfunc(space)
- return w_glob
- build_applevelinterp_dict = classmethod(build_applevelinterp_dict)
-
- _setup_done = False
-
- def _setup(cls):
- """NOT_RPYTHON"""
- lp = py.path.local
- import pypy, os
- p = lp(pypy.__file__).new(basename='_cache').ensure(dir=1)
- cls.cache_path = p
- ini = p.join('__init__.py')
- try:
- if not ini.check():
- raise ImportError # don't import if only a .pyc file left!!!
- from pypy._cache import known_code, \
- GI_VERSION_RENDERED
- except ImportError:
- GI_VERSION_RENDERED = 0
- from pypy.translator.geninterplevel import GI_VERSION
- cls.seed = md5(str(GI_VERSION)).digest()
- if GI_VERSION != GI_VERSION_RENDERED or GI_VERSION is None:
- for pth in p.listdir():
- if pth.check(file=1):
- try:
- pth.remove()
- except: pass
- f = file(get_tmp_file_name(str(ini)), "w")
- f.write("""\
-# This folder acts as a cache for code snippets which have been
-# compiled by compile_as_module().
-# It will get a new entry for every piece of code that has
-# not been seen, yet.
-#
-# Caution! Only the code snippet is checked. If something
-# is imported, changes are not detected. Also, changes
-# to geninterplevel or gateway are also not checked.
-# Exception: There is a checked version number in geninterplevel.py
-#
-# If in doubt, remove this file from time to time.
-
-GI_VERSION_RENDERED = %r
-
-known_code = {}
-
-# self-destruct on double-click:
-def harakiri():
- import pypy._cache as _c
- import py
- lp = py.path.local
- for pth in lp(_c.__file__).dirpath().listdir():
- try:
- pth.remove()
- except: pass
-
-if __name__ == "__main__":
- harakiri()
-
-del harakiri
-""" % GI_VERSION)
- f.close()
- rename_tmp_to_eventual_file_name(str(ini))
- import pypy._cache
- cls.known_code = pypy._cache.known_code
- cls._setup_done = True
- _setup = classmethod(_setup)
-
-
-def gethostname(_cache=[]):
- if not _cache:
- try:
- import socket
- hostname = socket.gethostname()
- except:
- hostname = ''
- _cache.append(hostname)
- return _cache[0]
-
-def get_tmp_file_name(fname):
- return '%s~%s~%d' % (fname, gethostname(), os.getpid())
-
-def rename_tmp_to_eventual_file_name(fname):
- # generated files are first written to the host- and process-specific
- # file 'tmpname', and then atomically moved to their final 'fname'
- # to avoid problems if py.py is started several times in parallel
- tmpname = get_tmp_file_name(fname)
- try:
- os.rename(tmpname, fname)
- except (OSError, IOError):
- os.unlink(fname) # necessary on Windows
- os.rename(tmpname, fname)
-
# ____________________________________________________________
def appdef(source, applevel=ApplevelClass, filename=None):
@@ -1190,11 +1030,6 @@
return build_applevel_dict(self, space)
-class applevelinterp_temp(ApplevelClass):
- hidden_applevel = False
- def getwdict(self, space): # no cache
- return PyPyCacheDir.build_applevelinterp_dict(self, space)
-
# app2interp_temp is used for testing mainly
def app2interp_temp(func, applevel_temp=applevel_temp, filename=None):
""" NOT_RPYTHON """
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -224,13 +224,8 @@
raise NotImplementedError
@jit.unroll_safe
- def MAKE_CLOSURE(self, numdefaults, next_instr):
- w_codeobj = self.popvalue()
- codeobj = self.space.interp_w(pycode.PyCode, w_codeobj)
- w_freevarstuple = self.popvalue()
+ def MAKE_CLOSURE(self, oparg, next_instr):
+ w_freevarstuple = self.peekvalue(1)
freevars = [self.space.interp_w(Cell, cell)
for cell in self.space.fixedview(w_freevarstuple)]
- defaultarguments = self.popvalues(numdefaults)
- fn = function.Function(self.space, codeobj, self.w_globals,
- defaultarguments, freevars)
- self.pushvalue(self.space.wrap(fn))
+ self._make_function(oparg, freevars)
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -50,8 +50,7 @@
assert argcount >= 0 # annotator hint
assert kwonlyargcount >= 0
argnames = list(code.co_varnames[:argcount])
- n = argcount + kwonlyargcount
- kwonlyargs = list(code.co_varnames[argcount:n])
+ kwonlyargs = list(code.co_varnames[argcount:argcount + kwonlyargcount])
if code.co_flags & CO_VARARGS:
varargname = code.co_varnames[argcount]
argcount += 1
@@ -225,7 +224,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(None, fresh_frame.locals_stack_w,
func.name,
- sig, func.defs_w)
+ sig, func.defs_w, func.w_kw_defs)
fresh_frame.init_cells()
return frame.run()
@@ -238,7 +237,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(w_obj, fresh_frame.locals_stack_w,
func.name,
- sig, func.defs_w)
+ sig, func.defs_w, func.w_kw_defs)
fresh_frame.init_cells()
return frame.run()
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -584,6 +584,7 @@
items = self.space.fixedview_unroll(w_iterable, itemcount)
self.pushrevvalues(itemcount, items)
+ @jit.unroll_safe
def UNPACK_EX(self, oparg, next_instr):
"a, *b, c = range(10)"
left = oparg & 0xFF
@@ -990,13 +991,36 @@
w_varargs = self.popvalue()
self.call_function(oparg, w_varargs, w_varkw)
- def MAKE_FUNCTION(self, numdefaults, next_instr):
+ def _make_function(self, oparg, freevars=None):
+ space = self.space
w_codeobj = self.popvalue()
codeobj = self.space.interp_w(PyCode, w_codeobj)
- defaultarguments = self.popvalues(numdefaults)
- fn = function.Function(self.space, codeobj, self.w_globals,
- defaultarguments)
- self.pushvalue(self.space.wrap(fn))
+ if freevars is not None:
+ # Pop freevars
+ self.popvalue()
+ posdefaults = oparg & 0xFF
+ kwdefaults = (oparg >> 8) & 0xFF
+ num_annotations = (oparg >> 16) & 0xFF
+ w_ann = None
+ if num_annotations:
+ names_w = space.fixedview(self.popvalue())
+ w_ann = space.newdict(strdict=True)
+ for i in range(len(names_w) - 1, -1, -1):
+ space.setitem(w_ann, names_w[i], self.popvalue())
+ defaultarguments = self.popvalues(posdefaults)
+ w_kw_defs = None
+ if kwdefaults:
+ w_kw_defs = space.newdict(strdict=True)
+ for i in range(kwdefaults - 1, -1, -1):
+ w_name = self.popvalue()
+ w_def = self.popvalue()
+ space.setitem(w_kw_defs, w_def, w_name)
+ fn = function.Function(space, codeobj, self.w_globals, defaultarguments,
+ w_kw_defs, freevars, w_ann)
+ self.pushvalue(space.wrap(fn))
+
+ def MAKE_FUNCTION(self, oparg, next_instr):
+ return self._make_function(oparg)
def BUILD_SLICE(self, numargs, next_instr):
if numargs == 3:
@@ -1414,11 +1438,9 @@
if lastchar.isspace() and lastchar != ' ':
return
file_softspace(stream, True)
- print_item_to._annspecialcase_ = "specialize:argtype(0)"
def print_item(x):
print_item_to(x, sys_stdout())
- print_item._annspecialcase_ = "flowspace:print_item"
def print_newline_to(stream):
stream.write("\n")
@@ -1426,7 +1448,6 @@
def print_newline():
print_newline_to(sys_stdout())
- print_newline._annspecialcase_ = "flowspace:print_newline"
def file_softspace(file, newflag):
try:
diff --git a/pypy/interpreter/pyparser/data/Grammar3.2 b/pypy/interpreter/pyparser/data/Grammar3.2
--- a/pypy/interpreter/pyparser/data/Grammar3.2
+++ b/pypy/interpreter/pyparser/data/Grammar3.2
@@ -22,7 +22,7 @@
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef)
-funcdef: 'def' NAME parameters ':' suite
+funcdef: 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])* [','
['*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef] | '**' tfpdef]]
@@ -53,7 +53,8 @@
raise_stmt: 'raise' [test ['from' test]]
import_stmt: import_name | import_from
import_name: 'import' dotted_as_names
-import_from: ('from' ('.'* dotted_name | '.'+)
+# note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
+import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
'import' ('*' | '(' import_as_names ')' | import_as_names))
import_as_name: NAME ['as' NAME]
dotted_as_name: dotted_name ['as' NAME]
@@ -79,20 +80,16 @@
except_clause: 'except' [test ['as' NAME]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
-# Backward compatibility cruft to support:
-# [ x for x in lambda: True, lambda: False if x() ]
-# even while also allowing:
-# lambda x: 5 if x else 2
-# (But not a mix of the two)
-testlist_safe: old_test [(',' old_test)+ [',']]
-old_test: or_test | old_lambdef
-old_lambdef: 'lambda' [varargslist] ':' old_test
-
test: or_test ['if' or_test 'else' test] | lambdef
+test_nocond: or_test | lambdef_nocond
+lambdef: 'lambda' [varargslist] ':' test
+lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison
comparison: expr (comp_op expr)*
+# <> isn't actually a valid comparison operator in Python. It's here for the
+# sake of a __future__ import described in PEP 401
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
star_expr: '*' expr
expr: xor_expr ('|' xor_expr)*
@@ -106,16 +103,14 @@
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
- NAME | NUMBER | STRING+)
+ NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
-lambdef: 'lambda' [varargslist] ':' test
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
-subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
+subscript: test | [test] ':' [test] [sliceop]
sliceop: ':' [test]
-exprlist: expr (',' expr)* [',']
+exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
testlist: test (',' test)* [',']
-dictmaker: test ':' test (',' test ':' test)* [',']
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
(test (comp_for | (',' test)* [','])) )
@@ -126,12 +121,10 @@
|'**' test)
# The reason that keywords are test nodes instead of NAME is that using NAME
# results in an ambiguity. ast.c makes sure it's a NAME.
-argument: test [comp_for] | test '=' test
+argument: test [comp_for] | test '=' test # Really [keyword '='] test
comp_iter: comp_for | comp_if
comp_for: 'for' exprlist 'in' or_test [comp_iter]
-comp_if: 'if' old_test [comp_iter]
-
-testlist1: test (',' test)*
+comp_if: 'if' test_nocond [comp_iter]
# not used in grammar, but may appear in "node" passed from Parser to Compiler
encoding_decl: NAME
diff --git a/pypy/interpreter/pyparser/dfa_generated.py b/pypy/interpreter/pyparser/dfa_generated.py
--- a/pypy/interpreter/pyparser/dfa_generated.py
+++ b/pypy/interpreter/pyparser/dfa_generated.py
@@ -5,38 +5,39 @@
from pypy.interpreter.pyparser import automata
accepts = [True, True, True, True, True, True, True, True,
- True, True, False, True, True, True, True, False,
- False, False, True, False, False, False, True,
- False, True, False, True, False, True, False,
- False, True, False, False, True, True, True,
- False, False, True, False, False, False, True]
+ True, True, False, True, True, True, True, True,
+ False, False, False, True, False, False, False,
+ True, False, True, False, True, False, False,
+ True, False, False, True, False, False, True,
+ True, True, False, False, True, False, False,
+ False, True]
states = [
# 0
- {'\t': 0, '\n': 13, '\x0c': 0,
- '\r': 14, ' ': 0, '!': 10, '"': 16,
- '#': 18, '%': 12, '&': 12, "'": 15,
- '(': 13, ')': 13, '*': 7, '+': 12,
- ',': 13, '-': 12, '.': 6, '/': 11,
+ {'\t': 0, '\n': 14, '\x0c': 0,
+ '\r': 15, ' ': 0, '!': 10, '"': 17,
+ '#': 19, '%': 13, '&': 13, "'": 16,
+ '(': 14, ')': 14, '*': 7, '+': 13,
+ ',': 14, '-': 11, '.': 6, '/': 12,
'0': 4, '1': 5, '2': 5, '3': 5,
'4': 5, '5': 5, '6': 5, '7': 5,
- '8': 5, '9': 5, ':': 13, ';': 13,
- '<': 9, '=': 12, '>': 8, '@': 13,
+ '8': 5, '9': 5, ':': 14, ';': 14,
+ '<': 9, '=': 13, '>': 8, '@': 14,
'A': 1, 'B': 2, 'C': 1, 'D': 1,
'E': 1, 'F': 1, 'G': 1, 'H': 1,
'I': 1, 'J': 1, 'K': 1, 'L': 1,
'M': 1, 'N': 1, 'O': 1, 'P': 1,
'Q': 1, 'R': 3, 'S': 1, 'T': 1,
'U': 1, 'V': 1, 'W': 1, 'X': 1,
- 'Y': 1, 'Z': 1, '[': 13, '\\': 17,
- ']': 13, '^': 12, '_': 1, '`': 13,
+ 'Y': 1, 'Z': 1, '[': 14, '\\': 18,
+ ']': 14, '^': 13, '_': 1, '`': 14,
'a': 1, 'b': 2, 'c': 1, 'd': 1,
'e': 1, 'f': 1, 'g': 1, 'h': 1,
'i': 1, 'j': 1, 'k': 1, 'l': 1,
'm': 1, 'n': 1, 'o': 1, 'p': 1,
'q': 1, 'r': 3, 's': 1, 't': 1,
'u': 1, 'v': 1, 'w': 1, 'x': 1,
- 'y': 1, 'z': 1, '{': 13, '|': 12,
- '}': 13, '~': 13},
+ 'y': 1, 'z': 1, '{': 14, '|': 13,
+ '}': 14, '~': 14},
# 1
{'0': 1, '1': 1, '2': 1, '3': 1,
'4': 1, '5': 1, '6': 1, '7': 1,
@@ -55,7 +56,7 @@
't': 1, 'u': 1, 'v': 1, 'w': 1,
'x': 1, 'y': 1, 'z': 1},
# 2
- {'"': 16, "'": 15, '0': 1, '1': 1,
+ {'"': 17, "'": 16, '0': 1, '1': 1,
'2': 1, '3': 1, '4': 1, '5': 1,
'6': 1, '7': 1, '8': 1, '9': 1,
'A': 1, 'B': 1, 'C': 1, 'D': 1,
@@ -73,7 +74,7 @@
'v': 1, 'w': 1, 'x': 1, 'y': 1,
'z': 1},
# 3
- {'"': 16, "'": 15, '0': 1, '1': 1,
+ {'"': 17, "'": 16, '0': 1, '1': 1,
'2': 1, '3': 1, '4': 1, '5': 1,
'6': 1, '7': 1, '8': 1, '9': 1,
'A': 1, 'B': 1, 'C': 1, 'D': 1,
@@ -91,137 +92,141 @@
'v': 1, 'w': 1, 'x': 1, 'y': 1,
'z': 1},
# 4
- {'.': 24, '0': 22, '1': 23, '2': 23,
- '3': 23, '4': 23, '5': 23, '6': 23,
- '7': 23, '8': 23, '9': 23, 'B': 21,
- 'E': 25, 'J': 13, 'O': 20, 'X': 19,
- 'b': 21, 'e': 25, 'j': 13, 'o': 20,
- 'x': 19},
+ {'.': 25, '0': 23, '1': 24, '2': 24,
+ '3': 24, '4': 24, '5': 24, '6': 24,
+ '7': 24, '8': 24, '9': 24, 'B': 22,
+ 'E': 26, 'J': 14, 'O': 21, 'X': 20,
+ 'b': 22, 'e': 26, 'j': 14, 'o': 21,
+ 'x': 20},
# 5
- {'.': 24, '0': 5, '1': 5, '2': 5,
+ {'.': 25, '0': 5, '1': 5, '2': 5,
'3': 5, '4': 5, '5': 5, '6': 5,
- '7': 5, '8': 5, '9': 5, 'E': 25,
- 'J': 13, 'e': 25, 'j': 13},
+ '7': 5, '8': 5, '9': 5, 'E': 26,
+ 'J': 14, 'e': 26, 'j': 14},
# 6
- {'0': 26, '1': 26, '2': 26, '3': 26,
- '4': 26, '5': 26, '6': 26, '7': 26,
- '8': 26, '9': 26},
+ {'.': 28, '0': 27, '1': 27, '2': 27,
+ '3': 27, '4': 27, '5': 27, '6': 27,
+ '7': 27, '8': 27, '9': 27},
# 7
- {'*': 12, '=': 13},
+ {'*': 13, '=': 14},
# 8
- {'=': 13, '>': 12},
+ {'=': 14, '>': 13},
# 9
- {'<': 12, '=': 13, '>': 13},
+ {'<': 13, '=': 14, '>': 14},
# 10
- {'=': 13},
+ {'=': 14},
# 11
- {'/': 12, '=': 13},
+ {'=': 14, '>': 14},
# 12
- {'=': 13},
+ {'/': 13, '=': 14},
# 13
+ {'=': 14},
+ # 14
{},
- # 14
- {'\n': 13},
# 15
- {automata.DEFAULT: 30, '\n': 27,
- '\r': 27, "'": 28, '\\': 29},
+ {'\n': 14},
# 16
- {automata.DEFAULT: 33, '\n': 27,
- '\r': 27, '"': 31, '\\': 32},
+ {automata.DEFAULT: 32, '\n': 29,
+ '\r': 29, "'": 30, '\\': 31},
# 17
- {'\n': 13, '\r': 14},
+ {automata.DEFAULT: 35, '\n': 29,
+ '\r': 29, '"': 33, '\\': 34},
# 18
- {automata.DEFAULT: 18, '\n': 27, '\r': 27},
+ {'\n': 14, '\r': 15},
# 19
- {'0': 34, '1': 34, '2': 34, '3': 34,
- '4': 34, '5': 34, '6': 34, '7': 34,
- '8': 34, '9': 34, 'A': 34, 'B': 34,
- 'C': 34, 'D': 34, 'E': 34, 'F': 34,
- 'a': 34, 'b': 34, 'c': 34, 'd': 34,
- 'e': 34, 'f': 34},
+ {automata.DEFAULT: 19, '\n': 29, '\r': 29},
# 20
- {'0': 35, '1': 35, '2': 35, '3': 35,
- '4': 35, '5': 35, '6': 35, '7': 35},
+ {'0': 36, '1': 36, '2': 36, '3': 36,
+ '4': 36, '5': 36, '6': 36, '7': 36,
+ '8': 36, '9': 36, 'A': 36, 'B': 36,
+ 'C': 36, 'D': 36, 'E': 36, 'F': 36,
+ 'a': 36, 'b': 36, 'c': 36, 'd': 36,
+ 'e': 36, 'f': 36},
# 21
- {'0': 36, '1': 36},
+ {'0': 37, '1': 37, '2': 37, '3': 37,
+ '4': 37, '5': 37, '6': 37, '7': 37},
# 22
- {'.': 24, '0': 22, '1': 23, '2': 23,
- '3': 23, '4': 23, '5': 23, '6': 23,
- '7': 23, '8': 23, '9': 23, 'E': 25,
- 'J': 13, 'e': 25, 'j': 13},
+ {'0': 38, '1': 38},
# 23
- {'.': 24, '0': 23, '1': 23, '2': 23,
- '3': 23, '4': 23, '5': 23, '6': 23,
- '7': 23, '8': 23, '9': 23, 'E': 25,
- 'J': 13, 'e': 25, 'j': 13},
+ {'.': 25, '0': 23, '1': 24, '2': 24,
+ '3': 24, '4': 24, '5': 24, '6': 24,
+ '7': 24, '8': 24, '9': 24, 'E': 26,
+ 'J': 14, 'e': 26, 'j': 14},
# 24
- {'0': 24, '1': 24, '2': 24, '3': 24,
- '4': 24, '5': 24, '6': 24, '7': 24,
- '8': 24, '9': 24, 'E': 37, 'J': 13,
- 'e': 37, 'j': 13},
+ {'.': 25, '0': 24, '1': 24, '2': 24,
+ '3': 24, '4': 24, '5': 24, '6': 24,
+ '7': 24, '8': 24, '9': 24, 'E': 26,
+ 'J': 14, 'e': 26, 'j': 14},
# 25
- {'+': 38, '-': 38, '0': 39, '1': 39,
- '2': 39, '3': 39, '4': 39, '5': 39,
- '6': 39, '7': 39, '8': 39, '9': 39},
+ {'0': 25, '1': 25, '2': 25, '3': 25,
+ '4': 25, '5': 25, '6': 25, '7': 25,
+ '8': 25, '9': 25, 'E': 39, 'J': 14,
+ 'e': 39, 'j': 14},
# 26
- {'0': 26, '1': 26, '2': 26, '3': 26,
- '4': 26, '5': 26, '6': 26, '7': 26,
- '8': 26, '9': 26, 'E': 37, 'J': 13,
- 'e': 37, 'j': 13},
+ {'+': 40, '-': 40, '0': 41, '1': 41,
+ '2': 41, '3': 41, '4': 41, '5': 41,
+ '6': 41, '7': 41, '8': 41, '9': 41},
# 27
+ {'0': 27, '1': 27, '2': 27, '3': 27,
+ '4': 27, '5': 27, '6': 27, '7': 27,
+ '8': 27, '9': 27, 'E': 39, 'J': 14,
+ 'e': 39, 'j': 14},
+ # 28
+ {'.': 14},
+ # 29
{},
- # 28
- {"'": 13},
- # 29
- {automata.DEFAULT: 40, '\n': 13, '\r': 14},
# 30
- {automata.DEFAULT: 30, '\n': 27,
- '\r': 27, "'": 13, '\\': 29},
+ {"'": 14},
# 31
- {'"': 13},
+ {automata.DEFAULT: 42, '\n': 14, '\r': 15},
# 32
- {automata.DEFAULT: 41, '\n': 13, '\r': 14},
+ {automata.DEFAULT: 32, '\n': 29,
+ '\r': 29, "'": 14, '\\': 31},
# 33
- {automata.DEFAULT: 33, '\n': 27,
- '\r': 27, '"': 13, '\\': 32},
+ {'"': 14},
# 34
- {'0': 34, '1': 34, '2': 34, '3': 34,
- '4': 34, '5': 34, '6': 34, '7': 34,
- '8': 34, '9': 34, 'A': 34, 'B': 34,
- 'C': 34, 'D': 34, 'E': 34, 'F': 34,
- 'a': 34, 'b': 34, 'c': 34, 'd': 34,
- 'e': 34, 'f': 34},
+ {automata.DEFAULT: 43, '\n': 14, '\r': 15},
# 35
- {'0': 35, '1': 35, '2': 35, '3': 35,
- '4': 35, '5': 35, '6': 35, '7': 35},
+ {automata.DEFAULT: 35, '\n': 29,
+ '\r': 29, '"': 14, '\\': 34},
# 36
- {'0': 36, '1': 36},
+ {'0': 36, '1': 36, '2': 36, '3': 36,
+ '4': 36, '5': 36, '6': 36, '7': 36,
+ '8': 36, '9': 36, 'A': 36, 'B': 36,
+ 'C': 36, 'D': 36, 'E': 36, 'F': 36,
+ 'a': 36, 'b': 36, 'c': 36, 'd': 36,
+ 'e': 36, 'f': 36},
# 37
- {'+': 42, '-': 42, '0': 43, '1': 43,
- '2': 43, '3': 43, '4': 43, '5': 43,
- '6': 43, '7': 43, '8': 43, '9': 43},
+ {'0': 37, '1': 37, '2': 37, '3': 37,
+ '4': 37, '5': 37, '6': 37, '7': 37},
# 38
- {'0': 39, '1': 39, '2': 39, '3': 39,
- '4': 39, '5': 39, '6': 39, '7': 39,
- '8': 39, '9': 39},
+ {'0': 38, '1': 38},
# 39
- {'0': 39, '1': 39, '2': 39, '3': 39,
- '4': 39, '5': 39, '6': 39, '7': 39,
- '8': 39, '9': 39, 'J': 13, 'j': 13},
+ {'+': 44, '-': 44, '0': 45, '1': 45,
+ '2': 45, '3': 45, '4': 45, '5': 45,
+ '6': 45, '7': 45, '8': 45, '9': 45},
# 40
- {automata.DEFAULT: 40, '\n': 27,
- '\r': 27, "'": 13, '\\': 29},
+ {'0': 41, '1': 41, '2': 41, '3': 41,
+ '4': 41, '5': 41, '6': 41, '7': 41,
+ '8': 41, '9': 41},
# 41
- {automata.DEFAULT: 41, '\n': 27,
- '\r': 27, '"': 13, '\\': 32},
+ {'0': 41, '1': 41, '2': 41, '3': 41,
+ '4': 41, '5': 41, '6': 41, '7': 41,
+ '8': 41, '9': 41, 'J': 14, 'j': 14},
# 42
- {'0': 43, '1': 43, '2': 43, '3': 43,
- '4': 43, '5': 43, '6': 43, '7': 43,
- '8': 43, '9': 43},
+ {automata.DEFAULT: 42, '\n': 29,
+ '\r': 29, "'": 14, '\\': 31},
# 43
- {'0': 43, '1': 43, '2': 43, '3': 43,
- '4': 43, '5': 43, '6': 43, '7': 43,
- '8': 43, '9': 43, 'J': 13, 'j': 13},
+ {automata.DEFAULT: 43, '\n': 29,
+ '\r': 29, '"': 14, '\\': 34},
+ # 44
+ {'0': 45, '1': 45, '2': 45, '3': 45,
+ '4': 45, '5': 45, '6': 45, '7': 45,
+ '8': 45, '9': 45},
+ # 45
+ {'0': 45, '1': 45, '2': 45, '3': 45,
+ '4': 45, '5': 45, '6': 45, '7': 45,
+ '8': 45, '9': 45, 'J': 14, 'j': 14},
]
pseudoDFA = automata.DFA(states, accepts)
diff --git a/pypy/interpreter/pyparser/gendfa.py b/pypy/interpreter/pyparser/gendfa.py
--- a/pypy/interpreter/pyparser/gendfa.py
+++ b/pypy/interpreter/pyparser/gendfa.py
@@ -131,6 +131,7 @@
maybe(states, newArcPair(states, "="))),
chainStr(states, "<>"),
chainStr(states, "!="),
+ chainStr(states, "->"),
chain(states,
chainStr(states, "//"),
maybe(states, newArcPair(states, "="))),
@@ -141,6 +142,7 @@
bracket = groupStr(states, "[](){}")
special = group(states,
makeEOL(),
+ chainStr(states, "..."),
groupStr(states, "@:;.,`"))
funny = group(states, operator, bracket, special)
# ____________________________________________________________
diff --git a/pypy/interpreter/pyparser/pytoken.py b/pypy/interpreter/pyparser/pytoken.py
--- a/pypy/interpreter/pyparser/pytoken.py
+++ b/pypy/interpreter/pyparser/pytoken.py
@@ -61,6 +61,8 @@
_add_tok('DOUBLESLASH', "//" )
_add_tok('DOUBLESLASHEQUAL',"//=" )
_add_tok('AT', "@" )
+_add_tok('RARROW', "->")
+_add_tok('ELLIPSIS', "...")
_add_tok('OP')
_add_tok('ERRORTOKEN')
diff --git a/pypy/interpreter/pyparser/pytokenizer.py b/pypy/interpreter/pyparser/pytokenizer.py
--- a/pypy/interpreter/pyparser/pytokenizer.py
+++ b/pypy/interpreter/pyparser/pytokenizer.py
@@ -172,8 +172,9 @@
pos = end
token, initial = line[start:end], line[start]
- if initial in numchars or \
- (initial == '.' and token != '.'): # ordinary number
+ if (initial in numchars or \
+ (initial == '.' and token != '.' and token != '...')):
+ # ordinary number
token_list.append((tokens.NUMBER, token, lnum, start, line))
last_comment = ''
elif initial in '\r\n':
diff --git a/pypy/interpreter/test/test_appinterp.py b/pypy/interpreter/test/test_appinterp.py
--- a/pypy/interpreter/test/test_appinterp.py
+++ b/pypy/interpreter/test/test_appinterp.py
@@ -1,6 +1,6 @@
import py
-from pypy.interpreter.gateway import appdef, ApplevelClass, applevel_temp, applevelinterp_temp
+from pypy.interpreter.gateway import appdef, ApplevelClass, applevel_temp
from pypy.interpreter.error import OperationError
def test_execwith_novars(space):
@@ -82,9 +82,6 @@
w_res = g(space, space.wrap(10), space.wrap(1))
assert space.eq_w(w_res, space.wrap(-9))
-def test_applevelinterp_functions(space):
- test_applevel_functions(space, applevel_temp = applevelinterp_temp)
-
def test_applevel_class(space, applevel_temp = applevel_temp):
app = applevel_temp('''
class C(object):
@@ -99,9 +96,6 @@
w_clsattr = space.getattr(c, space.wrap('attr'))
assert space.eq_w(w_clsattr, space.wrap(17))
-def test_applevelinterp_class(space):
- test_applevel_class(space, applevel_temp = applevelinterp_temp)
-
def app_test_something_at_app_level():
x = 2
assert x/2 == 1
@@ -161,7 +155,7 @@
w_str = space1.getattr(w_mymod1, space1.wrap("hi"))
assert space1.str_w(w_str) == "hello"
- def test_geninterp_can_unfreeze(self):
+ def test_random_stuff_can_unfreeze(self):
# When a module contains an "import" statement in applevel code, the
# imported module is initialized, possibly after it has been already
# frozen.
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -357,16 +357,16 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults_w=None, blindargs=0):
+ defaults_w=None, w_kw_defs=None, blindargs=0):
defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults_w, blindargs))
+ signature.has_kwarg(), defaults_w, w_kw_defs, blindargs))
args._match_signature = _match_signature
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], None, None))
assert len(calls) == 1
assert calls[0] == (None, [None, None], ["a", "b"], False, False,
- [], 0)
+ [], None, 0)
assert calls[0][1] is scope_w
calls = []
@@ -374,7 +374,7 @@
blindargs=1)
assert len(calls) == 1
assert calls[0] == (None, [None, None, None], ["a", "b"], True, False,
- [], 1)
+ [], None, 1)
calls = []
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], "args", "kw"),
@@ -382,7 +382,7 @@
assert len(calls) == 1
assert calls[0] == (None, [None, None, None, None], ["a", "b"],
True, True,
- ["x", "y"], 0)
+ ["x", "y"], None, 0)
calls = []
scope_w = args.parse_obj("obj", "foo", Signature(["a", "b"], "args", "kw"),
@@ -390,7 +390,7 @@
assert len(calls) == 1
assert calls[0] == ("obj", [None, None, None, None], ["a", "b"],
True, True,
- ["x", "y"], 1)
+ ["x", "y"], None, 1)
class FakeArgErr(ArgErr):
@@ -415,17 +415,17 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults_w=None, blindargs=0):
+ defaults_w=None, w_kw_defs=None, blindargs=0):
defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults_w, blindargs))
+ signature.has_kwarg(), defaults_w, w_kw_defs, blindargs))
args._match_signature = _match_signature
scope_w = [None, None]
args.parse_into_scope(None, scope_w, "foo", Signature(["a", "b"], None, None))
assert len(calls) == 1
assert calls[0] == (None, scope_w, ["a", "b"], False, False,
- [], 0)
+ [], None, 0)
assert calls[0][1] is scope_w
calls = []
@@ -435,7 +435,7 @@
assert len(calls) == 1
assert calls[0] == (None, scope_w, ["a", "b"],
True, True,
- ["x", "y"], 0)
+ ["x", "y"], None, 0)
calls = []
scope_w = [None, None, None, None]
@@ -445,7 +445,7 @@
assert len(calls) == 1
assert calls[0] == ("obj", scope_w, ["a", "b"],
True, True,
- ["x", "y"], 0)
+ ["x", "y"], None, 0)
class FakeArgErr(ArgErr):
@@ -493,34 +493,34 @@
def test_missing_args(self):
# got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
# defaults_w, missing_args
- err = ArgErrCount(1, 0, 0, False, False, None, 0)
+ err = ArgErrCount(1, 0, 0, False, False, None, None, 0)
s = err.getmsg()
assert s == "takes no arguments (1 given)"
- err = ArgErrCount(0, 0, 1, False, False, [], 1)
+ err = ArgErrCount(0, 0, 1, False, False, [], None, 1)
s = err.getmsg()
assert s == "takes exactly 1 argument (0 given)"
- err = ArgErrCount(3, 0, 2, False, False, [], 0)
+ err = ArgErrCount(3, 0, 2, False, False, [], None, 0)
s = err.getmsg()
assert s == "takes exactly 2 arguments (3 given)"
- err = ArgErrCount(3, 0, 2, False, False, ['a'], 0)
+ err = ArgErrCount(3, 0, 2, False, False, ['a'], None, 0)
s = err.getmsg()
assert s == "takes at most 2 arguments (3 given)"
- err = ArgErrCount(1, 0, 2, True, False, [], 1)
+ err = ArgErrCount(1, 0, 2, True, False, [], None, 1)
s = err.getmsg()
assert s == "takes at least 2 arguments (1 given)"
- err = ArgErrCount(0, 1, 2, True, False, ['a'], 1)
+ err = ArgErrCount(0, 1, 2, True, False, ['a'], None, 1)
s = err.getmsg()
assert s == "takes at least 1 non-keyword argument (0 given)"
- err = ArgErrCount(2, 1, 1, False, True, [], 0)
+ err = ArgErrCount(2, 1, 1, False, True, [], None, 0)
s = err.getmsg()
assert s == "takes exactly 1 non-keyword argument (2 given)"
- err = ArgErrCount(0, 1, 1, False, True, [], 1)
+ err = ArgErrCount(0, 1, 1, False, True, [], None, 1)
s = err.getmsg()
assert s == "takes exactly 1 non-keyword argument (0 given)"
- err = ArgErrCount(0, 1, 1, True, True, [], 1)
+ err = ArgErrCount(0, 1, 1, True, True, [], None, 1)
s = err.getmsg()
assert s == "takes at least 1 non-keyword argument (0 given)"
- err = ArgErrCount(2, 1, 1, False, True, ['a'], 0)
+ err = ArgErrCount(2, 1, 1, False, True, ['a'], None, 0)
s = err.getmsg()
assert s == "takes at most 1 non-keyword argument (2 given)"
diff --git a/pypy/interpreter/test/test_code.py b/pypy/interpreter/test/test_code.py
--- a/pypy/interpreter/test/test_code.py
+++ b/pypy/interpreter/test/test_code.py
@@ -23,12 +23,14 @@
'co_names': (),
'co_varnames': (),
'co_argcount': 0,
+ 'co_kwonlyargcount': 0,
'co_consts': (None,)
}),
(g.__code__, {'co_name': 'g',
'co_names': (),
'co_varnames': ('x', 'y', 'z'),
'co_argcount': 1,
+ 'co_kwonlyargcount': 0,
'co_consts': ("docstring", None),
}),
]
@@ -58,6 +60,12 @@
for key, value in expected.items():
assert getattr(code, key) == value
+ def test_kwonlyargcount(self):
+ """
+ def f(*args, a, b, **kw): pass
+ assert f.__code__.co_kwonlyargcount == 2
+ """
+
def test_co_names(self):
src = '''if 1:
def foo():
diff --git a/pypy/interpreter/test/test_compiler.py b/pypy/interpreter/test/test_compiler.py
--- a/pypy/interpreter/test/test_compiler.py
+++ b/pypy/interpreter/test/test_compiler.py
@@ -449,6 +449,9 @@
space = self.space
w_d = space.newdict()
space.exec_(code, w_d, w_d)
+ snip = "d[. . .]"
+ space.raises_w(space.w_SyntaxError, self.compiler.compile,
+ snip, '<test>', 'exec', 0)
def test_chained_access_augassign(self):
snippet = str(py.code.Source(r'''
@@ -757,6 +760,25 @@
assert math.copysign(1., ns['c'][0]) == -1.0
assert math.copysign(1., ns['c'][1]) == -1.0
+ def test_ellipsis_anywhere(self):
+ """
+ x = ...
+ assert x is Ellipsis
+ """
+
+ def test_keywordonly_syntax_errors(self):
+ cases = ("def f(p, *):\n pass\n",
+ "def f(p1, *, p1=100):\n pass\n",
+ "def f(p1, *k1, k1=100):\n pass\n",
+ "def f(p1, *, k1, k1=100):\n pass\n",
+ "def f(p1, *, **k1):\n pass\n",
+ "def f(p1, *, k1, **k1):\n pass\n",
+ "def f(p1, *, None, **k1):\n pass\n",
+ "def f(p, *, (k1, k2), **kw):\n pass\n")
+ for case in cases:
+ raises(SyntaxError, compile, case, "<test>", "exec")
+
+
class AppTestOptimizer:
@@ -779,13 +801,15 @@
output = s.getvalue()
assert output.count('LOAD_CONST') == 1
- def test_none_constant(self):
+ def test_constant_name(self):
import opcode
- co = compile("def f(): return None", "<test>", "exec").co_consts[0]
- assert "None" not in co.co_names
- co = co.co_code
- op = co[0] + (co[1] << 8)
- assert op == opcode.opmap["LOAD_CONST"]
+ for name in "None", "True", "False":
+ snip = "def f(): return " + name
+ co = compile(snip, "<test>", "exec").co_consts[0]
+ assert name not in co.co_names
+ co = co.co_code
+ op = co[0]
+ assert op == opcode.opmap["LOAD_CONST"]
def test_tuple_constants(self):
ns = {}
@@ -793,6 +817,10 @@
assert isinstance(ns["x"][0], int)
assert isinstance(ns["y"][0], int)
+ def test_ellipsis_truth(self):
+ co = compile("if ...: x + 3\nelse: x + 4", "<test>", "exec")
+ assert 4 not in co.co_consts
+
def test_division_folding(self):
def code(source):
return compile(source, "<test>", "exec")
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -20,6 +20,31 @@
assert f.__name__ == 'f'
assert f.__module__ == 'mymodulename'
+ def test_annotations(self):
+ def f(): pass
+ ann = f.__annotations__
+ assert ann == {}
+ assert f.__annotations__ is ann
+ raises(TypeError, setattr, f, "__annotations__", 42)
+ del f.__annotations__
+ assert f.__annotations__ is not ann
+ f.__annotations__ = ann
+ assert f.__annotations__ is ann
+
+ def test_kwdefaults(self):
+ """
+ def f(*, kw=3): return kw
+ assert f.__kwdefaults__ == {"kw" : 3}
+ f.__kwdefaults__["kw"] = 4
+ assert f() == 4
+ f.__kwdefaults__ = {"kw" : 5}
+ assert f() == 5
+ del f.__kwdefaults__
+ assert f.__kwdefaults__ is None
+ raises(TypeError, f)
+ assert f(kw=42) == 42
+ """
+
def test_code_is_ok(self):
def f(): pass
assert not hasattr(f.__code__, '__dict__')
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -12,6 +12,7 @@
self.space = space
self.name = name
self.defs_w = []
+ self.w_kw_defs = None
class TestBuiltinCode:
def test_signature(self):
@@ -101,14 +102,6 @@
g3 = gateway.app2interp_temp(noapp_g3, gateway.applevel_temp)
assert self.space.eq_w(g3(self.space, w('foo'), w('bar')), w('foobar'))
- def test_app2interp2(self):
- """same but using transformed code"""
- w = self.space.wrap
- def noapp_g3(a, b):
- return a+b
- g3 = gateway.app2interp_temp(noapp_g3, gateway.applevelinterp_temp)
- assert self.space.eq_w(g3(self.space, w('foo'), w('bar')), w('foobar'))
-
def test_app2interp_general_args(self):
w = self.space.wrap
def app_general(x, *args, **kwds):
diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -237,8 +237,17 @@
'''
assert self.codetest(code, 'f', []) == os.name
+ def test_kwonlyargs_with_kwarg(self):
+ code = """ def f():
+ def g(a, *arg, c, **kw):
+ return [a, arg, c, kw]
+ return g(1, 2, 3, c=4, d=5)
+ """
+ exp = [1, (2, 3), 4, {"d" : 5}]
+ assert self.codetest(code, "f", []) == exp
+
def test_kwonlyargs_default_parameters(self):
- code = """ def f(a, b, c=3, *, d=4):
+ code = """ def f(a, b, c=3, d=4):
return a, b, c, d
"""
assert self.codetest(code, "f", [1, 2]) == (1, 2, 3, 4)
@@ -324,3 +333,18 @@
assert str(e) == "maximum recursion depth exceeded"
else:
assert 0, "should have raised!"
+
+ def test_kwonlyargs_mixed_args(self):
+ """
+ def mixedargs_sum(a, b=0, *args, k1, k2=0):
+ return a + b + k1 + k2 + sum(args)
+ assert mixedargs_sum.__code__.co_varnames == ("a", "b", "k1", "k2", "args")
+ assert mixedargs_sum(1, k1=2) == 1 + 2
+ """
+
+ def test_kwonlyargs_lambda(self):
+ """
+ l = lambda x, y, *, k=20: x+y+k
+ assert l(1, 2) == 1 + 2 + 20
+ assert l(1, 2, k=10) == 1 + 2 + 10
+ """
diff --git a/pypy/interpreter/test/test_syntax.py b/pypy/interpreter/test/test_syntax.py
--- a/pypy/interpreter/test/test_syntax.py
+++ b/pypy/interpreter/test/test_syntax.py
@@ -612,6 +612,17 @@
"""
exec(s)
+class AppTestFunctionAnnotations:
+
+ def test_simple(self):
+ """
+ def f(e:3=4): pass
+ assert f.__annotations__ == {"e" : 3}
+ def f(a : 1, b : 2, *var : 3, hi : 4, bye : 5=0, **kw : 6) -> 42: pass
+ assert f.__annotations__ == {"a" : 1, "b" : 2, "var" : 3, "hi" : 4,
+ "bye" : 5, "kw" : 6, "return" : 42}
+ """
+
class AppTestSyntaxError:
def test_tokenizer_error_location(self):
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -730,6 +730,7 @@
__reduce__ = interp2app(PyCode.descr__reduce__),
__repr__ = interp2app(PyCode.repr),
co_argcount = interp_attrproperty('co_argcount', cls=PyCode),
+ co_kwonlyargcount = interp_attrproperty('co_kwonlyargcount', cls=PyCode),
co_nlocals = interp_attrproperty('co_nlocals', cls=PyCode),
co_stacksize = interp_attrproperty('co_stacksize', cls=PyCode),
co_flags = interp_attrproperty('co_flags', cls=PyCode),
@@ -788,10 +789,16 @@
getset_func_defaults = GetSetProperty(Function.fget_func_defaults,
Function.fset_func_defaults,
Function.fdel_func_defaults)
+getset_func_kwdefaults = GetSetProperty(Function.fget_func_kwdefaults,
+ Function.fset_func_kwdefaults,
+ Function.fdel_func_kwdefaults)
getset_func_code = GetSetProperty(Function.fget_func_code,
Function.fset_func_code)
getset_func_name = GetSetProperty(Function.fget_func_name,
Function.fset_func_name)
+getset_func_annotations = GetSetProperty(Function.fget_func_annotations,
+ Function.fset_func_annotations,
+ Function.fdel_func_annotations)
getset_func_dict = GetSetProperty(descr_get_dict, descr_set_dict, cls=Function)
@@ -808,6 +815,8 @@
__name__ = getset_func_name,
__dict__ = getset_func_dict,
__defaults__ = getset_func_defaults,
+ __kwdefaults__ = getset_func_kwdefaults,
+ __annotations__ = getset_func_annotations,
__globals__ = interp_attrproperty_w('w_func_globals', cls=Function),
__closure__ = GetSetProperty( Function.fget_func_closure ),
__module__ = getset___module__,
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -11,6 +11,7 @@
from pypy.jit.tool.oparser import parse
from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
from pypy.jit.metainterp.optimizeopt.util import equaloplists
+from pypy.rlib.rarithmetic import is_valid_int
def test_boehm():
gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -103,7 +104,7 @@
gcrootmap.put(retaddr, shapeaddr)
assert gcrootmap._gcmap[0] == retaddr
assert gcrootmap._gcmap[1] == shapeaddr
- p = rffi.cast(rffi.LONGP, gcrootmap.gcmapstart())
+ p = rffi.cast(rffi.SIGNEDP, gcrootmap.gcmapstart())
assert p[0] == retaddr
assert (gcrootmap.gcmapend() ==
gcrootmap.gcmapstart() + rffi.sizeof(lltype.Signed) * 2)
@@ -419,9 +420,9 @@
assert newops[0].getarg(1) == v_value
assert newops[0].result is None
wbdescr = newops[0].getdescr()
- assert isinstance(wbdescr.jit_wb_if_flag, int)
- assert isinstance(wbdescr.jit_wb_if_flag_byteofs, int)
- assert isinstance(wbdescr.jit_wb_if_flag_singlebyte, int)
+ assert is_valid_int(wbdescr.jit_wb_if_flag)
+ assert is_valid_int(wbdescr.jit_wb_if_flag_byteofs)
+ assert is_valid_int(wbdescr.jit_wb_if_flag_singlebyte)
def test_get_rid_of_debug_merge_point(self):
operations = [
diff --git a/pypy/jit/backend/test/support.py b/pypy/jit/backend/test/support.py
--- a/pypy/jit/backend/test/support.py
+++ b/pypy/jit/backend/test/support.py
@@ -3,6 +3,7 @@
from pypy.rlib.debug import debug_print
from pypy.translator.translator import TranslationContext, graphof
from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
+from pypy.rlib.rarithmetic import is_valid_int
class BaseCompiledMixin(object):
@@ -24,7 +25,7 @@
from pypy.annotation import model as annmodel
for arg in args:
- assert isinstance(arg, int)
+ assert is_valid_int(arg)
self.pre_translation_hook()
t = self._get_TranslationContext()
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1185,14 +1185,14 @@
def bhimpl_getinteriorfield_gc_f(cpu, array, index, descr):
return cpu.bh_getinteriorfield_gc_f(array, index, descr)
- @arguments("cpu", "r", "i", "d", "i")
- def bhimpl_setinteriorfield_gc_i(cpu, array, index, descr, value):
+ @arguments("cpu", "r", "i", "i", "d")
+ def bhimpl_setinteriorfield_gc_i(cpu, array, index, value, descr):
cpu.bh_setinteriorfield_gc_i(array, index, descr, value)
- @arguments("cpu", "r", "i", "d", "r")
- def bhimpl_setinteriorfield_gc_r(cpu, array, index, descr, value):
+ @arguments("cpu", "r", "i", "r", "d")
+ def bhimpl_setinteriorfield_gc_r(cpu, array, index, value, descr):
cpu.bh_setinteriorfield_gc_r(array, index, descr, value)
- @arguments("cpu", "r", "i", "d", "f")
- def bhimpl_setinteriorfield_gc_f(cpu, array, index, descr, value):
+ @arguments("cpu", "r", "i", "f", "d")
+ def bhimpl_setinteriorfield_gc_f(cpu, array, index, value, descr):
cpu.bh_setinteriorfield_gc_f(array, index, descr, value)
@arguments("cpu", "r", "d", returns="i")
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3784,6 +3784,15 @@
assert res == 11 * 12 * 13
self.check_operations_history(int_add=3, int_mul=2)
+ def test_setinteriorfield(self):
+ A = lltype.GcArray(lltype.Struct('S', ('x', lltype.Signed)))
+ a = lltype.malloc(A, 5, immortal=True)
+ def g(n):
+ a[n].x = n + 2
+ return a[n].x
+ res = self.interp_operations(g, [1])
+ assert res == 3
+
class TestLLtype(BaseLLtypeTests, LLJitMixin):
def test_tagged(self):
diff --git a/pypy/jit/metainterp/test/test_list.py b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -232,6 +232,7 @@
def test_newlist_hint(self):
def f(i):
l = newlist_hint(i)
+ l[0] = 55
return len(l)
r = self.interp_operations(f, [3])
diff --git a/pypy/jit/tl/tlc.py b/pypy/jit/tl/tlc.py
--- a/pypy/jit/tl/tlc.py
+++ b/pypy/jit/tl/tlc.py
@@ -6,6 +6,8 @@
from pypy.jit.tl.tlopcode import *
from pypy.jit.tl import tlopcode
from pypy.rlib.jit import JitDriver, elidable
+from pypy.rlib.rarithmetic import is_valid_int
+
class Obj(object):
@@ -219,7 +221,7 @@
class Frame(object):
def __init__(self, args, pc):
- assert isinstance(pc, int)
+ assert is_valid_int(pc)
self.args = args
self.pc = pc
self.stack = []
@@ -239,7 +241,7 @@
return interp_eval(code, pc, args, pool).int_o()
def interp_eval(code, pc, args, pool):
- assert isinstance(pc, int)
+ assert is_valid_int(pc)
frame = Frame(args, pc)
pc = frame.pc
diff --git a/pypy/module/__builtin__/__init__.py b/pypy/module/__builtin__/__init__.py
--- a/pypy/module/__builtin__/__init__.py
+++ b/pypy/module/__builtin__/__init__.py
@@ -20,7 +20,6 @@
'all' : 'app_functional.all',
'sum' : 'app_functional.sum',
'map' : 'app_functional.map',
- 'reduce' : 'app_functional.reduce',
'filter' : 'app_functional.filter',
'zip' : 'app_functional.zip',
'vars' : 'app_inspect.vars',
diff --git a/pypy/module/__builtin__/app_functional.py b/pypy/module/__builtin__/app_functional.py
--- a/pypy/module/__builtin__/app_functional.py
+++ b/pypy/module/__builtin__/app_functional.py
@@ -93,28 +93,6 @@
else:
return result
-sentinel = object()
-
-def reduce(func, sequence, initial=sentinel):
- """reduce(function, sequence[, initial]) -> value
-
-Apply a function of two arguments cumulatively to the items of a sequence,
-from left to right, so as to reduce the sequence to a single value.
-For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
-((((1+2)+3)+4)+5). If initial is present, it is placed before the items
-of the sequence in the calculation, and serves as a default when the
-sequence is empty."""
- iterator = iter(sequence)
- if initial is sentinel:
- try:
- initial = next(iterator)
- except StopIteration:
- raise TypeError("reduce() of empty sequence with no initial value")
- result = initial
- for item in iterator:
- result = func(result, item)
- return result
-
def filter(func, seq):
"""filter(function or None, sequence) -> list, tuple, or string
diff --git a/pypy/module/__builtin__/app_inspect.py b/pypy/module/__builtin__/app_inspect.py
--- a/pypy/module/__builtin__/app_inspect.py
+++ b/pypy/module/__builtin__/app_inspect.py
@@ -8,8 +8,6 @@
from __pypy__ import lookup_special
def _caller_locals():
- # note: the reason why this is working is because the functions in here are
- # compiled by geninterp, so they don't have a frame
return sys._getframe(0).f_locals
def vars(*obj):
@@ -26,17 +24,6 @@
except AttributeError:
raise TypeError("vars() argument must have __dict__ attribute")
-# Replaced by the interp-level helper space.callable():
-##def callable(ob):
-## import __builtin__ # XXX this is insane but required for now for geninterp
-## for c in type(ob).__mro__:
-## if '__call__' in c.__dict__:
-## if isinstance(ob, __builtin__._instance): # old style instance!
-## return getattr(ob, '__call__', None) is not None
-## return True
-## else:
-## return False
-
def dir(*args):
"""dir([object]) -> list of strings
diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -87,18 +87,6 @@
def test_three_lists(self):
assert zip([1,2,3], [1,2], [1,2,3]) == [(1,1,1), (2,2,2)]
-class AppTestReduce:
- def test_None(self):
- raises(TypeError, reduce, lambda x, y: x+y, [1,2,3], None)
-
- def test_sum(self):
- assert reduce(lambda x, y: x+y, [1,2,3,4], 0) == 10
- assert reduce(lambda x, y: x+y, [1,2,3,4]) == 10
-
- def test_minus(self):
- assert reduce(lambda x, y: x-y, [10, 2, 8]) == 0
- assert reduce(lambda x, y: x-y, [2, 8], 10) == 0
-
class AppTestFilter:
def test_None(self):
assert list(filter(None, ['a', 'b', 1, 0, None])) == ['a', 'b', 1]
diff --git a/pypy/module/__builtin__/test/test_reduce.py b/pypy/module/__builtin__/test/test_reduce.py
deleted file mode 100644
--- a/pypy/module/__builtin__/test/test_reduce.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import autopath
-
-
-class AppTestReduce:
- def test_None(self):
- raises(TypeError, reduce, lambda x, y: x+y, [1,2,3], None)
-
- def test_sum(self):
- assert reduce(lambda x, y: x+y, [1,2,3,4], 0) == 10
- assert reduce(lambda x, y: x+y, [1,2,3,4]) == 10
-
- def test_minus(self):
- assert reduce(lambda x, y: x-y, [10, 2, 8]) == 0
- assert reduce(lambda x, y: x-y, [2, 8], 10) == 0
-
- def test_from_cpython(self):
- class SequenceClass(object):
- def __init__(self, n):
- self.n = n
- def __getitem__(self, i):
- if 0 <= i < self.n:
- return i
- else:
- raise IndexError
-
- from operator import add
- assert reduce(add, SequenceClass(5)) == 10
- assert reduce(add, SequenceClass(5), 42) == 52
- raises(TypeError, reduce, add, SequenceClass(0))
- assert reduce(add, SequenceClass(0), 42) == 42
- assert reduce(add, SequenceClass(1)) == 0
- assert reduce(add, SequenceClass(1), 42) == 42
-
- d = {"one": 1, "two": 2, "three": 3}
- assert reduce(add, d) == "".join(d.keys())
-
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -46,9 +46,6 @@
x.bar = 80
assert lookup_special(x, "foo")() == 42
assert lookup_special(x, "bar") is None
- class X:
- pass
- raises(TypeError, lookup_special, X(), "foo")
def test_do_what_I_mean(self):
from __pypy__ import do_what_I_mean
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -1,7 +1,6 @@
from pypy.conftest import gettestobjspace
from pypy.module._multiprocessing.interp_semaphore import (
RECURSIVE_MUTEX, SEMAPHORE)
-from pypy.rlib.rarithmetic import is_valid_int
class AppTestSemaphore:
@@ -22,7 +21,7 @@
sem = SemLock(kind, value, maxvalue)
assert sem.kind == kind
assert sem.maxvalue == maxvalue
- assert is_valid_int(sem.handle)
+ assert isinstance(sem.handle, (int, long))
assert sem._count() == 0
if sys.platform == 'darwin':
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -23,7 +23,6 @@
from pypy.interpreter.function import StaticMethod
from pypy.objspace.std.sliceobject import W_SliceObject
from pypy.module.__builtin__.descriptor import W_Property
-from pypy.module.__builtin__.interp_classobj import W_ClassObject
from pypy.module.__builtin__.interp_memoryview import W_MemoryView
from pypy.rlib.entrypoint import entrypoint
from pypy.rlib.unroll import unrolling_iterable
@@ -402,7 +401,6 @@
'Module': 'space.gettypeobject(Module.typedef)',
'Property': 'space.gettypeobject(W_Property.typedef)',
'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
- 'Class': 'space.gettypeobject(W_ClassObject.typedef)',
'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
@@ -823,6 +821,8 @@
pypy_decls.append("#ifdef __cplusplus")
pypy_decls.append("extern \"C\" {")
pypy_decls.append("#endif\n")
+ pypy_decls.append('#define Signed long /* xxx temporary fix */\n')
+ pypy_decls.append('#define Unsigned unsigned long /* xxx temporary fix */\n')
for decl in FORWARD_DECLS:
pypy_decls.append("%s;" % (decl,))
@@ -854,6 +854,8 @@
typ = 'PyObject*'
pypy_decls.append('PyAPI_DATA(%s) %s;' % (typ, name))
+ pypy_decls.append('#undef Signed /* xxx temporary fix */\n')
+ pypy_decls.append('#undef Unsigned /* xxx temporary fix */\n')
pypy_decls.append("#ifdef __cplusplus")
pypy_decls.append("}")
pypy_decls.append("#endif")
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -121,5 +121,5 @@
pathname = code.co_filename
w_mod = importing.add_module(space, w_name)
space.setattr(w_mod, space.wrap('__file__'), space.wrap(pathname))
- importing.exec_code_module(space, w_mod, code)
+ importing.exec_code_module(space, w_mod, code, pathname)
return w_mod
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -130,6 +130,11 @@
@cpython_api([PyObject], rffi.CCHARP, error=0)
def PyString_AsString(space, ref):
+ if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str:
+ pass # typecheck returned "ok" without forcing 'ref' at all
+ elif not PyString_Check(space, ref): # otherwise, use the alternate way
+ raise OperationError(space.w_TypeError, space.wrap(
+ "PyString_AsString only support strings"))
ref_str = rffi.cast(PyStringObject, ref)
if not ref_str.c_buffer:
# copy string buffer
diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -101,9 +101,9 @@
space.wrap((2, 7)))):
py.test.skip("unsupported before Python 2.7")
- assert api._PyLong_Sign(space.wrap(0L)) == 0
- assert api._PyLong_Sign(space.wrap(2L)) == 1
- assert api._PyLong_Sign(space.wrap(-2L)) == -1
+ assert api._PyLong_Sign(space.wraplong(0L)) == 0
+ assert api._PyLong_Sign(space.wraplong(2L)) == 1
+ assert api._PyLong_Sign(space.wraplong(-2L)) == -1
assert api._PyLong_NumBits(space.wrap(0)) == 0
assert api._PyLong_NumBits(space.wrap(1)) == 1
diff --git a/pypy/module/cpyext/test/test_number.py b/pypy/module/cpyext/test/test_number.py
--- a/pypy/module/cpyext/test/test_number.py
+++ b/pypy/module/cpyext/test/test_number.py
@@ -6,12 +6,12 @@
class TestIterator(BaseApiTest):
def test_check(self, space, api):
assert api.PyIndex_Check(space.wrap(12))
- assert api.PyIndex_Check(space.wrap(-12L))
+ assert api.PyIndex_Check(space.wraplong(-12L))
assert not api.PyIndex_Check(space.wrap(12.1))
assert not api.PyIndex_Check(space.wrap('12'))
assert api.PyNumber_Check(space.wrap(12))
- assert api.PyNumber_Check(space.wrap(-12L))
+ assert api.PyNumber_Check(space.wraplong(-12L))
assert api.PyNumber_Check(space.wrap(12.1))
assert not api.PyNumber_Check(space.wrap('12'))
assert not api.PyNumber_Check(space.wrap(1+3j))
@@ -21,7 +21,7 @@
assert api.PyLong_CheckExact(w_l)
def test_number_int(self, space, api):
- w_l = api.PyNumber_Int(space.wrap(123L))
+ w_l = api.PyNumber_Int(space.wraplong(123L))
assert api.PyInt_CheckExact(w_l)
w_l = api.PyNumber_Int(space.wrap(2 << 65))
assert api.PyLong_CheckExact(w_l)
@@ -29,7 +29,7 @@
assert api.PyInt_CheckExact(w_l)
def test_number_index(self, space, api):
- w_l = api.PyNumber_Index(space.wrap(123L))
+ w_l = api.PyNumber_Index(space.wraplong(123L))
assert api.PyLong_CheckExact(w_l)
w_l = api.PyNumber_Index(space.wrap(42.3))
assert w_l is None
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -12,6 +12,7 @@
from pypy.interpreter.eval import Code
from pypy.interpreter.pycode import PyCode
from pypy.rlib import streamio, jit
+from pypy.rlib.rstring import assert_str0
from pypy.rlib.streamio import StreamErrors
from pypy.rlib.objectmodel import we_are_translated, specialize
from pypy.module.sys.version import PYPY_VERSION
@@ -859,8 +860,8 @@
space.wrap(space.builtin))
if pathname is not None:
w_pathname = get_sourcefile(space, pathname)
- if w_pathname is None:
- w_pathname = code_w.w_filename
+ else:
+ w_pathname = space.wrap(code_w.co_filename)
space.setitem(w_dict, space.wrap("__file__"), w_pathname)
space.setitem(w_dict, space.wrap("__cached__"), space.wrap(cpathname))
code_w.exec_code(space, w_dict, w_dict)
@@ -924,14 +925,15 @@
return result
def get_sourcefile(space, filename):
- l = len(filename)
- if l < 5 or filename[-4:-1].lower() != ".py":
+ start = len(filename) - 4
+ stop = len(filename) - 1
+ if not 0 <= start <= stop or filename[start:stop].lower() != ".py":
return space.wrap(filename)
py = make_source_pathname(filename)
if py is None:
py = filename[:-1]
try:
- st = os.stat(py)
+ st = os.stat(assert_str0(py))
except OSError:
pass
else:
@@ -950,7 +952,7 @@
if space.config.objspace.usepycfiles:
cpathname = make_compiled_pathname(pathname)
- src_stat = os.stat(pathname)
+ src_stat = os.stat(assert_str0(pathname))
mtime = int(src_stat[stat.ST_MTIME])
mode = src_stat[stat.ST_MODE]
stream = check_compiled_module(space, cpathname, mtime)
diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -768,6 +768,29 @@
ret = space.int_w(w_ret)
assert ret == 42
+ def test_load_compiled_module_nopathname(self):
+ space = self.space
+ mtime = 12345
+ co = compile('x = 42', '?', 'exec')
+ cpathname = _testfile(space, importing.get_pyc_magic(space), mtime, co)
+ w_modulename = space.wrap('somemodule')
+ stream = streamio.open_file_as_stream(cpathname, "rb")
+ try:
+ w_mod = space.wrap(Module(space, w_modulename))
+ magic = importing._r_long(stream)
+ timestamp = importing._r_long(stream)
+ w_ret = importing.load_compiled_module(space,
+ w_modulename,
+ w_mod,
+ None,
+ magic,
+ timestamp,
+ stream.readall())
+ finally:
+ stream.close()
+ filename = space.getattr(w_ret, space.wrap('__file__'))
+ assert space.str_w(filename) == u'?'
+
def test_parse_source_module(self):
space = self.space
pathname = _testfilesource()
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -422,7 +422,7 @@
def getcwd(space):
"""Return the current working directory as a string."""
try:
- cur = os.getcwdb()
+ cur = os.getcwdu()
except OSError, e:
raise wrap_oserror(space, e)
else:
diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -138,8 +138,6 @@
if mod == 'pypy.rlib.rbigint' or mod == 'pypy.rlib.rlocale' or mod == 'pypy.rlib.rsocket':
return False
- if '_geninterp_' in func.func_globals: # skip all geninterped stuff
- return False
if mod.startswith('pypy.interpreter.astcompiler.'):
return False
if mod.startswith('pypy.interpreter.pyparser.'):
diff --git a/pypy/module/pypyjit/test/test_policy.py b/pypy/module/pypyjit/test/test_policy.py
--- a/pypy/module/pypyjit/test/test_policy.py
+++ b/pypy/module/pypyjit/test/test_policy.py
@@ -14,12 +14,6 @@
from pypy.rlib.rlocale import setlocale
assert not pypypolicy.look_inside_function(setlocale)
-def test_geninterp():
- d = {'_geninterp_': True}
- exec """def f():
- pass""" in d
- assert not pypypolicy.look_inside_function(d['f'])
-
def test_astcompiler():
from pypy.interpreter.astcompiler import ast
assert not pypypolicy.look_inside_function(ast.AST.walkabout)
diff --git a/pypy/module/rbench/__init__.py b/pypy/module/rbench/__init__.py
deleted file mode 100644
--- a/pypy/module/rbench/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Package initialisation
-from pypy.interpreter.mixedmodule import MixedModule
-
-class Module(MixedModule):
- """geninterpreted benchmarks"""
-
- appleveldefs = {
- 'pystone': 'app_bench.pystone',
- 'richards': 'app_bench.richards',
- }
-
- interpleveldefs = {}
diff --git a/pypy/module/rbench/app_bench.py b/pypy/module/rbench/app_bench.py
deleted file mode 100644
--- a/pypy/module/rbench/app_bench.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from pypy.translator.test.rpystone import main as pystone
-from pypy.translator.goal.richards import main as richards
diff --git a/pypy/module/__builtin__/test/test_range.py b/pypy/module/test_lib_pypy/test__functools.py
rename from pypy/module/__builtin__/test/test_range.py
rename to pypy/module/test_lib_pypy/test__functools.py
--- a/pypy/module/__builtin__/test/test_range.py
+++ b/pypy/module/test_lib_pypy/test__functools.py
@@ -1,6 +1,6 @@
-import autopath
+from _functools import reduce
-class AppTestRange:
+class TestRange:
def test_range_toofew(self):
raises(TypeError, range)
@@ -22,7 +22,7 @@
def test_range_twoargs(self):
assert list(range(1, 2)) == [1]
-
+
def test_range_decreasingtwoargs(self):
assert list(range(3, 1)) == []
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -150,7 +150,7 @@
importing._prepare_module(space, w_mod, real_name, pkgpath)
co_filename = self.make_co_filename(filename)
code_w = importing.parse_source_module(space, co_filename, buf)
- importing.exec_code_module(space, w_mod, code_w)
+ importing.exec_code_module(space, w_mod, code_w, co_filename, None)
return w_mod
def _parse_mtime(self, space, filename):
diff --git a/pypy/objspace/flow/objspace.py b/pypy/objspace/flow/objspace.py
--- a/pypy/objspace/flow/objspace.py
+++ b/pypy/objspace/flow/objspace.py
@@ -105,7 +105,7 @@
is_ = None # real version added by add_operations()
id = None # real version added by add_operations()
- def newdict(self):
+ def newdict(self, module="ignored"):
if self.concrete_mode:
return Constant({})
return self.do_operation('newdict')
@@ -223,10 +223,8 @@
except UnwrapException:
raise Exception, "non-constant except guard"
if check_class in (NotImplementedError, AssertionError):
- # if we are in geninterp, we cannot catch these exceptions
- if not self.config.translation.builtins_can_raise_exceptions:
- raise error.FlowingError("Catching %s is not valid in RPython" %
- check_class.__name__)
+ raise error.FlowingError("Catching %s is not valid in RPython" %
+ check_class.__name__)
if not isinstance(check_class, tuple):
# the simple case
return ObjSpace.exception_match(self, w_exc_type, w_check_class)
@@ -440,41 +438,33 @@
exceptions = [Exception] # *any* exception by default
if isinstance(w_callable, Constant):
c = w_callable.value
- if not self.config.translation.builtins_can_raise_exceptions:
- if (isinstance(c, (types.BuiltinFunctionType,
- types.BuiltinMethodType,
- types.ClassType,
- types.TypeType)) and
- c.__module__ in ['__builtin__', 'exceptions']):
- exceptions = operation.implicit_exceptions.get(c)
+ if (isinstance(c, (types.BuiltinFunctionType,
+ types.BuiltinMethodType,
+ types.ClassType,
+ types.TypeType)) and
+ c.__module__ in ['__builtin__', 'exceptions']):
+ exceptions = operation.implicit_exceptions.get(c)
self.handle_implicit_exceptions(exceptions)
return w_res
def handle_implicit_exceptions(self, exceptions):
if not exceptions:
return
- if not self.config.translation.builtins_can_raise_exceptions:
- # clean up 'exceptions' by removing the non-RPythonic exceptions
- # which might be listed for geninterp.
- exceptions = [exc for exc in exceptions
- if exc is not TypeError and
- exc is not AttributeError]
- if exceptions:
- # catch possible exceptions implicitly. If the OperationError
- # below is not caught in the same function, it will produce an
- # exception-raising return block in the flow graph. Note that
- # even if the interpreter re-raises the exception, it will not
- # be the same ImplicitOperationError instance internally.
- context = self.getexecutioncontext()
- outcome, w_exc_cls, w_exc_value = context.guessexception(*exceptions)
- if outcome is not None:
- # we assume that the caught exc_cls will be exactly the
- # one specified by 'outcome', and not a subclass of it,
- # unless 'outcome' is Exception.
- #if outcome is not Exception:
- #w_exc_cls = Constant(outcome) Now done by guessexception itself
- #pass
- raise operation.ImplicitOperationError(w_exc_cls, w_exc_value)
+ # catch possible exceptions implicitly. If the OperationError
+ # below is not caught in the same function, it will produce an
+ # exception-raising return block in the flow graph. Note that
+ # even if the interpreter re-raises the exception, it will not
+ # be the same ImplicitOperationError instance internally.
+ context = self.getexecutioncontext()
+ outcome, w_exc_cls, w_exc_value = context.guessexception(*exceptions)
+ if outcome is not None:
+ # we assume that the caught exc_cls will be exactly the
+ # one specified by 'outcome', and not a subclass of it,
+ # unless 'outcome' is Exception.
+ #if outcome is not Exception:
+ #w_exc_cls = Constant(outcome) Now done by guessexception itself
+ #pass
+ raise operation.ImplicitOperationError(w_exc_cls, w_exc_value)
def w_KeyboardInterrupt(self):
# the reason to do this is: if you interrupt the flowing of a function
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -262,8 +262,6 @@
OverflowError: 'ovf',
IndexError: 'idx',
KeyError: 'key',
- AttributeError: 'att',
- TypeError: 'typ',
ZeroDivisionError: 'zer',
ValueError: 'val',
}
@@ -298,11 +296,6 @@
lis.append(OverflowError)
implicit_exceptions[name+"_ovf"] = lis
-for _name in 'getattr', 'delattr':
- _add_exceptions(_name, AttributeError)
-del _name
-
-_add_exceptions('iter', TypeError)
_add_exceptions("""div mod divmod truediv floordiv pow
inplace_div inplace_mod inplace_divmod inplace_truediv
inplace_floordiv inplace_pow""", ZeroDivisionError)
diff --git a/pypy/objspace/flow/specialcase.py b/pypy/objspace/flow/specialcase.py
--- a/pypy/objspace/flow/specialcase.py
+++ b/pypy/objspace/flow/specialcase.py
@@ -49,35 +49,9 @@
else:
raise Exception, "should call %r with exactly %d arguments" % (
fn, Arity[opname])
- if space.config.translation.builtins_can_raise_exceptions:
- # in this mode, avoid constant folding and raise an implicit Exception
- w_result = space.do_operation(opname, *args_w)
- space.handle_implicit_exceptions([Exception])
- return w_result
- else:
- # in normal mode, completely replace the call with the underlying
- # operation and its limited implicit exceptions semantic
- return getattr(space, opname)(*args_w)
-
-
-# This is not a space cache.
-# It is just collecting the compiled functions from all the source snippets.
-
-class FunctionCache(Cache):
- """A cache mapping applevel instances to dicts with simple functions"""
-
- def _build(app):
- """NOT_RPYTHON.
- Called indirectly by ApplevelClass.interphook().appcaller()."""
- dic = {}
- if not app.can_use_geninterp:
- return None
- if app.filename is not None:
- dic['__file__'] = app.filename
- dic['__name__'] = app.modname
- exec py.code.Source(app.source).compile() in dic
- return dic
- _build = staticmethod(_build)
+ # completely replace the call with the underlying
+ # operation and its limited implicit exceptions semantic
+ return getattr(space, opname)(*args_w)
# _________________________________________________________________________
# a simplified version of the basic printing routines, for RPython programs
@@ -99,29 +73,21 @@
s = '\n'
import os
os.write(1, s)
-# _________________________________________________________________________
-
-compiled_funcs = FunctionCache()
def sc_applevel(space, app, name, args_w):
- dic = compiled_funcs.getorbuild(app)
- if not dic:
- return None # signal that this is not RPython
- func = dic[name]
- if getattr(func, '_annspecialcase_', '').startswith('flowspace:'):
- # a hack to replace specific app-level helpers with simplified
- # RPython versions
- name = func._annspecialcase_[len('flowspace:'):]
- if name == 'print_item': # more special cases...
- w_s = space.do_operation('str', *args_w)
- args_w = (w_s,)
- func = globals()['rpython_' + name]
+ # special case only for print_item and print_newline
+ if 'pyopcode' in app.filename and name == 'print_item':
+ w_s = space.do_operation('str', *args_w)
+ args_w = (w_s,)
+ elif 'pyopcode' in app.filename and name == 'print_newline':
+ pass
else:
- # otherwise, just call the app-level helper and hope that it
- # is RPython enough
- pass
+ raise Exception("not RPython: calling %r from %r" % (name, app))
+ func = globals()['rpython_' + name]
return space.do_operation('simple_call', Constant(func), *args_w)
+# _________________________________________________________________________
+
def sc_r_uint(space, r_uint, args):
args_w, kwds_w = args.unpack()
assert not kwds_w
diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -968,61 +968,6 @@
g = self.codetest(f)
-class TestGenInterpStyle(Base):
- def setup_class(cls):
- cls.space = FlowObjSpace()
- cls.space.config.translation.builtins_can_raise_exceptions = True
-
- def reraiseAttributeError(v):
- try:
- x = getattr(v, "y")
- except AttributeError:
- raise
-
- def test_reraiseAttributeError(self):
- x = self.codetest(self.reraiseAttributeError)
- simplify_graph(x)
- self.show(x)
- excfound = []
- for link in x.iterlinks():
- if link.target is x.exceptblock:
- excfound.append(link.exitcase)
- assert len(excfound) == 2
- excfound.sort()
- expected = [Exception, AttributeError]
- expected.sort()
- assert excfound == expected
-
- def reraiseTypeError(dic):
- try:
- x = dic[5]
- except TypeError:
- raise
-
- def test_reraiseTypeError(self):
- x = self.codetest(self.reraiseTypeError)
- simplify_graph(x)
- self.show(x)
- excfound = []
- for link in x.iterlinks():
- if link.target is x.exceptblock:
- excfound.append(link.exitcase)
- assert len(excfound) == 2
- excfound.sort()
- expected = [Exception, TypeError]
- expected.sort()
- assert excfound == expected
-
- def test_can_catch_special_exceptions(self):
- def f():
- try:
- f()
- except NotImplementedError:
- pass
- graph = self.codetest(f)
- # assert did not crash
-
-
DATA = {'x': 5,
'y': 6}
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -6,7 +6,7 @@
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.register_all import register_all
from pypy.rlib import jit
-from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, r_uint
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, r_uint, is_valid_int
from pypy.rlib.rbigint import rbigint
"""
@@ -42,6 +42,7 @@
from pypy.objspace.std.longtype import long_typedef as typedef
def __init__(w_self, intval):
+ assert is_valid_int(intval)
w_self.intval = intval
def __repr__(w_self):
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -9,7 +9,7 @@
from pypy.objspace.descroperation import DescrOperation, raiseattrerror
from pypy.rlib.objectmodel import instantiate, r_dict, specialize, is_annotation_constant
from pypy.rlib.debug import make_sure_not_resized
-from pypy.rlib.rarithmetic import base_int, widen, maxint
+from pypy.rlib.rarithmetic import base_int, widen, maxint, is_valid_int
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib import jit
@@ -168,10 +168,6 @@
return self.newbool(x)
else:
return self.newint(x)
- # this is an inlined 'is_valid_int' which cannot be used
- # due to the special annotation nature of 'wrap'.
- if isinstance(x, long) and (-maxint - 1 <= x <= maxint):
- return self.newint(x)
if isinstance(x, str):
return wrapunicode(self, x.decode('ascii'))
if isinstance(x, unicode):
@@ -202,6 +198,11 @@
"NOT_RPYTHON"
# _____ this code is here to support testing only _____
+ # we might get there in non-translated versions if 'x' is
+ # a long that fits the correct range.
+ if is_valid_int(x):
+ return self.newint(x)
+
# wrap() of a container works on CPython, but the code is
# not RPython. Don't use -- it is kept around mostly for tests.
# Use instead newdict(), newlist(), newtuple().
@@ -220,17 +221,7 @@
# The following cases are even stranger.
# Really really only for tests.
if type(x) is long:
- if self.config.objspace.std.withsmalllong:
- from pypy.rlib.rarithmetic import r_longlong
- try:
- rx = r_longlong(x)
- except OverflowError:
- pass
- else:
- from pypy.objspace.std.smalllongobject import \
- W_SmallLongObject
- return W_SmallLongObject(rx)
- return W_LongObject.fromlong(x)
+ return self.wraplong(x)
if isinstance(x, slice):
return W_SliceObject(self.wrap(x.start),
self.wrap(x.stop),
@@ -271,6 +262,20 @@
return w_result
return None
+ def wraplong(self, x):
+ "NOT_RPYTHON"
+ if self.config.objspace.std.withsmalllong:
+ from pypy.rlib.rarithmetic import r_longlong
+ try:
+ rx = r_longlong(x)
+ except OverflowError:
+ pass
+ else:
+ from pypy.objspace.std.smalllongobject import \
+ W_SmallLongObject
+ return W_SmallLongObject(rx)
+ return W_LongObject.fromlong(x)
+
def unwrap(self, w_obj):
"""NOT_RPYTHON"""
if isinstance(w_obj, Wrappable):
diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -2,7 +2,7 @@
import sys
from pypy.objspace.std import intobject as iobj
from pypy.objspace.std.multimethod import FailedToImplement
-from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.rarithmetic import r_uint, is_valid_int
from pypy.rlib.rbigint import rbigint
@@ -15,7 +15,7 @@
while 1:
ires = x << n
lres = l << n
- if type(ires) is long or lres != ires:
+ if not is_valid_int(ires) or lres != ires:
return n
n += 1
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -3,6 +3,7 @@
from pypy.objspace.std.listobject import W_ListObject, SizeListStrategy,\
IntegerListStrategy, ObjectListStrategy
from pypy.interpreter.error import OperationError
+from pypy.rlib.rarithmetic import is_valid_int
from pypy.conftest import gettestobjspace, option
@@ -242,7 +243,7 @@
self.space.raises_w(self.space.w_IndexError,
self.space.setitem, w_list, w(key), w(42))
else:
- if isinstance(value, int): # non-slicing
+ if is_valid_int(value): # non-slicing
if random.random() < 0.25: # deleting
self.space.delitem(w_list, w(key))
del expected[key]
diff --git a/pypy/objspace/std/test/test_newformat.py b/pypy/objspace/std/test/test_newformat.py
--- a/pypy/objspace/std/test/test_newformat.py
+++ b/pypy/objspace/std/test/test_newformat.py
@@ -358,6 +358,13 @@
for x in l[0]:
assert isinstance(x, str)
+ def test_formatter_parser_escape(self):
+ import _string
+ l = list(_string.formatter_parser("{{a}}"))
+ assert l == [('{', None, None, None), ('a}', None, None, None)]
+ l = list(_string.formatter_parser("{{{{"))
+ assert l == [('{', None, None, None), ('{', None, None, None)]
+
def test_formatter_field_name_split(self):
import _string
first, rest = _string.formatter_field_name_split('')
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -531,6 +531,8 @@
# Need default encoding utf-8, but sys.setdefaultencoding
# is removed after startup.
import sys
+ if not hasattr(sys, 'setdefaultencoding'):
+ skip("sys.setdefaultencoding() not available")
old_encoding = sys.getdefaultencoding()
# Duplicate unittest.test_support.CleanImport logic because it won't
# import.
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -92,7 +92,10 @@
We therefore can no longer use the int type as it is, but need
to use long everywhere.
"""
-
+
+# XXX returning int(n) should not be necessary and should be simply n.
+# XXX TODO: replace all int(n) by long(n) and fix everything that breaks.
+# XXX Then relax it and replace int(n) by n.
def intmask(n):
if isinstance(n, objectmodel.Symbolic):
return n # assume Symbolics don't overflow
@@ -137,8 +140,11 @@
maxint = int(LONG_TEST - 1)
def is_valid_int(r):
- return isinstance(r, (int, long)) and (
+ if objectmodel.we_are_translated():
+ return isinstance(r, int)
+ return type(r) in (int, long, bool) and (
-maxint - 1 <= r <= maxint)
+is_valid_int._annspecialcase_ = 'specialize:argtype(0)'
def ovfcheck(r):
"NOT_RPYTHON"
diff --git a/pypy/rlib/rzlib.py b/pypy/rlib/rzlib.py
--- a/pypy/rlib/rzlib.py
+++ b/pypy/rlib/rzlib.py
@@ -1,6 +1,7 @@
from __future__ import with_statement
import sys
+from pypy.rlib import rgc
from pypy.rlib.rstring import StringBuilder
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.tool import rffi_platform
@@ -236,6 +237,7 @@
compress data.
"""
stream = lltype.malloc(z_stream, flavor='raw', zero=True)
+ rgc.add_memory_pressure(rffi.sizeof(z_stream))
err = _deflateInit2(stream, level, method, wbits, memLevel, strategy)
if err == Z_OK:
return stream
@@ -264,6 +266,7 @@
decompress data.
"""
stream = lltype.malloc(z_stream, flavor='raw', zero=True)
+ rgc.add_memory_pressure(rffi.sizeof(z_stream))
err = _inflateInit2(stream, wbits)
if err == Z_OK:
return stream
diff --git a/pypy/rlib/test/test_rarithmetic.py b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -330,6 +330,15 @@
return a == b
py.test.raises(MissingRTypeOperation, "self.interpret(f, [42.0])")
+ def test_is_valid_int(self):
+ def f(x):
+ return (is_valid_int(x) * 4 +
+ is_valid_int(x > 0) * 2 +
+ is_valid_int(x + 0.5))
+ assert f(123) == 4 + 2
+ res = self.interpret(f, [123])
+ assert res == 4 + 2
+
class TestLLtype(BaseTestRarithmetic, LLRtypeMixin):
pass
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1,6 +1,6 @@
from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception
from pypy.rlib.rarithmetic import intmask, r_uint, ovfcheck, r_longlong
-from pypy.rlib.rarithmetic import r_ulonglong
+from pypy.rlib.rarithmetic import r_ulonglong, is_valid_int
from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap
from pypy.rpython.lltypesystem import rclass
from pypy.rpython.ootypesystem import ootype
@@ -1021,22 +1021,22 @@
# Overflow-detecting variants
def op_int_neg_ovf(self, x):
- assert type(x) is int
+ assert is_valid_int(x)
try:
return ovfcheck(-x)
except OverflowError:
self.make_llexception()
def op_int_abs_ovf(self, x):
- assert type(x) is int
+ assert is_valid_int(x)
try:
return ovfcheck(abs(x))
except OverflowError:
self.make_llexception()
def op_int_lshift_ovf(self, x, y):
- assert isinstance(x, int)
- assert isinstance(y, int)
+ assert is_valid_int(x)
+ assert is_valid_int(y)
try:
return ovfcheck(x << y)
except OverflowError:
@@ -1060,7 +1060,9 @@
return r
'''%locals()
elif operator == '%':
- code = '''r = %(checkfn)s(x %% y)
+ ## overflow check on % does not work with emulated int
+ code = '''%(checkfn)s(x // y)
+ r = x %% y
if x^y < 0 and x%%y != 0:
r -= y
return r
@@ -1077,15 +1079,15 @@
self.make_llexception()
""" % locals()).compile() in globals(), d
- _makefunc2('op_int_add_ovf', '+', '(int, llmemory.AddressOffset)')
- _makefunc2('op_int_mul_ovf', '*', '(int, llmemory.AddressOffset)', 'int')
- _makefunc2('op_int_sub_ovf', '-', 'int')
- _makefunc2('op_int_floordiv_ovf', '//', 'int') # XXX negative args
- _makefunc2('op_int_floordiv_zer', '//', 'int') # can get off-by-one
- _makefunc2('op_int_floordiv_ovf_zer', '//', 'int') # (see op_int_floordiv)
- _makefunc2('op_int_mod_ovf', '%', 'int')
- _makefunc2('op_int_mod_zer', '%', 'int')
- _makefunc2('op_int_mod_ovf_zer', '%', 'int')
+ _makefunc2('op_int_add_ovf', '+', '(int, long, llmemory.AddressOffset)')
+ _makefunc2('op_int_mul_ovf', '*', '(int, long, llmemory.AddressOffset)', '(int, long)')
+ _makefunc2('op_int_sub_ovf', '-', '(int, long)')
+ _makefunc2('op_int_floordiv_ovf', '//', '(int, long)') # XXX negative args
+ _makefunc2('op_int_floordiv_zer', '//', '(int, long)') # can get off-by-one
+ _makefunc2('op_int_floordiv_ovf_zer', '//', '(int, long)') # (see op_int_floordiv)
+ _makefunc2('op_int_mod_ovf', '%', '(int, long)')
+ _makefunc2('op_int_mod_zer', '%', '(int, long)')
+ _makefunc2('op_int_mod_ovf_zer', '%', '(int, long)')
_makefunc2('op_uint_floordiv_zer', '//', 'r_uint')
_makefunc2('op_uint_mod_zer', '%', 'r_uint')
@@ -1107,7 +1109,7 @@
x = x.default
# if type(x) is a subclass of Symbolic, bool(x) will usually raise
# a TypeError -- unless __nonzero__ has been explicitly overridden.
- assert isinstance(x, (int, Symbolic))
+ assert is_valid_int(x) or isinstance(x, Symbolic)
return bool(x)
# hack for jit.codegen.llgraph
@@ -1129,7 +1131,7 @@
def op_oonewarray(self, ARRAY, length):
assert isinstance(ARRAY, ootype.Array)
- assert isinstance(length, int)
+ assert is_valid_int(length)
return ootype.oonewarray(ARRAY, length)
def op_runtimenew(self, class_):
diff --git a/pypy/rpython/lltypesystem/llmemory.py b/pypy/rpython/lltypesystem/llmemory.py
--- a/pypy/rpython/lltypesystem/llmemory.py
+++ b/pypy/rpython/lltypesystem/llmemory.py
@@ -8,6 +8,8 @@
from pypy.rlib.objectmodel import Symbolic
from pypy.rpython.lltypesystem import lltype
from pypy.tool.uid import uid
+from pypy.rlib.rarithmetic import is_valid_int
+
class AddressOffset(Symbolic):
@@ -28,7 +30,7 @@
def __ge__(self, other):
if self is other:
return True
- elif (isinstance(other, (int, long)) and other == 0 and
+ elif (is_valid_int(other) and other == 0 and
self.known_nonneg()):
return True
else:
@@ -58,7 +60,7 @@
return "<ItemOffset %r %r>" % (self.TYPE, self.repeat)
def __mul__(self, other):
- if not isinstance(other, int):
+ if not is_valid_int(other):
return NotImplemented
return ItemOffset(self.TYPE, self.repeat * other)
diff --git a/pypy/rpython/memory/gc/test/test_direct.py b/pypy/rpython/memory/gc/test/test_direct.py
--- a/pypy/rpython/memory/gc/test/test_direct.py
+++ b/pypy/rpython/memory/gc/test/test_direct.py
@@ -9,7 +9,7 @@
import py
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder
-from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.rlib.rarithmetic import LONG_BIT, is_valid_int
WORD = LONG_BIT // 8
@@ -286,7 +286,7 @@
p = self.malloc(S)
hash = self.gc.identityhash(p)
print hash
- assert isinstance(hash, (int, long))
+ assert is_valid_int(hash)
assert hash == self.gc.identityhash(p)
self.stackroots.append(p)
for i in range(6):
@@ -299,7 +299,7 @@
self.gc.collect()
hash = self.gc.identityhash(self.stackroots[-1])
print hash
- assert isinstance(hash, (int, long))
+ assert is_valid_int(hash)
for i in range(6):
self.gc.collect()
assert hash == self.gc.identityhash(self.stackroots[-1])
@@ -311,7 +311,7 @@
self.gc.collect()
hash = self.gc.identityhash(self.stackroots[-1])
print hash
- assert isinstance(hash, (int, long))
+ assert is_valid_int(hash)
for i in range(2):
self.gc.collect()
assert hash == self.gc.identityhash(self.stackroots[-1])
@@ -319,7 +319,7 @@
# (4) p is a prebuilt object
hash = self.gc.identityhash(p_const)
print hash
- assert isinstance(hash, (int, long))
+ assert is_valid_int(hash)
assert hash == self.gc.identityhash(p_const)
# (5) p is actually moving (for the markcompact gc)
p0 = self.malloc(S)
diff --git a/pypy/rpython/test/test_llinterp.py b/pypy/rpython/test/test_llinterp.py
--- a/pypy/rpython/test/test_llinterp.py
+++ b/pypy/rpython/test/test_llinterp.py
@@ -353,13 +353,16 @@
try:
return ovfcheck((-sys.maxint - 1) % x)
except OverflowError:
- return 1
+ return 43
except ZeroDivisionError:
- return 0
+ return 42
res = interpret(f, [0])
- assert res == 0
+ assert res == 42
+ # the following test doesn't work any more before translation,
+ # but "too bad" is the best answer I suppose
res = interpret(f, [-1])
- assert res == 1
+ if 0:
+ assert res == 43
res = interpret(f, [30])
assert res == (-sys.maxint - 1) % 30
diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -5,7 +5,7 @@
from pypy.rlib.debug import llinterpcall
from pypy.rpython.lltypesystem import lltype
from pypy.tool import udir
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, is_valid_int
from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
from pypy.annotation.builtin import *
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
@@ -567,7 +567,7 @@
if r_longlong is not r_int:
assert isinstance(res, r_longlong)
else:
- assert isinstance(res, int)
+ assert is_valid_int(res)
#
def llfn(v):
return rffi.cast(rffi.ULONGLONG, v)
diff --git a/pypy/translator/c/src/debug_print.c b/pypy/translator/c/src/debug_print.c
--- a/pypy/translator/c/src/debug_print.c
+++ b/pypy/translator/c/src/debug_print.c
@@ -13,6 +13,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
+#include "common_header.h"
#include "src/profiling.h"
#include "src/debug_print.h"
diff --git a/pypy/translator/c/test/test_database.py b/pypy/translator/c/test/test_database.py
--- a/pypy/translator/c/test/test_database.py
+++ b/pypy/translator/c/test/test_database.py
@@ -232,7 +232,7 @@
B = Signed
db = LowLevelDatabase()
assert db.gettype(A) == "int @"
- assert db.gettype(B) == "long @"
+ assert db.gettype(B) == "Signed @"
def test_recursive_struct():
diff --git a/pypy/translator/c/test/test_newgc.py b/pypy/translator/c/test/test_newgc.py
--- a/pypy/translator/c/test/test_newgc.py
+++ b/pypy/translator/c/test/test_newgc.py
@@ -675,8 +675,8 @@
gc.collect()
p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0]
p_a2 = rffi.cast(rffi.VOIDPP, ll_args[1])[0]
- a1 = rffi.cast(rffi.LONGP, p_a1)[0]
- a2 = rffi.cast(rffi.LONGP, p_a2)[0]
+ a1 = rffi.cast(rffi.SIGNEDP, p_a1)[0]
+ a2 = rffi.cast(rffi.SIGNEDP, p_a2)[0]
res = rffi.cast(rffi.INTP, ll_res)
if a1 > a2:
res[0] = rffi.cast(rffi.INT, 1)
@@ -692,7 +692,7 @@
ptr = CallbackFuncPtr([ffi_type_pointer, ffi_type_pointer],
ffi_type_sint, callback)
- TP = rffi.CArray(rffi.LONG)
+ TP = rffi.CArray(lltype.Signed)
to_sort = lltype.malloc(TP, 4, flavor='raw')
to_sort[0] = 4
to_sort[1] = 3
@@ -700,7 +700,7 @@
to_sort[3] = 2
qsort.push_arg(rffi.cast(rffi.VOIDP, to_sort))
qsort.push_arg(rffi.cast(rffi.SIZE_T, 4))
- qsort.push_arg(rffi.cast(rffi.SIZE_T, rffi.sizeof(rffi.LONG)))
+ qsort.push_arg(rffi.cast(rffi.SIZE_T, rffi.sizeof(lltype.Signed)))
qsort.push_arg(rffi.cast(rffi.VOIDP, ptr.ll_closure))
qsort.call(lltype.Void)
result = [to_sort[i] for i in range(4)] == [1,2,3,4]
@@ -1202,7 +1202,7 @@
def f():
from pypy.rpython.lltypesystem import lltype, rffi
alist = [A() for i in range(50000)]
- idarray = lltype.malloc(rffi.LONGP.TO, len(alist), flavor='raw')
+ idarray = lltype.malloc(rffi.SIGNEDP.TO, len(alist), flavor='raw')
# Compute the id of all elements of the list. The goal is
# to not allocate memory, so that if the GC needs memory to
# remember the ids, it will trigger some collections itself
diff --git a/pypy/translator/geninterplevel.py b/pypy/translator/geninterplevel.py
deleted file mode 100644
--- a/pypy/translator/geninterplevel.py
+++ /dev/null
@@ -1,1544 +0,0 @@
-"""
-Implementation of a translator from application Python to
-interpreter level RPython.
-
-The idea is that we can automatically transform application level
-implementations of methods into some equivalent representation at
-interpreter level. Then, the RPython to C translation might
-hopefully spit out some more efficient code than always interpreting
-these methods.
-
-Note that the application level functions are treated as rpythonic,
-in a sense that globals are constants, for instance. This definition
-is not exact and might change.
-
-The interface for this module is
-
- (initfunc, newsrc) = translate_as_module(
- sourcetext,
- filename=None,
- modname="app2interpexec",
- tmpname=None)
-
-If filename is given, it is used as a reference where
-this sourcetext can be literally found, to produce
-real line numbers. It cannot be just any name but
-must exist and contain the source code somewhere.
-
-modname is optional and will be put into the dictionary
-to be created.
-
-tmpname is optional. If given, a temporary file will
-be created for debugging purposes.
-
-The returned newsrc is the generated source text.
-It is used in gateway.py's caching mechanism.
-The initfunc result is a function named "init"+modname
-It must be called with a space instance and returns
-a wrapped dict which is suitable to use as a module dict,
-containing all trnaslatedobjects with their originalname.
-
-Integration of this module is finished.
-There are no longer hand-generated source
-pieces in pypy svn.
-"""
-
-import autopath, os, sys, types
-import inspect
-import cPickle as pickle, __builtin__
-from copy_reg import _HEAPTYPE
-from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
-from pypy.objspace.flow.model import c_last_exception, checkgraph
-from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS
-from types import FunctionType, CodeType, ModuleType, MethodType
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.argument import ArgumentsForTranslation, Arguments
-from pypy.translator.backendopt.ssa import SSI_to_SSA
-
-from pypy.translator.translator import TranslationContext
-from pypy.objspace.flow.objspace import FlowObjSpace
-
-from pypy.tool.sourcetools import render_docstr, NiceCompile
-
-from pypy.translator.gensupp import ordered_blocks, UniqueList, builtin_base, \
- uniquemodulename, C_IDENTIFIER, NameManager
-from pypy.tool.identity_dict import identity_dict
-
-import pypy # __path__
-import py.path
-from pypy.tool.ansi_print import ansi_log
-
-log = py.log.Producer("geninterp")
-py.log.setconsumer("geninterp", ansi_log)
-
-GI_VERSION = '1.2.9' # bump this for substantial changes
-# ____________________________________________________________
-
-try:
- set
-except NameError:
- class fake_set(object):
- pass
- class fake_frozenset(object):
- pass
- builtin_set = fake_set
- builtin_frozenset = fake_frozenset
- faked_set = True
-else:
- builtin_set = set
- builtin_frozenset = frozenset
- faked_set = False
-
-def eval_helper(self, typename, expr):
- name = self.uniquename("gtype_%s" % typename)
- unique = self.uniquenameofprebuilt("eval_helper", eval_helper)
- self.initcode.append1(
- 'def %s(expr):\n'
- ' dic = space.newdict()\n'
- ' if "types." in expr:\n'
- ' space.exec_("import types", dic, dic, hidden_applevel=True)\n'
- ' else:\n'
- ' space.exec_("", dic, dic, hidden_applevel=True)\n'
- ' return space.eval(expr, dic, dic, hidden_applevel=True)' % (unique, ))
- self.initcode.append1('%s = %s(%r)' % (name, unique, expr))
- return name
-
-def unpickle_helper(self, name, value):
- unique = self.uniquenameofprebuilt("unpickle_helper", unpickle_helper)
- self.initcode.append1(
- 'def %s(value):\n'
- ' dic = space.newdict()\n'
- ' space.exec_("import cPickle as pickle", dic, dic, hidden_applevel=True)\n'
- ' return space.eval("pickle.loads(%%r)" %% value, dic, dic, hidden_applevel=True)' % unique)
- self.initcode.append1('%s = %s(%r)' % (
- name, unique, pickle.dumps(value, 2)) )
-
-# hey, for longs we can do even easier:
-def long_helper(self, name, value):
- unique = self.uniquenameofprebuilt("long_helper", long_helper)
- self.initcode.append1(
- 'def %s(value):\n'
- ' dic = space.newdict()\n'
- ' space.exec_("", dic, dic, hidden_applevel=True) # init __builtins__\n'
- ' return space.eval(value, dic, dic, hidden_applevel=True)' % unique)
- self.initcode.append1('%s = %s(%r)' % (
- name, unique, repr(value) ) )
-
-def bltinmod_helper(self, mod):
- name = self.uniquename("mod_%s" % mod.__name__)
- unique = self.uniquenameofprebuilt("bltinmod_helper", bltinmod_helper)
- self.initcode.append1(
- 'def %s(name):\n'
- ' dic = space.newdict()\n'
- ' space.exec_("import %%s" %% name, dic, dic, hidden_applevel=True)\n'
- ' return space.eval("%%s" %% name, dic, dic, hidden_applevel=True)' % (unique, ))
- self.initcode.append1('%s = %s(%r)' % (name, unique, mod.__name__))
- return name
-
-class GenRpy:
- def __init__(self, translator, entrypoint=None, modname=None, moddict=None):
- self.translator = translator
- if entrypoint is None:
- entrypoint = translator.entrypoint
- self.entrypoint = entrypoint
- self.modname = self.trans_funcname(modname or
- uniquemodulename(entrypoint))
- self.moddict = moddict # the dict if we translate a module
-
- def late_OperationError():
- self.initcode.append1(
- 'from pypy.interpreter.error import OperationError as gOperationError')
- return 'gOperationError'
- def late_Arguments():
- self.initcode.append1('from pypy.interpreter import gateway')
- return 'gateway.Arguments'
-
- self.rpynames = {Constant(None).key: 'space.w_None',
- Constant(False).key: 'space.w_False',
- Constant(True).key: 'space.w_True',
- Constant(Ellipsis).key: 'space.w_Ellipsis',
- Constant(NotImplemented).key: 'space.w_NotImplemented',
- Constant(OperationError).key: late_OperationError,
- Constant(Arguments).key: late_Arguments,
- }
- self.initcode = UniqueList() # list of lines for the module's initxxx()
- self.latercode = UniqueList()
- # list of generators generating extra lines
- # for later in initxxx() -- for recursive
- # objects
- self.namespace = NameManager()
- self.namespace.make_reserved_names('__doc__ __args__ space goto')
- self.globaldecl = []
- self.globalobjects = []
- self.pendingfunctions = []
- self.currentfunc = None
- self.debugstack = () # linked list of nested nameof()
-
- # special constructors:
- self.has_listarg = {}
- for name in "newtuple newlist".split():
- self.has_listarg[name] = name
-
- # catching all builtins in advance, to avoid problems
- # with modified builtins
-
- class bltinstub:
- def __init__(self, name):
- self.__name__ = name
- def __repr__(self):
- return '<%s>' % self.__name__
-
- self.ibuiltin_ids = identity_dict()
- self.ibuiltin_ids.update([
- (value, bltinstub(key))
- for key, value in __builtin__.__dict__.items()
- if callable(value) and type(value) not in [types.ClassType, type] ] )
-
- self.space = FlowObjSpace() # for introspection
-
- self.use_fast_call = True
- self.specialize_goto = False
- self._labeltable = {} # unique label names, reused per func
-
- self._space_arities = None
-
- self._signature_cache = {}
- self._defaults_cache = {}
-
- def expr(self, v, localscope, wrapped = True):
- if isinstance(v, Variable):
- return localscope.localname(v.name, wrapped)
- elif isinstance(v, Constant):
- return self.nameof(v.value,
- debug=('Constant in the graph of', self.currentfunc))
- else:
- raise TypeError, "expr(%r)" % (v,)
-
- def arglist(self, args, localscope):
- res = [self.expr(arg, localscope) for arg in args]
- return ", ".join(res)
-
- def oper(self, op, localscope):
- if op.opname in ('issubtype', 'isinstance'):
- arg = op.args[1]
- if (not isinstance(arg, Constant)
- or not isinstance(arg.value, (type, types.ClassType))):
- func = issubclass if op.opname == 'issubtype' else isinstance
- op = SpaceOperation("simple_call",
- [Constant(func)]+op.args,
- op.result)
- if op.opname == "simple_call":
- v = op.args[0]
- space_shortcut = self.try_space_shortcut_for_builtin(v, len(op.args)-1,
- op.args[1:])
- if space_shortcut is not None:
- # space method call
- exv = space_shortcut
- fmt = "%(res)s = %(func)s(%(args)s)"
- else:
- # import sys|__builtin__|_codecs avoid going through __import__
- if isinstance(v, Constant) and v.value is __builtin__.__import__:
- name, glb, loc, frm_lst = op.args[1:]
- if (isinstance(name, Constant) and name.value in ('sys', '__builtin__', '_codecs') and
- isinstance(loc, Constant) and loc.value is None and
- isinstance(frm_lst, Constant) and frm_lst.value is None):
- return "%s = space.getbuiltinmodule(%r)" % (self.expr(op.result, localscope),
- name.value)
- exv = self.expr(v, localscope)
- # default for a spacecall:
- fmt = "%(res)s = space.call_function(%(func)s, %(args)s)"
- # see if we can optimize for a fast call.
- # we just do the very simple ones.
- if self.use_fast_call and (isinstance(v, Constant)
- and exv.startswith('gfunc_')):
- func = v.value
- if (not func.func_code.co_flags & CO_VARARGS) and (
- func.func_defaults is None):
- fmt = "%(res)s = fastf_%(func)s(space, %(args)s)"
- exv = exv[6:]
- return fmt % {"res" : self.expr(op.result, localscope),
- "func": exv,
- "args": self.arglist(op.args[1:], localscope) }
- if op.opname == "call_args":
- v = op.args[0]
- exv = self.expr(v, localscope)
- fmt = (
- "_args = %(Arg)s(space, [%(args_w)s], %(keywords)s, [%(keywords_w)s], %(w_stararg)s, %(w_starstararg)s)\n"
- "%(res)s = space.call_args(%(func)s, _args)")
- assert isinstance(op.args[1], Constant)
- shape = op.args[1].value
- # make a list out of the second shape elt.
- shape = shape[0], list(shape[1]), shape[2], shape[3]
- arglist = [self.expr(arg, localscope) for arg in op.args[2:]]
- args = ArgumentsForTranslation.fromshape(None, shape, arglist)
- return fmt % {"res": self.expr(op.result, localscope),
- "func": exv,
- "args_w": ", ".join(args.arguments_w),
- "keywords": args.keywords,
- "keywords_w": ", ".join(args.keywords_w),
- "w_stararg": args.w_stararg,
- "w_starstararg": args.w_starstararg,
- 'Arg': self.nameof(Arguments) }
- if op.opname == "hint":
- return "%s = %s" % (self.expr(op.result, localscope),
- self.expr(op.args[0], localscope))
- if op.opname in self.has_listarg:
- fmt = "%s = %s([%s])"
- else:
- fmt = "%s = %s(%s)"
- # special case is_true
- opname = op.opname
- if opname.startswith('getitem_'):
- opname = 'getitem'
- wrapped = opname != "is_true"
- oper = "space.%s" % opname
- return fmt % (self.expr(op.result, localscope, wrapped), oper,
- self.arglist(op.args, localscope))
-
- def large_assignment(self, left, right, margin=65):
- expr = "(%s) = (%s)" % (", ".join(left), ", ".join(right))
- pieces = expr.split(",")
- res = [pieces.pop(0)]
- for piece in pieces:
- if len(res[-1])+len(piece)+1 > margin:
- res[-1] += ","
- res.append(piece)
- else:
- res[-1] += (","+piece)
- return res
-
- def large_initialize(self, vars, margin=65):
- res = []
- nonestr = "None"
- margin -= len(nonestr)
- for var in vars:
- ass = var+"="
- if not res or len(res[-1]) >= margin:
- res.append(ass)
- else:
- res[-1] += ass
- res = [line + nonestr for line in res]
- return res
-
- def mklabel(self, blocknum):
- if self.specialize_goto:
- lbname = self._labeltable.get(blocknum)
- if not lbname:
- self.initcode.append1(
- 'from pypy.objspace.flow.framestate import SpecTag')
- lbname = self.uniquename("glabel_%d" % blocknum)
- self._labeltable[blocknum] = lbname
- self.initcode.append1('%s = SpecTag()' % lbname)
- return lbname
- else:
- return repr(blocknum)
-
- def gen_link(self, link, localscope, blocknum, block, linklocalvars=None):
- "Generate the code to jump across the given Link."
- linklocalvars = linklocalvars or {}
- left, right = [], []
- for a1, a2 in zip(link.args, link.target.inputargs):
- if a1 in linklocalvars:
- src = linklocalvars[a1]
- else:
- src = self.expr(a1, localscope)
- dest = self.expr(a2, localscope)
- if src != dest:
- left.append(dest)
- right.append(src)
- if left: # anything at all?
- txt = "%s = %s" % (", ".join(left), ", ".join(right))
- if len(txt) <= 65: # arbitrary
- yield txt
- else:
- for line in self.large_assignment(left, right):
- yield line
- goto = blocknum[link.target]
- yield 'goto = %s' % self.mklabel(goto)
- if goto <= blocknum[block]:
- yield 'continue'
-
- def register_early(self, obj, name):
- # this was needed for recursive lists.
- # note that self.latercode led to too late initialization.
- key = Constant(obj).key
- self.rpynames[key] = name
-
- def nameof(self, obj, debug=None, namehint=None):
- key = Constant(obj).key
- try:
- txt = self.rpynames[key]
- if type(txt) is not str:
- # this is a predefined constant, initialized on first use
- func = txt
- txt = func()
- self.rpynames[key] = txt
- return txt
-
- except KeyError:
- if debug:
- stackentry = debug, obj
- else:
- stackentry = obj
- self.debugstack = (self.debugstack, stackentry)
- obj_builtin_base = builtin_base(obj)
- if obj_builtin_base in (object, int, long) and type(obj) is not obj_builtin_base:
- # assume it's a user defined thingy
- name = self.nameof_instance(obj)
- else:
- # shortcutting references to __builtin__
- if obj in self.ibuiltin_ids:
- func = self.ibuiltin_ids[obj]
- #name = self.get_nameof_builtin_func(func)
- # the above is quicker in principle, but pulls more
- # stuff in, so it is slower right now.
- name = "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- else:
- for cls in type(obj).__mro__:
- meth = getattr(self,
- 'nameof_' + cls.__name__.replace(' ', ''),
- None)
- if meth:
- break
- else:
- raise Exception, "nameof(%r)" % (obj,)
-
- code = meth.im_func.func_code
- if namehint and 'namehint' in code.co_varnames[:code.co_argcount]:
- name = meth(obj, namehint=namehint)
- else:
- name = meth(obj)
- self.debugstack, x = self.debugstack
- assert x is stackentry
- self.rpynames[key] = name
- return name
-
- def get_nameof_builtin_func(self, func):
- # this is a hack!
- # in some cases, like exceptions, we don't have space.builtin available,
- #so we crate a fall-back...
- name = self.uniquename('gbltin_' + func.__name__)
- self.initcode.append1('''\
-try:
- # see if we have space.builtin in this context
- space.builtin
-except AttributeError:
- print "didn\'t get", %(bltin)r
- def %(name)s(space, __args__):
- w_func = space.builtin.get(%(bltin)r)
- return space.call_args(w_func, __args__)
- %(name)s = space.wrap(gateway.interp2app(%(name)s, unwrap_spec=[gateway.ObjSpace, gateway.Arguments]))
-else:
- print "got it:", %(bltin)r
- %(name)s = space.builtin.get(%(bltin)r)'''
- % {'name': name, 'bltin': func.__name__} )
- return name
-
- def uniquename(self, basename):
- name = self.namespace.uniquename(basename)
- self.globalobjects.append(name)
- self.globaldecl.append('# global object %s' % (name,))
- return name
-
- def uniquenameofprebuilt(self, basename, obj):
- # identifying an object and giving it a name,
- # without the attempt to render it.
- key = Constant(obj).key
- try:
- txt = self.rpynames[key]
- except KeyError:
- self.rpynames[key] = txt = self.uniquename(basename)
- return txt
-
- def nameof_object(self, value):
- if type(value) is not object:
- # try to just wrap it?
- name = self.uniquename('g_%sinst_%r' % (type(value).__name__, value))
- self.initcode.append1('%s = space.wrap(%r)' % (name, value))
- return name
- name = self.uniquename('g_object')
- self.initcode.append('_tup = space.newtuple([])\n'
- '%s = space.call(space.w_object, _tup)'
- % name)
- return name
-
- def is_module_builtin(self, mod):
- if not hasattr(mod, "__file__") or mod.__file__ is None:
- return True
- if not (mod.__file__.endswith('.pyc') or
- mod.__file__.endswith('.py') or
- mod.__file__.endswith('.pyo')):
- return True
- if mod.__file__.endswith('*.py'): # on top of PyPy, a mixed module
- return True
- return False
-
- def nameof_module(self, value):
- if value is os or self.is_module_builtin(value):
- return bltinmod_helper(self, value)
-
- # we might have createda reference to a module
- # that is non-standard.
-
- # SKIPPING
- return "space.w_None"
-
- # check whether we can import
- try:
- import value
- need_extra_path = False
- except ImportError:
- need_extra_path = True
- name = self.uniquename('mod_%s' % value.__name__)
- if need_extra_path:
- assert False
- ## self.initcode.append1('import pypy')
- ## self.initcode.append1('import sys')
- ## self.initcode.append1('import os')
- ## self.initcode.append1('for pkgdir in pypy.__path__:\n'
- ## ' libdir = os.path.join(pkgdir, "lib")\n'
- ## ' if os.path.isdir(libdir):\n'
- ## ' break\n'
- ## 'else:\n'
- ## ' raise Exception, "cannot find pypy/lib directory"\n'
- ## 'sys.path.insert(0, libdir)\n')
- ## self.initcode.append1('try:\n'
- ## ' import %s as _tmp\n'
- ## 'finally:\n'
- ## ' if libdir in sys.path:\n'
- ## ' sys.path.remove(libdir)\n' % value.__name__)
- else:
- self.initcode.append1('import %s as _tmp' % value.__name__)
- self.initcode.append1('%s = space.wrap(_tmp)' % (name))
- return name
-
-
- def nameof_int(self, value):
- if value >= 0:
- name = 'gi_%d' % value
- else:
- # make sure that the type ident is completely described by
- # the prefixbefore the initial '_' for easy postprocessing
- name = 'gi_minus_%d' % abs(value)
- name = self.uniquename(name)
- self.initcode.append1('%s = space.wrap(%d)' % (name, value))
- return name
-
- def nameof_long(self, value):
- # assume we want them in hex most of the time
- if value < 256L:
- s = "%dL" % value
- else:
- s = "0x%08xL" % value
- if value >= 0:
- name = 'glong_%s' % s
- else:
- # mae sure that the type ident is completely described by
- # the prefix before the initial '_'
- name = 'glong_minus_%d' % abs(value)
- name = self.uniquename(name)
- # allow literally short longs only, meaning they
- # must fit into a machine word.
- if (sys.maxint*2+1)&value == value:
- self.initcode.append1('%s = space.wrap(%s) # XXX implement long!' % (name, s))
- else:
- long_helper(self, name, value)
- return name
-
- def nameof_float(self, value):
- name = 'gfloat_%s' % value
- name = (name.replace('-', 'minus')
- .replace('.', 'dot'))
- name = self.uniquename(name)
- # handle overflows
- if value != 0.0 and 2*value == value:
- self.initcode.append1('float_inf = 1e200\nfloat_inf *= float_inf')
- sign = '-+'[value >= 0]
- self.initcode.append('%s = space.wrap(%sfloat_inf)' % (name, sign))
- else:
- self.initcode.append('%s = space.wrap(%r)' % (name, value))
- return name
-
- def nameof_str(self, value):
- if [c for c in value if c<' ' or c>'~' or c=='"' or c=='\\']:
- # non-printable string
- namestr = repr(value)[1:-1]
- else:
- # printable string
- namestr = value
- if not namestr:
- namestr = "_emptystr_"
- name = self.uniquename('gs_' + namestr[:32])
- if len(value) < 30 and "\n" not in value:
- txt = '%s = space.new_interned_str(%r)' % (name, value)
- else:
- txt = render_docstr(value, '%s = space.new_interned_str(\n' % name, ')')
- txt = txt, # not splitted
- self.initcode.append(txt)
- return name
-
- def skipped_function(self, func):
- # debugging only! Generates a placeholder for missing functions
- # that raises an exception when called.
- name = self.uniquename('gskippedfunc_' + func.__name__)
- self.globaldecl.append('# global decl %s' % (name, ))
- self.initcode.append('# build func %s' % name)
- return name
-
- def skipped_class(self, cls):
- # debugging only! Generates a placeholder for missing classes
- # that raises an exception when called.
- name = self.uniquename('gskippedclass_' + cls.__name__)
- self.globaldecl.append('# global decl %s' % (name, ))
- self.initcode.append1('# build class %s' % name)
- return name
-
- def trans_funcname(self, s):
- return s.translate(C_IDENTIFIER)
-
- def nameof_function(self, func, namehint=''):
- if hasattr(func, 'geninterplevel_name'):
- return func.geninterplevel_name(self)
- if func.func_globals is None:
- # built-in functions on top of PyPy
- return self.nameof_builtin_function(func)
-
- printable_name = '(%s:%d) %s' % (
- self.trans_funcname(func.func_globals.get('__name__', '?')),
- func.func_code.co_firstlineno,
- func.__name__)
- if (func.func_doc and
- func.func_doc.lstrip().startswith('NOT_RPYTHON')):
- log.WARNING("skipped %s" % printable_name)
- return self.skipped_function(func)
- name = self.uniquename('gfunc_' + self.trans_funcname(
- namehint + func.__name__))
-
- positional, varargs, varkwds, defs = inspect.getargspec(func)
- if varargs is varkwds is defs is None:
- unwrap = ', '.join(['gateway.W_Root']*len(positional))
- interp_name = 'fastf_' + name[6:]
- else:
- unwrap = 'gateway.Arguments'
- interp_name = 'f_' + name[6:]
-
- self.initcode.append1('from pypy.interpreter import gateway')
- self.initcode.append1('%s = space.wrap(gateway.interp2app(%s, unwrap_spec=[gateway.ObjSpace, %s]))' %
- (name, interp_name, unwrap))
- self.pendingfunctions.append(func)
- return name
-
- def nameof_staticmethod(self, sm):
- # XXX XXX XXXX
- func = sm.__get__(42.5)
- name = self.uniquename('gsm_' + func.__name__)
- functionname = self.nameof(func)
- self.initcode.append1('%s = space.wrap(%s)' % (name, functionname))
- return name
-
- def nameof_instancemethod(self, meth):
- if (not hasattr(meth.im_func, 'func_globals') or
- meth.im_func.func_globals is None):
- # built-in methods (bound or not) on top of PyPy or possibly 2.4
- return self.nameof_builtin_method(meth)
- if meth.im_self is None:
- # no error checking here
- return self.nameof(meth.im_func, namehint="%s_" % meth.im_class.__name__)
- else:
- ob = self.nameof(meth.im_self)
- func = self.nameof(meth.im_func)
- typ = self.nameof(meth.im_class)
- name = self.uniquename('gmeth_' + meth.im_func.__name__)
- funcname = self.nameof(meth.im_func.__name__)
- self.initcode.append1(
- '%s = space.getattr(%s, %s)' % (name, ob, funcname))
- return name
-
- nameof_method = nameof_instancemethod # when run on top of PyPy
-
- def should_translate_attr(self, pbc, attr):
- ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', [])
- if attr in ignore:
- return False
- else:
- return "probably" # True
-
- def later(self, gen):
- self.latercode.append1((gen, self.debugstack))
-
- def nameof_instance(self, instance):
- klass = instance.__class__
- name = self.uniquename('ginst_' + klass.__name__)
- cls = self.nameof(klass)
- if hasattr(klass, '__base__'):
- base_class = builtin_base(instance)
- base = self.nameof(base_class)
- else:
- base_class = None
- base = cls
- def initinstance():
- content = instance.__dict__.items()
- content.sort()
- for key, value in content:
- if self.should_translate_attr(instance, key):
- try:
- yield 'space.setattr(%s, %s, %s)' % (
- name, self.nameof(key), self.nameof(value))
- except:
- log.ERROR("Problem while generating %s of %r" % (
- name, instance))
- raise
- self.initcode.append1("%s = space.call_method(%s, '__new__', %s)" % (
- name, cls, cls))
- self.later(initinstance())
- return name
-
- def space_arities(self):
- if self._space_arities is None:
- arities = self._space_arities = {}
- for name, sym, arity, specnames in self.space.MethodTable:
- arities[name] = arity
- del arities["isinstance"]
- return self._space_arities
-
- def try_space_shortcut_for_builtin(self, v, nargs, args):
- if isinstance(v, Constant) and v.value in self.ibuiltin_ids:
- name = self.ibuiltin_ids[v.value].__name__
- if (hasattr(self.space, name) and
- self.space_arities().get(name, -1) == nargs):
- return "space.%s" % name
- return None
-
- def nameof_builtin_function_or_method(self, func):
- if func.__self__ is None:
- return self.nameof_builtin_function(func)
- else:
- return self.nameof_builtin_method(func)
-
- def nameof_builtin_function(self, func):
- # builtin function
- if func in self.ibuiltin_ids:
- func = self.ibuiltin_ids[func]
- return "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- # where does it come from? Python2.2 doesn't have func.__module__
- for modname, module in sys.modules.items():
- if not self.is_module_builtin(module):
- continue # skip non-builtin modules
- if func is getattr(module, func.__name__, None):
- break
- else:
- raise Exception, '%r not found in any built-in module' % (func,)
- #if modname == '__builtin__':
- # # be lazy
- # return "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- if modname == 'sys':
- # be lazy
- return "(space.sys.get(space.str_w(%s)))" % self.nameof(func.__name__)
- else:
- name = self.uniquename('gbltin_' + func.__name__)
- self.initcode.append1('%s = space.getattr(%s, %s)' % (
- name, self.nameof(module), self.nameof(func.__name__)))
- return name
-
- def nameof_builtin_method(self, meth):
- try:
- im_self = meth.__self__
- except AttributeError:
- im_self = meth.im_self # on top of PyPy
- if im_self is None:
- # builtin unbound method (only on top of PyPy)
- name = self.nameof_wrapper_descriptor(meth)
- else:
- # builtin (bound) method
- name = self.uniquename('gbltinmethod_' + meth.__name__)
- self.initcode.append1('%s = space.getattr(%s, %s)' % (
- name, self.nameof(im_self), self.nameof(meth.__name__)))
- return name
-
- def nameof_classobj(self, cls):
- initcode = []
- printable_name = cls.__name__
- if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'):
- #raise Exception, "%r should never be reached" % (cls,)
- log.WARNING("skipped class %s" % printable_name)
- return self.skipped_class(cls)
-
- metaclass = "space.w_type"
- name = self.uniquename('gcls_' + cls.__name__)
-
- if issubclass(cls, py.builtin.BaseException):
- # if cls.__module__ == 'exceptions':
- # don't rely on this, py.magic redefines AssertionError
- if getattr(__builtin__,cls.__name__,None) is cls:
- # exception are defined on the space
- return 'space.w_%s' % cls.__name__
-
- if not isinstance(cls, type):
- assert type(cls) is types.ClassType
- # do *not* change metaclass, but leave the
- # decision to what PyPy thinks is correct.
- # metaclass = 'space.w_classobj'
-
- basenames = [self.nameof(base) for base in cls.__bases__]
-
- def initclassobj():
- content = cls.__dict__.items()
- content.sort()
- for key, value in content:
- if key.startswith('__'):
- if key in ['__module__', '__doc__', '__dict__',
- '__weakref__', '__metaclass__', '__slots__',
- '__new__', '__del__']:
- continue
-
- # redirect value through class interface, in order to
- # get methods instead of functions.
- value = getattr(cls, key)
-
- if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen:
- log.WARNING("skipped staticmethod: %s" % value)
- continue
- if isinstance(value, MethodType) and value.im_self is cls:
- log.WARNING("skipped classmethod: %s" % value)
- continue
-
- yield 'space.setattr(%s, %s, %s)' % (
- name, self.nameof(key), self.nameof(value))
-
- baseargs = ", ".join(basenames)
- initcode.append('_dic = space.newdict()')
- for key, value in cls.__dict__.items():
- if key.startswith('__'):
- if key in ['__module__', '__metaclass__', '__slots__',
- '__new__', '__del__']:
- keyname = self.nameof(key)
- valname = self.nameof(value)
- initcode.append("space.setitem(_dic, %s, %s)" % (
- keyname, valname))
-
- if cls.__doc__ is not None:
- sdoc = self.nameof("__doc__")
- docobj = cls.__dict__["__doc__"]
- if type(docobj) in (str, unicode):
- docstr = render_docstr(cls, "_doc = space.wrap(", ")")
- initcode.append((docstr,)) # not splitted
- else:
- initcode.append("_doc = %s" % self.nameof(docobj) )
- initcode.append("space.setitem(_dic, %s, _doc)" % (sdoc,))
- cls_name = self.nameof(cls.__name__)
- for l in initcode:
- self.initcode.append(l)
- self.initcode.append1('_bases = space.newtuple([%(bases)s])\n'
- '_args = space.newtuple([%(name)s, _bases, _dic])\n'
- '%(klass)s = space.call(%(meta)s, _args)'
- % {"bases": baseargs,
- "klass": name,
- "name" : cls_name,
- "meta" : metaclass} )
-
- self.later(initclassobj())
- return name
-
- nameof_class = nameof_classobj # for Python 2.2
-
- typename_mapping = {
- object: 'space.w_object',
- int: 'space.w_int',
- long: 'space.w_int',
- bool: 'space.w_bool',
- list: 'space.w_list',
- tuple: 'space.w_tuple',
- dict: 'space.w_dict',
- str: 'space.w_str',
- float: 'space.w_float',
- slice: 'space.w_slice',
- types.InstanceType: (eval_helper, 'InstanceType', 'types.InstanceType'),
- type: 'space.w_type',
- complex: (eval_helper, 'complex', 'types.ComplexType'),
- unicode:'space.w_unicode',
- basestring: (eval_helper, 'basestring', 'basestring'),
- file: (eval_helper, 'file', 'file'),
- type(None): (eval_helper, 'NoneType', 'type(None)'),
- CodeType: (eval_helper, 'code', 'type((lambda:42).func_code)'),
- ModuleType: (eval_helper, 'ModuleType', 'types.ModuleType'),
- xrange: (eval_helper, 'xrange', 'xrange'),
-
- ##r_int: 'space.w_int',
- ##r_uint: 'space.w_int',
-
- type(len): (eval_helper, 'FunctionType', 'type(lambda:42)'),
- # type 'method_descriptor':
- # XXX small problem here:
- # XXX with space.eval, we get <W_TypeObject(method)>
- # XXX but with wrap, we get <W_TypeObject(instancemethod)>
- type(list.append): (eval_helper, "method_descriptor", "type(list.append)"),
- # type 'wrapper_descriptor':
- type(type(None).__repr__): (eval_helper, "wrapper_descriptor",
- "type(type(None).__repr__)"),
- # type 'getset_descriptor':
- # XXX here we get <W_TypeObject(FakeDescriptor)>,
- # while eval gives us <W_TypeObject(GetSetProperty)>
- type(type.__dict__['__dict__']): (eval_helper, "getset_descriptor",
- "type(type.__dict__[\'__dict__\'])"),
- # type 'member_descriptor':
- # XXX this does not work in eval!
- # type(type.__dict__['__basicsize__']): "cannot eval type(type.__dict__['__basicsize__'])",
- # XXX there seems to be no working support for member descriptors ???
- type(types.GeneratorType.gi_frame):
- (eval_helper, "member_descriptor", 'type(property.fdel)'),
- types.ClassType: 'space.w_type',
- types.MethodType: (eval_helper, "instancemethod",
- "type((lambda:42).__get__(42))"),
- type(Ellipsis): (eval_helper, 'EllipsisType', 'types.EllipsisType'),
- builtin_set: (eval_helper, "set", "set"),
- builtin_frozenset: (eval_helper, "frozenset", "frozenset"),
- buffer: (eval_helper, "buffer", "buffer"),
- }
-
- def nameof_type(self, cls):
- if cls in self.typename_mapping:
- ret = self.typename_mapping[cls]
- if type(ret) is tuple:
- ret = ret[0](self, ret[1], ret[2])
- return ret
- if issubclass(cls, py.builtin.BaseException): # Python 2.5 only
- # if cls.__module__ == 'exceptions':
- # don't rely on this, py.magic redefines AssertionError
- if getattr(__builtin__,cls.__name__,None) is cls:
- # exception are defined on the space
- return 'space.w_%s' % cls.__name__
- assert cls.__module__ != '__builtin__' or cls.__flags__&_HEAPTYPE, (
- "built-in class %r not found in typename_mapping "
- "while compiling %s" % (cls, self.currentfunc and
- self.currentfunc.__name__ or "*no function at all*"))
- return self.nameof_classobj(cls)
-
- def nameof_tuple(self, tup):
- name = self.uniquename('g%dtuple' % len(tup))
- args = [self.nameof(x) for x in tup]
- args = ', '.join(args)
- self.initcode.append1('%s = space.newtuple([%s])' % (name, args))
- return name
-
- def nameof_list(self, lis):
- name = self.uniquename('g%dlist' % len(lis))
- # note that self.latercode led to too late initialization.
- self.register_early(lis, name)
- # try to save at least one assignment.
- if lis and lis[0] is not lis:
- default = lis[0]
- else:
- default = None
- self.initcode.append('%s = space.newlist([%s])' % (name, self.nameof(default)))
- self.initcode.append('%s = space.mul(%s, %s)' % (name, name, self.nameof(len(lis))))
- for i in range(len(lis)):
- if lis[i] is not default:
- item = self.nameof(lis[i])
- self.initcode.append('space.setitem(%s, %s, %s);' % (
- name, self.nameof(i), item))
- return name
-
- def nameof_dict(self, dic):
- assert dic is not __builtins__
- name = self.uniquename('g%ddict' % len(dic))
- self.register_early(dic, name)
- self.initcode.append('%s = space.newdict()' % (name,))
- for k in dic:
- if k == '__builtins__':
- continue
- self.initcode.append('space.setitem(%s, %s, %s)'%(
- name, self.nameof(k), self.nameof(dic[k])))
- return name
-
- # strange prebuilt instances below, don't look too closely
- # XXX oh well.
- def nameof_member_descriptor(self, md):
- try:
- im_class = md.__objclass__
- except AttributeError:
- im_class = md.im_class # on top of PyPy
- name = self.uniquename('gdescriptor_%s_%s' % (
- im_class.__name__, md.__name__))
- cls = self.nameof(im_class)
- self.initcode.append1('%s = space.getattr(%s, %s)' %
- (name, cls, self.nameof(md.__name__)))
- return name
- nameof_getset_descriptor = nameof_member_descriptor
- nameof_method_descriptor = nameof_member_descriptor
- nameof_wrapper_descriptor = nameof_member_descriptor
-
- def nameof_property(self, prop):
- origin = prop.__doc__ # XXX quite a hack
- if not origin:
- raise ValueError("sorry, cannot build properties"
- " without a helper in __doc__")
- name = self.uniquename('gprop_' + origin)
- # property is lazy loaded app-level as well, trigger it*s creation
- self.initcode.append1('space.builtin.get("property") # pull it in')
- globname = self.nameof(self.moddict)
- self.initcode.append('space.setitem(%s, space.new_interned_str("__builtins__"), '
- 'space.builtin.w_dict)' % globname)
- self.initcode.append('%s = space.eval("property(%s)", %s, %s, hidden_applevel=True)' %(
- name, origin, globname, globname) )
- self.initcode.append('space.delitem(%s, space.new_interned_str("__builtins__"))'
- % globname)
- return name
-
- def nameof_file(self, fil):
- if fil is sys.stdin:
- return 'space.sys.get("stdin")'
- if fil is sys.stdout:
- return 'space.sys.get("stdout")'
- if fil is sys.stderr:
- return 'space.sys.get("stderr")'
- raise Exception, 'Cannot translate an already-open file: %r' % (fil,)
-
- def gen_source(self, fname, ftmpname=None, file=file):
- self.fname = fname
- self.ftmpname = ftmpname
-
- # generate unordered source file, first.
- # I prefer this over ordering everything in memory.
- fname = self.fname
- if self.ftmpname:
- fname = self.ftmpname
- f = file(fname, "w")
- # generate ordered source file
- try:
- self.f = f
- self.gen_source_temp()
- finally:
- f.close()
-
- def copyfile(source, target):
- f = file(source)
- data = f.read()
- f.close()
- f = file(target, "w")
- f.write(data)
- f.close()
-
- def order_sections(fname):
- sep = "\n##SECTION##\n"
- f = file(fname)
- txt = f.read()
- f.close()
- pieces = txt.split(sep)
- prelude = pieces.pop(0)
- postlude = pieces.pop()
- dic = {}
- while pieces:
- func = pieces.pop()
- head = pieces.pop()
- key = makekey(head, len(pieces))
- dic[key] = head + sep + func
- lis = dic.items()
- lis.sort()
- lis = [prelude] + [func for head, func in lis] + [postlude]
- txt = sep.join(lis)
- f = file(fname, "w")
- f.write(txt)
- f.close()
-
- def makekey(txt, uniqueno):
- dic = {}
- for line in txt.split("\n"):
- ign, name, value = line.split(None, 2)
- dic[name] = eval(value, {})
- key = (dic["filename"], dic["firstlineno"],
- dic["function"], uniqueno)
- return key
-
- order_sections(fname)
- if self.ftmpname:
- copyfile(self.ftmpname, self.fname)
-
- def gen_source_temp(self):
- f = self.f
-
- # header
- print >> f, self.RPY_HEADER
- print >> f
-
- info = {
- 'modname': self.modname,
- # the side-effects of this is kick-start the process
- 'entrypoint': None # self.nameof(self.entrypoint),
- }
- # header """def initmodule(space):"""
- print >> f, self.RPY_INIT_HEADER % info
-
- # doc
- if self.moddict and self.moddict.get("__doc__"):
- doc = self.moddict["__doc__"]
- print >> f, render_docstr(doc, " __doc__ = \\\n")
- print >> f
- # make sure it is not rendered again
- key = Constant(doc).key
- self.rpynames[key] = "w__doc__"
- self.initcode.append("w__doc__ = space.new_interned_str(__doc__)")
-
- # info.entrypoint must be done *after* __doc__ is handled,
- # because nameof(entrypoint) might touch __doc__ early.
- info["entrypoint"] = self.nameof(self.entrypoint)
-
- # function implementations
- while self.pendingfunctions or self.latercode:
- if self.pendingfunctions:
- func = self.pendingfunctions.pop()
- self.currentfunc = func
- self.gen_rpyfunction(func)
- # collect more of the latercode after each function
- while self.latercode:
- gen, self.debugstack = self.latercode.pop()
- #self.initcode.extend(gen) -- eats TypeError! bad CPython!
- for line in gen:
- self.initcode.append1(line)
- self.debugstack = ()
- self.gen_global_declarations()
-
- # set the final splitter
- print >> f, "##SECTION##"
- # footer, init code
- for codelines in self.initcode:
- # keep docstrings unindented
- indent = " "
- if type(codelines) is tuple:
- codelines = codelines[0].split("\n", 1)
- codelines[0] = indent + codelines[0]
- indent = ""
- else:
- codelines = codelines.split("\n")
- for codeline in codelines:
- print >> f, indent + codeline
-
- self.gen_trailer(info, " ")
- # do not close the file here!
-
- def gen_trailer(self, info, indent):
- if self.moddict:
- # we are generating a module, no __main__ etc.
- print >> self.f, indent + "return %s" % self.nameof(self.entrypoint)
- print >> self.f
- else:
- # we should have an entrypoint function
- info['entrypointname'] = self.trans_funcname(self.entrypoint.__name__)
- print >> self.f, self.RPY_INIT_FOOTER % info
-
- def gen_global_declarations(self):
- g = self.globaldecl
- if g:
- f = self.f
- print >> f, '# global declaration%s' % ('s'*(len(g)>1))
- for line in g:
- print >> f, line
- print >> f
- del g[:]
- g = self.globalobjects
- for name in g:
- pass # self.initcode.append1('# REGISTER_GLOBAL(%s)' % (name,))
- del g[:]
-
- def rel_filename(self, name):
- # try to find a name relative to pypy and unify.
- # if not possible, stick with the original.
- ref = py.path.local(pypy.__path__[0])
- rel = py.path.local(name).relto(ref)
- if rel:
- # make it os independent
- return rel.replace('\\', '/')
- return name # no success
-
- def getsignature(self, argnamelist, varargname, varkwname):
- key = (argnamelist, varargname, varkwname)
- try:
- return self._signature_cache[key]
- except KeyError:
- pass
- signame = self.uniquename('sig')
- self._signature_cache[key] = signame
- self.initcode.append("%s = gateway.Signature(%r, %r, %r)" % (
- signame, list(argnamelist), varargname, varkwname))
- return signame
-
- def getdefaults(self, names):
- key = tuple(names)
- try:
- return self._defaults_cache[key]
- except KeyError:
- pass
- defaultsname = self.uniquename('default')
- self._defaults_cache[key] = defaultsname
- self.initcode.append("%s = [%s]" % (defaultsname, ', '.join(names)))
- return defaultsname
-
- def gen_rpyfunction(self, func):
- try:
- graph = self.translator.buildflowgraph(func, True)
- except Exception, e:
- print 20*"*", e
- print func
- raise
- SSI_to_SSA(graph)
- checkgraph(graph)
-
- f = self.f
- print >> f, "##SECTION##" # simple to split, afterwards
- print >> f, ("## filename %r\n"
- "## function %r\n"
- "## firstlineno %d") % (
- self.rel_filename(func.func_code.co_filename),
- func.func_code.co_name,
- func.func_code.co_firstlineno)
- print >> f, "##SECTION##"
- localscope = self.namespace.localScope()
- body = list(self.rpyfunction_body(graph, localscope))
- name_of_defaults = [self.nameof(x, debug=('Default argument of', func))
- for x in (func.func_defaults or ())]
- self.gen_global_declarations()
-
- # print header
- docstr = render_docstr(func, " ")
- cname = self.nameof(func)
- assert cname.startswith('gfunc_')
- f_name = 'f_' + cname[6:]
-
- # collect all the arguments
- vararg = varkw = None
- varargname = varkwname = None
- all_args = graph.getargs()
- p = len(all_args)
- if func.func_code.co_flags & CO_VARKEYWORDS:
- p -= 1
- varkw = graph.getargs()[p]
- varkwname = func.func_code.co_varnames[p]
- if func.func_code.co_flags & CO_VARARGS:
- p -= 1
- vararg = graph.getargs()[p]
- varargname = func.func_code.co_varnames[p]
- positional_args = all_args[:p]
- argnamelist = func.func_code.co_varnames[:func.func_code.co_argcount]
-
- fast_args = [self.expr(a, localscope) for a in positional_args]
- if vararg is not None:
- vararg = self.expr(vararg, localscope)
- fast_args.append(vararg)
- if varkw is not None:
- varkw = self.expr(varkw, localscope)
- fast_args.append(varkw)
- fast_name = 'fast' + f_name
-
- fast_set = dict(zip(fast_args, fast_args))
-
- simple = (varargname is varkwname is None) and not name_of_defaults
-
- # create function declaration
- name = self.trans_funcname(func.__name__) # for <lambda>
- argstr = ", ".join(['space'] + fast_args)
- fast_function_header = (' def %s(%s):'
- % (name, argstr))
-
- def install_func(f_name, name):
- yield ''
- yield ' %s = %s' % (f_name, name)
- yield ' %s.__name__ = %r' % (f_name, f_name)
- #import __builtin__
- #dic = __builtin__.__dict__
- #if dic.get(name):
- # yield 'del %s # hiding a builtin!' % name
- #else:
- # self.initcode.append1('del m.%s' % (name,))
-
- def tupstr(seq):
- if len(seq) == 1:
- fmt = '%s,'
- else:
- fmt = '%s'
- return fmt % ', '.join(seq)
- def tupassstr(seq):
- if not seq:
- return ""
- else:
- return tupstr(seq) + " = "
-
- if not simple:
- print >> f, ' def %s(space, __args__):' % (name,)
- if docstr is not None:
- print >> f, docstr
- print >> f
-
- signame = self.getsignature(argnamelist, varargname, varkwname)
- defaultsname = self.getdefaults(name_of_defaults)
- print >> f, ' %s__args__.parse_obj(None, %r, %s, %s)' % (
- tupassstr(fast_args), func.__name__, signame, defaultsname)
- print >> f, ' return %s(%s)' % (fast_name,
- ', '.join(["space"]+fast_args))
-
- for line in install_func(f_name, name):
- print >> f, line
-
- print >> f
-
- print >> f, fast_function_header
- if docstr is not None:
- print >> f, docstr
-
- # print the body
- for line in body:
- print >> f, line
- for line in install_func("fast"+f_name, name):
- print >> f, line
- print >> f
-
- # print the PyMethodDef
- # skipped
-
-
- def rpyfunction_body(self, graph, localscope):
- start = graph.startblock
- allblocks = ordered_blocks(graph)
- nblocks = len(allblocks)
-
- blocknum = {}
- for block in allblocks:
- blocknum[block] = len(blocknum)+1
-
- yield " goto = %s # startblock" % self.mklabel(blocknum[start])
- yield " while True:"
-
- def render_block(block):
- catch_exception = block.exitswitch == c_last_exception
- regular_op = len(block.operations) - catch_exception
- # render all but maybe the last op
- for op in block.operations[:regular_op]:
- for line in self.oper(op, localscope).split("\n"):
- yield "%s" % line
- # render the last op if it is exception handled
- for op in block.operations[regular_op:]:
- yield "try:"
- for line in self.oper(op, localscope).split("\n"):
- yield " %s" % line
-
- if len(block.exits) == 0:
- if len(block.inputargs) == 2: # exc_cls, exc_value
- # exceptional return block
- exc_cls = self.expr(block.inputargs[0], localscope)
- exc_val = self.expr(block.inputargs[1], localscope)
- yield "raise %s(%s, %s)" % (self.nameof(OperationError),
- exc_cls, exc_val)
- else:
- # regular return block
- retval = self.expr(block.inputargs[0], localscope)
- yield "return %s" % retval
- return
- elif block.exitswitch is None:
- # single-exit block
- assert len(block.exits) == 1
- for op in self.gen_link(block.exits[0], localscope, blocknum, block):
- yield "%s" % op
- elif catch_exception:
- # block catching the exceptions raised by its last operation
- # we handle the non-exceptional case first
- link = block.exits[0]
- assert link.exitcase is None
- for op in self.gen_link(link, localscope, blocknum, block):
- yield " %s" % op
- # we must catch the exception raised by the last operation,
- # which goes to the last err%d_%d label written above.
- # Since we only have OperationError, we need to select:
- yield "except %s, e:" % (self.nameof(OperationError),)
- yield " e.normalize_exception(space)"
- q = "if"
- for link in block.exits[1:]:
- assert issubclass(link.exitcase, py.builtin.BaseException)
- # Exeption classes come unwrapped in link.exitcase
- yield " %s e.match(space, %s):" % (q,
- self.nameof(link.exitcase))
- q = "elif"
- for op in self.gen_link(link, localscope, blocknum, block, {
- link.last_exception: 'e.w_type',
- link.last_exc_value: 'e.get_w_value(space)'}):
- yield " %s" % op
- yield " else:raise # unhandled case, should not happen"
- else:
- # block ending in a switch on a value
- exits = list(block.exits)
- if len(exits) == 2 and (
- exits[0].exitcase is False and exits[1].exitcase is True):
- # order these guys like Python does
- exits.reverse()
- q = "if"
- for link in exits[:-1]:
- yield "%s %s == %s:" % (q, self.expr(block.exitswitch,
- localscope),
- link.exitcase)
- for op in self.gen_link(link, localscope, blocknum, block):
- yield " %s" % op
- q = "elif"
- link = exits[-1]
- yield "else:"
- for op in self.gen_link(exits[-1], localscope, blocknum, block):
- yield " %s" % op
-
- cmpop = ('==', 'is') [self.specialize_goto]
- for block in allblocks:
- blockno = blocknum[block]
- yield ""
- yield " if goto %s %s:" % (cmpop, self.mklabel(blockno))
- for line in render_block(block):
- yield " %s" % line
-
-# ____________________________________________________________
-
- RPY_HEADER = '''#!/bin/env python
-# -*- coding: LATIN-1 -*-'''
-
- RPY_SEP = "#*************************************************************"
-
- RPY_INIT_HEADER = RPY_SEP + '''
-__name__ = "_geninterp_"+%(modname)r
-_geninterp_ = True
-
-def init%(modname)s(space):
- """NOT_RPYTHON"""
-'''
-
- RPY_INIT_FOOTER = '''
-# entry point: %(entrypointname)s, %(entrypoint)s
-if __name__ == "__main__":
- from pypy.objspace.std import StdObjSpace
- from pypy.objspace.std.model import UnwrapError
- space = StdObjSpace()
- init%(modname)s(space)
- ret = space.call(%(entrypoint)s, space.newtuple([]))
- try:
- print space.unwrap(ret)
- except UnwrapError:
- print "cannot unwrap, here the wrapped result:"
- print ret
-'''
-
-# _____________________________________________________________________
-
-# implementation of the interface that is finally only
-# used: translate_as_module
-
-import py.code
-import cStringIO as StringIO
-
-class memfile(object):
- _storage = {}
- def __init__(self, name, mode="r"):
- if mode == "w":
- self._storage[name] = StringIO.StringIO()
- elif mode == "r":
- try:
- data = self._storage[name].getvalue()
- except IndexError:
- f = file(name)
- data = f.read()
- f.close()
- self._storage[name] = StringIO.StringIO(data)
- else:
- raise ValueError, "mode %s not supported" % mode
- self._file = self._storage[name]
- def __getattr__(self, name):
- return getattr(self._file, name)
- def close(self):
- pass
-
-def translate_as_module(sourcetext, filename=None, modname="app2interpexec",
- do_imports_immediately=False, tmpname=None):
- """ compile sourcetext as a module, translating to interp level.
- The result is the init function that creates the wrapped module dict,
- together with the generated source text.
- This init function needs a space as argument.
- tmpname can be passed for debugging purposes.
-
- Example:
-
- initfunc, newsrc = translate_as_module(text)
- from pypy.objspace.std import Space
- space = Space()
- dic = initfunc(space)
- # and now use the members of the dict
- """
- from pypy.tool.lib_pypy import LIB_PYPY
- # create something like a module
- if type(sourcetext) is str:
- code = py.code.Source(sourcetext).compile()
- else:
- # assume we got an already compiled source
- code = sourcetext
- dic = {'__name__': modname}
- if filename:
- dic['__file__'] = filename
-
- # XXX allow the app-level code to contain e.g. "import _formatting"
- libdir = str(LIB_PYPY)
- sys.path.insert(0, libdir)
- try:
- if faked_set:
- import __builtin__
- __builtin__.set = fake_set
- __builtin__.frozenset = fake_frozenset
- try:
- exec code in dic
- finally:
- if libdir in sys.path:
- sys.path.remove(libdir)
-
- entrypoint = dic
- t = TranslationContext(verbose=False, simplifying=True,
- builtins_can_raise_exceptions=True,
- list_comprehension_operations=False)
- t.no_annotator_but_do_imports_immediately = do_imports_immediately
- gen = GenRpy(t, entrypoint, modname, dic)
-
- finally:
- if faked_set:
- del __builtin__.set
- del __builtin__.frozenset
-
- if tmpname:
- _file = file
- else:
- _file = memfile
- tmpname = 'nada'
- out = _file(tmpname, 'w')
- gen.f = out
- try:
- if faked_set:
- import __builtin__
- __builtin__.set = fake_set
- __builtin__.frozenset = fake_frozenset
- gen.gen_source(tmpname, file=_file)
- finally:
- if faked_set:
- del __builtin__.set
- del __builtin__.frozenset
- out.close()
- f = _file(tmpname)
- newsrc = f.read()
- f.close()
- code = py.code.Source(newsrc).compile()
- dic = {}
- exec code in dic
- # now we just need to return the init function,
- # which then needs to be called with the space to return the dict.
- return dic['init%s' % modname], newsrc
-
-#___________________________________________________________________
-
-# some testing code
-
-testcode = """
-def f(a, b):
- return a + b
-
-def g():
- return f(f(1, 2), f(4, 8))
-"""
-
-if __name__ == '__main__':
- res = translate_as_module(testcode, tmpname='/tmp/look.py')
diff --git a/pypy/translator/gensupp.py b/pypy/translator/gensupp.py
--- a/pypy/translator/gensupp.py
+++ b/pypy/translator/gensupp.py
@@ -5,61 +5,6 @@
import sys
-from pypy.objspace.flow.model import Block
-
-# ordering the blocks of a graph by source position
-
-def ordered_blocks(graph):
- # collect all blocks
- allblocks = []
- for block in graph.iterblocks():
- # first we order by offset in the code string
- if block.operations:
- ofs = block.operations[0].offset
- else:
- ofs = sys.maxint
- # then we order by input variable name or value
- if block.inputargs:
- txt = str(block.inputargs[0])
- else:
- txt = "dummy"
- allblocks.append((ofs, txt, block))
- allblocks.sort()
- #for ofs, txt, block in allblocks:
- # print ofs, txt, block
- return [block for ofs, txt, block in allblocks]
-
-# a unique list, similar to a list.
-# append1 appends an object only if it is not there, already.
-
-class UniqueList(list):
- def __init__(self, *args, **kwds):
- list.__init__(self, *args, **kwds)
- self.dic = {}
-
- def append1(self, arg):
- try:
- self.dic[arg]
- except KeyError:
- self.dic[arg] = 1
- list.append(self, arg)
- except TypeError: # not hashable
- if arg not in self:
- list.append(self, arg)
-
-def builtin_base(obj):
- typ = type(obj)
- return builtin_type_base(typ)
-
-def builtin_type_base(typ):
- from copy_reg import _HEAPTYPE
- while typ.__flags__&_HEAPTYPE:
- typ = typ.__base__
- return typ
-
-def c_string(s):
- return '"%s"' % (s.replace('\\', '\\\\').replace('"', '\"'),)
-
def uniquemodulename(name, SEEN={}):
# never reuse the same module name within a Python session!
i = 0
diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -242,7 +242,6 @@
filename = os.path.join(this_dir, 'app_main.py')
app = gateway.applevel(open(filename).read(), 'app_main.py', 'app_main')
app.hidden_applevel = False
- app.can_use_geninterp = False
w_dict = app.getwdict(space)
entry_point = create_entry_point(space, w_dict)
diff --git a/pypy/translator/oosupport/test_template/overflow.py b/pypy/translator/oosupport/test_template/overflow.py
--- a/pypy/translator/oosupport/test_template/overflow.py
+++ b/pypy/translator/oosupport/test_template/overflow.py
@@ -3,9 +3,12 @@
class BaseTestOverflow:
- def check(self, fn, args):
+ def check(self, fn, args, expected=None):
res1 = self.interpret(fn, args)
- res2 = fn(*args)
+ if expected is not None:
+ res2 = expected
+ else:
+ res2 = fn(*args)
assert res1 == res2
def test_add(self):
@@ -63,7 +66,9 @@
return ovfcheck(x % y)
except OverflowError:
return 42
- self.check(fn, [-sys.maxint-1, -1])
+ # force the expected result to be 42, because direct run of ovfcheck()
+ # cannot detect this particular overflow case
+ self.check(fn, [-sys.maxint-1, -1], expected=42)
def test_div(self):
def fn(x, y):
diff --git a/pypy/translator/test/snippet.py b/pypy/translator/test/snippet.py
--- a/pypy/translator/test/snippet.py
+++ b/pypy/translator/test/snippet.py
@@ -647,49 +647,6 @@
result += 1.0 / n
return result
-
-# specifically for geninterp testing
-
-def t_isinstance(x, y):
- return isinstance(x, (int, long)) and isinstance(y, int)
-
-def t_issubclass(x, y):
- return issubclass(type(x), (int, long)) and issubclass(type(y), int)
-
-def t_neg_long():
- return -132
-
-def t_attrerror(x):
- try:
- return x.foobar
- except AttributeError:
- return 567
-
-
-class Exc(Exception):
- def __init__(self, v):
- Exception.__init__(self, v)
-
-def exception_subclass_sanity(x):
- try:
- raise Exc(x)
- except Exception, e:
- return e.args[0]
-
-
-class HaveProp(object):
-
- def __init__(self, v):
- self.v = v
-
- def _hi(self):
- return self.v
- hi = property(_hi, doc="HaveProp._hi")
-
-
-def run_prop(v):
- return HaveProp(v).hi
-
# --------------------(Currently) Non runnable Functions ---------------------
def _somebug1(n=int):
diff --git a/pypy/translator/test/test_geninterp.py b/pypy/translator/test/test_geninterp.py
deleted file mode 100644
--- a/pypy/translator/test/test_geninterp.py
+++ /dev/null
@@ -1,302 +0,0 @@
-"""
-Description
-_____________________________
-
-This test is almost a copy of test_genc.py
-The setup code is slightly different:
-Instead of compiling single functions from
-snippets.py, almost all of snippets is translated,
-up to the point where they are untranslatable.
-snippets has been slightly re-ordered for that.
-
-The idea was to create a couple of tests without much
-extra work, in a sense derived from the test_genc.
-
-A problem with that is, that the tests actually should
-be run at application level. The test code checks real
-Python values,so we have to do tricks to unwrap things.
-This is limited:
-Some tests cannot work, since they mutate their arguments.
-Some tests operate with un-unwrappable things.
-Those are disabled for the moment by an 'needapp_' prefix.
-
-XXX think about a way to produce more tests from a common
-XXX basis. Should we write generators for such tests like this?
-"""
-import autopath
-import py
-from pypy.tool.udir import udir
-from pypy.objspace.flow.model import *
-from pypy.translator.geninterplevel import translate_as_module
-from pypy.translator.test import snippet
-from pypy.interpreter.error import OperationError
-from py.code import Source
-
-class TestGenRpyTestCase:
- objspacename = 'std'
-
- snippet_ad = """if 1:
- def import_func():
- import copyreg
- return copyreg._reconstructor.__code__.co_name
-
- def import_sys_func():
- import sys
- return sys.__name__
-"""
-
- def setup_class(cls):
- # simply compile snippets just once
- src = str(Source(snippet))
- # truncate non-compilable stuff for now:
- p = src.index('Non compilable Functions')
- src = src[:p] + '\n'
- # put our ad into snippet
- exec cls.snippet_ad in snippet.__dict__
- src += cls.snippet_ad
- # just in case of trouble, we produce a tempfile
- ini, newsrc = translate_as_module(src, tmpname = str(
- udir.join("_geninterp_test.py")))
- cls.w_glob = ini(cls.space)
-
- def build_interpfunc(self, func, *morefuncs):
- # we ignore morefuncs, since they live in snippets
- space = self.space
- func = space.getitem(self.w_glob, space.wrap(func.__name__))
- def wrapunwrap(*args):
- w_args = space.wrap(args)
- try:
- w_res = space.call(func, w_args)
- except OperationError, e:
- w_typ = e.w_type
- # XXX how to unwrap an exception?
- name = space.unwrap(space.getattr(w_typ, space.wrap('__name__')))
- exc = __builtins__[name]
- raise exc
- return space.unwrap(w_res)
- return wrapunwrap
-
- # small addition to see whether imports look fine
- def test_import(self):
- import copy_reg
- impfunc = self.build_interpfunc(snippet.import_func)
- assert impfunc() == '_reconstructor'
-
- def test_import_sys(self):
- impfunc = self.build_interpfunc(snippet.import_sys_func)
- assert impfunc() == 'sys'
-
- def test_simple_func(self):
- cfunc = self.build_interpfunc(snippet.simple_func)
- assert cfunc(1) == 2
-
- def test_while_func(self):
- while_func = self.build_interpfunc(snippet.while_func)
- assert while_func(10) == 55
-
- def test_nested_whiles(self):
- nested_whiles = self.build_interpfunc(snippet.nested_whiles)
- assert nested_whiles(111, 114) == (
- '...!...!...!...!...!')
-
- def test_poor_man_range(self):
- poor_man_range = self.build_interpfunc(snippet.poor_man_range)
- assert poor_man_range(10) == range(10)
-
- def poor_man_rev_range(self):
- poor_man_rev_range = self.build_interpfunc(snippet.poor_man_rev_range)
- assert poor_man_rev_range(10) == range(9,-1,-1)
-
- def test_simple_id(self):
- #we just want to see, if renaming of parameter works correctly
- #if the first branch is the end branch
- simple_id = self.build_interpfunc(snippet.simple_id)
- assert simple_id(9) == 9
-
- def test_branch_id(self):
- branch_id = self.build_interpfunc(snippet.branch_id)
- assert branch_id(1, 2, 3) == 2
- assert branch_id(0, 2, 3) == 3
-
- def test_int_id(self):
- int_id = self.build_interpfunc(snippet.int_id)
- assert int_id(3) == 3
-
- def dont_test_attrs(self):
- attrs = self.build_interpfunc(snippet.attrs)
- assert attrs() == 9
-
- def test_builtinusage(self):
- fun = self.build_interpfunc(snippet.builtinusage)
- assert fun() == 4
-
- def xpensive_test_sieve(self):
- sieve = self.build_interpfunc(snippet.sieve_of_eratosthenes)
- assert sieve() == 1028
-
- def test_slice(self):
- half = self.build_interpfunc(snippet.half_of_n)
- assert half(10) == 5
-
- def test_poly_branch(self):
- poly_branch = self.build_interpfunc(snippet.poly_branch)
- assert poly_branch(10) == [1,2,3]*2
- assert poly_branch(0) == ['a','b','c']*2
-
- def test_and(self):
- sand = self.build_interpfunc(snippet.s_and)
- assert sand(5, 6) == "yes"
- assert sand(5, 0) == "no"
- assert sand(0, 6) == "no"
- assert sand(0, 0) == "no"
-
- def test_yast(self):
- yast = self.build_interpfunc(snippet.yast)
- assert yast([1000,100,10,1]) == 1111
- assert yast(range(100)) == (99*100)/2
-
- def test_with_init(self):
- with_init = self.build_interpfunc(snippet.with_init)
- assert with_init(0) == 0
- assert with_init(-100) == -100
-
- def test_with_more_init(self):
- with_more_init = self.build_interpfunc(snippet.with_more_init)
- assert with_more_init(10, False) == -10
- assert with_more_init(20, True) == 20
-
- def needapp_test_global_instance(self):
- global_instance = self.build_interpfunc(snippet.global_instance)
- assert global_instance() == 42
-
- def needapp_test_global_newstyle_instance(self):
- global_newstyle_instance = self.build_interpfunc(snippet.global_newstyle_instance)
- assert global_newstyle_instance().a == 1
-
- def needapp_test_global_recursive_list(self):
- global_recursive_list = self.build_interpfunc(snippet.global_recursive_list)
- lst = global_recursive_list()
- assert len(lst) == 1
- assert lst[0] is lst
-
-## def test_global_badinit(self):
-## global_badinit = self.build_interpfunc(snippet.global_badinit)
-## self.assertEquals(global_badinit(), 1)
-
- def test_multiple_inheritance(self):
- multiple_inheritance = self.build_interpfunc(snippet.multiple_inheritance)
- assert multiple_inheritance() == 1+2+3+4
-
- def test_call_star_args0(self):
- call_star_args = self.build_interpfunc(snippet.call_star_args0)
- assert call_star_args(42) == 21
-
- def test_call_star_args1(self):
- call_star_args = self.build_interpfunc(snippet.call_star_args1)
- assert call_star_args(30) == 40
-
- def test_call_star_args1def(self):
- call_star_args = self.build_interpfunc(snippet.call_star_args1def)
- assert call_star_args(7) == 45
-
- def test_call_star_args(self):
- call_star_args = self.build_interpfunc(snippet.call_star_args)
- assert call_star_args(42) == 52
-
- def test_call_default_args(self):
- call_default_args = self.build_interpfunc(snippet.call_default_args)
- assert call_default_args(42) == 111+42+3
-
- def test_call_default_and_star_args(self):
- call_default_and_star_args = self.build_interpfunc(
- snippet.call_default_and_star_args)
- assert call_default_and_star_args(42) == (
- (111+42+3+0, -1000-2000-3000+2))
-
- def test_call_with_star(self):
- call_with_star = self.build_interpfunc(snippet.call_with_star)
- assert call_with_star(()) == -15L
- assert call_with_star((4,)) == -13L
- assert call_with_star((4,7)) == -9L
- assert call_with_star([]) == -15L
- assert call_with_star([4]) == -13L
- assert call_with_star([4,7]) == -9L
- raises(TypeError, call_with_star, (4,7,12))
- raises(TypeError, call_with_star, [4,7,12,63])
- raises(TypeError, call_with_star, 521)
-
- def test_call_with_keyword(self):
- call_with_keyword = self.build_interpfunc(snippet.call_with_keyword)
- assert call_with_keyword(100) == 82
-
- def test_call_very_complex(self):
- call_very_complex = self.build_interpfunc(snippet.call_very_complex,
- snippet.default_args)
- assert call_very_complex(5, (3,), {}) == -12
- assert call_very_complex(5, (), {'y': 3}) == -12
- raises(TypeError, call_very_complex, 5, (3,), {'y': 4})
-
- def test_finallys(self):
- finallys = self.build_interpfunc(snippet.finallys)
- assert finallys(['hello']) == 8
- assert finallys('X') == 8
- assert finallys([]) == 6
- assert finallys('XY') == 6
-
- def needapp_test_finally2(self):
- finally2 = self.build_interpfunc(snippet.finally2)
- lst = range(10)
- finally2(lst, 5)
- assert lst == [0,1,2,3,4, 6, 6,7,8, 'done']
- dic = {}
- raises(KeyError, finally2, dic, "won't find this key")
- assert dic == {-1: 'done'}
-
- def test_bare_raise(self):
- bare_raise = self.build_interpfunc(snippet.bare_raise)
- assert bare_raise(range(0, 100, 10), False) == 50
- assert bare_raise(range(0, 100, 10), True) == 50
- raises(IndexError, bare_raise, range(0, 30, 10), False)
- assert bare_raise(range(0, 30, 10), True) == None
-
- def needapp_test_get_set_del_slice(self):
- fn = self.build_interpfunc(snippet.get_set_del_slice)
- l = list('abcdefghij')
- result = fn(l)
- assert l == [3, 'c', 8, 11, 'h', 9]
- assert result == ([3, 'c'], [9], [11, 'h'])
-
- def test_do_try_raise_choose(self):
- fn = self.build_interpfunc(snippet.do_try_raise_choose)
- result = fn()
- assert result == [-1,0,1,2]
-
-
- def test_t_isinstance(self):
- fn = self.build_interpfunc(snippet.t_isinstance)
- result = fn(1, 2)
- assert result == True
-
- def test_t_issubclass(self):
- fn = self.build_interpfunc(snippet.t_issubclass)
- result = fn(1, 2)
- assert result == True
-
- def test_negative_long(self):
- fn = self.build_interpfunc(snippet.t_neg_long)
- result = fn()
- assert result == -132 and type(result) is int
-
- def test_attributeerror(self):
- fn = self.build_interpfunc(snippet.t_attrerror)
- result = fn(42)
- assert result == 567
-
- def test_Exception_subclass(self):
- fn = self.build_interpfunc(snippet.exception_subclass_sanity)
- result = fn(7)
- assert result == 7
-
- def test_property(self):
- fn = self.build_interpfunc(snippet.run_prop)
- assert fn(23) == 23
diff --git a/pypy/translator/test/test_rpystone.py b/pypy/translator/test/test_rpystone.py
deleted file mode 100644
--- a/pypy/translator/test/test_rpystone.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from pypy.translator.geninterplevel import translate_as_module, __file__ as __
-from pypy.objspace.std import Space
-import os
-fname = os.path.join(os.path.dirname(__), "test", "rpystone.py")
-src = file(fname).read()
-init, ign = translate_as_module(src)#, tmpname="/tmp/look.py")
-
-LOOPS = 25
-
-def test_rpystone():
- space = Space()
- modic = init(space)
- entry = space.getitem(modic, space.wrap("entrypoint"))
- # warm-up,to get everything translated
- space.call(entry, space.newtuple([space.wrap(-1)]))
- # now this is the real one
- space.call(entry, space.newtuple([space.wrap(LOOPS)]))
-
-if __name__ == "__main__":
- test_rpystone()
\ No newline at end of file
diff --git a/pypy/translator/translator.py b/pypy/translator/translator.py
--- a/pypy/translator/translator.py
+++ b/pypy/translator/translator.py
@@ -21,7 +21,6 @@
FLOWING_FLAGS = {
'verbose': False,
'simplifying': True,
- 'builtins_can_raise_exceptions': False,
'list_comprehension_operations': False, # True, - not super-tested
}
@@ -31,7 +30,6 @@
config = get_pypy_config(translating=True)
# ZZZ should go away in the end
for attr in ['verbose', 'simplifying',
- 'builtins_can_raise_exceptions',
'list_comprehension_operations']:
if attr in flowing_flags:
setattr(config.translation, attr, flowing_flags[attr])
More information about the pypy-commit
mailing list