def make_label(func, enter=False): from pycket.AST import AST func = jit.unroll_safe(func) func_argnames, varargs, varkw, defaults = inspect.getargspec(func) assert not varkw and not defaults if varargs: # grrr, bad class Args(Cont): _immutable_fields_ = ["args"] def __init__(self, *args): Cont.__init__(self, args[-2], args[-1]) self.args = args[:-2] def _get_args(self): return self.args def tostring(self): return "%s%s" % (self.__class__.__name__, len(self._get_args())) else: assert func_argnames[-2] == "env", "next to last argument to %s must be named 'env', not %r" % (func.func_name, func_argnames[-2]) Args = _make_args_class(Cont, func_argnames[:-2]) def __init__(self, *args): env = args[-2] cont = args[-1] Cont.__init__(self, env, cont) args = args[:-2] self._init_args(*args) Args.__init__ = __init__ # The @label decorator will produce a new Label per each use, as an @label can be # used to encode a loop (as they act in a manner similar to an assembly label). if enter: clsname = "LoopLabel" else: clsname = "Label" strrepr = "%s(%s:%s:%s)" % (clsname, func.func_name, func.__module__, func.__code__.co_firstlineno) class Label(AST): is_label = True should_enter = enter app_like = False def interpret(self, env, cont): assert type(cont) is Args args = cont._get_args() args += (cont.env, cont.prev) return func(*args) def tostring(self): return strrepr Label.__name__ = clsname the_label = Label() def make(*args): env = args[-2] return the_label, env, Args(*args) return make
def make_label(func, enter=False): import pycket.values from pycket.AST import AST func = jit.unroll_safe(func) func_argnames, varargs, varkw, defaults = inspect.getargspec(func) assert not varkw and not defaults if varargs: # grrr, bad class Args(Cont): _attrs_ = _immutable_fields_ = ["args"] def __init__(self, *args): Cont.__init__(self, args[-2], args[-1]) self.args = args[:-2] def _get_args(self): return self.args def tostring(self): return "%s%s" % (self.__class__.__name__, len( self._get_args())) else: assert func_argnames[ -2] == "env", "next to last argument to %s must be named 'env', not %r" % ( func.func_name, func_argnames[-2]) Args = _make_args_class(Cont, func_argnames[:-2]) def __init__(self, *args): env = args[-2] cont = args[-1] Cont.__init__(self, env, cont) args = args[:-2] self._init_args(*args) Args.__init__ = __init__ # The @label decorator will produce a new Label per each use, as an @label can be # used to encode a loop (as they act in a manner similar to an assembly label). if enter: clsname = "LoopLabel" else: clsname = "Label" strrepr = "%s(%s:%s:%s)" % (clsname, func.func_name, func.__module__, func.__code__.co_firstlineno) class Label(AST): should_enter = enter def interpret(self, env, cont): assert type(cont) is Args args = cont._get_args() args += (cont.env, cont.prev) return func(*args) def tostring(self): return strrepr Label.__name__ = clsname the_label = Label() def make(*args): env = args[-2] return the_label, env, Args(*args) return make
break if has_key: w_compare_with = space.call_function(w_key, w_item) else: w_compare_with = w_item if not has_item or \ space.is_true(compare(w_compare_with, w_max_val)): has_item = True w_max_item = w_item w_max_val = w_compare_with if w_max_item is None: msg = "arg is an empty sequence" raise OperationError(space.w_ValueError, space.wrap(msg)) return w_max_item if unroll: min_max_impl = jit.unroll_safe(min_max_impl) return min_max_impl min_max_unroll = make_min_max(True) min_max_normal = make_min_max(False) @specialize.arg(2) def min_max(space, args, implementation_of): if not jit.we_are_jitted() or len(args.arguments_w) != 1 and \ jit.loop_unrolling_heuristic(args.arguments_w, len(args.arguments_w)): return min_max_unroll(space, args, implementation_of) else: return min_max_normal(space, args, implementation_of) min_max._always_inline = True def max(space, __args__):
def make_min_max(unroll): @specialize.arg(2) def min_max_impl(space, args, implementation_of): if implementation_of == "max": compare = space.gt jitdriver = max_jitdriver else: compare = space.lt jitdriver = min_jitdriver any_kwds = bool(args.keywords) args_w = args.arguments_w if len(args_w) > 1: if unroll and len(args_w) == 2 and not any_kwds: # a fast path for the common case, useful for interpreted # mode and to reduce the length of the jit trace w0, w1 = args_w if space.is_true(compare(w1, w0)): return w1 else: return w0 w_sequence = space.newtuple(args_w) elif len(args_w): w_sequence = args_w[0] else: raise oefmt(space.w_TypeError, "%s() expects at least one argument", implementation_of) w_key = None if any_kwds: kwds = args.keywords if kwds[0] == "key" and len(kwds) == 1: w_key = args.keywords_w[0] else: raise oefmt(space.w_TypeError, "%s() got unexpected keyword argument", implementation_of) w_iter = space.iter(w_sequence) w_type = space.type(w_iter) has_key = w_key is not None has_item = False w_max_item = None w_max_val = None while True: if not unroll: jitdriver.jit_merge_point(has_key=has_key, has_item=has_item, w_type=w_type) try: w_item = space.next(w_iter) except OperationError as e: if not e.match(space, space.w_StopIteration): raise break if has_key: w_compare_with = space.call_function(w_key, w_item) else: w_compare_with = w_item if not has_item or \ space.is_true(compare(w_compare_with, w_max_val)): has_item = True w_max_item = w_item w_max_val = w_compare_with if w_max_item is None: raise oefmt(space.w_ValueError, "arg is an empty sequence") return w_max_item if unroll: min_max_impl = jit.unroll_safe(min_max_impl) return min_max_impl