/examples/ompc_mfunction_poormans.py

https://bitbucket.org/juricap/ompc/ · Python · 146 lines · 116 code · 12 blank · 18 comment · 15 complexity · 4eb589eb4222d3f137b63136381eb931 MD5 · raw file

  1. def _get_narginout():
  2. """Return how many values the caller is expecting.
  3. """
  4. import inspect, dis
  5. f = inspect.currentframe()
  6. # step into the function that called us
  7. fb = f.f_back
  8. innames = fb.f_code.co_varnames[:fb.f_code.co_argcount]
  9. nargin = len([ x for x in innames if fb.f_locals.get(x, None) ])
  10. # nargout is one frame back
  11. f = f.f_back.f_back
  12. c = f.f_code
  13. i = f.f_lasti
  14. bytecode = c.co_code
  15. instruction = ord(bytecode[i+3])
  16. if instruction == dis.opmap['UNPACK_SEQUENCE']:
  17. howmany = ord(bytecode[i+4])
  18. return nargin, howmany
  19. elif instruction == dis.opmap['POP_TOP']:
  20. # MATLAB always assumes at least 1 value
  21. return nargin, 1
  22. return nargin, 1
  23. def _check_nargout(nargout, maxout):
  24. if nargout > maxout:
  25. error("Too many output arguments!")
  26. def get_source(obj):
  27. """Get object's source code. Returns None when source can't be found.
  28. """
  29. from inspect import findsource
  30. try: lines, lnum = findsource(obj)
  31. except (IOError, TypeError): return None
  32. return lines, lnum
  33. def get_func_source(obj):
  34. """Get object's source code. Returns None when source can't be found.
  35. """
  36. from inspect import findsource
  37. from dis import findlinestarts
  38. try:
  39. lines, lnum = findsource(obj)
  40. ls = list(findlinestarts(obj.func_code))
  41. lstart = ls[0][1]
  42. lend = ls[-1][1]
  43. except (IOError, TypeError):
  44. return None
  45. return ''.join(lines[lstart-1:lend])
  46. def get_comment_doc(obj, lines=None, lnum=None):
  47. """Get lines of comments immediately preceding an object's source code.
  48. Returns None when source can't be found.
  49. """
  50. from inspect import ismodule
  51. if lines is None:
  52. try:
  53. from inspect import findsource
  54. lines, lnum = findsource(obj)
  55. except (IOError, TypeError):
  56. return None
  57. if ismodule(obj):
  58. lnum = 0
  59. # Look for a comment block at the top of the file.
  60. start = lnum
  61. if lnum == 0:
  62. if lines and lines[0][:2] == '#!': start = 1
  63. else:
  64. start += 1
  65. if lines[start].lstrip()[:3] == 'def': start += 1
  66. while start < len(lines) and lines[start].strip() in ('', '#'):
  67. start = start + 1
  68. if start < len(lines) and lines[start].lstrip()[:1] == '#':
  69. comments = []
  70. end = start
  71. while end < len(lines) and lines[end].lstrip()[:1] == '#':
  72. comments.append(lines[end].strip()[2:])
  73. end = end + 1
  74. return '\n'.join(comments)
  75. MFUNC_TEMPLATE = '''\
  76. def %(name)s(%(args)s):
  77. """%(doc)s"""
  78. nargin, nargout = _get_narginout()
  79. if nargout > %(maxout)d:
  80. error("Too many output arguments!")
  81. %(body)s
  82. return (%(outnames)s,)[:nargout]
  83. '''
  84. def mfunction(outnames):
  85. # from functools import update_wrappe
  86. def dec(func):
  87. innames = func.func_code.co_varnames[:func.func_code.co_argcount]
  88. lines, lnum = get_source(func)
  89. doc = get_comment_doc(func, lines, lnum)
  90. func_src = MFUNC_TEMPLATE%{'name': func.func_name,
  91. 'args': ', '.join(innames),
  92. 'doc': doc,
  93. 'maxout': len(outnames.split(',')),
  94. 'body': get_func_source(func),
  95. 'outnames': outnames}
  96. g = func.func_globals
  97. exec func_src in g
  98. open('%s.temp.py'%func.func_name, 'wb').write(func_src)
  99. func_new = g[func.func_name]
  100. return func_new
  101. return dec
  102. @mfunction("x")
  103. def coinflip(ndraws=None, p=None):
  104. # Generate a list x of zeros and ones according to coin flipping (i.e.
  105. # Bernoulli) statistics with probability p of getting a 1.
  106. # 1/20/97 dhb Delete obsolet rand('uniform').
  107. # 7/24/04 awi Cosmetic.
  108. # Generate ndraws random variables on the real interval [0,1).
  109. unif = rand(ndraws, 1)
  110. # Find all of the ones that are less than p.
  111. # On average, this proportion will be p.
  112. index = find(unif < p)
  113. [nones, m] = size(index)
  114. # Generate an array of zeros and then set
  115. # the ones found in the previous step to 1.
  116. x = zeros(ndraws, 1)
  117. if (nones != 0):
  118. x(index).lvalue = ones(nones, m)
  119. end
  120. @mfunction("out1, out2")
  121. def add(a=None, b=None):
  122. # adds 2 numbers
  123. if nargin == 2:
  124. out2 = (a, b)
  125. out1 = a + b
  126. #help(coinflip)
  127. #help(add)
  128. print "Adding 1 and 2"
  129. print add(1, 2)