[pypy-svn] rev 1263 - pypy/branch/builtinrefactor/pypy/interpreter
arigo at codespeak.net
arigo at codespeak.net
Sat Aug 9 15:48:31 CEST 2003
Author: arigo
Date: Sat Aug 9 15:48:30 2003
New Revision: 1263
Added:
pypy/branch/builtinrefactor/pypy/interpreter/error.py (contents, props changed)
- copied, changed from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
pypy/branch/builtinrefactor/pypy/interpreter/eval.py
pypy/branch/builtinrefactor/pypy/interpreter/function.py
pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py (contents, props changed)
- copied, changed from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
Removed:
pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
Modified:
pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
Log:
This is a middle-work check-in. Nothing works.
A interpreter/eval.py
New abstract base classes Code and Frame
A interpreter/pycode.py
M interpreter/pyframe.py
Concrete subclasses of Code and Frame
D interpreter/opcode.py
AM interpreter/pyopcode.py
A interpreter/pyfastscope.py
A interpreter/pynestedscope.py
Opcodes moved into three seperate files
defining a subclass of PyFrame each
M interpreter/gateway.py
M interpreter/baseobjspace.py
Various changes here, work in progress
A interpreter/function.py
The one and unique Function class, with argument parsing
M interpreter/executioncontext.py
AM interpreter/error.py
OperationError moved to its own module
Modified: pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/baseobjspace.py Sat Aug 9 15:48:30 2003
@@ -1,18 +1,14 @@
-from executioncontext import ExecutionContext, OperationError, NoValue
-import threadlocals
+from pypy.interpreter.executioncontext import ExecutionContext, Stack
+from pypy.interpreter.error import OperationError
+from pypy.interpreter import threadlocals
-__all__ = ['ObjSpace', 'OperationError', 'NoValue', 'PyPyError']
+__all__ = ['ObjSpace', 'OperationError', 'NoValue']
+
+
+class NoValue(Exception):
+ """Raised to signal absence of value, e.g. in the iterator accessing
+ method 'op.next()' of object spaces."""
-class PyPyError(Exception):
- "Raise this when you encounter an exceptional situation in PyPy itself."
- def __init__(self, space, operationerr):
- self.space = space
- self.operationerr = operationerr
-
-class Null:
- """ marker object for Null values within the interpreter
- (not visible at app-level)
- """
class ObjSpace:
"""Base class for the interpreter-level implementations of object spaces.
@@ -146,31 +142,19 @@
check_list = [w_check_class]
while check_list:
w_item = check_list.pop()
- #Test within iterables (i.e. tuples)
+ # Match identical items.
+ if self.is_true(self.is_(w_exc_type, w_item)):
+ return True
+ # Test within iterables (i.e. tuples)
try:
exclst = self.unpackiterable(w_item)
check_list.extend(exclst)
- except KeyboardInterrupt:
- raise
- except:
- #w_check_class is not iterable
- pass
- #w_item should now be an Exception (or string?)
- #Match identical items.
- w_rv = self.is_(w_exc_type, w_item)
- if self.is_true(w_rv):
- return w_rv
- #Match subclasses.
- try:
- w_rv = self.issubtype(w_exc_type, w_item)
- except KeyboardInterrupt:
- raise
- except:
- pass
- else:
- if self.is_true(w_rv):
- return w_rv
- return self.w_False
+ except OperationError:
+ # w_item is not iterable; it should then be an Exception.
+ # Match subclasses.
+ if self.is_true(self.issubtype(w_exc_type, w_item)):
+ return True
+ return False
def call_function(self, w_func, *args_w, **kw_w):
w_kw = self.newdict([(self.wrap(k), w_v) for k, w_v in kw_w.iteritems()])
Copied: pypy/branch/builtinrefactor/pypy/interpreter/error.py (from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/error.py Sat Aug 9 15:48:30 2003
@@ -1,53 +1,11 @@
import sys
-import threadlocals
-class ExecutionContext:
- def __init__(self, space):
+class PyPyError(Exception):
+ "Raise this when you encounter an exceptional situation in PyPy itself."
+ def __init__(self, space, operationerr):
self.space = space
- self.framestack = Stack()
-
- def eval_frame(self, frame):
- locals = threadlocals.getlocals()
- self.framestack.push(frame)
- previous_ec = locals.executioncontext
- locals.executioncontext = self
- try:
- result = frame.eval(self)
- finally:
- locals.executioncontext = previous_ec
- self.framestack.pop()
- return result
-
- def get_w_builtins(self):
- if self.framestack.empty():
- return self.space.w_builtins
- else:
- return self.framestack.top().w_builtins
-
- def make_standard_w_globals(self):
- "Create a new empty 'globals' dictionary."
- w_key = self.space.wrap("__builtins__")
- w_value = self.get_w_builtins()
- w_globals = self.space.newdict([(w_key, w_value)])
- return w_globals
-
- def bytecode_trace(self, frame):
- "Trace function called before each bytecode."
-
- def exception_trace(self, operationerr):
- "Trace function called upon OperationError."
- operationerr.record_interpreter_traceback()
- #operationerr.print_detailed_traceback(self.space)
-
- def sys_exc_info(self):
- """Implements sys.exc_info().
- Return an OperationError instance or None."""
- for i in range(self.framestack.depth()):
- frame = self.framestack.top(i)
- if frame.last_exception is not None:
- return frame.last_exception
- return None
+ self.operationerr = operationerr
class OperationError(Exception):
@@ -71,7 +29,7 @@
def match(self, space, w_check_class):
"Check if this application-level exception matches 'w_check_class'."
- return space.is_true(space.exception_match(self.w_type, w_check_class))
+ return space.exception_match(self.w_type, w_check_class)
def __str__(self):
"Convenience for tracebacks."
@@ -155,11 +113,6 @@
print >> file, exc_typename+':', exc_value
-class NoValue(Exception):
- """Raised to signal absence of value, e.g. in the iterator accessing
- method 'op.next()' of object spaces."""
-
-
# Utilities
def inlinecompile(source, space, symbol='exec'):
@@ -203,40 +156,6 @@
if self.linestart:
self.file.write('\n')
-class Stack:
- """Utility class implementing a stack."""
-
- def __init__(self):
- self.items = []
-
- def clone(self):
- s = self.__class__()
- for item in self.items:
- try:
- item = item.clone()
- except AttributeError:
- pass
- s.push(item)
- return s
-
-
- def push(self, item):
- self.items.append(item)
-
- def pop(self):
- return self.items.pop()
-
- def top(self, position=0):
- """'position' is 0 for the top of the stack, 1 for the item below,
- and so on. It must not be negative."""
- return self.items[~position]
-
- def depth(self):
- return len(self.items)
-
- def empty(self):
- return not self.items
-
# installing the excepthook for OperationErrors
def operr_excepthook(exctype, value, traceback):
if issubclass(exctype, OperationError):
Added: pypy/branch/builtinrefactor/pypy/interpreter/eval.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/eval.py Sat Aug 9 15:48:30 2003
@@ -0,0 +1,118 @@
+"""
+This module defines the abstract base classes that support execution:
+Code and Frame.
+"""
+
+
+class Code(object):
+ """A code is a compiled version of some source code.
+ Abstract base class."""
+
+ def __init__(self, co_name):
+ self.co_name = co_name
+
+ def create_frame(self, space):
+ "Create an empty frame object suitable for evaluation of this code."
+ raise TypeError, "abstract"
+
+ def exec_code(self, space, w_globals, w_locals):
+ "Implements the 'exec' statement."
+ frame = self.create_frame(space)
+ frame.setglobaldict(w_globals)
+ frame.setlocaldict(w_locals)
+ frame.setclosure(None)
+ return frame.run()
+
+ def signature(self):
+ "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+ return [], None, None
+
+ def getargcount(self):
+ "Number of arguments including * and **."
+ argnames, varargname, kwargname = self.signature()
+ count = len(argnames)
+ if varargname is not None:
+ count += 1
+ if kwargname is not None:
+ count += 1
+ return count
+
+ def getlocalvarname(self, index):
+ "Default implementation, can be overridden."
+ argnames, varargname, kwargname = self.signature()
+ try:
+ return argnames[index]
+ except IndexError:
+ index -= len(argnames)
+ if varargname is not None:
+ if index == 0:
+ return varargname
+ index -= 1
+ if kwargname is not None:
+ if index == 0:
+ return kwargname
+ index -= 1
+ raise IndexError, "local variable index out of bounds"
+
+
+class Frame(object):
+ """A frame is an environment supporting the execution of a code object.
+ Abstract base class."""
+
+ def __init__(self, space, code):
+ self.space = space
+ self.code = code # Code instance
+ self.w_globals = None # wrapped dict of globals
+ self.w_locals = None # wrapped dict of locals
+
+ def run(self):
+ "Run the frame."
+ executioncontext = self.space.getexecutioncontext()
+ previous = executioncontext.enter(self)
+ try:
+ result = self.eval(executioncontext)
+ finally:
+ executioncontext.leave(previous)
+ return result
+
+ def eval(self, executioncontext):
+ "Abstract method to override."
+ raise TypeError, "abstract"
+
+ def getglobaldict(self):
+ return self.w_globals
+
+ def setglobaldict(self):
+ self.w_globals = w_globals
+
+ def getlocaldict(self):
+ "Overriden by subclasses with another representation for locals."
+ return self.w_locals
+
+ def setlocaldict(self, w_locals):
+ """Initialize the locals from a dictionary.
+ Overriden by subclasses with another representation for locals."""
+ self.w_locals = w_locals
+
+ def getlocalvar(self, index):
+ """Get the value of the indexth local variable
+ where numbering is according to self.code.signature().
+ Default implementation, to be overridden."""
+ varname = self.code.getlocalvarname(index)
+ return self.space.getitem(w_locals, self.space.wrap(varname))
+
+ def setlocalvar(self, index, w_value):
+ """Set the value of the indexth local variable,
+ where numbering is according to self.code.signature().
+ Default implementation, to be overridden."""
+ if self.w_locals is None:
+ self.w_locals = self.space.newdict([])
+ varname = self.code.getlocalvarname(index)
+ self.space.setitem(self.w_locals, self.space.wrap(varname), w_value)
+
+ def setclosure(self, closure):
+ """Initialize the closure from the given data, which should be None or
+ a list of Cells for PyFrame. This should be called after setlocalvar()
+ or setlocaldict() is used to initialize the frame."""
+ if closure:
+ raise TypeError, "%s instance expects no closure" % self.__class__
Modified: pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/executioncontext.py Sat Aug 9 15:48:30 2003
@@ -1,23 +1,24 @@
-import sys
-import threadlocals
+from pypy.interpreter import threadlocals
class ExecutionContext:
-
+ """An ExecutionContext holds the state of an execution thread
+ in the Python interpreter."""
+
def __init__(self, space):
+ # Note that self.framestack only contains PyFrames
self.space = space
self.framestack = Stack()
- def eval_frame(self, frame):
+ def enter(self, frame):
locals = threadlocals.getlocals()
self.framestack.push(frame)
previous_ec = locals.executioncontext
locals.executioncontext = self
- try:
- result = frame.eval(self)
- finally:
- locals.executioncontext = previous_ec
- self.framestack.pop()
- return result
+ return previous_ec
+
+ def leave(self, previous_ec):
+ locals.executioncontext = previous_ec
+ self.framestack.pop()
def get_w_builtins(self):
if self.framestack.empty():
@@ -50,159 +51,6 @@
return None
-class OperationError(Exception):
- """Interpreter-level exception that signals an exception that should be
- sent to the application level.
-
- OperationError instances have three public attributes (and no .args),
- w_type, w_value and application_traceback, which contain the wrapped
- type and value describing the exception, and the unwrapped list of
- (frame, instruction_position) making the application-level traceback.
- """
-
- def __init__(self, w_type, w_value):
- self.w_type = w_type
- self.w_value = w_value
- self.application_traceback = []
- self.debug_tbs = []
-
- def record_application_traceback(self, frame, last_instruction):
- self.application_traceback.append((frame, last_instruction))
-
- def match(self, space, w_check_class):
- "Check if this application-level exception matches 'w_check_class'."
- return space.is_true(space.exception_match(self.w_type, w_check_class))
-
- def __str__(self):
- "Convenience for tracebacks."
- return '[%s: %s]' % (self.w_type, self.w_value)
-
- def errorstr(self, space):
- "The exception class and value, as a string."
- exc_type = space.unwrap(
- space.getattr(self.w_type, space.wrap('__name__')))
- exc_value = space.unwrap(space.str(self.w_value))
- return '%s: %s' % (exc_type, exc_value)
-
- def getframe(self):
- "The frame this exception was raised in, or None."
- if self.application_traceback:
- frame, last_instruction = self.application_traceback[0]
- return frame
- else:
- return None
-
- def record_interpreter_traceback(self):
- """Records the current traceback inside the interpreter.
- This traceback is only useful to debug the interpreter, not the
- application."""
- self.debug_tbs.append(sys.exc_info()[2])
-
- def print_application_traceback(self, space, file=None):
- "Dump a standard application-level traceback."
- if file is None: file = sys.stderr
- self.print_app_tb_only(file)
- print >> file, self.errorstr(space)
-
- def print_app_tb_only(self, file):
- tb = self.application_traceback[:]
- if tb:
- import linecache
- tb.reverse()
- print >> file, "Traceback (application-level):"
- for f, i in tb:
- co = f.bytecode
- lineno = offset2lineno(co, i)
- fname = co.co_filename
- if fname.startswith('<inline>\n'):
- lines = fname.split('\n')
- fname = lines[0].strip()
- try:
- l = lines[lineno]
- except IndexError:
- l = ''
- else:
- l = linecache.getline(fname, lineno)
- print >> file, " File \"%s\"," % fname,
- print >> file, "line", lineno, "in", co.co_name
- if l:
- if l.endswith('\n'):
- l = l[:-1]
- print >> file, l
-
- def print_detailed_traceback(self, space=None, file=None):
- """Dump a nice detailed interpreter- and application-level traceback,
- useful to debug the interpreter."""
- if file is None: file = sys.stderr
- for i in range(len(self.debug_tbs)-1, -1, -1):
- import traceback
- interpr_file = LinePrefixer(file, '||')
- print >> interpr_file, "Traceback (interpreter-level):"
- traceback.print_tb(self.debug_tbs[i], file=interpr_file)
- self.print_app_tb_only(file)
- if space is None:
- exc_typename = str(self.w_type)
- exc_value = self.w_value
- else:
- w = space.wrap
- exc_typename = space.unwrap(
- space.getattr(self.w_type, w('__name__')))
- exc_value = space.unwrap(space.str(self.w_value))
- print >> file, '(application-level)',
- if exc_value is None:
- print >> file, exc_typename
- else:
- print >> file, exc_typename+':', exc_value
-
-
-class NoValue(Exception):
- """Raised to signal absence of value, e.g. in the iterator accessing
- method 'op.next()' of object spaces."""
-
-
-# Utilities
-
-def inlinecompile(source, space, symbol='exec'):
- """Compile the given 'source' string.
- This function differs from the built-in compile() because it abuses
- co_filename to store a copy of the complete source code.
- This lets OperationError.print_application_traceback() print the
- actual source line in the traceback."""
- compile = space.builtin.compile
- w = space.wrap
- return compile(w(source), w('<inline>\n%s'%source), w(symbol), w(0), w(0))
-
-
-def offset2lineno(c, stopat):
- tab = c.co_lnotab
- line = c.co_firstlineno
- addr = 0
- for i in range(0, len(tab), 2):
- addr = addr + ord(tab[i])
- if addr > stopat:
- break
- line = line + ord(tab[i+1])
- return line
-
-class LinePrefixer:
- """File-like class that inserts a prefix string
- at the beginning of each line it prints."""
- def __init__(self, file, prefix):
- self.file = file
- self.prefix = prefix
- self.linestart = True
- def write(self, data):
- if self.linestart:
- self.file.write(self.prefix)
- if data.endswith('\n'):
- data = data[:-1]
- self.linestart = True
- else:
- self.linestart = False
- self.file.write(data.replace('\n', '\n'+self.prefix))
- if self.linestart:
- self.file.write('\n')
-
class Stack:
"""Utility class implementing a stack."""
@@ -219,7 +67,6 @@
s.push(item)
return s
-
def push(self, item):
self.items.append(item)
@@ -236,13 +83,3 @@
def empty(self):
return not self.items
-
-# installing the excepthook for OperationErrors
-def operr_excepthook(exctype, value, traceback):
- if issubclass(exctype, OperationError):
- value.debug_tbs.append(traceback)
- value.print_detailed_traceback()
- else:
- old_excepthook(exctype, value, traceback)
-old_excepthook = sys.excepthook
-sys.excepthook = operr_excepthook
Added: pypy/branch/builtinrefactor/pypy/interpreter/function.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/function.py Sat Aug 9 15:48:30 2003
@@ -0,0 +1,168 @@
+"""
+Function objects.
+
+In PyPy there is no difference between built-in and user-defined function
+objects; the difference lies in the code object found in their func_code
+attribute.
+"""
+
+class Function:
+ """A function is a code object captured with some environment:
+ an object space, a dictionary of globals, default arguments,
+ and an arbitrary 'closure' passed to the code object."""
+
+ def __init__(self, space, code, w_globals, w_defs=None, closure=None):
+ self.space = space
+ self.func_code = code # Code instance
+ self.w_globals = w_globals # the globals dictionary
+ self.w_defs = w_defs # wrapped sequence of default args or None
+ self.closure = closure # normally, list of Cell instances or None
+
+ def parse_args(self, frame, w_args, w_kwargs=None):
+ """ parse args and kwargs to initialize the frame.
+ """
+ space = self.space
+ signature = self.func_code.signature()
+ argnames, varargname, kwargname = signature
+ # test for 'simple case':
+ if (varargname is None and kwargname is None and # no */**
+ (w_kwargs is None or not space.is_true(w_kwargs)) and # no kwargs
+ self.unwrap(self.len(w_args)) == len(argnames)): # correct #args
+ for index in range(len(argnames)):
+ w_index = self.wrap(index)
+ w_argument = self.getitem(w_args, w_index)
+ frame.setlocalvar(index, w_argument)
+ else:
+ #print "complicated case of arguments for", self.func_code.co_name
+ if w_kwargs is None:
+ w_kwargs = space.w_None
+ self.parse_args_complex(frame, w_args, w_kwargs,
+ space.wrap(signature))
+ frame.setclosure(self.closure)
+
+ def app_parse_args_complex(self, frame, args, kws, signature):
+ """ app-level helper for the complex case of parse_args().
+ """
+ # ===== ATTENTION =====
+ #
+ # This code is pretty fundamental to pypy and great care must be taken
+ # to avoid infinite recursion. In particular:
+ #
+ # - All calls here must be "easy", i.e. not involve default or keyword
+ # arguments. For example, all range() calls need three arguments.
+ #
+ # - You cannot *catch* any exceptions (raising is fine).
+ #
+ # Assumptions:
+ # frame = empty frame to be initialized
+ # args = sequence of the normal actual parameters
+ # kws = dictionary of keyword parameters or None
+ # self.defs = sequence of defaults
+ #
+ # We try to give error messages following CPython's, which are
+ # very informative.
+
+ argnames, varargname, kwargname = signature
+ input_argcount = len(args)
+ co_argcount = len(argnames)
+ deffirst = co_argcount - len(self.defs)
+ if kws:
+ kwargs = kws.copy()
+ else:
+ kwargs = {}
+
+ # fetch all arguments left-to-right
+ for i in range(0, co_argcount, 1):
+ argname = argnames[i]
+ if i < input_argcount:
+ value = args[i]
+ # check that no keyword argument also gives a value here
+ if argname in kwargs:
+ raise TypeError, self.argerr_multiple_values(argname)
+ elif argname in kwargs:
+ # positional arguments exhausted,
+ # complete with keyword arguments
+ value = kwargs[argname]
+ del kwargs[argname]
+ elif i >= deffirst:
+ # no matching keyword argument, but there is a default value
+ value = self.defs[i - deffirst]
+ else:
+ raise TypeError, self.argerr(signature, args, kws, False)
+ frame.setlocalvar(i, value)
+
+ # collect extra positional arguments into the *vararg
+ specialarg = co_argcount
+ if varargname is not None:
+ var_tuple = args[co_argcount:]
+ frame.setlocalvar(specialarg, var_tuple)
+ specialarg += 1
+ elif input_argcount > co_argcount:
+ # cannot do anything with these extra positional arguments
+ raise TypeError, self.argerr(signature, args, kws, True)
+
+ # collect extra keyword arguments into the **kwarg
+ if kwargname is not None:
+ # XXX this doesn't check that the keys of kwargs are strings
+ frame.setlocalvar(specialarg, kwargs)
+ specialarg += 1
+ elif kwargs:
+ # cannot do anything with these extra keyword arguments
+ raise TypeError, self.argerr_unknown_kwds(kwargs)
+ parse_args_complex = app2interp(app_parse_args_complex)
+
+ # helper functions to build error message for the above
+
+ def app_argerr(self, signature, args, kws, too_many):
+ argnames, varargname, kwargname = signature
+ n = len(argnames)
+ if n == 0:
+ n = len(args)
+ if kwargname is not None:
+ msg2 = "non-keyword "
+ else:
+ msg2 = ""
+ n += len(kws)
+ return "%s() takes no %sargument (%d given)" % (
+ self.func_code.co_name,
+ msg2,
+ n)
+ else:
+ defcount = len(self.defs)
+ if defcount == 0:
+ msg1 = "exactly"
+ elif too_many:
+ msg1 = "at most"
+ else:
+ msg1 = "at least"
+ n -= defcount
+ if kws:
+ msg2 = "non-keyword "
+ else:
+ msg2 = ""
+ if n == 1:
+ plural = ""
+ else:
+ plural = "s"
+ return "%s() takes %s %d %sargument%s (%d given)" % (
+ self.func_code.co_name,
+ msg1,
+ n,
+ msg2,
+ plural,
+ len(args))
+
+ def app_argerr_multiple_values(self, argname):
+ return "%s() got multiple values for keyword argument %s" % (
+ self.func_code.co_name,
+ argname)
+
+ def app_argerr_unknown_kwds(self, kws):
+ if len(kws) == 1:
+ return "%s() got an unexpected keyword argument '%s'" % (
+ self.func_code.co_name,
+ kws.keys()[0])
+ else:
+ return "%s() got %d unexpected keyword arguments" % (
+ self.func_code.co_name,
+ len(kws))
Modified: pypy/branch/builtinrefactor/pypy/interpreter/gateway.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/gateway.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/gateway.py Sat Aug 9 15:48:30 2003
@@ -1,10 +1,23 @@
"""
-gateway between app-level and interpreter-level
+Gateway between app-level and interpreter-level:
+the Wrappable base class.
"""
-import inspect
-CO_VARARGS, CO_VARKEYWORDS = 0x4, 0x8
+
+class Wrappable(object):
+ """A subclass of Wrappable is an internal, interpreter-level class
+ that can nevertheless be exposed at application-level,
+ via space.wrap().
+
+ The methods and attributes that a class wants to expose are defined
+ with a naming convension: 'app_xxx' is exposed as 'xxx'.
+ In general, 'app_xxx' should be a gateway (see below)."""
+
+# XXX most code from some classes below have been "stolen" in
+# XXX new classes in other modules. Will be removed.
+
+
class ScopedCode(object):
""" a code object within a certain global and closure scope.
Deleted: /pypy/branch/builtinrefactor/pypy/interpreter/opcode.py
==============================================================================
--- /pypy/branch/builtinrefactor/pypy/interpreter/opcode.py Sat Aug 9 15:48:30 2003
+++ (empty file)
@@ -1,758 +0,0 @@
-from appfile import AppFile
-from pypy.interpreter.baseobjspace import OperationError, NoValue
-from pypy.interpreter.pyframe import _NULL
-import dis
-from pypy.interpreter import pyframe, baseobjspace
-from pypy.interpreter.gateway import InterpretedFunction, ScopedCode
-
-
-# dynamically loaded application-space utilities
-appfile = AppFile(__name__, ["interpreter"])
-
-
-class unaryoperation:
- def __init__(self, operationname):
- self.operationname = operationname
- def __call__(self, f):
- operation = getattr(f.space, self.operationname)
- w_1 = f.valuestack.pop()
- w_result = operation(w_1)
- f.valuestack.push(w_result)
-
-class binaryoperation:
- def __init__(self, operationname):
- self.operationname = operationname
- def __call__(self, f):
- operation = getattr(f.space, self.operationname)
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- w_result = operation(w_1, w_2)
- f.valuestack.push(w_result)
-
-
-################################################################
-## Implementation of the opcodes
-##
-
-def LOAD_FAST(f, varindex):
- # access a local variable through its cell object
- w_value = f.locals_w[varindex]
- if w_value is _NULL:
- varname = f.getlocalvarname(varindex)
- message = "local variable '%s' referenced before assignment" % varname
- raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
- f.valuestack.push(w_value)
-
-def LOAD_CONST(f, constindex):
- w_const = f.space.wrap(f.getconstant(constindex))
- f.valuestack.push(w_const)
-
-def STORE_FAST(f, varindex):
- try:
- w_newvalue = f.valuestack.pop()
- f.locals_w[varindex] = w_newvalue
- except:
- print "exception: got index error"
- print " varindex:", varindex
- print " len(locals_w)", len(f.locals_w)
- import dis
- print dis.dis(f.bytecode)
- print "co_varnames", f.bytecode.co_varnames
- print "co_nlocals", f.bytecode.co_nlocals
- raise
-
-
-def POP_TOP(f):
- f.valuestack.pop()
-
-def ROT_TWO(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_2)
-
-def ROT_THREE(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- w_3 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_3)
- f.valuestack.push(w_2)
-
-def ROT_FOUR(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- w_3 = f.valuestack.pop()
- w_4 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_4)
- f.valuestack.push(w_3)
- f.valuestack.push(w_2)
-
-def DUP_TOP(f):
- w_1 = f.valuestack.top()
- f.valuestack.push(w_1)
-
-def DUP_TOPX(f, itemcount):
- assert 1 <= itemcount <= 5, "limitation of the current interpreter"
- for i in range(itemcount):
- w_1 = f.valuestack.top(itemcount-1)
- f.valuestack.push(w_1)
-
-UNARY_POSITIVE = unaryoperation("pos")
-UNARY_NEGATIVE = unaryoperation("neg")
-UNARY_NOT = unaryoperation("not_")
-UNARY_CONVERT = unaryoperation("repr")
-UNARY_INVERT = unaryoperation("invert")
-
-def BINARY_POWER(f):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- w_result = f.space.pow(w_1, w_2, f.space.w_None)
- f.valuestack.push(w_result)
-
-BINARY_MULTIPLY = binaryoperation("mul")
-BINARY_TRUE_DIVIDE = binaryoperation("truediv")
-BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
-BINARY_DIVIDE = binaryoperation("div")
-BINARY_MODULO = binaryoperation("mod")
-BINARY_ADD = binaryoperation("add")
-BINARY_SUBTRACT = binaryoperation("sub")
-BINARY_SUBSCR = binaryoperation("getitem")
-BINARY_LSHIFT = binaryoperation("lshift")
-BINARY_RSHIFT = binaryoperation("rshift")
-BINARY_AND = binaryoperation("and_")
-BINARY_XOR = binaryoperation("xor")
-BINARY_OR = binaryoperation("or_")
-
-def INPLACE_POWER(f):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
- f.valuestack.push(w_result)
-
-INPLACE_MULTIPLY = binaryoperation("inplace_mul")
-INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv")
-INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
-INPLACE_DIVIDE = binaryoperation("inplace_div")
-INPLACE_MODULO = binaryoperation("inplace_mod")
-INPLACE_ADD = binaryoperation("inplace_add")
-INPLACE_SUBTRACT = binaryoperation("inplace_sub")
-INPLACE_LSHIFT = binaryoperation("inplace_lshift")
-INPLACE_RSHIFT = binaryoperation("inplace_rshift")
-INPLACE_AND = binaryoperation("inplace_and")
-INPLACE_XOR = binaryoperation("inplace_xor")
-INPLACE_OR = binaryoperation("inplace_or")
-
-def slice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- w_result = f.space.getitem(w_obj, w_slice)
- f.valuestack.push(w_result)
-
-def SLICE_0(f):
- slice(f, None, None)
-
-def SLICE_1(f):
- w_start = f.valuestack.pop()
- slice(f, w_start, None)
-
-def SLICE_2(f):
- w_end = f.valuestack.pop()
- slice(f, None, w_end)
-
-def SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- slice(f, w_start, w_end)
-
-def storeslice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setitem(w_obj, w_slice, w_newvalue)
-
-def STORE_SLICE_0(f):
- storeslice(f, None, None)
-
-def STORE_SLICE_1(f):
- w_start = f.valuestack.pop()
- storeslice(f, w_start, None)
-
-def STORE_SLICE_2(f):
- w_end = f.valuestack.pop()
- storeslice(f, None, w_end)
-
-def STORE_SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- storeslice(f, w_start, w_end)
-
-def deleteslice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- f.space.delitem(w_obj, w_slice)
-
-def DELETE_SLICE_0(f):
- deleteslice(f, None, None)
-
-def DELETE_SLICE_1(f):
- w_start = f.valuestack.pop()
- deleteslice(f, w_start, None)
-
-def DELETE_SLICE_2(f):
- w_end = f.valuestack.pop()
- deleteslice(f, None, w_end)
-
-def DELETE_SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- deleteslice(f, w_start, w_end)
-
-def STORE_SUBSCR(f):
- "obj[subscr] = newvalue"
- w_subscr = f.valuestack.pop()
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setitem(w_obj, w_subscr, w_newvalue)
-
-def DELETE_SUBSCR(f):
- "del obj[subscr]"
- w_subscr = f.valuestack.pop()
- w_obj = f.valuestack.pop()
- f.space.delitem(w_obj, w_subscr)
-
-def PRINT_EXPR(f):
- w_expr = f.valuestack.pop()
- #print f.space.unwrap(w_expr)
- f.space.gethelper(appfile).call("print_expr", [w_expr])
-
-def PRINT_ITEM_TO(f):
- w_stream = f.valuestack.pop()
- w_item = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
-
-def PRINT_ITEM(f):
- w_item = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_item", [w_item])
-
-def PRINT_NEWLINE_TO(f):
- w_stream = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_newline_to", [w_stream])
-
-def PRINT_NEWLINE(f):
- f.space.gethelper(appfile).call("print_newline", [])
-
-def BREAK_LOOP(f):
- raise pyframe.SBreakLoop
-
-def CONTINUE_LOOP(f, startofloop):
- raise pyframe.SContinueLoop(startofloop)
-
-def RAISE_VARARGS(f, nbargs):
- # we use the .app.py file to prepare the exception/value/traceback
- # but not to actually raise it, because we cannot use the 'raise'
- # statement to implement RAISE_VARARGS
- if nbargs == 0:
- w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
- elif nbargs == 1:
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
- elif nbargs == 2:
- w_value = f.valuestack.pop()
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, w_value, f.space.w_None])
- elif nbargs == 3:
- w_traceback = f.valuestack.pop()
- w_value = f.valuestack.pop()
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, w_value, w_traceback])
- else:
- raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
- w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
- # XXX the three-arguments 'raise' is not supported yet
- raise OperationError(w_type, w_value)
-
-def LOAD_LOCALS(f):
- f.valuestack.push(f.w_locals)
-
-def RETURN_VALUE(f):
- w_returnvalue = f.valuestack.pop()
- raise pyframe.SReturnValue(w_returnvalue)
-
-def YIELD_VALUE(f):
- w_yieldedvalue = f.valuestack.pop()
- raise pyframe.SYieldValue(w_yieldedvalue)
-YIELD_STMT = YIELD_VALUE # misnamed in dis.opname
-
-def EXEC_STMT(f):
- w_locals = f.valuestack.pop()
- w_globals = f.valuestack.pop()
- w_prog = f.valuestack.pop()
- w_tuple = f.space.gethelper(appfile).call("exec_statement",
- [w_prog, w_globals, w_locals,
- f.w_builtins, f.w_globals, f.w_locals])
- w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
- w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
- w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
-
- plain = (w_locals is f.w_locals)
- if plain:
- f.fast2locals()
- scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
- scopedcode.eval_frame(w_locals)
- #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
- if plain:
- f.locals2fast()
-
-def POP_BLOCK(f):
- block = f.blockstack.pop()
- block.cleanup(f) # the block knows how to clean up the value stack
-
-def END_FINALLY(f):
- # unlike CPython, when we reach this opcode the value stack has
- # always been set up as follows (topmost first):
- # [exception type or None]
- # [exception value or None]
- # [wrapped stack unroller ]
- f.valuestack.pop() # ignore the exception type
- f.valuestack.pop() # ignore the exception value
- unroller = f.space.unwrap(f.valuestack.pop())
- if unroller is not None:
- raise unroller # re-raise the unroller, if any
-
-def BUILD_CLASS(f):
- w_methodsdict = f.valuestack.pop()
- w_bases = f.valuestack.pop()
- w_name = f.valuestack.pop()
- # XXX it would be best to have all opcodes on a class that has a 'space' attribute
- # then the following initialization could be done at init-time.
- build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
- w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
- f.valuestack.push(w_newclass)
-
-def app_build_class(name, bases, namespace, globals):
- if '__metaclass__' in namespace:
- metaclass = namespace['__metaclass__']
- elif len(bases) > 0:
- base = bases[0]
- if hasattr(base, '__class__'):
- metaclass = base.__class__
- else:
- metaclass = type(base)
- elif '__metaclass__' in globals:
- metaclass = globals['__metaclass__']
- else:
- metaclass = type
- return metaclass(name, bases, namespace)
-
-def STORE_NAME(f, varindex):
- varname = f.getname(varindex)
- w_varname = f.space.wrap(varname)
- w_newvalue = f.valuestack.pop()
- f.space.setitem(f.w_locals, w_varname, w_newvalue)
-
-def DELETE_NAME(f, varindex):
- varname = f.getname(varindex)
- w_varname = f.space.wrap(varname)
- try:
- f.space.delitem(f.w_locals, w_varname)
- except OperationError, e:
- # catch KeyErrors and turn them into NameErrors
- if not e.match(f.space, f.space.w_KeyError):
- raise
- message = "name '%s' is not defined" % varname
- raise OperationError(f.space.w_NameError, f.space.wrap(message))
-
-def UNPACK_SEQUENCE(f, itemcount):
- w_iterable = f.valuestack.pop()
- try:
- items = f.space.unpackiterable(w_iterable, itemcount)
- except ValueError, e:
- raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
- items.reverse()
- for item in items:
- f.valuestack.push(item)
-
-def STORE_ATTR(f, nameindex):
- "obj.attributename = newvalue"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setattr(w_obj, w_attributename, w_newvalue)
-
-def DELETE_ATTR(f, nameindex):
- "del obj.attributename"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- f.space.delattr(w_obj, w_attributename)
-
-def STORE_GLOBAL(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- w_newvalue = f.valuestack.pop()
- f.space.setitem(f.w_globals, w_varname, w_newvalue)
-
-def DELETE_GLOBAL(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- f.space.delitem(f.w_globals, w_varname)
-
-def LOAD_NAME(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- try:
- w_value = f.space.getitem(f.w_locals, w_varname)
- except OperationError, e:
- if not e.match(f.space, f.space.w_KeyError):
- raise
- try:
- w_value = f.space.getitem(f.w_globals, w_varname)
- except OperationError, e:
- if not e.match(f.space, f.space.w_KeyError):
- raise
- try:
- w_value = f.space.getitem(f.w_builtins, w_varname)
- except OperationError, e:
- if not e.match(f.space, f.space.w_KeyError):
- raise
- message = "global name '%s' is not defined" % varname
- w_exc_type = f.space.w_NameError
- w_exc_value = f.space.wrap(message)
- raise OperationError(w_exc_type, w_exc_value)
- f.valuestack.push(w_value)
- # XXX the implementation can be pushed back into app-space as an
- # when exception handling begins to behave itself. For now, it
- # was getting on my nerves -- mwh
-# w_value = f.space.gethelper(appfile).call(
-# "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
-# f.valuestack.push(w_value)
-
-def LOAD_GLOBAL(f, nameindex):
- assert f.w_globals is not None
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- try:
- w_value = f.space.getitem(f.w_globals, w_varname)
- except OperationError, e:
- # catch KeyErrors
- if not e.match(f.space, f.space.w_KeyError):
- raise
- # we got a KeyError, now look in the built-ins
- try:
- w_value = f.space.getitem(f.w_builtins, w_varname)
- except OperationError, e:
- # catch KeyErrors again
- if not e.match(f.space, f.space.w_KeyError):
- raise
- message = "global name '%s' is not defined" % varname
- w_exc_type = f.space.w_NameError
- w_exc_value = f.space.wrap(message)
- raise OperationError(w_exc_type, w_exc_value)
- f.valuestack.push(w_value)
-
-def DELETE_FAST(f, varindex):
- w_value = f.locals_w[varindex]
- if f.locals_w[varindex] is _NULL:
- varname = f.getlocalvarname(varindex)
- message = "local variable '%s' referenced before assignment" % varname
- raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
- f.locals_w[varindex] = _NULL
-
-def LOAD_CLOSURE(f, varindex):
- # nested scopes: access the cell object
- cell = f.closure_w[varindex]
- w_value = f.space.wrap(cell)
- f.valuestack.push(w_value)
-
-def LOAD_DEREF(f, varindex):
- # nested scopes: access a variable through its cell object
- cell = f.closure_w[varindex]
- try:
- w_value = cell.get()
- except ValueError:
- varname = f.getfreevarname(varindex)
- if f.iscellvar(varindex):
- message = "local variable '%s' referenced before assignment"
- w_exc_type = f.space.w_UnboundLocalError
- else:
- message = ("free variable '%s' referenced before assignment"
- " in enclosing scope")
- w_exc_type = f.space.w_NameError
- raise OperationError(w_exc_type, f.space.wrap(message % varname))
- f.valuestack.push(w_value)
-
-def STORE_DEREF(f, varindex):
- # nested scopes: access a variable through its cell object
- w_newvalue = f.valuestack.pop()
- try:
- cell = f.closure_w[varindex]
- except IndexError:
- #import pdb; pdb.set_trace()
- raise
- cell.set(w_newvalue)
-
-def BUILD_TUPLE(f, itemcount):
- items = [f.valuestack.pop() for i in range(itemcount)]
- items.reverse()
- w_tuple = f.space.newtuple(items)
- f.valuestack.push(w_tuple)
-
-def BUILD_LIST(f, itemcount):
- items = [f.valuestack.pop() for i in range(itemcount)]
- items.reverse()
- w_list = f.space.newlist(items)
- f.valuestack.push(w_list)
-
-def BUILD_MAP(f, zero):
- if zero != 0:
- raise pyframe.BytecodeCorruption
- w_dict = f.space.newdict([])
- f.valuestack.push(w_dict)
-
-def LOAD_ATTR(f, nameindex):
- "obj.attributename"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- w_value = f.space.getattr(w_obj, w_attributename)
- f.valuestack.push(w_value)
-
-def cmp_lt(f, w_1, w_2): return f.space.lt(w_1, w_2)
-def cmp_le(f, w_1, w_2): return f.space.le(w_1, w_2)
-def cmp_eq(f, w_1, w_2): return f.space.eq(w_1, w_2)
-def cmp_ne(f, w_1, w_2): return f.space.ne(w_1, w_2)
-def cmp_gt(f, w_1, w_2): return f.space.gt(w_1, w_2)
-def cmp_ge(f, w_1, w_2): return f.space.ge(w_1, w_2)
-
-def cmp_in(f, w_1, w_2):
- return f.space.contains(w_2, w_1)
-def cmp_not_in(f, w_1, w_2):
- return f.space.not_(f.space.contains(w_2, w_1))
-def cmp_is(f, w_1, w_2):
- return f.space.is_(w_1, w_2)
-def cmp_is_not(f, w_1, w_2):
- return f.space.not_(f.space.is_(w_1, w_2))
-def cmp_exc_match(f, w_1, w_2):
- return f.space.exception_match(w_1, w_2)
-
-compare_dispatch_table = {
- 0: cmp_lt, # "<"
- 1: cmp_le, # "<="
- 2: cmp_eq, # "=="
- 3: cmp_ne, # "!="
- 4: cmp_gt, # ">"
- 5: cmp_ge, # ">="
- 6: cmp_in,
- 7: cmp_not_in,
- 8: cmp_is,
- 9: cmp_is_not,
- 10: cmp_exc_match,
- }
-def COMPARE_OP(f, testnum):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- try:
- testfn = compare_dispatch_table[testnum]
- except KeyError:
- raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
- w_result = testfn(f, w_1, w_2)
- f.valuestack.push(w_result)
-
-def IMPORT_NAME(f, nameindex):
- modulename = f.getname(nameindex)
- w_modulename = f.space.wrap(modulename)
- w_fromlist = f.valuestack.pop()
- w_obj = f.space.gethelper(appfile).call(
- "import_name", [f.w_builtins,
- w_modulename, f.w_globals, f.w_locals, w_fromlist])
- f.valuestack.push(w_obj)
-
-def IMPORT_STAR(f):
- w_module = f.valuestack.pop()
- f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
-
-def IMPORT_FROM(f, nameindex):
- name = f.getname(nameindex)
- w_name = f.space.wrap(name)
- w_module = f.valuestack.top()
- w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
- f.valuestack.push(w_obj)
-
-def JUMP_FORWARD(f, stepby):
- f.next_instr += stepby
-
-def JUMP_IF_FALSE(f, stepby):
- w_cond = f.valuestack.top()
- if not f.space.is_true(w_cond):
- f.next_instr += stepby
-
-def JUMP_IF_TRUE(f, stepby):
- w_cond = f.valuestack.top()
- if f.space.is_true(w_cond):
- f.next_instr += stepby
-
-def JUMP_ABSOLUTE(f, jumpto):
- f.next_instr = jumpto
-
-def GET_ITER(f):
- w_iterable = f.valuestack.pop()
- w_iterator = f.space.iter(w_iterable)
- f.valuestack.push(w_iterator)
-
-def FOR_ITER(f, jumpby):
- w_iterator = f.valuestack.top()
- try:
- w_nextitem = f.space.next(w_iterator)
- except NoValue:
- # iterator exhausted
- f.valuestack.pop()
- f.next_instr += jumpby
- else:
- f.valuestack.push(w_nextitem)
-
-def FOR_LOOP(f, oparg):
- raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
-
-def SETUP_LOOP(f, offsettoend):
- block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def SETUP_EXCEPT(f, offsettoend):
- block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def SETUP_FINALLY(f, offsettoend):
- block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def call_function_extra(f, oparg, with_varargs, with_varkw):
- n_arguments = oparg & 0xff
- n_keywords = (oparg>>8) & 0xff
- if with_varkw:
- w_varkw = f.valuestack.pop()
- if with_varargs:
- w_varargs = f.valuestack.pop()
- keywords = []
- for i in range(n_keywords):
- w_value = f.valuestack.pop()
- w_key = f.valuestack.pop()
- keywords.append((w_key, w_value))
- arguments = [f.valuestack.pop() for i in range(n_arguments)]
- arguments.reverse()
- w_function = f.valuestack.pop()
- w_arguments = f.space.newtuple(arguments)
- w_keywords = f.space.newdict(keywords)
- if with_varargs:
- w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
- [w_arguments, w_varargs])
- if with_varkw:
- w_keywords = f.space.gethelper(appfile).call("concatenate_keywords",
- [w_keywords, w_varkw])
- w_result = f.space.call(w_function, w_arguments, w_keywords)
- f.valuestack.push(w_result)
-
-def CALL_FUNCTION(f, oparg):
- call_function_extra(f, oparg, False, False)
-
-def CALL_FUNCTION_VAR(f, oparg):
- call_function_extra(f, oparg, True, False)
-
-def CALL_FUNCTION_KW(f, oparg):
- call_function_extra(f, oparg, False, True)
-
-def CALL_FUNCTION_VAR_KW(f, oparg):
- call_function_extra(f, oparg, True, True)
-
-def MAKE_FUNCTION(f, numdefaults):
- w_codeobj = f.valuestack.pop()
- defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
- defaultarguments.reverse()
- w_defaultarguments = f.space.newtuple(defaultarguments)
- w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
- f.w_globals, w_defaultarguments)
- f.valuestack.push(w_func)
-
-def MAKE_CLOSURE(f, numdefaults):
- w_codeobj = f.valuestack.pop()
- codeobj = f.space.unwrap(w_codeobj)
- nfreevars = len(codeobj.co_freevars)
- freevars = [f.valuestack.pop() for i in range(nfreevars)]
- freevars.reverse()
- w_freevars = f.space.newtuple(freevars)
- defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
- defaultarguments.reverse()
- w_defaultarguments = f.space.newtuple(defaultarguments)
- w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
- f.w_globals, w_defaultarguments, w_freevars)
- f.valuestack.push(w_func)
-
-def BUILD_SLICE(f, numargs):
- if numargs == 3:
- w_step = f.valuestack.pop()
- elif numargs == 2:
- w_step = None
- else:
- raise pyframe.BytecodeCorruption
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- w_slice = f.space.newslice(w_start, w_end, w_step)
- f.valuestack.push(w_slice)
-
-def SET_LINENO(f, lineno):
- pass
-
-def EXTENDED_ARG(f, oparg):
- opcode = f.nextop()
- oparg = oparg<<16 | f.nextarg()
- dispatch_arg(f, oparg)
-
-def MISSING_OPCODE(f, oparg=None):
- raise pyframe.BytecodeCorruption, "unknown opcode"
-
-
-################################################################
-
-dispatch_table = []
-for i in range(256):
- opname = dis.opname[i].replace('+', '_')
- fn = MISSING_OPCODE
- if opname in globals():
- fn = globals()[opname]
- elif not opname.startswith('<') and i>0:
- #import warnings
- #warnings.warn("* Warning, missing opcode %s" % opname)
- pass
- dispatch_table.append(fn)
-
-
-def name(thing):
- try:
- return thing.operationname
- except AttributeError:
- return thing.__name__
-
-def has_arg(opcode):
- return opcode >= dis.HAVE_ARGUMENT
-
-def dispatch_noarg(f, opcode):
- try:
- fn = dispatch_table[opcode]
-# print name(fn)
- except KeyError:
- raise KeyError, "missing opcode %s" % dis.opname[opcode]
- fn(f)
-
-def dispatch_arg(f, opcode, oparg):
- assert oparg >= 0
- try:
- fn = dispatch_table[opcode]
-# print name(fn)
- except KeyError:
- raise KeyError, "missing opcode %s" % dis.opname[opcode]
- fn(f, oparg)
Added: pypy/branch/builtinrefactor/pypy/interpreter/pycode.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pycode.py Sat Aug 9 15:48:30 2003
@@ -0,0 +1,105 @@
+"""
+Python-style code objects.
+PyCode instances have the same co_xxx arguments as CPython code objects.
+The bytecode interpreter itself is implemented by the PyFrame class.
+"""
+
+from pypy.interpreter import eval
+from pypy.interpreter.pyopcode import PyOperationalFrame
+from pypy.interpreter.pyfastscope import PyFastScopeFrame
+from pypy.interpreter.pynestedscope import PyNestedScopeFrame
+
+
+# code object contants, for co_flags below
+CO_OPTIMIZED = 0x0001
+CO_NEWLOCALS = 0x0002
+CO_VARARGS = 0x0004
+CO_VARKEYWORDS = 0x0008
+CO_NESTED = 0x0010
+CO_GENERATOR = 0x0020
+
+
+class PyCode(eval.Code):
+ "CPython-style code objects."
+
+ def __init__(self, co_name):
+ eval.Code.__init__(self, co_name)
+ self.co_argcount = 0 # #arguments, except *vararg and **kwarg
+ self.co_nlocals = 0 # #local variables
+ self.co_stacksize = 0 # #entries needed for evaluation stack
+ self.co_flags = 0 # CO_..., see above
+ self.co_code = None # string: instruction opcodes
+ self.co_consts = () # tuple: constants used
+ self.co_names = () # tuple of strings: names (for attrs,...)
+ self.co_varnames = () # tuple of strings: local variable names
+ self.co_freevars = () # tuple of strings: free variable names
+ self.co_cellvars = () # tuple of strings: cell variable names
+ # The rest doesn't count for hash/cmp
+ self.co_filename = "" # string: where it was loaded from
+ #self.co_name (in base class)# string: name, for reference
+ self.co_firstlineno = 0 # first source line number
+ self.co_lnotab = "" # string: encoding addr<->lineno mapping
+
+ def _from_code(self, code):
+ """ Initialize the code object from a real (CPython) one.
+ This is just a hack, until we have our own compile.
+ At the moment, we just fake this.
+ This method is called by our compile builtin function.
+ """
+ import types
+ assert isinstance(code, types.CodeType)
+ # simply try to suck in all attributes we know of
+ for name in self.__dict__.keys():
+ value = getattr(code, name)
+ setattr(self, name, value)
+ newconsts = ()
+ for const in code.co_consts:
+ if isinstance(const, types.CodeType):
+ newc = PyCode(const.co_name)
+ newc._from_code(const)
+ newconsts = newconsts + (newc,)
+ else:
+ newconsts = newconsts + (const,)
+ self.co_consts = newconsts
+
+ def create_frame(self, space):
+ "Create an empty PyFrame suitable for this code object."
+ # select the appropriate kind of frame; see below
+ if self.co_cellvars or self.co_freevars:
+ frameclass = PyNestedScopeFrame
+ elif self.co_nlocals:
+ frameclass = PyFastScopeFrame
+ else:
+ frameclass = PyOperationalFrame
+ return frameclass(space, self)
+
+ def signature(self):
+ "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)."
+ argcount = self.co_argcount
+ argnames = self.co_varnames[:argcount]
+ if self.co_flags & CO_VARARGS:
+ varargname = self.co_varnames[argcount]
+ argcount += 1
+ else:
+ varargname = None
+ if self.co_flags & CO_VARKEYWORDS:
+ kwargname = self.co_varnames[argcount]
+ argcount += 1
+ else:
+ kwargname = None
+ return argnames, varargname, kwargname
+
+ def getargcount(self):
+ count = self.co_argcount
+ if self.co_flags & CO_VARARGS:
+ count += 1
+ if self.co_flags & CO_VARKEYWORDS:
+ count += 1
+ return count
+
+ def getlocalvarname(self, index):
+ # nb. this is duplicated in PyFastScopeFrame.getlocalvarname()
+ return self.co_varnames[index]
+
+ def is_generator(self):
+ return self.co_flags & CO_GENERATOR
Added: pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyfastscope.py Sat Aug 9 15:48:30 2003
@@ -0,0 +1,91 @@
+from pypy.interpreter.pyopcode import PyOperationalFrame
+
+
+UNDEFINED = object() # marker for undefined local variables
+
+
+class PyFastScopeFrame(PyOperationalFrame):
+ "A PyFrame that knows about fast scopes."
+
+ # this is the class that knows about "fast locals", i.e.
+ # the fact that local variables are better represented as an array
+ # of values accessed by index (by the LOAD_FAST, STORE_FAST and
+ # DELETE_FAST opcodes).
+
+ def __init__(self, space, code):
+ PyOperationalFrame.__init__(self, space, code)
+ self.locals_w = [UNDEFINED] * code.co_nlocals
+
+ def getlocalvarname(self, index):
+ return self.bytecode.co_varnames[index]
+
+ def getlocaldict(self):
+ self.fast2locals()
+ return self.w_locals
+
+ def setlocaldict(self, w_locals):
+ self.w_locals = w_locals
+ self.locals2fast()
+
+ def getlocalvar(self, index):
+ return self.locals_w[index]
+
+ def setlocalvar(self, index, w_value):
+ self.locals_w[index] = w_value
+
+ def fast2locals(self):
+ # Copy values from self.locals_w to self.w_locals
+ if self.w_locals is None:
+ self.w_locals = self.space.newdict([])
+ for name, w_value in zip(self.bytecode.co_varnames, self.locals_w):
+ if w_value is not UNDEFINED:
+ w_name = self.space.wrap(name)
+ self.space.setitem(self.w_locals, w_name, w_value)
+
+ def locals2fast(self):
+ # Copy values from self.w_locals to self.locals_w
+ for i in range(self.bytecode.co_nlocals):
+ w_name = self.space.wrap(self.bytecode.co_varnames[i])
+ try:
+ w_value = self.space.getitem(self.w_locals, w_name)
+ except OperationError, e:
+ if not e.match(self.space, self.space.w_KeyError):
+ raise
+ else:
+ self.locals_w[i] = w_value
+
+ ### extra opcodes ###
+
+ def LOAD_FAST(f, varindex):
+ # access a local variable directly
+ w_value = f.locals_w[varindex]
+ if w_value is UNDEFINED:
+ varname = f.getlocalvarname(varindex)
+ message = "local variable '%s' referenced before assignment" % varname
+ raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
+ f.valuestack.push(w_value)
+
+ def STORE_FAST(f, varindex):
+ try:
+ w_newvalue = f.valuestack.pop()
+ f.locals_w[varindex] = w_newvalue
+ except:
+ print "exception: got index error"
+ print " varindex:", varindex
+ print " len(locals_w)", len(f.locals_w)
+ import dis
+ print dis.dis(f.bytecode)
+ print "co_varnames", f.bytecode.co_varnames
+ print "co_nlocals", f.bytecode.co_nlocals
+ raise
+
+ def DELETE_FAST(f, varindex):
+ w_value = f.locals_w[varindex]
+ if f.locals_w[varindex] is UNDEFINED:
+ varname = f.getlocalvarname(varindex)
+ message = "local variable '%s' referenced before assignment" % varname
+ raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
+ f.locals_w[varindex] = UNDEFINED
+
+
+PyFastScopeFrame.setup_dispatch_table()
Modified: pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyframe.py Sat Aug 9 15:48:30 2003
@@ -1,61 +1,53 @@
""" PyFrame class implementation with the interpreter main loop.
"""
-from pypy.interpreter.executioncontext import OperationError, Stack, NoValue
-from pypy.interpreter.gateway import app2interp, Cell, _NULL
+from pypy.interpreter.executioncontext import Stack
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import app2interp
+from pypy.interpreter import eval, baseobjspace
-class PyFrame:
+class PyFrame(eval.Frame):
"""Represents a frame for a regular Python function
that needs to be interpreted.
+ See also pyopcode.PyStandardFrame and pynestedscope.PyNestedScopeFrame.
+
Public fields:
* 'space' is the object space this frame is running in
+ * 'bytecode' is the PyCode object this frame runs
* 'w_locals' is the locals dictionary to use
* 'w_globals' is the attached globals dictionary
* 'w_builtins' is the attached built-ins dictionary
* 'valuestack', 'blockstack', 'next_instr' control the interpretation
"""
- def initialize(self, scopedcode):
- self.space = scopedcode.space
- self.bytecode = scopedcode.cpycode
- self.w_globals = scopedcode.w_globals
- self.closure_w = scopedcode.closure_w or ()
+ def __init__(self, space, code):
+ eval.Frame.__init__(self, space, code)
+ self.bytecode = code # Misnomer; this is really like a code object
self.valuestack = Stack()
self.blockstack = Stack()
self.last_exception = None
self.next_instr = 0
self.w_builtins = self.space.w_builtins
- def setdictscope(self, w_locals):
- self.w_locals = w_locals
- self.locals_w = [_NULL] * self.bytecode.co_nlocals
- self.locals2fast()
-
- def setfastscope(self, locals_w):
- self.locals_w = locals_w
- self.w_locals = self.space.newdict([])
- self.fast2locals()
-
- def XXXclone(self):
- f = self.__class__()
- f.space = self.space
- f.bytecode = self.bytecode
- f.w_globals = self.w_globals
- f.w_locals = self.w_locals
- f.w_builtins = self.w_builtins
- f.valuestack = self.valuestack.clone()
- f.blockstack = self.blockstack.clone()
- f.localcells = [x.clone() for x in self.localcells]
- f.nestedcells = [x.clone() for x in self.nestedcells]
- f.last_exception = self.last_exception
- f.next_instr = self.next_instr
- return f
+## def XXXclone(self):
+## f = self.__class__()
+## f.space = self.space
+## f.bytecode = self.bytecode
+## f.w_globals = self.w_globals
+## f.w_locals = self.w_locals
+## f.w_builtins = self.w_builtins
+## f.valuestack = self.valuestack.clone()
+## f.blockstack = self.blockstack.clone()
+## f.localcells = [x.clone() for x in self.localcells]
+## f.nestedcells = [x.clone() for x in self.nestedcells]
+## f.last_exception = self.last_exception
+## f.next_instr = self.next_instr
+## return f
def eval(self, executioncontext):
"Interpreter main loop!"
- from pypy.interpreter import opcode
try:
while True:
try:
@@ -63,12 +55,8 @@
last_instr = self.next_instr
try:
# fetch and dispatch the next opcode
- op = self.nextop()
- if opcode.has_arg(op):
- oparg = self.nextarg()
- opcode.dispatch_arg(self, op, oparg)
- else:
- opcode.dispatch_noarg(self, op)
+ # dispatch() is abstract, see pyopcode.
+ self.dispatch()
except OperationError, e:
#import traceback
#traceback.print_exc()
@@ -93,7 +81,20 @@
w_exitvalue = e.args[0]
return w_exitvalue
- ### accessor functions ###
+ ### opcode dispatch ###
+
+ # 'dispatch_table' is a class attribute: a list of functions.
+ # Currently, it is always created by setup_dispatch_table in pyopcode.py
+ # but it could be a custom table.
+
+ def dispatch(self):
+ opcode = self.nextop()
+ fn = self.dispatch_table[opcode]
+ if fn.has_arg:
+ oparg = self.nextarg()
+ fn(self, oparg)
+ else:
+ fn(self)
def nextop(self):
c = self.bytecode.co_code[self.next_instr]
@@ -105,45 +106,6 @@
hi = self.nextop()
return (hi<<8) + lo
- def getconstant(self, index):
- return self.bytecode.co_consts[index]
-
- def getlocalvarname(self, index):
- return self.bytecode.co_varnames[index]
-
- def getname(self, index):
- return self.bytecode.co_names[index]
-
- def getfreevarname(self, index):
- freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
- return freevarnames[index]
-
- def iscellvar(self, index):
- # is the variable given by index a cell or a free var?
- return index < len(self.bytecode.co_cellvars)
-
- def fast2locals(self):
- # Copy values from self.localcells to self.w_locals
- for name, w_value in zip(self.bytecode.co_varnames, self.locals_w):
- w_name = self.space.wrap(name)
- if w_value is not _NULL:
- self.space.setitem(self.w_locals, w_name, w_value)
-
- def locals2fast(self):
- # Copy values from self.w_locals to self.localcells
- for i in range(self.bytecode.co_nlocals):
- w_name = self.space.wrap(self.bytecode.co_varnames[i])
- try:
- w_value = self.space.getitem(self.w_locals, w_name)
- except OperationError, e:
- if not e.match(self.space, self.space.w_KeyError):
- raise
- else:
- self.locals_w[i] = w_value
-
- ### frame initialization ###
-
-
### exception stack ###
def clean_exceptionstack(self):
@@ -240,7 +202,7 @@
evalue = (evalue,)
evalue = etype(*evalue)
else:
- raise Exception, "?!"
+ raise Exception, "?!" # XXX
return etype, evalue
normalize_exception = app2interp(app_normalize_exception)
@@ -324,8 +286,8 @@
"""Signals a 'return' statement.
Argument is the wrapped object to return."""
def emptystack(self, frame):
- if frame.bytecode.co_flags & 0x0020:#CO_GENERATOR:
- raise NoValue
+ if frame.bytecode.is_generator():
+ raise baseobjspace.NoValue
w_returnvalue = self.args[0]
raise ExitFrame(w_returnvalue)
Added: pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py
==============================================================================
--- (empty file)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pynestedscope.py Sat Aug 9 15:48:30 2003
@@ -0,0 +1,173 @@
+from pypy.interpreter.pyfastscope import PyFastScopeFrame, UNDEFINED
+
+
+class Cell(object):
+ "A simple container for a wrapped value."
+
+ def __init__(self, w_value=UNDEFINED):
+ self.w_value = w_value
+
+ def clone(self):
+ return self.__class__(self.w_value)
+
+ def empty(self):
+ return self.w_value is UNDEFINED
+
+ def get(self):
+ if self.w_value is UNDEFINED:
+ raise ValueError, "get() from an empty cell"
+ return self.w_value
+
+ def set(self, w_value):
+ self.w_value = w_value
+
+ def delete(self):
+ if self.w_value is UNDEFINED:
+ raise ValueError, "delete() on an empty cell"
+ self.w_value = UNDEFINED
+
+ def __repr__(self):
+ """ representation for debugging purposes """
+ if self.w_value is UNDEFINED:
+ content = ""
+ else:
+ content = repr(self.w_value)
+ return "<%s(%s) at 0x%x>" % (self.__class__.__name__,
+ content, id(self))
+
+
+class PyNestedScopeFrame(PyFastScopeFrame):
+ """This class enhances a standard frame with nested scope abilities,
+ i.e. handling of cell/free variables."""
+
+ def __init__(self, space, code):
+ PyFastScopeFrame.__init__(self, space, code)
+ ncellvars = len(code.co_cellvars)
+ nfreevars = len(code.co_freevars)
+ self.cells = [None] * (ncellvars + nfreevars)
+
+ def fast2locals(self):
+ PyFastScopeFrame.fast2locals(self)
+ freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+ for name, cell in zip(freevarnames, self.cells):
+ try:
+ w_value = cell.get()
+ except ValueError:
+ pass
+ else:
+ w_name = self.space.wrap(name)
+ self.space.setitem(self.w_locals, w_name, w_value)
+
+ def locals2fast(self):
+ PyFastScopeFrame.locals2fast(self)
+ freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+ for name, cell in zip(freevarnames, self.cells):
+ w_name = self.space.wrap(name)
+ try:
+ w_value = self.space.getitem(self.w_locals, w_name)
+ except OperationError, e:
+ if not e.match(self.space, self.space.w_KeyError):
+ raise
+ else:
+ cell.set(w_value)
+
+ def setclosure(self, closure):
+ # Cell Vars:
+ # my local variables that are exposed to my inner functions
+ # Free Vars:
+ # variables coming from a parent function in which i'm nested
+ # 'closure' is a list of Cell instances: the received free vars.
+ code = self.bytecode
+ ncellvars = len(code.co_cellvars)
+ nfreevars = len(code.co_freevars)
+ if ncellvars:
+ # the first few cell vars could shadow already-set arguments,
+ # in the same order as they appear in co_varnames
+ nargvars = code.getargcount()
+ argvars = code.co_varnames
+ cellvars = code.co_cellvars
+ next = 0
+ nextname = cellvars[0]
+ for i in range(nargvars):
+ if argvars[i] == nextname:
+ # argument i has the same name as the next cell var
+ w_value = self.locals_w[i]
+ self.cells[next] = Cell(w_value)
+ next += 1
+ try:
+ nextname = cellvars[next]
+ except IndexError:
+ break # all cell vars initialized this way
+ else:
+ # the remaining cell vars are empty
+ for i in range(next, ncellvars):
+ self.cells[i] = Cell()
+ # following the cell vars are the free vars, copied from 'closure'
+ if closure is None:
+ closure = []
+ if len(closure) != nfreevars:
+ raise TypeError, ("%d free variables expected, got %d" %
+ (nfreevars, len(closure))) # internal error
+ self.cells[ncellvars:] = closure
+
+ def getfreevarname(self, index):
+ freevarnames = self.bytecode.co_cellvars + self.bytecode.co_freevars
+ return freevarnames[index]
+
+ def iscellvar(self, index):
+ # is the variable given by index a cell or a free var?
+ return index < len(self.bytecode.co_cellvars)
+
+ ### extra opcodes ###
+
+ def LOAD_CLOSURE(f, varindex):
+ # nested scopes: access the cell object
+ cell = f.cells[varindex]
+ assert cell is not None, "setclosure() was not called"
+ w_value = f.space.wrap(cell)
+ f.valuestack.push(w_value)
+
+ def LOAD_DEREF(f, varindex):
+ # nested scopes: access a variable through its cell object
+ cell = f.cells[varindex]
+ try:
+ w_value = cell.get()
+ except ValueError:
+ varname = f.getfreevarname(varindex)
+ if f.iscellvar(varindex):
+ message = "local variable '%s' referenced before assignment"
+ w_exc_type = f.space.w_UnboundLocalError
+ else:
+ message = ("free variable '%s' referenced before assignment"
+ " in enclosing scope")
+ w_exc_type = f.space.w_NameError
+ raise OperationError(w_exc_type, f.space.wrap(message % varname))
+ else:
+ f.valuestack.push(w_value)
+
+ def STORE_DEREF(f, varindex):
+ # nested scopes: access a variable through its cell object
+ w_newvalue = f.valuestack.pop()
+ #try:
+ cell = f.cells[varindex]
+ #except IndexError:
+ # import pdb; pdb.set_trace()
+ # raise
+ cell.set(w_newvalue)
+
+ def MAKE_CLOSURE(f, numdefaults):
+ w_codeobj = f.valuestack.pop()
+ codeobj = f.space.unwrap(w_codeobj)
+ nfreevars = len(codeobj.co_freevars)
+ freevars = [f.valuestack.pop() for i in range(nfreevars)]
+ freevars.reverse()
+ w_freevars = f.space.newtuple(freevars)
+ defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
+ defaultarguments.reverse()
+ w_defaultarguments = f.space.newtuple(defaultarguments)
+ w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
+ f.w_globals, w_defaultarguments, w_freevars)
+ f.valuestack.push(w_func)
+
+
+PyNestedScopeFrame.setup_dispatch_table()
Copied: pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py (from rev 1262, pypy/branch/builtinrefactor/pypy/interpreter/opcode.py)
==============================================================================
--- pypy/branch/builtinrefactor/pypy/interpreter/opcode.py (original)
+++ pypy/branch/builtinrefactor/pypy/interpreter/pyopcode.py Sat Aug 9 15:48:30 2003
@@ -1,13 +1,13 @@
-from appfile import AppFile
+"""
+Implementation of a part of the standard Python opcodes.
+The rest, dealing with variables in optimized ways, is in
+pyfastscope.py and pynestedscope.py.
+"""
+
from pypy.interpreter.baseobjspace import OperationError, NoValue
-from pypy.interpreter.pyframe import _NULL
import dis
-from pypy.interpreter import pyframe, baseobjspace
-from pypy.interpreter.gateway import InterpretedFunction, ScopedCode
-
-
-# dynamically loaded application-space utilities
-appfile = AppFile(__name__, ["interpreter"])
+from pypy.interpreter import baseobjspace
+from pypy.interpreter.pyframe import PyFrame
class unaryoperation:
@@ -30,729 +30,648 @@
f.valuestack.push(w_result)
-################################################################
-## Implementation of the opcodes
-##
-
-def LOAD_FAST(f, varindex):
- # access a local variable through its cell object
- w_value = f.locals_w[varindex]
- if w_value is _NULL:
- varname = f.getlocalvarname(varindex)
- message = "local variable '%s' referenced before assignment" % varname
- raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
- f.valuestack.push(w_value)
-
-def LOAD_CONST(f, constindex):
- w_const = f.space.wrap(f.getconstant(constindex))
- f.valuestack.push(w_const)
+class PyOperationalFrame(PyFrame):
+ """A PyFrame that knows about all operational Python opcodes.
+ It does not know about 'fast variables' nor 'nested scopes'."""
+
+ ### accessor functions ###
+
+ def getconstant(self, index):
+ return self.bytecode.co_consts[index]
+
+ def getname(self, index):
+ return self.bytecode.co_names[index]
+
+ ################################################################
+ ## Implementation of the "operational" opcodes
+ ## See also pyfastscope.py and pynestedscope.py for the rest.
+ ##
+
+ # the 'self' argument of opcode implementations is called 'f'
+ # for historical reasons
-def STORE_FAST(f, varindex):
- try:
- w_newvalue = f.valuestack.pop()
- f.locals_w[varindex] = w_newvalue
- except:
- print "exception: got index error"
- print " varindex:", varindex
- print " len(locals_w)", len(f.locals_w)
- import dis
- print dis.dis(f.bytecode)
- print "co_varnames", f.bytecode.co_varnames
- print "co_nlocals", f.bytecode.co_nlocals
- raise
-
-
-def POP_TOP(f):
- f.valuestack.pop()
-
-def ROT_TWO(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_2)
-
-def ROT_THREE(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- w_3 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_3)
- f.valuestack.push(w_2)
-
-def ROT_FOUR(f):
- w_1 = f.valuestack.pop()
- w_2 = f.valuestack.pop()
- w_3 = f.valuestack.pop()
- w_4 = f.valuestack.pop()
- f.valuestack.push(w_1)
- f.valuestack.push(w_4)
- f.valuestack.push(w_3)
- f.valuestack.push(w_2)
-
-def DUP_TOP(f):
- w_1 = f.valuestack.top()
- f.valuestack.push(w_1)
-
-def DUP_TOPX(f, itemcount):
- assert 1 <= itemcount <= 5, "limitation of the current interpreter"
- for i in range(itemcount):
- w_1 = f.valuestack.top(itemcount-1)
+ def LOAD_CONST(f, constindex):
+ w_const = f.space.wrap(f.getconstant(constindex))
+ f.valuestack.push(w_const)
+
+ def POP_TOP(f):
+ f.valuestack.pop()
+
+ def ROT_TWO(f):
+ w_1 = f.valuestack.pop()
+ w_2 = f.valuestack.pop()
f.valuestack.push(w_1)
+ f.valuestack.push(w_2)
-UNARY_POSITIVE = unaryoperation("pos")
-UNARY_NEGATIVE = unaryoperation("neg")
-UNARY_NOT = unaryoperation("not_")
-UNARY_CONVERT = unaryoperation("repr")
-UNARY_INVERT = unaryoperation("invert")
-
-def BINARY_POWER(f):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- w_result = f.space.pow(w_1, w_2, f.space.w_None)
- f.valuestack.push(w_result)
-
-BINARY_MULTIPLY = binaryoperation("mul")
-BINARY_TRUE_DIVIDE = binaryoperation("truediv")
-BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
-BINARY_DIVIDE = binaryoperation("div")
-BINARY_MODULO = binaryoperation("mod")
-BINARY_ADD = binaryoperation("add")
-BINARY_SUBTRACT = binaryoperation("sub")
-BINARY_SUBSCR = binaryoperation("getitem")
-BINARY_LSHIFT = binaryoperation("lshift")
-BINARY_RSHIFT = binaryoperation("rshift")
-BINARY_AND = binaryoperation("and_")
-BINARY_XOR = binaryoperation("xor")
-BINARY_OR = binaryoperation("or_")
-
-def INPLACE_POWER(f):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
- f.valuestack.push(w_result)
-
-INPLACE_MULTIPLY = binaryoperation("inplace_mul")
-INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv")
-INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
-INPLACE_DIVIDE = binaryoperation("inplace_div")
-INPLACE_MODULO = binaryoperation("inplace_mod")
-INPLACE_ADD = binaryoperation("inplace_add")
-INPLACE_SUBTRACT = binaryoperation("inplace_sub")
-INPLACE_LSHIFT = binaryoperation("inplace_lshift")
-INPLACE_RSHIFT = binaryoperation("inplace_rshift")
-INPLACE_AND = binaryoperation("inplace_and")
-INPLACE_XOR = binaryoperation("inplace_xor")
-INPLACE_OR = binaryoperation("inplace_or")
-
-def slice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- w_result = f.space.getitem(w_obj, w_slice)
- f.valuestack.push(w_result)
-
-def SLICE_0(f):
- slice(f, None, None)
-
-def SLICE_1(f):
- w_start = f.valuestack.pop()
- slice(f, w_start, None)
-
-def SLICE_2(f):
- w_end = f.valuestack.pop()
- slice(f, None, w_end)
-
-def SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- slice(f, w_start, w_end)
-
-def storeslice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setitem(w_obj, w_slice, w_newvalue)
-
-def STORE_SLICE_0(f):
- storeslice(f, None, None)
-
-def STORE_SLICE_1(f):
- w_start = f.valuestack.pop()
- storeslice(f, w_start, None)
-
-def STORE_SLICE_2(f):
- w_end = f.valuestack.pop()
- storeslice(f, None, w_end)
-
-def STORE_SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- storeslice(f, w_start, w_end)
-
-def deleteslice(f, w_start, w_end):
- w_slice = f.space.newslice(w_start, w_end, None)
- w_obj = f.valuestack.pop()
- f.space.delitem(w_obj, w_slice)
-
-def DELETE_SLICE_0(f):
- deleteslice(f, None, None)
-
-def DELETE_SLICE_1(f):
- w_start = f.valuestack.pop()
- deleteslice(f, w_start, None)
-
-def DELETE_SLICE_2(f):
- w_end = f.valuestack.pop()
- deleteslice(f, None, w_end)
-
-def DELETE_SLICE_3(f):
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- deleteslice(f, w_start, w_end)
-
-def STORE_SUBSCR(f):
- "obj[subscr] = newvalue"
- w_subscr = f.valuestack.pop()
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setitem(w_obj, w_subscr, w_newvalue)
-
-def DELETE_SUBSCR(f):
- "del obj[subscr]"
- w_subscr = f.valuestack.pop()
- w_obj = f.valuestack.pop()
- f.space.delitem(w_obj, w_subscr)
-
-def PRINT_EXPR(f):
- w_expr = f.valuestack.pop()
- #print f.space.unwrap(w_expr)
- f.space.gethelper(appfile).call("print_expr", [w_expr])
-
-def PRINT_ITEM_TO(f):
- w_stream = f.valuestack.pop()
- w_item = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
-
-def PRINT_ITEM(f):
- w_item = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_item", [w_item])
-
-def PRINT_NEWLINE_TO(f):
- w_stream = f.valuestack.pop()
- f.space.gethelper(appfile).call("print_newline_to", [w_stream])
-
-def PRINT_NEWLINE(f):
- f.space.gethelper(appfile).call("print_newline", [])
-
-def BREAK_LOOP(f):
- raise pyframe.SBreakLoop
-
-def CONTINUE_LOOP(f, startofloop):
- raise pyframe.SContinueLoop(startofloop)
-
-def RAISE_VARARGS(f, nbargs):
- # we use the .app.py file to prepare the exception/value/traceback
- # but not to actually raise it, because we cannot use the 'raise'
- # statement to implement RAISE_VARARGS
- if nbargs == 0:
- w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
- elif nbargs == 1:
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
- elif nbargs == 2:
- w_value = f.valuestack.pop()
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, w_value, f.space.w_None])
- elif nbargs == 3:
- w_traceback = f.valuestack.pop()
- w_value = f.valuestack.pop()
- w_type = f.valuestack.pop()
- w_resulttuple = f.space.gethelper(appfile).call(
- "prepare_raise", [w_type, w_value, w_traceback])
- else:
- raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
- w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
- # XXX the three-arguments 'raise' is not supported yet
- raise OperationError(w_type, w_value)
-
-def LOAD_LOCALS(f):
- f.valuestack.push(f.w_locals)
-
-def RETURN_VALUE(f):
- w_returnvalue = f.valuestack.pop()
- raise pyframe.SReturnValue(w_returnvalue)
-
-def YIELD_VALUE(f):
- w_yieldedvalue = f.valuestack.pop()
- raise pyframe.SYieldValue(w_yieldedvalue)
-YIELD_STMT = YIELD_VALUE # misnamed in dis.opname
-
-def EXEC_STMT(f):
- w_locals = f.valuestack.pop()
- w_globals = f.valuestack.pop()
- w_prog = f.valuestack.pop()
- w_tuple = f.space.gethelper(appfile).call("exec_statement",
- [w_prog, w_globals, w_locals,
- f.w_builtins, f.w_globals, f.w_locals])
- w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
- w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
- w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
-
- plain = (w_locals is f.w_locals)
- if plain:
- f.fast2locals()
- scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
- scopedcode.eval_frame(w_locals)
- #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
- if plain:
- f.locals2fast()
-
-def POP_BLOCK(f):
- block = f.blockstack.pop()
- block.cleanup(f) # the block knows how to clean up the value stack
-
-def END_FINALLY(f):
- # unlike CPython, when we reach this opcode the value stack has
- # always been set up as follows (topmost first):
- # [exception type or None]
- # [exception value or None]
- # [wrapped stack unroller ]
- f.valuestack.pop() # ignore the exception type
- f.valuestack.pop() # ignore the exception value
- unroller = f.space.unwrap(f.valuestack.pop())
- if unroller is not None:
- raise unroller # re-raise the unroller, if any
-
-def BUILD_CLASS(f):
- w_methodsdict = f.valuestack.pop()
- w_bases = f.valuestack.pop()
- w_name = f.valuestack.pop()
- # XXX it would be best to have all opcodes on a class that has a 'space' attribute
- # then the following initialization could be done at init-time.
- build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
- w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
- f.valuestack.push(w_newclass)
-
-def app_build_class(name, bases, namespace, globals):
- if '__metaclass__' in namespace:
- metaclass = namespace['__metaclass__']
- elif len(bases) > 0:
- base = bases[0]
- if hasattr(base, '__class__'):
- metaclass = base.__class__
+ def ROT_THREE(f):
+ w_1 = f.valuestack.pop()
+ w_2 = f.valuestack.pop()
+ w_3 = f.valuestack.pop()
+ f.valuestack.push(w_1)
+ f.valuestack.push(w_3)
+ f.valuestack.push(w_2)
+
+ def ROT_FOUR(f):
+ w_1 = f.valuestack.pop()
+ w_2 = f.valuestack.pop()
+ w_3 = f.valuestack.pop()
+ w_4 = f.valuestack.pop()
+ f.valuestack.push(w_1)
+ f.valuestack.push(w_4)
+ f.valuestack.push(w_3)
+ f.valuestack.push(w_2)
+
+ def DUP_TOP(f):
+ w_1 = f.valuestack.top()
+ f.valuestack.push(w_1)
+
+ def DUP_TOPX(f, itemcount):
+ assert 1 <= itemcount <= 5, "limitation of the current interpreter"
+ for i in range(itemcount):
+ w_1 = f.valuestack.top(itemcount-1)
+ f.valuestack.push(w_1)
+
+ UNARY_POSITIVE = unaryoperation("pos")
+ UNARY_NEGATIVE = unaryoperation("neg")
+ UNARY_NOT = unaryoperation("not_")
+ UNARY_CONVERT = unaryoperation("repr")
+ UNARY_INVERT = unaryoperation("invert")
+
+ def BINARY_POWER(f):
+ w_2 = f.valuestack.pop()
+ w_1 = f.valuestack.pop()
+ w_result = f.space.pow(w_1, w_2, f.space.w_None)
+ f.valuestack.push(w_result)
+
+ BINARY_MULTIPLY = binaryoperation("mul")
+ BINARY_TRUE_DIVIDE = binaryoperation("truediv")
+ BINARY_FLOOR_DIVIDE = binaryoperation("floordiv")
+ BINARY_DIVIDE = binaryoperation("div")
+ BINARY_MODULO = binaryoperation("mod")
+ BINARY_ADD = binaryoperation("add")
+ BINARY_SUBTRACT = binaryoperation("sub")
+ BINARY_SUBSCR = binaryoperation("getitem")
+ BINARY_LSHIFT = binaryoperation("lshift")
+ BINARY_RSHIFT = binaryoperation("rshift")
+ BINARY_AND = binaryoperation("and_")
+ BINARY_XOR = binaryoperation("xor")
+ BINARY_OR = binaryoperation("or_")
+
+ def INPLACE_POWER(f):
+ w_2 = f.valuestack.pop()
+ w_1 = f.valuestack.pop()
+ w_result = f.space.inplace_pow(w_1, w_2, f.space.w_None)
+ f.valuestack.push(w_result)
+
+ INPLACE_MULTIPLY = binaryoperation("inplace_mul")
+ INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv")
+ INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv")
+ INPLACE_DIVIDE = binaryoperation("inplace_div")
+ INPLACE_MODULO = binaryoperation("inplace_mod")
+ INPLACE_ADD = binaryoperation("inplace_add")
+ INPLACE_SUBTRACT = binaryoperation("inplace_sub")
+ INPLACE_LSHIFT = binaryoperation("inplace_lshift")
+ INPLACE_RSHIFT = binaryoperation("inplace_rshift")
+ INPLACE_AND = binaryoperation("inplace_and")
+ INPLACE_XOR = binaryoperation("inplace_xor")
+ INPLACE_OR = binaryoperation("inplace_or")
+
+ def slice(f, w_start, w_end):
+ w_slice = f.space.newslice(w_start, w_end, None)
+ w_obj = f.valuestack.pop()
+ w_result = f.space.getitem(w_obj, w_slice)
+ f.valuestack.push(w_result)
+
+ def SLICE_0(f):
+ slice(f, None, None)
+
+ def SLICE_1(f):
+ w_start = f.valuestack.pop()
+ slice(f, w_start, None)
+
+ def SLICE_2(f):
+ w_end = f.valuestack.pop()
+ slice(f, None, w_end)
+
+ def SLICE_3(f):
+ w_end = f.valuestack.pop()
+ w_start = f.valuestack.pop()
+ slice(f, w_start, w_end)
+
+ def storeslice(f, w_start, w_end):
+ w_slice = f.space.newslice(w_start, w_end, None)
+ w_obj = f.valuestack.pop()
+ w_newvalue = f.valuestack.pop()
+ f.space.setitem(w_obj, w_slice, w_newvalue)
+
+ def STORE_SLICE_0(f):
+ storeslice(f, None, None)
+
+ def STORE_SLICE_1(f):
+ w_start = f.valuestack.pop()
+ storeslice(f, w_start, None)
+
+ def STORE_SLICE_2(f):
+ w_end = f.valuestack.pop()
+ storeslice(f, None, w_end)
+
+ def STORE_SLICE_3(f):
+ w_end = f.valuestack.pop()
+ w_start = f.valuestack.pop()
+ storeslice(f, w_start, w_end)
+
+ def deleteslice(f, w_start, w_end):
+ w_slice = f.space.newslice(w_start, w_end, None)
+ w_obj = f.valuestack.pop()
+ f.space.delitem(w_obj, w_slice)
+
+ def DELETE_SLICE_0(f):
+ deleteslice(f, None, None)
+
+ def DELETE_SLICE_1(f):
+ w_start = f.valuestack.pop()
+ deleteslice(f, w_start, None)
+
+ def DELETE_SLICE_2(f):
+ w_end = f.valuestack.pop()
+ deleteslice(f, None, w_end)
+
+ def DELETE_SLICE_3(f):
+ w_end = f.valuestack.pop()
+ w_start = f.valuestack.pop()
+ deleteslice(f, w_start, w_end)
+
+ def STORE_SUBSCR(f):
+ "obj[subscr] = newvalue"
+ w_subscr = f.valuestack.pop()
+ w_obj = f.valuestack.pop()
+ w_newvalue = f.valuestack.pop()
+ f.space.setitem(w_obj, w_subscr, w_newvalue)
+
+ def DELETE_SUBSCR(f):
+ "del obj[subscr]"
+ w_subscr = f.valuestack.pop()
+ w_obj = f.valuestack.pop()
+ f.space.delitem(w_obj, w_subscr)
+
+ def PRINT_EXPR(f):
+ w_expr = f.valuestack.pop()
+ #print f.space.unwrap(w_expr)
+ f.space.gethelper(appfile).call("print_expr", [w_expr])
+
+ def PRINT_ITEM_TO(f):
+ w_stream = f.valuestack.pop()
+ w_item = f.valuestack.pop()
+ f.space.gethelper(appfile).call("print_item_to", [w_item, w_stream])
+
+ def PRINT_ITEM(f):
+ w_item = f.valuestack.pop()
+ f.space.gethelper(appfile).call("print_item", [w_item])
+
+ def PRINT_NEWLINE_TO(f):
+ w_stream = f.valuestack.pop()
+ f.space.gethelper(appfile).call("print_newline_to", [w_stream])
+
+ def PRINT_NEWLINE(f):
+ f.space.gethelper(appfile).call("print_newline", [])
+
+ def BREAK_LOOP(f):
+ raise pyframe.SBreakLoop
+
+ def CONTINUE_LOOP(f, startofloop):
+ raise pyframe.SContinueLoop(startofloop)
+
+ def RAISE_VARARGS(f, nbargs):
+ # we use the .app.py file to prepare the exception/value/traceback
+ # but not to actually raise it, because we cannot use the 'raise'
+ # statement to implement RAISE_VARARGS
+ if nbargs == 0:
+ w_resulttuple = f.space.gethelper(appfile).call("prepare_raise0", [])
+ elif nbargs == 1:
+ w_type = f.valuestack.pop()
+ w_resulttuple = f.space.gethelper(appfile).call(
+ "prepare_raise", [w_type, f.space.w_None, f.space.w_None])
+ elif nbargs == 2:
+ w_value = f.valuestack.pop()
+ w_type = f.valuestack.pop()
+ w_resulttuple = f.space.gethelper(appfile).call(
+ "prepare_raise", [w_type, w_value, f.space.w_None])
+ elif nbargs == 3:
+ w_traceback = f.valuestack.pop()
+ w_value = f.valuestack.pop()
+ w_type = f.valuestack.pop()
+ w_resulttuple = f.space.gethelper(appfile).call(
+ "prepare_raise", [w_type, w_value, w_traceback])
+ else:
+ raise pyframe.BytecodeCorruption, "bad RAISE_VARARGS oparg"
+ w_type, w_value, w_traceback = f.space.unpacktuple(w_resulttuple)
+ # XXX the three-arguments 'raise' is not supported yet
+ raise OperationError(w_type, w_value)
+
+ def LOAD_LOCALS(f):
+ f.valuestack.push(f.w_locals)
+
+ def RETURN_VALUE(f):
+ w_returnvalue = f.valuestack.pop()
+ raise pyframe.SReturnValue(w_returnvalue)
+
+ def YIELD_VALUE(f):
+ w_yieldedvalue = f.valuestack.pop()
+ raise pyframe.SYieldValue(w_yieldedvalue)
+ YIELD_STMT = YIELD_VALUE # misnamed in dis.opname
+
+ def EXEC_STMT(f):
+ w_locals = f.valuestack.pop()
+ w_globals = f.valuestack.pop()
+ w_prog = f.valuestack.pop()
+ w_tuple = f.space.gethelper(appfile).call("exec_statement",
+ [w_prog, w_globals, w_locals,
+ f.w_builtins, f.w_globals, f.w_locals])
+ w_prog = f.space.getitem(w_tuple,f.space.wrap(0))
+ w_globals = f.space.getitem(w_tuple,f.space.wrap(1))
+ w_locals = f.space.getitem(w_tuple,f.space.wrap(2))
+
+ #plain = ... ... w_locals = f.getlocaldict() XXX XXX
+
+ scopedcode = ScopedCode(f.space, f.space.unwrap(w_prog), w_globals)
+ scopedcode.eval_frame(w_locals)
+ #f.space.unwrap(w_prog).eval_code(f.space, w_globals, w_locals)
+ if plain:
+ f.setlocaldict(w_locals)
+
+ def POP_BLOCK(f):
+ block = f.blockstack.pop()
+ block.cleanup(f) # the block knows how to clean up the value stack
+
+ def END_FINALLY(f):
+ # unlike CPython, when we reach this opcode the value stack has
+ # always been set up as follows (topmost first):
+ # [exception type or None]
+ # [exception value or None]
+ # [wrapped stack unroller ]
+ f.valuestack.pop() # ignore the exception type
+ f.valuestack.pop() # ignore the exception value
+ unroller = f.space.unwrap(f.valuestack.pop())
+ if unroller is not None:
+ raise unroller # re-raise the unroller, if any
+
+ def BUILD_CLASS(f):
+ w_methodsdict = f.valuestack.pop()
+ w_bases = f.valuestack.pop()
+ w_name = f.valuestack.pop()
+ # XXX it would be best to have all opcodes on a class that has a 'space' attribute
+ # then the following initialization could be done at init-time.
+ build_class = InterpretedFunction(f.space.gethelperspace(), app_build_class)
+ w_newclass = build_class(w_name, w_bases, w_methodsdict, f.w_globals)
+ f.valuestack.push(w_newclass)
+
+ def app_build_class(name, bases, namespace, globals):
+ if '__metaclass__' in namespace:
+ metaclass = namespace['__metaclass__']
+ elif len(bases) > 0:
+ base = bases[0]
+ if hasattr(base, '__class__'):
+ metaclass = base.__class__
+ else:
+ metaclass = type(base)
+ elif '__metaclass__' in globals:
+ metaclass = globals['__metaclass__']
else:
- metaclass = type(base)
- elif '__metaclass__' in globals:
- metaclass = globals['__metaclass__']
- else:
- metaclass = type
- return metaclass(name, bases, namespace)
-
-def STORE_NAME(f, varindex):
- varname = f.getname(varindex)
- w_varname = f.space.wrap(varname)
- w_newvalue = f.valuestack.pop()
- f.space.setitem(f.w_locals, w_varname, w_newvalue)
-
-def DELETE_NAME(f, varindex):
- varname = f.getname(varindex)
- w_varname = f.space.wrap(varname)
- try:
- f.space.delitem(f.w_locals, w_varname)
- except OperationError, e:
- # catch KeyErrors and turn them into NameErrors
- if not e.match(f.space, f.space.w_KeyError):
- raise
- message = "name '%s' is not defined" % varname
- raise OperationError(f.space.w_NameError, f.space.wrap(message))
-
-def UNPACK_SEQUENCE(f, itemcount):
- w_iterable = f.valuestack.pop()
- try:
- items = f.space.unpackiterable(w_iterable, itemcount)
- except ValueError, e:
- raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
- items.reverse()
- for item in items:
- f.valuestack.push(item)
-
-def STORE_ATTR(f, nameindex):
- "obj.attributename = newvalue"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- w_newvalue = f.valuestack.pop()
- f.space.setattr(w_obj, w_attributename, w_newvalue)
-
-def DELETE_ATTR(f, nameindex):
- "del obj.attributename"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- f.space.delattr(w_obj, w_attributename)
-
-def STORE_GLOBAL(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- w_newvalue = f.valuestack.pop()
- f.space.setitem(f.w_globals, w_varname, w_newvalue)
-
-def DELETE_GLOBAL(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- f.space.delitem(f.w_globals, w_varname)
-
-def LOAD_NAME(f, nameindex):
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- try:
- w_value = f.space.getitem(f.w_locals, w_varname)
- except OperationError, e:
- if not e.match(f.space, f.space.w_KeyError):
- raise
+ metaclass = type
+ return metaclass(name, bases, namespace)
+
+ def STORE_NAME(f, varindex):
+ varname = f.getname(varindex)
+ w_varname = f.space.wrap(varname)
+ w_newvalue = f.valuestack.pop()
+ f.space.setitem(f.w_locals, w_varname, w_newvalue)
+
+ def DELETE_NAME(f, varindex):
+ varname = f.getname(varindex)
+ w_varname = f.space.wrap(varname)
+ try:
+ f.space.delitem(f.w_locals, w_varname)
+ except OperationError, e:
+ # catch KeyErrors and turn them into NameErrors
+ if not e.match(f.space, f.space.w_KeyError):
+ raise
+ message = "name '%s' is not defined" % varname
+ raise OperationError(f.space.w_NameError, f.space.wrap(message))
+
+ def UNPACK_SEQUENCE(f, itemcount):
+ w_iterable = f.valuestack.pop()
+ try:
+ items = f.space.unpackiterable(w_iterable, itemcount)
+ except ValueError, e:
+ raise OperationError(f.space.w_ValueError, f.space.wrap(str(e)))
+ items.reverse()
+ for item in items:
+ f.valuestack.push(item)
+
+ def STORE_ATTR(f, nameindex):
+ "obj.attributename = newvalue"
+ attributename = f.getname(nameindex)
+ w_attributename = f.space.wrap(attributename)
+ w_obj = f.valuestack.pop()
+ w_newvalue = f.valuestack.pop()
+ f.space.setattr(w_obj, w_attributename, w_newvalue)
+
+ def DELETE_ATTR(f, nameindex):
+ "del obj.attributename"
+ attributename = f.getname(nameindex)
+ w_attributename = f.space.wrap(attributename)
+ w_obj = f.valuestack.pop()
+ f.space.delattr(w_obj, w_attributename)
+
+ def STORE_GLOBAL(f, nameindex):
+ varname = f.getname(nameindex)
+ w_varname = f.space.wrap(varname)
+ w_newvalue = f.valuestack.pop()
+ f.space.setitem(f.w_globals, w_varname, w_newvalue)
+
+ def DELETE_GLOBAL(f, nameindex):
+ varname = f.getname(nameindex)
+ w_varname = f.space.wrap(varname)
+ f.space.delitem(f.w_globals, w_varname)
+
+ def LOAD_NAME(f, nameindex):
+ varname = f.getname(nameindex)
+ w_varname = f.space.wrap(varname)
+ try:
+ w_value = f.space.getitem(f.w_locals, w_varname)
+ except OperationError, e:
+ if not e.match(f.space, f.space.w_KeyError):
+ raise
+ try:
+ w_value = f.space.getitem(f.w_globals, w_varname)
+ except OperationError, e:
+ if not e.match(f.space, f.space.w_KeyError):
+ raise
+ try:
+ w_value = f.space.getitem(f.w_builtins, w_varname)
+ except OperationError, e:
+ if not e.match(f.space, f.space.w_KeyError):
+ raise
+ message = "global name '%s' is not defined" % varname
+ w_exc_type = f.space.w_NameError
+ w_exc_value = f.space.wrap(message)
+ raise OperationError(w_exc_type, w_exc_value)
+ f.valuestack.push(w_value)
+ # XXX the implementation can be pushed back into app-space as an
+ # when exception handling begins to behave itself. For now, it
+ # was getting on my nerves -- mwh
+ # w_value = f.space.gethelper(appfile).call(
+ # "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
+ # f.valuestack.push(w_value)
+
+ def LOAD_GLOBAL(f, nameindex):
+ assert f.w_globals is not None
+ varname = f.getname(nameindex)
+ w_varname = f.space.wrap(varname)
try:
w_value = f.space.getitem(f.w_globals, w_varname)
except OperationError, e:
+ # catch KeyErrors
if not e.match(f.space, f.space.w_KeyError):
raise
+ # we got a KeyError, now look in the built-ins
try:
w_value = f.space.getitem(f.w_builtins, w_varname)
except OperationError, e:
+ # catch KeyErrors again
if not e.match(f.space, f.space.w_KeyError):
raise
message = "global name '%s' is not defined" % varname
w_exc_type = f.space.w_NameError
w_exc_value = f.space.wrap(message)
raise OperationError(w_exc_type, w_exc_value)
- f.valuestack.push(w_value)
- # XXX the implementation can be pushed back into app-space as an
- # when exception handling begins to behave itself. For now, it
- # was getting on my nerves -- mwh
-# w_value = f.space.gethelper(appfile).call(
-# "load_name", [w_varname, f.w_locals, f.w_globals, f.w_builtins])
-# f.valuestack.push(w_value)
-
-def LOAD_GLOBAL(f, nameindex):
- assert f.w_globals is not None
- varname = f.getname(nameindex)
- w_varname = f.space.wrap(varname)
- try:
- w_value = f.space.getitem(f.w_globals, w_varname)
- except OperationError, e:
- # catch KeyErrors
- if not e.match(f.space, f.space.w_KeyError):
- raise
- # we got a KeyError, now look in the built-ins
+ f.valuestack.push(w_value)
+
+ def BUILD_TUPLE(f, itemcount):
+ items = [f.valuestack.pop() for i in range(itemcount)]
+ items.reverse()
+ w_tuple = f.space.newtuple(items)
+ f.valuestack.push(w_tuple)
+
+ def BUILD_LIST(f, itemcount):
+ items = [f.valuestack.pop() for i in range(itemcount)]
+ items.reverse()
+ w_list = f.space.newlist(items)
+ f.valuestack.push(w_list)
+
+ def BUILD_MAP(f, zero):
+ if zero != 0:
+ raise pyframe.BytecodeCorruption
+ w_dict = f.space.newdict([])
+ f.valuestack.push(w_dict)
+
+ def LOAD_ATTR(f, nameindex):
+ "obj.attributename"
+ attributename = f.getname(nameindex)
+ w_attributename = f.space.wrap(attributename)
+ w_obj = f.valuestack.pop()
+ w_value = f.space.getattr(w_obj, w_attributename)
+ f.valuestack.push(w_value)
+
+ def cmp_lt(f, w_1, w_2): return f.space.lt(w_1, w_2)
+ def cmp_le(f, w_1, w_2): return f.space.le(w_1, w_2)
+ def cmp_eq(f, w_1, w_2): return f.space.eq(w_1, w_2)
+ def cmp_ne(f, w_1, w_2): return f.space.ne(w_1, w_2)
+ def cmp_gt(f, w_1, w_2): return f.space.gt(w_1, w_2)
+ def cmp_ge(f, w_1, w_2): return f.space.ge(w_1, w_2)
+
+ def cmp_in(f, w_1, w_2):
+ return f.space.contains(w_2, w_1)
+ def cmp_not_in(f, w_1, w_2):
+ return f.space.not_(f.space.contains(w_2, w_1))
+ def cmp_is(f, w_1, w_2):
+ return f.space.is_(w_1, w_2)
+ def cmp_is_not(f, w_1, w_2):
+ return f.space.not_(f.space.is_(w_1, w_2))
+ def cmp_exc_match(f, w_1, w_2):
+ return f.space.newbool(f.space.exception_match(w_1, w_2))
+
+ compare_dispatch_table = {
+ 0: cmp_lt, # "<"
+ 1: cmp_le, # "<="
+ 2: cmp_eq, # "=="
+ 3: cmp_ne, # "!="
+ 4: cmp_gt, # ">"
+ 5: cmp_ge, # ">="
+ 6: cmp_in,
+ 7: cmp_not_in,
+ 8: cmp_is,
+ 9: cmp_is_not,
+ 10: cmp_exc_match,
+ }
+ def COMPARE_OP(f, testnum):
+ w_2 = f.valuestack.pop()
+ w_1 = f.valuestack.pop()
try:
- w_value = f.space.getitem(f.w_builtins, w_varname)
- except OperationError, e:
- # catch KeyErrors again
- if not e.match(f.space, f.space.w_KeyError):
- raise
- message = "global name '%s' is not defined" % varname
- w_exc_type = f.space.w_NameError
- w_exc_value = f.space.wrap(message)
- raise OperationError(w_exc_type, w_exc_value)
- f.valuestack.push(w_value)
-
-def DELETE_FAST(f, varindex):
- w_value = f.locals_w[varindex]
- if f.locals_w[varindex] is _NULL:
- varname = f.getlocalvarname(varindex)
- message = "local variable '%s' referenced before assignment" % varname
- raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message))
- f.locals_w[varindex] = _NULL
-
-def LOAD_CLOSURE(f, varindex):
- # nested scopes: access the cell object
- cell = f.closure_w[varindex]
- w_value = f.space.wrap(cell)
- f.valuestack.push(w_value)
-
-def LOAD_DEREF(f, varindex):
- # nested scopes: access a variable through its cell object
- cell = f.closure_w[varindex]
- try:
- w_value = cell.get()
- except ValueError:
- varname = f.getfreevarname(varindex)
- if f.iscellvar(varindex):
- message = "local variable '%s' referenced before assignment"
- w_exc_type = f.space.w_UnboundLocalError
- else:
- message = ("free variable '%s' referenced before assignment"
- " in enclosing scope")
- w_exc_type = f.space.w_NameError
- raise OperationError(w_exc_type, f.space.wrap(message % varname))
- f.valuestack.push(w_value)
-
-def STORE_DEREF(f, varindex):
- # nested scopes: access a variable through its cell object
- w_newvalue = f.valuestack.pop()
- try:
- cell = f.closure_w[varindex]
- except IndexError:
- #import pdb; pdb.set_trace()
- raise
- cell.set(w_newvalue)
-
-def BUILD_TUPLE(f, itemcount):
- items = [f.valuestack.pop() for i in range(itemcount)]
- items.reverse()
- w_tuple = f.space.newtuple(items)
- f.valuestack.push(w_tuple)
-
-def BUILD_LIST(f, itemcount):
- items = [f.valuestack.pop() for i in range(itemcount)]
- items.reverse()
- w_list = f.space.newlist(items)
- f.valuestack.push(w_list)
-
-def BUILD_MAP(f, zero):
- if zero != 0:
- raise pyframe.BytecodeCorruption
- w_dict = f.space.newdict([])
- f.valuestack.push(w_dict)
-
-def LOAD_ATTR(f, nameindex):
- "obj.attributename"
- attributename = f.getname(nameindex)
- w_attributename = f.space.wrap(attributename)
- w_obj = f.valuestack.pop()
- w_value = f.space.getattr(w_obj, w_attributename)
- f.valuestack.push(w_value)
-
-def cmp_lt(f, w_1, w_2): return f.space.lt(w_1, w_2)
-def cmp_le(f, w_1, w_2): return f.space.le(w_1, w_2)
-def cmp_eq(f, w_1, w_2): return f.space.eq(w_1, w_2)
-def cmp_ne(f, w_1, w_2): return f.space.ne(w_1, w_2)
-def cmp_gt(f, w_1, w_2): return f.space.gt(w_1, w_2)
-def cmp_ge(f, w_1, w_2): return f.space.ge(w_1, w_2)
-
-def cmp_in(f, w_1, w_2):
- return f.space.contains(w_2, w_1)
-def cmp_not_in(f, w_1, w_2):
- return f.space.not_(f.space.contains(w_2, w_1))
-def cmp_is(f, w_1, w_2):
- return f.space.is_(w_1, w_2)
-def cmp_is_not(f, w_1, w_2):
- return f.space.not_(f.space.is_(w_1, w_2))
-def cmp_exc_match(f, w_1, w_2):
- return f.space.exception_match(w_1, w_2)
-
-compare_dispatch_table = {
- 0: cmp_lt, # "<"
- 1: cmp_le, # "<="
- 2: cmp_eq, # "=="
- 3: cmp_ne, # "!="
- 4: cmp_gt, # ">"
- 5: cmp_ge, # ">="
- 6: cmp_in,
- 7: cmp_not_in,
- 8: cmp_is,
- 9: cmp_is_not,
- 10: cmp_exc_match,
- }
-def COMPARE_OP(f, testnum):
- w_2 = f.valuestack.pop()
- w_1 = f.valuestack.pop()
- try:
- testfn = compare_dispatch_table[testnum]
- except KeyError:
- raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
- w_result = testfn(f, w_1, w_2)
- f.valuestack.push(w_result)
-
-def IMPORT_NAME(f, nameindex):
- modulename = f.getname(nameindex)
- w_modulename = f.space.wrap(modulename)
- w_fromlist = f.valuestack.pop()
- w_obj = f.space.gethelper(appfile).call(
- "import_name", [f.w_builtins,
- w_modulename, f.w_globals, f.w_locals, w_fromlist])
- f.valuestack.push(w_obj)
-
-def IMPORT_STAR(f):
- w_module = f.valuestack.pop()
- f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
-
-def IMPORT_FROM(f, nameindex):
- name = f.getname(nameindex)
- w_name = f.space.wrap(name)
- w_module = f.valuestack.top()
- w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
- f.valuestack.push(w_obj)
-
-def JUMP_FORWARD(f, stepby):
- f.next_instr += stepby
-
-def JUMP_IF_FALSE(f, stepby):
- w_cond = f.valuestack.top()
- if not f.space.is_true(w_cond):
- f.next_instr += stepby
+ testfn = f.compare_dispatch_table[testnum]
+ except KeyError:
+ raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg"
+ w_result = testfn(f, w_1, w_2)
+ f.valuestack.push(w_result)
+
+ def IMPORT_NAME(f, nameindex):
+ modulename = f.getname(nameindex)
+ w_modulename = f.space.wrap(modulename)
+ w_fromlist = f.valuestack.pop()
+ w_obj = f.space.gethelper(appfile).call(
+ "import_name", [f.w_builtins,
+ w_modulename, f.w_globals, f.w_locals, w_fromlist])
+ f.valuestack.push(w_obj)
+
+ def IMPORT_STAR(f):
+ w_module = f.valuestack.pop()
+ f.space.gethelper(appfile).call("import_all_from", [w_module, f.w_locals])
+
+ def IMPORT_FROM(f, nameindex):
+ name = f.getname(nameindex)
+ w_name = f.space.wrap(name)
+ w_module = f.valuestack.top()
+ w_obj = f.space.gethelper(appfile).call("import_from", [w_module, w_name])
+ f.valuestack.push(w_obj)
-def JUMP_IF_TRUE(f, stepby):
- w_cond = f.valuestack.top()
- if f.space.is_true(w_cond):
+ def JUMP_FORWARD(f, stepby):
f.next_instr += stepby
-def JUMP_ABSOLUTE(f, jumpto):
- f.next_instr = jumpto
+ def JUMP_IF_FALSE(f, stepby):
+ w_cond = f.valuestack.top()
+ if not f.space.is_true(w_cond):
+ f.next_instr += stepby
+
+ def JUMP_IF_TRUE(f, stepby):
+ w_cond = f.valuestack.top()
+ if f.space.is_true(w_cond):
+ f.next_instr += stepby
+
+ def JUMP_ABSOLUTE(f, jumpto):
+ f.next_instr = jumpto
+
+ def GET_ITER(f):
+ w_iterable = f.valuestack.pop()
+ w_iterator = f.space.iter(w_iterable)
+ f.valuestack.push(w_iterator)
-def GET_ITER(f):
- w_iterable = f.valuestack.pop()
- w_iterator = f.space.iter(w_iterable)
- f.valuestack.push(w_iterator)
-
-def FOR_ITER(f, jumpby):
- w_iterator = f.valuestack.top()
- try:
- w_nextitem = f.space.next(w_iterator)
- except NoValue:
- # iterator exhausted
- f.valuestack.pop()
- f.next_instr += jumpby
- else:
- f.valuestack.push(w_nextitem)
-
-def FOR_LOOP(f, oparg):
- raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
-
-def SETUP_LOOP(f, offsettoend):
- block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def SETUP_EXCEPT(f, offsettoend):
- block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def SETUP_FINALLY(f, offsettoend):
- block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
- f.blockstack.push(block)
-
-def call_function_extra(f, oparg, with_varargs, with_varkw):
- n_arguments = oparg & 0xff
- n_keywords = (oparg>>8) & 0xff
- if with_varkw:
- w_varkw = f.valuestack.pop()
- if with_varargs:
- w_varargs = f.valuestack.pop()
- keywords = []
- for i in range(n_keywords):
- w_value = f.valuestack.pop()
- w_key = f.valuestack.pop()
- keywords.append((w_key, w_value))
- arguments = [f.valuestack.pop() for i in range(n_arguments)]
- arguments.reverse()
- w_function = f.valuestack.pop()
- w_arguments = f.space.newtuple(arguments)
- w_keywords = f.space.newdict(keywords)
- if with_varargs:
- w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
- [w_arguments, w_varargs])
- if with_varkw:
- w_keywords = f.space.gethelper(appfile).call("concatenate_keywords",
- [w_keywords, w_varkw])
- w_result = f.space.call(w_function, w_arguments, w_keywords)
- f.valuestack.push(w_result)
-
-def CALL_FUNCTION(f, oparg):
- call_function_extra(f, oparg, False, False)
-
-def CALL_FUNCTION_VAR(f, oparg):
- call_function_extra(f, oparg, True, False)
-
-def CALL_FUNCTION_KW(f, oparg):
- call_function_extra(f, oparg, False, True)
-
-def CALL_FUNCTION_VAR_KW(f, oparg):
- call_function_extra(f, oparg, True, True)
-
-def MAKE_FUNCTION(f, numdefaults):
- w_codeobj = f.valuestack.pop()
- defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
- defaultarguments.reverse()
- w_defaultarguments = f.space.newtuple(defaultarguments)
- w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
- f.w_globals, w_defaultarguments)
- f.valuestack.push(w_func)
-
-def MAKE_CLOSURE(f, numdefaults):
- w_codeobj = f.valuestack.pop()
- codeobj = f.space.unwrap(w_codeobj)
- nfreevars = len(codeobj.co_freevars)
- freevars = [f.valuestack.pop() for i in range(nfreevars)]
- freevars.reverse()
- w_freevars = f.space.newtuple(freevars)
- defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
- defaultarguments.reverse()
- w_defaultarguments = f.space.newtuple(defaultarguments)
- w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
- f.w_globals, w_defaultarguments, w_freevars)
- f.valuestack.push(w_func)
-
-def BUILD_SLICE(f, numargs):
- if numargs == 3:
- w_step = f.valuestack.pop()
- elif numargs == 2:
- w_step = None
- else:
- raise pyframe.BytecodeCorruption
- w_end = f.valuestack.pop()
- w_start = f.valuestack.pop()
- w_slice = f.space.newslice(w_start, w_end, w_step)
- f.valuestack.push(w_slice)
-
-def SET_LINENO(f, lineno):
- pass
-
-def EXTENDED_ARG(f, oparg):
- opcode = f.nextop()
- oparg = oparg<<16 | f.nextarg()
- dispatch_arg(f, oparg)
-
-def MISSING_OPCODE(f, oparg=None):
- raise pyframe.BytecodeCorruption, "unknown opcode"
-
-
-################################################################
-
-dispatch_table = []
-for i in range(256):
- opname = dis.opname[i].replace('+', '_')
- fn = MISSING_OPCODE
- if opname in globals():
- fn = globals()[opname]
- elif not opname.startswith('<') and i>0:
- #import warnings
- #warnings.warn("* Warning, missing opcode %s" % opname)
+ def FOR_ITER(f, jumpby):
+ w_iterator = f.valuestack.top()
+ try:
+ w_nextitem = f.space.next(w_iterator)
+ except NoValue:
+ # iterator exhausted
+ f.valuestack.pop()
+ f.next_instr += jumpby
+ else:
+ f.valuestack.push(w_nextitem)
+
+ def FOR_LOOP(f, oparg):
+ raise pyframe.BytecodeCorruption, "old opcode, no longer in use"
+
+ def SETUP_LOOP(f, offsettoend):
+ block = pyframe.LoopBlock(f, f.next_instr + offsettoend)
+ f.blockstack.push(block)
+
+ def SETUP_EXCEPT(f, offsettoend):
+ block = pyframe.ExceptBlock(f, f.next_instr + offsettoend)
+ f.blockstack.push(block)
+
+ def SETUP_FINALLY(f, offsettoend):
+ block = pyframe.FinallyBlock(f, f.next_instr + offsettoend)
+ f.blockstack.push(block)
+
+ def call_function_extra(f, oparg, with_varargs, with_varkw):
+ n_arguments = oparg & 0xff
+ n_keywords = (oparg>>8) & 0xff
+ if with_varkw:
+ w_varkw = f.valuestack.pop()
+ if with_varargs:
+ w_varargs = f.valuestack.pop()
+ keywords = []
+ for i in range(n_keywords):
+ w_value = f.valuestack.pop()
+ w_key = f.valuestack.pop()
+ keywords.append((w_key, w_value))
+ arguments = [f.valuestack.pop() for i in range(n_arguments)]
+ arguments.reverse()
+ w_function = f.valuestack.pop()
+ w_arguments = f.space.newtuple(arguments)
+ w_keywords = f.space.newdict(keywords)
+ if with_varargs:
+ w_arguments = f.space.gethelper(appfile).call("concatenate_arguments",
+ [w_arguments, w_varargs])
+ if with_varkw:
+ w_keywords = f.space.gethelper(appfile).call("concatenate_keywords",
+ [w_keywords, w_varkw])
+ w_result = f.space.call(w_function, w_arguments, w_keywords)
+ f.valuestack.push(w_result)
+
+ def CALL_FUNCTION(f, oparg):
+ f.call_function_extra(oparg, False, False)
+
+ def CALL_FUNCTION_VAR(f, oparg):
+ f.call_function_extra(oparg, True, False)
+
+ def CALL_FUNCTION_KW(f, oparg):
+ f.call_function_extra(oparg, False, True)
+
+ def CALL_FUNCTION_VAR_KW(f, oparg):
+ f.call_function_extra(oparg, True, True)
+
+ def MAKE_FUNCTION(f, numdefaults):
+ w_codeobj = f.valuestack.pop()
+ defaultarguments = [f.valuestack.pop() for i in range(numdefaults)]
+ defaultarguments.reverse()
+ w_defaultarguments = f.space.newtuple(defaultarguments)
+ w_func = f.space.newfunction(f.space.unwrap(w_codeobj),
+ f.w_globals, w_defaultarguments)
+ f.valuestack.push(w_func)
+
+ def BUILD_SLICE(f, numargs):
+ if numargs == 3:
+ w_step = f.valuestack.pop()
+ elif numargs == 2:
+ w_step = None
+ else:
+ raise pyframe.BytecodeCorruption
+ w_end = f.valuestack.pop()
+ w_start = f.valuestack.pop()
+ w_slice = f.space.newslice(w_start, w_end, w_step)
+ f.valuestack.push(w_slice)
+
+ def SET_LINENO(f, lineno):
pass
- dispatch_table.append(fn)
+
+ def EXTENDED_ARG(f, oparg):
+ opcode = f.nextop()
+ oparg = oparg<<16 | f.nextarg()
+ fn = self.dispatch_table[opcode]
+ if not fn.has_arg:
+ raise pyframe.BytecodeCorruption
+ fn(f, oparg)
+
+ def MISSING_OPCODE(f, oparg=None):
+ raise pyframe.BytecodeCorruption, "unknown opcode"
+
+ ################################################################
+
+ # 'dispatch_table' is a class attribute: a list of functions
+ # it is created by 'cls.setup_dispatch_table()'.
+
+ def setup_dispatch_table(cls):
+ # create the 'cls.dispatch_table' attribute
+ dispatch_table = []
+ missing_opcode = cls.MISSING_OPCODE
+ for i in range(256):
+ opname = dis.opname[i].replace('+', '_')
+ fn = getattr(cls, opname, missing_opcode)
+ #if fn is missing_opcode and not opname.startswith('<') and i>0:
+ # import warnings
+ # warnings.warn("* Warning, missing opcode %s" % opname)
+ dispatch_table.append(fn)
+ cls.dispatch_table = dispatch_table
+ setup_dispatch_table = classmethod(setup_dispatch_table)
-def name(thing):
- try:
- return thing.operationname
- except AttributeError:
- return thing.__name__
-
-def has_arg(opcode):
- return opcode >= dis.HAVE_ARGUMENT
-
-def dispatch_noarg(f, opcode):
- try:
- fn = dispatch_table[opcode]
-# print name(fn)
- except KeyError:
- raise KeyError, "missing opcode %s" % dis.opname[opcode]
- fn(f)
-
-def dispatch_arg(f, opcode, oparg):
- assert oparg >= 0
- try:
- fn = dispatch_table[opcode]
-# print name(fn)
- except KeyError:
- raise KeyError, "missing opcode %s" % dis.opname[opcode]
- fn(f, oparg)
+PyOperationalFrame.setup_dispatch_table()
More information about the Pypy-commit
mailing list