PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/interpreter/gateway.py

https://bitbucket.org/pypy/pypy/
Python | 1172 lines | 1073 code | 72 blank | 27 comment | 24 complexity | e6b61586c3ee41f98cd62999173446f1 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. Gateway between app-level and interpreter-level:
  3. * BuiltinCode (call interp-level code from app-level)
  4. * app2interp (embed an app-level function into an interp-level callable)
  5. * interp2app (publish an interp-level object to be visible from app-level)
  6. * interpindirect2app (publish an interp-level object to be visible from
  7. app-level as an indirect call to implementation)
  8. """
  9. import sys
  10. import os
  11. import types
  12. import inspect
  13. import py
  14. from pypy.interpreter.eval import Code
  15. from pypy.interpreter.argument import Arguments
  16. from pypy.interpreter.signature import Signature
  17. from pypy.interpreter.baseobjspace import (W_Root, ObjSpace, SpaceCache,
  18. DescrMismatch)
  19. from pypy.interpreter.error import OperationError, oefmt
  20. from pypy.interpreter.function import ClassMethod, FunctionWithFixedCode
  21. from rpython.rlib import rstackovf
  22. from rpython.rlib.objectmodel import we_are_translated
  23. from rpython.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
  24. from rpython.tool.sourcetools import func_with_new_name, compile2
  25. # internal non-translatable parts:
  26. class SignatureBuilder(object):
  27. "NOT_RPYTHON"
  28. def __init__(self, func=None, argnames=None, varargname=None,
  29. kwargname=None, name=None):
  30. self.func = func
  31. if func is not None:
  32. self.name = func.__name__
  33. else:
  34. self.name = name
  35. if argnames is None:
  36. argnames = []
  37. self.argnames = argnames
  38. self.varargname = varargname
  39. self.kwargname = kwargname
  40. def append(self, argname):
  41. self.argnames.append(argname)
  42. def signature(self):
  43. return Signature(self.argnames, self.varargname, self.kwargname)
  44. #________________________________________________________________
  45. class Unwrapper(object):
  46. """A base class for custom unwrap_spec items.
  47. Subclasses must override unwrap().
  48. """
  49. def _freeze_(self):
  50. return True
  51. def unwrap(self, space, w_value):
  52. """NOT_RPYTHON"""
  53. raise NotImplementedError
  54. class UnwrapSpecRecipe(object):
  55. "NOT_RPYTHON"
  56. bases_order = [W_Root, ObjSpace, Arguments, Unwrapper, object]
  57. def dispatch(self, el, *args):
  58. if isinstance(el, str):
  59. getattr(self, "visit_%s" % (el,))(el, *args)
  60. elif isinstance(el, tuple):
  61. if el[0] == 'INTERNAL:self':
  62. self.visit_self(el[1], *args)
  63. else:
  64. assert False, "not supported any more, use WrappedDefault"
  65. elif isinstance(el, WrappedDefault):
  66. self.visit__W_Root(W_Root, *args)
  67. elif isinstance(el, type):
  68. for typ in self.bases_order:
  69. if issubclass(el, typ):
  70. visit = getattr(self, "visit__%s" % (typ.__name__,))
  71. visit(el, *args)
  72. break
  73. else:
  74. raise Exception("%s: no match for unwrap_spec element %s" % (
  75. self.__class__.__name__, el))
  76. else:
  77. raise Exception("unable to dispatch, %s, perhaps your parameter should have started with w_?" % el)
  78. def apply_over(self, unwrap_spec, *extra):
  79. dispatch = self.dispatch
  80. for el in unwrap_spec:
  81. dispatch(el, *extra)
  82. class UnwrapSpecEmit(UnwrapSpecRecipe):
  83. def __init__(self):
  84. self.n = 0
  85. self.miniglobals = {}
  86. def succ(self):
  87. n = self.n
  88. self.n += 1
  89. return n
  90. def use(self, obj):
  91. name = obj.__name__
  92. self.miniglobals[name] = obj
  93. return name
  94. #________________________________________________________________
  95. class UnwrapSpec_Check(UnwrapSpecRecipe):
  96. # checks for checking interp2app func argument names wrt unwrap_spec
  97. # and synthetizing an app-level signature
  98. def __init__(self, original_sig):
  99. self.func = original_sig.func
  100. self.orig_arg = iter(original_sig.argnames).next
  101. def visit_self(self, cls, app_sig):
  102. self.visit__W_Root(cls, app_sig)
  103. def checked_space_method(self, typname, app_sig):
  104. argname = self.orig_arg()
  105. assert not argname.startswith('w_'), (
  106. "unwrapped %s argument %s of built-in function %r in %r should "
  107. "not start with 'w_'" % (typname, argname, self.func.func_name, self.func.func_globals['__name__']))
  108. app_sig.append(argname)
  109. def visit_index(self, index, app_sig):
  110. self.checked_space_method(index, app_sig)
  111. def visit_bufferstr(self, el, app_sig):
  112. self.checked_space_method(el, app_sig)
  113. def visit_str_or_None(self, el, app_sig):
  114. self.checked_space_method(el, app_sig)
  115. def visit_str0(self, el, app_sig):
  116. self.checked_space_method(el, app_sig)
  117. def visit_nonnegint(self, el, app_sig):
  118. self.checked_space_method(el, app_sig)
  119. def visit_c_int(self, el, app_sig):
  120. self.checked_space_method(el, app_sig)
  121. def visit_c_uint(self, el, app_sig):
  122. self.checked_space_method(el, app_sig)
  123. def visit_c_nonnegint(self, el, app_sig):
  124. self.checked_space_method(el, app_sig)
  125. def visit_c_short(self, el, app_sig):
  126. self.checked_space_method(el, app_sig)
  127. def visit_c_ushort(self, el, app_sig):
  128. self.checked_space_method(el, app_sig)
  129. def visit_c_uid_t(self, el, app_sig):
  130. self.checked_space_method(el, app_sig)
  131. def visit_truncatedint_w(self, el, app_sig):
  132. self.checked_space_method(el, app_sig)
  133. def visit__Unwrapper(self, el, app_sig):
  134. self.checked_space_method(el, app_sig)
  135. def visit__ObjSpace(self, el, app_sig):
  136. self.orig_arg()
  137. def visit__W_Root(self, el, app_sig):
  138. argname = self.orig_arg()
  139. if argname == 'self':
  140. assert el is not W_Root
  141. app_sig.append(argname)
  142. return
  143. assert argname.startswith('w_'), (
  144. "argument %s of built-in function %r in %r should "
  145. "start with 'w_'" % (argname, self.func.func_name, self.func.func_globals['__name__']))
  146. app_sig.append(argname[2:])
  147. def visit__Arguments(self, el, app_sig):
  148. self.orig_arg()
  149. assert app_sig.varargname is None, (
  150. "built-in function %r has conflicting rest args specs" % self.func)
  151. app_sig.varargname = 'args'
  152. app_sig.kwargname = 'keywords'
  153. def visit_args_w(self, el, app_sig):
  154. argname = self.orig_arg()
  155. assert argname.endswith('_w'), (
  156. "rest arguments arg %s of built-in function %r should end in '_w'" %
  157. (argname, self.func))
  158. assert app_sig.varargname is None, (
  159. "built-in function %r has conflicting rest args specs" % self.func)
  160. app_sig.varargname = argname[:-2]
  161. def visit_w_args(self, el, app_sig):
  162. argname = self.orig_arg()
  163. assert argname.startswith('w_'), (
  164. "rest arguments arg %s of built-in function %r should start 'w_'" %
  165. (argname, self.func))
  166. assert app_sig.varargname is None, (
  167. "built-in function %r has conflicting rest args specs" % self.func)
  168. app_sig.varargname = argname[2:]
  169. def visit__object(self, typ, app_sig):
  170. name = int_unwrapping_space_method(typ)
  171. self.checked_space_method(name, app_sig)
  172. class UnwrapSpec_EmitRun(UnwrapSpecEmit):
  173. # collect code to emit for interp2app builtin frames based on unwrap_spec
  174. def __init__(self):
  175. UnwrapSpecEmit.__init__(self)
  176. self.run_args = []
  177. def scopenext(self):
  178. return "scope_w[%d]" % self.succ()
  179. def visit_self(self, typ):
  180. self.run_args.append("space.descr_self_interp_w(%s, %s)" %
  181. (self.use(typ), self.scopenext()))
  182. def visit__Unwrapper(self, typ):
  183. self.run_args.append("%s().unwrap(space, %s)" %
  184. (self.use(typ), self.scopenext()))
  185. def visit__ObjSpace(self, el):
  186. self.run_args.append('space')
  187. def visit__W_Root(self, el):
  188. if el is not W_Root:
  189. self.run_args.append("space.interp_w(%s, %s)" % (self.use(el),
  190. self.scopenext()))
  191. else:
  192. self.run_args.append(self.scopenext())
  193. def visit__Arguments(self, el):
  194. self.miniglobals['Arguments'] = Arguments
  195. self.run_args.append("Arguments.frompacked(space, %s, %s)"
  196. % (self.scopenext(), self.scopenext()))
  197. def visit_args_w(self, el):
  198. self.run_args.append("space.fixedview(%s)" % self.scopenext())
  199. def visit_w_args(self, el):
  200. self.run_args.append(self.scopenext())
  201. def visit__object(self, typ):
  202. name = int_unwrapping_space_method(typ)
  203. self.run_args.append("space.%s(%s)" %
  204. (name, self.scopenext()))
  205. def visit_index(self, typ):
  206. self.run_args.append("space.getindex_w(%s, space.w_OverflowError)"
  207. % (self.scopenext(), ))
  208. def visit_bufferstr(self, typ):
  209. self.run_args.append("space.bufferstr_w(%s)" % (self.scopenext(),))
  210. def visit_str_or_None(self, typ):
  211. self.run_args.append("space.str_or_None_w(%s)" % (self.scopenext(),))
  212. def visit_str0(self, typ):
  213. self.run_args.append("space.str0_w(%s)" % (self.scopenext(),))
  214. def visit_nonnegint(self, typ):
  215. self.run_args.append("space.gateway_nonnegint_w(%s)" % (
  216. self.scopenext(),))
  217. def visit_c_int(self, typ):
  218. self.run_args.append("space.c_int_w(%s)" % (self.scopenext(),))
  219. def visit_c_uint(self, typ):
  220. self.run_args.append("space.c_uint_w(%s)" % (self.scopenext(),))
  221. def visit_c_nonnegint(self, typ):
  222. self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
  223. def visit_c_short(self, typ):
  224. self.run_args.append("space.c_short_w(%s)" % (self.scopenext(),))
  225. def visit_c_ushort(self, typ):
  226. self.run_args.append("space.c_ushort_w(%s)" % (self.scopenext(),))
  227. def visit_c_uid_t(self, typ):
  228. self.run_args.append("space.c_uid_t_w(%s)" % (self.scopenext(),))
  229. def visit_truncatedint_w(self, typ):
  230. self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
  231. def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
  232. try:
  233. key = tuple(unwrap_spec)
  234. activation_factory_cls, run_args = cache[key]
  235. assert run_args == self.run_args, (
  236. "unexpected: same spec, different run_args")
  237. return activation_factory_cls
  238. except KeyError:
  239. parts = []
  240. for el in unwrap_spec:
  241. if isinstance(el, tuple):
  242. parts.append(''.join([getattr(subel, '__name__', subel)
  243. for subel in el]))
  244. elif isinstance(el, WrappedDefault):
  245. parts.append('W_Root')
  246. else:
  247. parts.append(getattr(el, '__name__', el))
  248. label = '_'.join(parts)
  249. #print label
  250. d = {}
  251. source = """if 1:
  252. def _run(self, space, scope_w):
  253. return self.behavior(%s)
  254. \n""" % (', '.join(self.run_args),)
  255. exec compile2(source) in self.miniglobals, d
  256. activation_cls = type("BuiltinActivation_UwS_%s" % label,
  257. (BuiltinActivation,), d)
  258. activation_cls._immutable_ = True
  259. cache[key] = activation_cls, self.run_args
  260. return activation_cls
  261. def make_activation(unwrap_spec, func):
  262. emit = UnwrapSpec_EmitRun()
  263. emit.apply_over(unwrap_spec)
  264. activation_uw_cls = emit._make_unwrap_activation_class(unwrap_spec)
  265. return activation_uw_cls(func)
  266. make_activation = staticmethod(make_activation)
  267. class BuiltinActivation(object):
  268. _immutable_ = True
  269. def __init__(self, behavior):
  270. """NOT_RPYTHON"""
  271. self.behavior = behavior
  272. def _run(self, space, scope_w):
  273. """Subclasses with behavior specific for an unwrap spec are generated"""
  274. raise TypeError("abstract")
  275. #________________________________________________________________
  276. class FastFuncNotSupported(Exception):
  277. pass
  278. class UnwrapSpec_FastFunc_Unwrap(UnwrapSpecEmit):
  279. def __init__(self):
  280. UnwrapSpecEmit.__init__(self)
  281. self.args = []
  282. self.unwrap = []
  283. self.finger = 0
  284. def dispatch(self, el, *args):
  285. UnwrapSpecEmit.dispatch(self, el, *args)
  286. self.finger += 1
  287. if self.n > 4:
  288. raise FastFuncNotSupported
  289. def nextarg(self):
  290. arg = "w%d" % self.succ()
  291. self.args.append(arg)
  292. return arg
  293. def visit_self(self, typ):
  294. self.unwrap.append("space.descr_self_interp_w(%s, %s)" %
  295. (self.use(typ), self.nextarg()))
  296. def visit__Unwrapper(self, typ):
  297. self.unwrap.append("%s().unwrap(space, %s)" %
  298. (self.use(typ), self.nextarg()))
  299. def visit__ObjSpace(self, el):
  300. if self.finger > 1:
  301. raise FastFuncNotSupported
  302. self.unwrap.append("space")
  303. def visit__W_Root(self, el):
  304. if el is not W_Root:
  305. self.unwrap.append("space.interp_w(%s, %s)" % (self.use(el),
  306. self.nextarg()))
  307. else:
  308. self.unwrap.append(self.nextarg())
  309. def visit__Arguments(self, el):
  310. raise FastFuncNotSupported
  311. def visit_args_w(self, el):
  312. raise FastFuncNotSupported
  313. def visit_w_args(self, el):
  314. raise FastFuncNotSupported
  315. def visit__object(self, typ):
  316. name = int_unwrapping_space_method(typ)
  317. self.unwrap.append("space.%s(%s)" % (name,
  318. self.nextarg()))
  319. def visit_index(self, typ):
  320. self.unwrap.append("space.getindex_w(%s, space.w_OverflowError)"
  321. % (self.nextarg()), )
  322. def visit_bufferstr(self, typ):
  323. self.unwrap.append("space.bufferstr_w(%s)" % (self.nextarg(),))
  324. def visit_str_or_None(self, typ):
  325. self.unwrap.append("space.str_or_None_w(%s)" % (self.nextarg(),))
  326. def visit_str0(self, typ):
  327. self.unwrap.append("space.str0_w(%s)" % (self.nextarg(),))
  328. def visit_nonnegint(self, typ):
  329. self.unwrap.append("space.gateway_nonnegint_w(%s)" % (self.nextarg(),))
  330. def visit_c_int(self, typ):
  331. self.unwrap.append("space.c_int_w(%s)" % (self.nextarg(),))
  332. def visit_c_uint(self, typ):
  333. self.unwrap.append("space.c_uint_w(%s)" % (self.nextarg(),))
  334. def visit_c_nonnegint(self, typ):
  335. self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
  336. def visit_c_short(self, typ):
  337. self.unwrap.append("space.c_short_w(%s)" % (self.nextarg(),))
  338. def visit_c_ushort(self, typ):
  339. self.unwrap.append("space.c_ushort_w(%s)" % (self.nextarg(),))
  340. def visit_c_uid_t(self, typ):
  341. self.unwrap.append("space.c_uid_t_w(%s)" % (self.nextarg(),))
  342. def visit_truncatedint_w(self, typ):
  343. self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
  344. def make_fastfunc(unwrap_spec, func):
  345. unwrap_info = UnwrapSpec_FastFunc_Unwrap()
  346. unwrap_info.apply_over(unwrap_spec)
  347. narg = unwrap_info.n
  348. args = ['space'] + unwrap_info.args
  349. if args == unwrap_info.unwrap:
  350. fastfunc = func
  351. else:
  352. # try to avoid excessive bloat
  353. mod = func.__module__
  354. if mod is None:
  355. mod = ""
  356. if mod == 'pypy.interpreter.astcompiler.ast':
  357. raise FastFuncNotSupported
  358. #if (not mod.startswith('pypy.module.__builtin__') and
  359. # not mod.startswith('pypy.module.sys') and
  360. # not mod.startswith('pypy.module.math')):
  361. # if not func.__name__.startswith('descr'):
  362. # raise FastFuncNotSupported
  363. d = {}
  364. unwrap_info.miniglobals['func'] = func
  365. source = """if 1:
  366. def fastfunc_%s_%d(%s):
  367. return func(%s)
  368. \n""" % (func.__name__.replace('-', '_'), narg,
  369. ', '.join(args),
  370. ', '.join(unwrap_info.unwrap))
  371. exec compile2(source) in unwrap_info.miniglobals, d
  372. fastfunc = d['fastfunc_%s_%d' % (func.__name__.replace('-', '_'), narg)]
  373. return narg, fastfunc
  374. make_fastfunc = staticmethod(make_fastfunc)
  375. def int_unwrapping_space_method(typ):
  376. assert typ in (int, str, float, unicode, r_longlong, r_uint, r_ulonglong, bool)
  377. if typ is r_int is r_longlong:
  378. return 'gateway_r_longlong_w'
  379. elif typ in (str, unicode, bool):
  380. return typ.__name__ + '_w'
  381. else:
  382. return 'gateway_' + typ.__name__ + '_w'
  383. def unwrap_spec(*spec, **kwargs):
  384. """A decorator which attaches the unwrap_spec attribute.
  385. Use either positional or keyword arguments.
  386. - positional arguments must be as many as the function parameters
  387. - keywords arguments allow to change only some parameter specs
  388. """
  389. assert spec or kwargs
  390. def decorator(func):
  391. if kwargs:
  392. if spec:
  393. raise ValueError("Please specify either positional or "
  394. "keywords arguments")
  395. func.unwrap_spec = kwargs
  396. else:
  397. func.unwrap_spec = spec
  398. return func
  399. return decorator
  400. class WrappedDefault(object):
  401. """ Can be used inside unwrap_spec as WrappedDefault(3) which means
  402. it'll be treated as W_Root, but fed with default which will be a wrapped
  403. argument to constructor.
  404. """
  405. def __init__(self, default_value):
  406. self.default_value = default_value
  407. def build_unwrap_spec(func, argnames, self_type=None):
  408. """build the list of parameter unwrap spec for the function.
  409. """
  410. unwrap_spec = getattr(func, 'unwrap_spec', None)
  411. if isinstance(unwrap_spec, dict):
  412. kw_spec = unwrap_spec
  413. unwrap_spec = None
  414. else:
  415. kw_spec = {}
  416. if unwrap_spec is None:
  417. # build unwrap_spec after the name of arguments
  418. unwrap_spec = []
  419. for argname in argnames:
  420. if argname == 'self':
  421. unwrap_spec.append('self')
  422. elif argname == 'space':
  423. unwrap_spec.append(ObjSpace)
  424. elif argname == '__args__':
  425. unwrap_spec.append(Arguments)
  426. elif argname == 'args_w':
  427. unwrap_spec.append('args_w')
  428. elif argname.startswith('w_'):
  429. unwrap_spec.append(W_Root)
  430. else:
  431. unwrap_spec.append(None)
  432. # apply kw_spec
  433. for name, spec in kw_spec.items():
  434. try:
  435. unwrap_spec[argnames.index(name)] = spec
  436. except ValueError:
  437. raise ValueError("unwrap_spec() got a keyword %r but it is not "
  438. "the name of an argument of the following "
  439. "function" % (name,))
  440. return unwrap_spec
  441. class BuiltinCode(Code):
  442. "The code object implementing a built-in (interpreter-level) hook."
  443. _immutable_ = True
  444. hidden_applevel = True
  445. descrmismatch_op = None
  446. descr_reqcls = None
  447. # When a BuiltinCode is stored in a Function object,
  448. # you get the functionality of CPython's built-in function type.
  449. def __init__(self, func, unwrap_spec=None, self_type=None,
  450. descrmismatch=None, doc=None):
  451. "NOT_RPYTHON"
  452. # 'implfunc' is the interpreter-level function.
  453. # Note that this uses a lot of (construction-time) introspection.
  454. Code.__init__(self, func.__name__)
  455. self.docstring = doc or func.__doc__
  456. self.identifier = "%s-%s-%s" % (func.__module__, func.__name__,
  457. getattr(self_type, '__name__', '*'))
  458. # unwrap_spec can be passed to interp2app or
  459. # attached as an attribute to the function.
  460. # It is a list of types or singleton objects:
  461. # baseobjspace.ObjSpace is used to specify the space argument
  462. # baseobjspace.W_Root is for wrapped arguments to keep wrapped
  463. # argument.Arguments is for a final rest arguments Arguments object
  464. # 'args_w' for fixedview applied to rest arguments
  465. # 'w_args' for rest arguments passed as wrapped tuple
  466. # str,int,float: unwrap argument as such type
  467. # (function, cls) use function to check/unwrap argument of type cls
  468. # First extract the signature from the (CPython-level) code object
  469. from pypy.interpreter import pycode
  470. argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
  471. self._argnames = argnames
  472. if unwrap_spec is None:
  473. unwrap_spec = build_unwrap_spec(func, argnames, self_type)
  474. if self_type:
  475. assert unwrap_spec[0] == 'self', "self_type without 'self' spec element"
  476. unwrap_spec = list(unwrap_spec)
  477. if descrmismatch is not None:
  478. assert issubclass(self_type, W_Root)
  479. unwrap_spec[0] = ('INTERNAL:self', self_type)
  480. self.descrmismatch_op = descrmismatch
  481. self.descr_reqcls = self_type
  482. else:
  483. unwrap_spec[0] = self_type
  484. else:
  485. assert descrmismatch is None, (
  486. "descrmismatch without a self-type specified")
  487. orig_sig = SignatureBuilder(func, argnames, varargname, kwargname)
  488. app_sig = SignatureBuilder(func)
  489. UnwrapSpec_Check(orig_sig).apply_over(unwrap_spec, app_sig)
  490. self.sig = argnames, varargname, kwargname = app_sig.signature()
  491. self.minargs = len(argnames)
  492. if varargname:
  493. self.maxargs = sys.maxint
  494. else:
  495. self.maxargs = self.minargs
  496. self.activation = UnwrapSpec_EmitRun.make_activation(unwrap_spec, func)
  497. self._bltin = func
  498. self._unwrap_spec = unwrap_spec
  499. # speed hack
  500. if 0 <= len(unwrap_spec) <= 5:
  501. try:
  502. arity, fastfunc = UnwrapSpec_FastFunc_Unwrap.make_fastfunc(
  503. unwrap_spec, func)
  504. except FastFuncNotSupported:
  505. if unwrap_spec == [ObjSpace, Arguments]:
  506. self.__class__ = BuiltinCodePassThroughArguments0
  507. self.func__args__ = func
  508. elif unwrap_spec == [ObjSpace, W_Root, Arguments]:
  509. self.__class__ = BuiltinCodePassThroughArguments1
  510. self.func__args__ = func
  511. elif unwrap_spec == [self_type, ObjSpace, Arguments]:
  512. self.__class__ = BuiltinCodePassThroughArguments1
  513. miniglobals = {'func': func, 'self_type': self_type}
  514. d = {}
  515. source = """if 1:
  516. def _call(space, w_obj, args):
  517. self = space.descr_self_interp_w(self_type, w_obj)
  518. return func(self, space, args)
  519. \n"""
  520. exec compile2(source) in miniglobals, d
  521. self.func__args__ = d['_call']
  522. else:
  523. self.__class__ = globals()['BuiltinCode%d' % arity]
  524. setattr(self, 'fastfunc_%d' % arity, fastfunc)
  525. def descr__reduce__(self, space):
  526. from pypy.interpreter.mixedmodule import MixedModule
  527. w_mod = space.getbuiltinmodule('_pickle_support')
  528. mod = space.interp_w(MixedModule, w_mod)
  529. builtin_code = mod.get('builtin_code')
  530. return space.newtuple([builtin_code,
  531. space.newtuple([space.wrap(self.identifier)])])
  532. def find(indentifier):
  533. from pypy.interpreter.function import Function
  534. return Function._all[indentifier].code
  535. find = staticmethod(find)
  536. def signature(self):
  537. return self.sig
  538. def getdocstring(self, space):
  539. return space.wrap(self.docstring)
  540. def funcrun(self, func, args):
  541. return BuiltinCode.funcrun_obj(self, func, None, args)
  542. def funcrun_obj(self, func, w_obj, args):
  543. space = func.space
  544. activation = self.activation
  545. scope_w = args.parse_obj(w_obj, func.name, self.sig,
  546. func.defs_w, self.minargs)
  547. try:
  548. w_result = activation._run(space, scope_w)
  549. except DescrMismatch:
  550. if w_obj is not None:
  551. args = args.prepend(w_obj)
  552. return scope_w[0].descr_call_mismatch(space,
  553. self.descrmismatch_op,
  554. self.descr_reqcls,
  555. args)
  556. except Exception as e:
  557. self.handle_exception(space, e)
  558. w_result = None
  559. if w_result is None:
  560. w_result = space.w_None
  561. return w_result
  562. def handle_exception(self, space, e):
  563. try:
  564. if not we_are_translated():
  565. raise
  566. raise e
  567. except KeyboardInterrupt:
  568. raise OperationError(space.w_KeyboardInterrupt, space.w_None)
  569. except MemoryError:
  570. raise OperationError(space.w_MemoryError, space.w_None)
  571. except rstackovf.StackOverflow as e:
  572. rstackovf.check_stack_overflow()
  573. raise oefmt(space.w_RuntimeError,
  574. "maximum recursion depth exceeded")
  575. except RuntimeError: # not on top of py.py
  576. raise OperationError(space.w_RuntimeError, space.w_None)
  577. # (verbose) performance hack below
  578. class BuiltinCodePassThroughArguments0(BuiltinCode):
  579. _immutable_ = True
  580. def funcrun(self, func, args):
  581. space = func.space
  582. try:
  583. w_result = self.func__args__(space, args)
  584. except DescrMismatch:
  585. return args.firstarg().descr_call_mismatch(space,
  586. self.descrmismatch_op,
  587. self.descr_reqcls,
  588. args)
  589. except Exception as e:
  590. self.handle_exception(space, e)
  591. w_result = None
  592. if w_result is None:
  593. w_result = space.w_None
  594. return w_result
  595. class BuiltinCodePassThroughArguments1(BuiltinCode):
  596. _immutable_ = True
  597. fast_natural_arity = Code.PASSTHROUGHARGS1
  598. def funcrun_obj(self, func, w_obj, args):
  599. space = func.space
  600. try:
  601. w_result = self.func__args__(space, w_obj, args)
  602. except DescrMismatch:
  603. return args.firstarg().descr_call_mismatch(space,
  604. self.descrmismatch_op,
  605. self.descr_reqcls,
  606. args.prepend(w_obj))
  607. except Exception as e:
  608. self.handle_exception(space, e)
  609. w_result = None
  610. if w_result is None:
  611. w_result = space.w_None
  612. return w_result
  613. class BuiltinCode0(BuiltinCode):
  614. _immutable_ = True
  615. fast_natural_arity = 0
  616. def fastcall_0(self, space, w_func):
  617. try:
  618. w_result = self.fastfunc_0(space)
  619. except DescrMismatch:
  620. raise oefmt(space.w_SystemError, "unexpected DescrMismatch error")
  621. except Exception as e:
  622. self.handle_exception(space, e)
  623. w_result = None
  624. if w_result is None:
  625. w_result = space.w_None
  626. return w_result
  627. class BuiltinCode1(BuiltinCode):
  628. _immutable_ = True
  629. fast_natural_arity = 1
  630. def fastcall_1(self, space, w_func, w1):
  631. try:
  632. w_result = self.fastfunc_1(space, w1)
  633. except DescrMismatch:
  634. return w1.descr_call_mismatch(space,
  635. self.descrmismatch_op,
  636. self.descr_reqcls,
  637. Arguments(space, [w1]))
  638. except Exception as e:
  639. self.handle_exception(space, e)
  640. w_result = None
  641. if w_result is None:
  642. w_result = space.w_None
  643. return w_result
  644. class BuiltinCode2(BuiltinCode):
  645. _immutable_ = True
  646. fast_natural_arity = 2
  647. def fastcall_2(self, space, w_func, w1, w2):
  648. try:
  649. w_result = self.fastfunc_2(space, w1, w2)
  650. except DescrMismatch:
  651. return w1.descr_call_mismatch(space,
  652. self.descrmismatch_op,
  653. self.descr_reqcls,
  654. Arguments(space, [w1, w2]))
  655. except Exception as e:
  656. self.handle_exception(space, e)
  657. w_result = None
  658. if w_result is None:
  659. w_result = space.w_None
  660. return w_result
  661. class BuiltinCode3(BuiltinCode):
  662. _immutable_ = True
  663. fast_natural_arity = 3
  664. def fastcall_3(self, space, func, w1, w2, w3):
  665. try:
  666. w_result = self.fastfunc_3(space, w1, w2, w3)
  667. except DescrMismatch:
  668. return w1.descr_call_mismatch(space,
  669. self.descrmismatch_op,
  670. self.descr_reqcls,
  671. Arguments(space, [w1, w2, w3]))
  672. except Exception as e:
  673. self.handle_exception(space, e)
  674. w_result = None
  675. if w_result is None:
  676. w_result = space.w_None
  677. return w_result
  678. class BuiltinCode4(BuiltinCode):
  679. _immutable_ = True
  680. fast_natural_arity = 4
  681. def fastcall_4(self, space, func, w1, w2, w3, w4):
  682. try:
  683. w_result = self.fastfunc_4(space, w1, w2, w3, w4)
  684. except DescrMismatch:
  685. return w1.descr_call_mismatch(space,
  686. self.descrmismatch_op,
  687. self.descr_reqcls,
  688. Arguments(space,
  689. [w1, w2, w3, w4]))
  690. except Exception as e:
  691. self.handle_exception(space, e)
  692. w_result = None
  693. if w_result is None:
  694. w_result = space.w_None
  695. return w_result
  696. def interpindirect2app(unbound_meth, unwrap_spec=None):
  697. base_cls = unbound_meth.im_class
  698. func = unbound_meth.im_func
  699. args = inspect.getargs(func.func_code)
  700. if args.varargs or args.keywords:
  701. raise TypeError("Varargs and keywords not supported in unwrap_spec")
  702. argspec = ', '.join([arg for arg in args.args[1:]])
  703. func_code = py.code.Source("""
  704. def f(self, %(args)s):
  705. return self.%(func_name)s(%(args)s)
  706. """ % {'args': argspec, 'func_name': func.func_name})
  707. d = {}
  708. exec func_code.compile() in d
  709. f = d['f']
  710. f.func_defaults = unbound_meth.func_defaults
  711. f.func_doc = unbound_meth.func_doc
  712. f.__module__ = func.__module__
  713. # necessary for unique identifiers for pickling
  714. f.func_name = func.func_name
  715. if unwrap_spec is None:
  716. unwrap_spec = getattr(unbound_meth, 'unwrap_spec', {})
  717. else:
  718. assert isinstance(unwrap_spec, dict)
  719. unwrap_spec = unwrap_spec.copy()
  720. unwrap_spec['self'] = base_cls
  721. return interp2app(globals()['unwrap_spec'](**unwrap_spec)(f))
  722. class interp2app(W_Root):
  723. """Build a gateway that calls 'f' at interp-level."""
  724. # Takes optionally an unwrap_spec, see BuiltinCode
  725. instancecache = {}
  726. def __new__(cls, f, app_name=None, unwrap_spec=None, descrmismatch=None,
  727. as_classmethod=False, doc=None):
  728. "NOT_RPYTHON"
  729. # f must be a function whose name does NOT start with 'app_'
  730. self_type = None
  731. if hasattr(f, 'im_func'):
  732. self_type = f.im_class
  733. f = f.im_func
  734. if not isinstance(f, types.FunctionType):
  735. raise TypeError("function expected, got %r instead" % f)
  736. if app_name is None:
  737. if f.func_name.startswith('app_'):
  738. raise ValueError("function name %r suspiciously starts "
  739. "with 'app_'" % f.func_name)
  740. app_name = f.func_name
  741. if unwrap_spec is not None:
  742. unwrap_spec_key = tuple(unwrap_spec)
  743. else:
  744. unwrap_spec_key = None
  745. key = (f, self_type, unwrap_spec_key, descrmismatch, as_classmethod)
  746. if key in cls.instancecache:
  747. result = cls.instancecache[key]
  748. assert result.__class__ is cls
  749. return result
  750. self = W_Root.__new__(cls)
  751. cls.instancecache[key] = self
  752. self._code = BuiltinCode(f, unwrap_spec=unwrap_spec,
  753. self_type=self_type,
  754. descrmismatch=descrmismatch,
  755. doc=doc)
  756. self.__name__ = f.func_name
  757. self.name = app_name
  758. self.as_classmethod = as_classmethod
  759. if not f.func_defaults:
  760. self._staticdefs = []
  761. else:
  762. argnames = self._code._argnames
  763. defaults = f.func_defaults
  764. self._staticdefs = zip(argnames[-len(defaults):], defaults)
  765. return self
  766. def _getdefaults(self, space):
  767. "NOT_RPYTHON"
  768. defs_w = []
  769. for name, defaultval in self._staticdefs:
  770. if name.startswith('w_'):
  771. assert defaultval is None, (
  772. "%s: default value for '%s' can only be None, got %r; "
  773. "use unwrap_spec(...=WrappedDefault(default))" % (
  774. self._code.identifier, name, defaultval))
  775. defs_w.append(None)
  776. elif name != '__args__' and name != 'args_w':
  777. defs_w.append(space.wrap(defaultval))
  778. if self._code._unwrap_spec:
  779. UNDEFINED = object()
  780. alldefs_w = [UNDEFINED] * len(self._code.sig[0])
  781. if defs_w:
  782. alldefs_w[-len(defs_w):] = defs_w
  783. code = self._code
  784. assert isinstance(code._unwrap_spec, (list, tuple))
  785. assert isinstance(code._argnames, list)
  786. assert len(code._unwrap_spec) == len(code._argnames)
  787. for i in range(len(code._unwrap_spec)-1, -1, -1):
  788. spec = code._unwrap_spec[i]
  789. argname = code._argnames[i]
  790. if isinstance(spec, tuple) and spec[0] is W_Root:
  791. assert False, "use WrappedDefault"
  792. if isinstance(spec, WrappedDefault):
  793. w_default = space.wrap(spec.default_value)
  794. assert isinstance(w_default, W_Root)
  795. assert argname.startswith('w_')
  796. argname = argname[2:]
  797. j = self._code.sig[0].index(argname)
  798. assert alldefs_w[j] in (UNDEFINED, None)
  799. alldefs_w[j] = w_default
  800. first_defined = 0
  801. while (first_defined < len(alldefs_w) and
  802. alldefs_w[first_defined] is UNDEFINED):
  803. first_defined += 1
  804. defs_w = alldefs_w[first_defined:]
  805. assert UNDEFINED not in defs_w
  806. return defs_w
  807. # lazy binding to space
  808. def __spacebind__(self, space):
  809. # we first make a real Function object out of it
  810. # and the result is a wrapped version of this Function.
  811. return self.get_function(space)
  812. def get_function(self, space):
  813. return self.getcache(space).getorbuild(self)
  814. def getcache(self, space):
  815. return space.fromcache(GatewayCache)
  816. class GatewayCache(SpaceCache):
  817. def build(cache, gateway):
  818. "NOT_RPYTHON"
  819. space = cache.space
  820. defs = gateway._getdefaults(space) # needs to be implemented by subclass
  821. code = gateway._code
  822. fn = FunctionWithFixedCode(space, code, None, defs, forcename=gateway.name)
  823. if not space.config.translating:
  824. fn.add_to_table()
  825. if gateway.as_classmethod:
  826. fn = ClassMethod(space.wrap(fn))
  827. #
  828. from pypy.module.sys.vm import exc_info
  829. if code._bltin is exc_info:
  830. assert space._code_of_sys_exc_info is None
  831. space._code_of_sys_exc_info = code
  832. #
  833. return fn
  834. #
  835. # the next gateways are to be used only for
  836. # temporary/initialization purposes
  837. class interp2app_temp(interp2app):
  838. "NOT_RPYTHON"
  839. def getcache(self, space):
  840. return self.__dict__.setdefault(space, GatewayCache(space))
  841. # and now for something completely different ...
  842. #
  843. class ApplevelClass:
  844. """NOT_RPYTHON
  845. A container for app-level source code that should be executed
  846. as a module in the object space; interphook() builds a static
  847. interp-level function that invokes the callable with the given
  848. name at app-level."""
  849. hidden_applevel = True
  850. def __init__(self, source, filename=None, modname='__builtin__'):
  851. # HAAACK (but a good one)
  852. self.filename = filename
  853. self.source = str(py.code.Source(source).deindent())
  854. self.modname = modname
  855. if filename is None:
  856. f = sys._getframe(1)
  857. filename = '<%s:%d>' % (f.f_code.co_filename, f.f_lineno)
  858. if not os.path.exists(filename):
  859. # make source code available for tracebacks
  860. lines = [x + "\n" for x in source.split("\n")]
  861. py.std.linecache.cache[filename] = (1, None, lines, filename)
  862. self.filename = filename
  863. def __repr__(self):
  864. return "<ApplevelClass filename=%r>" % (self.filename,)
  865. def getwdict(self, space):
  866. return space.fromcache(ApplevelCache).getorbuild(self)
  867. def buildmodule(self, space, name='applevel'):
  868. from pypy.interpreter.module import Module
  869. return Module(space, space.wrap(name), self.getwdict(space))
  870. def wget(self, space, name):
  871. w_globals = self.getwdict(space)
  872. return space.getitem(w_globals, space.wrap(name))
  873. def interphook(self, name):
  874. "NOT_RPYTHON"
  875. def appcaller(space, *args_w):
  876. if not isinstance(space, ObjSpace):
  877. raise TypeError("first argument must be a space instance.")
  878. # the last argument can be an Arguments
  879. w_func = self.wget(space, name)
  880. if not args_w:
  881. return space.call_function(w_func)
  882. else:
  883. args = args_w[-1]
  884. assert args is not None
  885. if not isinstance(args, Arguments):
  886. return space.call_function(w_func, *args_w)
  887. else:
  888. if len(args_w) == 2:
  889. return space.call_obj_args(w_func, args_w[0], args)
  890. elif len(args_w) > 2:
  891. # xxx is this used at all?
  892. # ...which is merged with the previous arguments, if any
  893. args = args.replace_arguments(list(args_w[:-1]) +
  894. args.arguments_w)
  895. return space.call_args(w_func, args)
  896. def get_function(space):
  897. w_func = self.wget(space, name)
  898. return space.unwrap(w_func)
  899. appcaller = func_with_new_name(appcaller, name)
  900. appcaller.get_function = get_function
  901. return appcaller
  902. def _freeze_(self):
  903. return True # hint for the annotator: applevel instances are constants
  904. class ApplevelCache(SpaceCache):
  905. """NOT_RPYTHON
  906. The cache mapping each applevel instance to its lazily built w_dict"""
  907. def build(self, app):
  908. "NOT_RPYTHON. Called indirectly by Applevel.getwdict()."
  909. return build_applevel_dict(app, self.space)
  910. # __________ pure applevel version __________
  911. def build_applevel_dict(self, space):
  912. "NOT_RPYTHON"
  913. w_glob = space.newdict(module=True)
  914. space.setitem(w_glob, space.wrap('__name__'), space.wrap(self.modname))
  915. space.exec_(self.source, w_glob, w_glob,
  916. hidden_applevel=self.hidden_applevel,
  917. filename=self.filename)
  918. return w_glob
  919. # ____________________________________________________________
  920. def appdef(source, applevel=ApplevelClass, filename=None):
  921. """ NOT_RPYTHON: build an app-level helper function, like for example:
  922. myfunc = appdef('''myfunc(x, y):
  923. return x+y
  924. ''')
  925. """
  926. prefix = ""
  927. if not isinstance(source, str):
  928. flags = source.__code__.co_flags
  929. source = py.std.inspect.getsource(source).lstrip()
  930. while source.startswith(('@py.test.mark.', '@pytest.mark.')):
  931. # these decorators are known to return the same function
  932. # object, we may ignore them
  933. assert '\n' in source
  934. source = source[source.find('\n') + 1:].lstrip()
  935. assert source.startswith("def "), "can only transform functions"
  936. source = source[4:]
  937. import __future__
  938. if flags & __future__.CO_FUTURE_DIVISION:
  939. prefix += "from __future__ import division\n"
  940. if flags & __future__.CO_FUTURE_ABSOLUTE_IMPORT:
  941. prefix += "from __future__ import absolute_import\n"
  942. if flags & __future__.CO_FUTURE_PRINT_FUNCTION:
  943. prefix += "from __future__ import print_function\n"
  944. if flags & __future__.CO_FUTURE_UNICODE_LITERALS:
  945. prefix += "from __future__ import unicode_literals\n"
  946. p = source.find('(')
  947. assert p >= 0
  948. funcname = source[:p].strip()
  949. source = source[p:]
  950. assert source.strip()
  951. funcsource = prefix + "def %s%s\n" % (funcname, source)
  952. #for debugging of wrong source code: py.std.parser.suite(funcsource)
  953. a = applevel(funcsource, filename=filename)
  954. return a.interphook(funcname)
  955. applevel = ApplevelClass # backward compatibility
  956. app2interp = appdef # backward compatibility
  957. class applevel_temp(ApplevelClass):
  958. hidden_applevel = False
  959. def getwdict(self, space): # no cache
  960. return build_applevel_dict(self, space)
  961. # app2interp_temp is used for testing mainly
  962. def app2interp_temp(func, applevel_temp=applevel_temp, filename=None):
  963. """ NOT_RPYTHON """
  964. return appdef(func, applevel_temp, filename=filename)