PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/annotator/signature.py

https://bitbucket.org/pypy/pypy/
Python | 173 lines | 153 code | 15 blank | 5 comment | 50 complexity | 5ee92b8abb6282f0f44548ae4b2f34a1 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from __future__ import absolute_import
  2. import types
  3. from rpython.annotator.model import (
  4. SomeBool, SomeInteger, SomeString, SomeFloat, SomeList, SomeDict, s_None,
  5. SomeObject, SomeInstance, SomeTuple, unionof, SomeUnicodeString, SomeType,
  6. AnnotatorError)
  7. from rpython.annotator.listdef import ListDef
  8. from rpython.annotator.dictdef import DictDef
  9. from rpython.rtyper import extregistry
  10. _annotation_cache = {}
  11. def _annotation_key(t):
  12. from rpython.rtyper import extregistry
  13. if type(t) is list:
  14. assert len(t) == 1
  15. return ('list', _annotation_key(t[0]))
  16. elif type(t) is dict:
  17. assert len(t.keys()) == 1
  18. return ('dict', _annotation_key(t.items()[0]))
  19. elif isinstance(t, tuple):
  20. return tuple([_annotation_key(i) for i in t])
  21. elif extregistry.is_registered(t):
  22. # XXX should it really be always different?
  23. return t
  24. return t
  25. def annotation(t, bookkeeper=None):
  26. if bookkeeper is None:
  27. key = _annotation_key(t)
  28. try:
  29. return _annotation_cache[key]
  30. except KeyError:
  31. t = _compute_annotation(t, bookkeeper)
  32. _annotation_cache[key] = t
  33. return t
  34. return _compute_annotation(t, bookkeeper)
  35. def _compute_annotation(t, bookkeeper=None):
  36. from rpython.rtyper.lltypesystem import lltype
  37. from rpython.rtyper.llannotation import lltype_to_annotation
  38. if isinstance(t, SomeObject):
  39. return t
  40. elif isinstance(t, lltype.LowLevelType):
  41. return lltype_to_annotation(t)
  42. elif isinstance(t, list):
  43. assert len(t) == 1, "We do not support type joining in list"
  44. listdef = ListDef(bookkeeper, annotation(t[0]), mutated=True, resized=True)
  45. return SomeList(listdef)
  46. elif isinstance(t, tuple):
  47. return SomeTuple(tuple([annotation(i) for i in t]))
  48. elif isinstance(t, dict):
  49. assert len(t) == 1, "We do not support type joining in dict"
  50. result = SomeDict(DictDef(bookkeeper, annotation(t.keys()[0]),
  51. annotation(t.values()[0])))
  52. return result
  53. elif type(t) is types.NoneType:
  54. return s_None
  55. elif extregistry.is_registered(t):
  56. entry = extregistry.lookup(t)
  57. entry.bookkeeper = bookkeeper
  58. return entry.compute_result_annotation()
  59. else:
  60. return annotationoftype(t, bookkeeper)
  61. def annotationoftype(t, bookkeeper=False):
  62. from rpython.rtyper import extregistry
  63. """The most precise SomeValue instance that contains all
  64. objects of type t."""
  65. assert isinstance(t, (type, types.ClassType))
  66. if t is bool:
  67. return SomeBool()
  68. elif t is int:
  69. return SomeInteger()
  70. elif t is float:
  71. return SomeFloat()
  72. elif issubclass(t, str): # py.lib uses annotated str subclasses
  73. return SomeString()
  74. elif t is unicode:
  75. return SomeUnicodeString()
  76. elif t is types.NoneType:
  77. return s_None
  78. elif bookkeeper and extregistry.is_registered_type(t):
  79. entry = extregistry.lookup_type(t)
  80. return entry.compute_annotation_bk(bookkeeper)
  81. elif t is type:
  82. return SomeType()
  83. elif bookkeeper and not hasattr(t, '_freeze_'):
  84. classdef = bookkeeper.getuniqueclassdef(t)
  85. return SomeInstance(classdef)
  86. else:
  87. raise AssertionError("annotationoftype(%r)" % (t,))
  88. class Sig(object):
  89. def __init__(self, *argtypes):
  90. self.argtypes = argtypes
  91. def __call__(self, funcdesc, inputcells):
  92. from rpython.rlib.objectmodel import NOT_CONSTANT
  93. from rpython.rtyper.lltypesystem import lltype
  94. args_s = []
  95. from rpython.annotator import model as annmodel
  96. for i, argtype in enumerate(self.argtypes):
  97. if isinstance(argtype, (types.FunctionType, types.MethodType)):
  98. argtype = argtype(*inputcells)
  99. if argtype is lltype.Void:
  100. # XXX the mapping between Void and annotation
  101. # is not quite well defined
  102. s_input = inputcells[i]
  103. assert isinstance(s_input, (annmodel.SomePBC, annmodel.SomeNone))
  104. assert s_input.is_constant()
  105. args_s.append(s_input)
  106. elif argtype is None:
  107. args_s.append(inputcells[i]) # no change
  108. elif argtype is NOT_CONSTANT:
  109. from rpython.annotator.model import not_const
  110. args_s.append(not_const(inputcells[i]))
  111. else:
  112. args_s.append(annotation(argtype, bookkeeper=funcdesc.bookkeeper))
  113. if len(inputcells) != len(args_s):
  114. raise SignatureError("%r: expected %d args, got %d" % (funcdesc,
  115. len(args_s),
  116. len(inputcells)))
  117. for i, (s_arg, s_input) in enumerate(zip(args_s, inputcells)):
  118. s_input = unionof(s_input, s_arg)
  119. if not s_arg.contains(s_input):
  120. raise SignatureError("%r argument %d:\n"
  121. "expected %s,\n"
  122. " got %s" % (funcdesc, i+1,
  123. s_arg,
  124. s_input))
  125. inputcells[:] = args_s
  126. class SignatureError(AnnotatorError):
  127. pass
  128. def finish_type(paramtype, bookkeeper, func):
  129. from rpython.rlib.types import SelfTypeMarker, AnyTypeMarker
  130. if isinstance(paramtype, SomeObject):
  131. return paramtype
  132. elif isinstance(paramtype, SelfTypeMarker):
  133. raise SignatureError("%r argument declared as annotation.types.self(); class needs decorator rlib.signature.finishsigs()" % (func,))
  134. elif isinstance(paramtype, AnyTypeMarker):
  135. return None
  136. else:
  137. return paramtype(bookkeeper)
  138. def enforce_signature_args(funcdesc, paramtypes, actualtypes):
  139. assert len(paramtypes) == len(actualtypes)
  140. params_s = [finish_type(paramtype, funcdesc.bookkeeper, funcdesc.pyobj) for paramtype in paramtypes]
  141. for i, (s_param, s_actual) in enumerate(zip(params_s, actualtypes)):
  142. if s_param is None: # can be anything
  143. continue
  144. if not s_param.contains(s_actual):
  145. raise SignatureError("%r argument %d:\n"
  146. "expected %s,\n"
  147. " got %s" % (funcdesc, i+1, s_param, s_actual))
  148. for i, s_param in enumerate(params_s):
  149. if s_param is None:
  150. continue
  151. actualtypes[i] = s_param
  152. def enforce_signature_return(funcdesc, sigtype, inferredtype):
  153. s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
  154. if s_sigret is not None and not s_sigret.contains(inferredtype):
  155. raise SignatureError("%r return value:\n"
  156. "expected %s,\n"
  157. " got %s" % (funcdesc, s_sigret, inferredtype))
  158. return s_sigret