PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/micronumpy/compile.py

https://bitbucket.org/oberstet/pypy
Python | 814 lines | 686 code | 117 blank | 11 comment | 93 complexity | 64272fd3cdb246f912ed31e5686f35f1 MD5 | raw file
Possible License(s): Apache-2.0
  1. """ This is a set of tools for standalone compiling of numpy expressions.
  2. It should not be imported by the module itself
  3. """
  4. import re
  5. from pypy.interpreter.baseobjspace import InternalSpaceCache, W_Root
  6. from pypy.interpreter.error import OperationError
  7. from pypy.module.micronumpy import interp_boxes
  8. from pypy.module.micronumpy.interp_dtype import get_dtype_cache
  9. from pypy.module.micronumpy.base import W_NDimArray
  10. from pypy.module.micronumpy.interp_numarray import array
  11. from pypy.module.micronumpy.interp_arrayops import where
  12. from pypy.module.micronumpy import interp_ufuncs
  13. from rpython.rlib.objectmodel import specialize, instantiate
  14. from rpython.rlib.nonconst import NonConstant
  15. class BogusBytecode(Exception):
  16. pass
  17. class ArgumentMismatch(Exception):
  18. pass
  19. class ArgumentNotAnArray(Exception):
  20. pass
  21. class WrongFunctionName(Exception):
  22. pass
  23. class TokenizerError(Exception):
  24. pass
  25. class BadToken(Exception):
  26. pass
  27. SINGLE_ARG_FUNCTIONS = ["sum", "prod", "max", "min", "all", "any",
  28. "unegative", "flat", "tostring","count_nonzero",
  29. "argsort"]
  30. TWO_ARG_FUNCTIONS = ["dot", 'take']
  31. TWO_ARG_FUNCTIONS_OR_NONE = ['view']
  32. THREE_ARG_FUNCTIONS = ['where']
  33. class W_TypeObject(W_Root):
  34. def __init__(self, name):
  35. self.name = name
  36. def lookup(self, name):
  37. return self.getdictvalue(self, name)
  38. class FakeSpace(object):
  39. w_ValueError = W_TypeObject("ValueError")
  40. w_TypeError = W_TypeObject("TypeError")
  41. w_IndexError = W_TypeObject("IndexError")
  42. w_OverflowError = W_TypeObject("OverflowError")
  43. w_NotImplementedError = W_TypeObject("NotImplementedError")
  44. w_AttributeError = W_TypeObject("AttributeError")
  45. w_None = None
  46. w_bool = W_TypeObject("bool")
  47. w_int = W_TypeObject("int")
  48. w_float = W_TypeObject("float")
  49. w_list = W_TypeObject("list")
  50. w_long = W_TypeObject("long")
  51. w_tuple = W_TypeObject('tuple')
  52. w_slice = W_TypeObject("slice")
  53. w_str = W_TypeObject("str")
  54. w_unicode = W_TypeObject("unicode")
  55. w_complex = W_TypeObject("complex")
  56. w_dict = W_TypeObject("dict")
  57. def __init__(self):
  58. """NOT_RPYTHON"""
  59. self.fromcache = InternalSpaceCache(self).getorbuild
  60. def _freeze_(self):
  61. return True
  62. def is_none(self, w_obj):
  63. return w_obj is None or w_obj is self.w_None
  64. def issequence_w(self, w_obj):
  65. return isinstance(w_obj, ListObject) or isinstance(w_obj, W_NDimArray)
  66. def len(self, w_obj):
  67. assert isinstance(w_obj, ListObject)
  68. return self.wrap(len(w_obj.items))
  69. def getattr(self, w_obj, w_attr):
  70. return StringObject(NonConstant('foo'))
  71. def isinstance_w(self, w_obj, w_tp):
  72. return w_obj.tp == w_tp
  73. def decode_index4(self, w_idx, size):
  74. if isinstance(w_idx, IntObject):
  75. return (self.int_w(w_idx), 0, 0, 1)
  76. else:
  77. assert isinstance(w_idx, SliceObject)
  78. start, stop, step = w_idx.start, w_idx.stop, w_idx.step
  79. if step == 0:
  80. return (0, size, 1, size)
  81. if start < 0:
  82. start += size
  83. if stop < 0:
  84. stop += size + 1
  85. if step < 0:
  86. lgt = (stop - start + 1) / step + 1
  87. else:
  88. lgt = (stop - start - 1) / step + 1
  89. return (start, stop, step, lgt)
  90. @specialize.argtype(1)
  91. def wrap(self, obj):
  92. if isinstance(obj, float):
  93. return FloatObject(obj)
  94. elif isinstance(obj, bool):
  95. return BoolObject(obj)
  96. elif isinstance(obj, int):
  97. return IntObject(obj)
  98. elif isinstance(obj, long):
  99. return LongObject(obj)
  100. elif isinstance(obj, W_Root):
  101. return obj
  102. elif isinstance(obj, str):
  103. return StringObject(obj)
  104. raise NotImplementedError
  105. def newlist(self, items):
  106. return ListObject(items)
  107. def newcomplex(self, r, i):
  108. return ComplexObject(r, i)
  109. def listview(self, obj, number=-1):
  110. assert isinstance(obj, ListObject)
  111. if number != -1:
  112. assert number == 2
  113. return [obj.items[0], obj.items[1]]
  114. return obj.items
  115. fixedview = listview
  116. def float(self, w_obj):
  117. if isinstance(w_obj, FloatObject):
  118. return w_obj
  119. assert isinstance(w_obj, interp_boxes.W_GenericBox)
  120. return self.float(w_obj.descr_float(self))
  121. def float_w(self, w_obj):
  122. assert isinstance(w_obj, FloatObject)
  123. return w_obj.floatval
  124. def int_w(self, w_obj):
  125. if isinstance(w_obj, IntObject):
  126. return w_obj.intval
  127. elif isinstance(w_obj, FloatObject):
  128. return int(w_obj.floatval)
  129. elif isinstance(w_obj, SliceObject):
  130. raise OperationError(self.w_TypeError, self.wrap("slice."))
  131. raise NotImplementedError
  132. def unpackcomplex(self, w_obj):
  133. if isinstance(w_obj, ComplexObject):
  134. return w_obj.r, w_obj.i
  135. raise NotImplementedError
  136. def index(self, w_obj):
  137. return self.wrap(self.int_w(w_obj))
  138. def str_w(self, w_obj):
  139. if isinstance(w_obj, StringObject):
  140. return w_obj.v
  141. raise NotImplementedError
  142. def int(self, w_obj):
  143. if isinstance(w_obj, IntObject):
  144. return w_obj
  145. assert isinstance(w_obj, interp_boxes.W_GenericBox)
  146. return self.int(w_obj.descr_int(self))
  147. def str(self, w_obj):
  148. if isinstance(w_obj, StringObject):
  149. return w_obj
  150. assert isinstance(w_obj, interp_boxes.W_GenericBox)
  151. return self.str(w_obj.descr_str(self))
  152. def is_true(self, w_obj):
  153. assert isinstance(w_obj, BoolObject)
  154. return w_obj.boolval
  155. def is_w(self, w_obj, w_what):
  156. return w_obj is w_what
  157. def issubtype(self, w_type1, w_type2):
  158. return BoolObject(True)
  159. def type(self, w_obj):
  160. if self.is_none(w_obj):
  161. return self.w_None
  162. try:
  163. return w_obj.tp
  164. except AttributeError:
  165. if isinstance(w_obj, W_NDimArray):
  166. return W_NDimArray
  167. return self.w_None
  168. def lookup(self, w_obj, name):
  169. w_type = self.type(w_obj)
  170. return w_type.lookup(name)
  171. def gettypefor(self, w_obj):
  172. return None
  173. def call_function(self, tp, w_dtype):
  174. return w_dtype
  175. def call_method(self, w_obj, s, *args):
  176. # XXX even the hacks have hacks
  177. return None
  178. #return getattr(w_obj, 'descr_' + s)(self, *args)
  179. @specialize.arg(1)
  180. def interp_w(self, tp, what):
  181. assert isinstance(what, tp)
  182. return what
  183. def allocate_instance(self, klass, w_subtype):
  184. return instantiate(klass)
  185. def newtuple(self, list_w):
  186. return ListObject(list_w)
  187. def newdict(self):
  188. return {}
  189. def setitem(self, dict, item, value):
  190. dict[item] = value
  191. def len_w(self, w_obj):
  192. if isinstance(w_obj, ListObject):
  193. return len(w_obj.items)
  194. # XXX array probably
  195. assert False
  196. def exception_match(self, w_exc_type, w_check_class):
  197. # Good enough for now
  198. raise NotImplementedError
  199. class FloatObject(W_Root):
  200. tp = FakeSpace.w_float
  201. def __init__(self, floatval):
  202. self.floatval = floatval
  203. class BoolObject(W_Root):
  204. tp = FakeSpace.w_bool
  205. def __init__(self, boolval):
  206. self.boolval = boolval
  207. class IntObject(W_Root):
  208. tp = FakeSpace.w_int
  209. def __init__(self, intval):
  210. self.intval = intval
  211. class LongObject(W_Root):
  212. tp = FakeSpace.w_long
  213. def __init__(self, intval):
  214. self.intval = intval
  215. class ListObject(W_Root):
  216. tp = FakeSpace.w_list
  217. def __init__(self, items):
  218. self.items = items
  219. class SliceObject(W_Root):
  220. tp = FakeSpace.w_slice
  221. def __init__(self, start, stop, step):
  222. self.start = start
  223. self.stop = stop
  224. self.step = step
  225. class StringObject(W_Root):
  226. tp = FakeSpace.w_str
  227. def __init__(self, v):
  228. self.v = v
  229. class ComplexObject(W_Root):
  230. tp = FakeSpace.w_complex
  231. def __init__(self, r, i):
  232. self.r = r
  233. self.i = i
  234. class InterpreterState(object):
  235. def __init__(self, code):
  236. self.code = code
  237. self.variables = {}
  238. self.results = []
  239. def run(self, space):
  240. self.space = space
  241. for stmt in self.code.statements:
  242. stmt.execute(self)
  243. class Node(object):
  244. def __eq__(self, other):
  245. return (self.__class__ == other.__class__ and
  246. self.__dict__ == other.__dict__)
  247. def __ne__(self, other):
  248. return not self == other
  249. def wrap(self, space):
  250. raise NotImplementedError
  251. def execute(self, interp):
  252. raise NotImplementedError
  253. class Assignment(Node):
  254. def __init__(self, name, expr):
  255. self.name = name
  256. self.expr = expr
  257. def execute(self, interp):
  258. interp.variables[self.name] = self.expr.execute(interp)
  259. def __repr__(self):
  260. return "%r = %r" % (self.name, self.expr)
  261. class ArrayAssignment(Node):
  262. def __init__(self, name, index, expr):
  263. self.name = name
  264. self.index = index
  265. self.expr = expr
  266. def execute(self, interp):
  267. arr = interp.variables[self.name]
  268. w_index = self.index.execute(interp)
  269. # cast to int
  270. if isinstance(w_index, FloatObject):
  271. w_index = IntObject(int(w_index.floatval))
  272. w_val = self.expr.execute(interp)
  273. assert isinstance(arr, W_NDimArray)
  274. arr.descr_setitem(interp.space, w_index, w_val)
  275. def __repr__(self):
  276. return "%s[%r] = %r" % (self.name, self.index, self.expr)
  277. class Variable(Node):
  278. def __init__(self, name):
  279. self.name = name.strip(" ")
  280. def execute(self, interp):
  281. if self.name == 'None':
  282. return None
  283. return interp.variables[self.name]
  284. def __repr__(self):
  285. return 'v(%s)' % self.name
  286. class Operator(Node):
  287. def __init__(self, lhs, name, rhs):
  288. self.name = name
  289. self.lhs = lhs
  290. self.rhs = rhs
  291. def execute(self, interp):
  292. w_lhs = self.lhs.execute(interp)
  293. if isinstance(self.rhs, SliceConstant):
  294. w_rhs = self.rhs.wrap(interp.space)
  295. else:
  296. w_rhs = self.rhs.execute(interp)
  297. if not isinstance(w_lhs, W_NDimArray):
  298. # scalar
  299. dtype = get_dtype_cache(interp.space).w_float64dtype
  300. w_lhs = W_NDimArray.new_scalar(interp.space, dtype, w_lhs)
  301. assert isinstance(w_lhs, W_NDimArray)
  302. if self.name == '+':
  303. w_res = w_lhs.descr_add(interp.space, w_rhs)
  304. elif self.name == '*':
  305. w_res = w_lhs.descr_mul(interp.space, w_rhs)
  306. elif self.name == '-':
  307. w_res = w_lhs.descr_sub(interp.space, w_rhs)
  308. elif self.name == '->':
  309. if isinstance(w_rhs, FloatObject):
  310. w_rhs = IntObject(int(w_rhs.floatval))
  311. assert isinstance(w_lhs, W_NDimArray)
  312. w_res = w_lhs.descr_getitem(interp.space, w_rhs)
  313. else:
  314. raise NotImplementedError
  315. if (not isinstance(w_res, W_NDimArray) and
  316. not isinstance(w_res, interp_boxes.W_GenericBox)):
  317. dtype = get_dtype_cache(interp.space).w_float64dtype
  318. w_res = W_NDimArray.new_scalar(interp.space, dtype, w_res)
  319. return w_res
  320. def __repr__(self):
  321. return '(%r %s %r)' % (self.lhs, self.name, self.rhs)
  322. class FloatConstant(Node):
  323. def __init__(self, v):
  324. self.v = float(v)
  325. def __repr__(self):
  326. return "Const(%s)" % self.v
  327. def wrap(self, space):
  328. return space.wrap(self.v)
  329. def execute(self, interp):
  330. return interp.space.wrap(self.v)
  331. class ComplexConstant(Node):
  332. def __init__(self, r, i):
  333. self.r = float(r)
  334. self.i = float(i)
  335. def __repr__(self):
  336. return 'ComplexConst(%s, %s)' % (self.r, self.i)
  337. def wrap(self, space):
  338. return space.newcomplex(self.r, self.i)
  339. def execute(self, interp):
  340. return self.wrap(interp.space)
  341. class RangeConstant(Node):
  342. def __init__(self, v):
  343. self.v = int(v)
  344. def execute(self, interp):
  345. w_list = interp.space.newlist(
  346. [interp.space.wrap(float(i)) for i in range(self.v)]
  347. )
  348. dtype = get_dtype_cache(interp.space).w_float64dtype
  349. return array(interp.space, w_list, w_dtype=dtype, w_order=None)
  350. def __repr__(self):
  351. return 'Range(%s)' % self.v
  352. class Code(Node):
  353. def __init__(self, statements):
  354. self.statements = statements
  355. def __repr__(self):
  356. return "\n".join([repr(i) for i in self.statements])
  357. class ArrayConstant(Node):
  358. def __init__(self, items):
  359. self.items = items
  360. def wrap(self, space):
  361. return space.newlist([item.wrap(space) for item in self.items])
  362. def execute(self, interp):
  363. w_list = self.wrap(interp.space)
  364. return array(interp.space, w_list)
  365. def __repr__(self):
  366. return "[" + ", ".join([repr(item) for item in self.items]) + "]"
  367. class SliceConstant(Node):
  368. def __init__(self, start, stop, step):
  369. # no negative support for now
  370. self.start = start
  371. self.stop = stop
  372. self.step = step
  373. def wrap(self, space):
  374. return SliceObject(self.start, self.stop, self.step)
  375. def execute(self, interp):
  376. return SliceObject(self.start, self.stop, self.step)
  377. def __repr__(self):
  378. return 'slice(%s,%s,%s)' % (self.start, self.stop, self.step)
  379. class ArrayClass(Node):
  380. def __init__(self):
  381. self.v = W_NDimArray
  382. def execute(self, interp):
  383. return self.v
  384. def __repr__(self):
  385. return '<class W_NDimArray>'
  386. class DtypeClass(Node):
  387. def __init__(self, dt):
  388. self.v = dt
  389. def execute(self, interp):
  390. if self.v == 'int':
  391. dtype = get_dtype_cache(interp.space).w_int64dtype
  392. elif self.v == 'float':
  393. dtype = get_dtype_cache(interp.space).w_float64dtype
  394. else:
  395. raise BadToken('unknown v to dtype "%s"' % self.v)
  396. return dtype
  397. def __repr__(self):
  398. return '<class %s dtype>' % self.v
  399. class Execute(Node):
  400. def __init__(self, expr):
  401. self.expr = expr
  402. def __repr__(self):
  403. return repr(self.expr)
  404. def execute(self, interp):
  405. interp.results.append(self.expr.execute(interp))
  406. class FunctionCall(Node):
  407. def __init__(self, name, args):
  408. self.name = name.strip(" ")
  409. self.args = args
  410. def __repr__(self):
  411. return "%s(%s)" % (self.name, ", ".join([repr(arg)
  412. for arg in self.args]))
  413. def execute(self, interp):
  414. arr = self.args[0].execute(interp)
  415. if not isinstance(arr, W_NDimArray):
  416. raise ArgumentNotAnArray
  417. if self.name in SINGLE_ARG_FUNCTIONS:
  418. if len(self.args) != 1 and self.name != 'sum':
  419. raise ArgumentMismatch
  420. if self.name == "sum":
  421. if len(self.args)>1:
  422. w_res = arr.descr_sum(interp.space,
  423. self.args[1].execute(interp))
  424. else:
  425. w_res = arr.descr_sum(interp.space)
  426. elif self.name == "prod":
  427. w_res = arr.descr_prod(interp.space)
  428. elif self.name == "max":
  429. w_res = arr.descr_max(interp.space)
  430. elif self.name == "min":
  431. w_res = arr.descr_min(interp.space)
  432. elif self.name == "any":
  433. w_res = arr.descr_any(interp.space)
  434. elif self.name == "all":
  435. w_res = arr.descr_all(interp.space)
  436. elif self.name == "unegative":
  437. neg = interp_ufuncs.get(interp.space).negative
  438. w_res = neg.call(interp.space, [arr])
  439. elif self.name == "cos":
  440. cos = interp_ufuncs.get(interp.space).cos
  441. w_res = cos.call(interp.space, [arr])
  442. elif self.name == "flat":
  443. w_res = arr.descr_get_flatiter(interp.space)
  444. elif self.name == "argsort":
  445. w_res = arr.descr_argsort(interp.space)
  446. elif self.name == "tostring":
  447. arr.descr_tostring(interp.space)
  448. w_res = None
  449. else:
  450. assert False # unreachable code
  451. elif self.name in TWO_ARG_FUNCTIONS:
  452. if len(self.args) != 2:
  453. raise ArgumentMismatch
  454. arg = self.args[1].execute(interp)
  455. if not isinstance(arg, W_NDimArray):
  456. raise ArgumentNotAnArray
  457. if self.name == "dot":
  458. w_res = arr.descr_dot(interp.space, arg)
  459. elif self.name == 'take':
  460. w_res = arr.descr_take(interp.space, arg)
  461. else:
  462. assert False # unreachable code
  463. elif self.name in THREE_ARG_FUNCTIONS:
  464. if len(self.args) != 3:
  465. raise ArgumentMismatch
  466. arg1 = self.args[1].execute(interp)
  467. arg2 = self.args[2].execute(interp)
  468. if not isinstance(arg1, W_NDimArray):
  469. raise ArgumentNotAnArray
  470. if not isinstance(arg2, W_NDimArray):
  471. raise ArgumentNotAnArray
  472. if self.name == "where":
  473. w_res = where(interp.space, arr, arg1, arg2)
  474. else:
  475. assert False
  476. elif self.name in TWO_ARG_FUNCTIONS_OR_NONE:
  477. if len(self.args) != 2:
  478. raise ArgumentMismatch
  479. arg = self.args[1].execute(interp)
  480. if self.name == 'view':
  481. w_res = arr.descr_view(interp.space, arg)
  482. else:
  483. assert False
  484. else:
  485. raise WrongFunctionName
  486. if isinstance(w_res, W_NDimArray):
  487. return w_res
  488. if isinstance(w_res, FloatObject):
  489. dtype = get_dtype_cache(interp.space).w_float64dtype
  490. elif isinstance(w_res, IntObject):
  491. dtype = get_dtype_cache(interp.space).w_int64dtype
  492. elif isinstance(w_res, BoolObject):
  493. dtype = get_dtype_cache(interp.space).w_booldtype
  494. elif isinstance(w_res, interp_boxes.W_GenericBox):
  495. dtype = w_res.get_dtype(interp.space)
  496. else:
  497. dtype = None
  498. return W_NDimArray.new_scalar(interp.space, dtype, w_res)
  499. _REGEXES = [
  500. ('-?[\d\.]+', 'number'),
  501. ('\[', 'array_left'),
  502. (':', 'colon'),
  503. ('\w+', 'identifier'),
  504. ('\]', 'array_right'),
  505. ('(->)|[\+\-\*\/]', 'operator'),
  506. ('=', 'assign'),
  507. (',', 'comma'),
  508. ('\|', 'pipe'),
  509. ('\(', 'paren_left'),
  510. ('\)', 'paren_right'),
  511. ]
  512. REGEXES = []
  513. for r, name in _REGEXES:
  514. REGEXES.append((re.compile(r' *(' + r + ')'), name))
  515. del _REGEXES
  516. class Token(object):
  517. def __init__(self, name, v):
  518. self.name = name
  519. self.v = v
  520. def __repr__(self):
  521. return '(%s, %s)' % (self.name, self.v)
  522. empty = Token('', '')
  523. class TokenStack(object):
  524. def __init__(self, tokens):
  525. self.tokens = tokens
  526. self.c = 0
  527. def pop(self):
  528. token = self.tokens[self.c]
  529. self.c += 1
  530. return token
  531. def get(self, i):
  532. if self.c + i >= len(self.tokens):
  533. return empty
  534. return self.tokens[self.c + i]
  535. def remaining(self):
  536. return len(self.tokens) - self.c
  537. def push(self):
  538. self.c -= 1
  539. def __repr__(self):
  540. return repr(self.tokens[self.c:])
  541. class Parser(object):
  542. def tokenize(self, line):
  543. tokens = []
  544. while True:
  545. for r, name in REGEXES:
  546. m = r.match(line)
  547. if m is not None:
  548. g = m.group(0)
  549. tokens.append(Token(name, g))
  550. line = line[len(g):]
  551. if not line:
  552. return TokenStack(tokens)
  553. break
  554. else:
  555. raise TokenizerError(line)
  556. def parse_number_or_slice(self, tokens):
  557. start_tok = tokens.pop()
  558. if start_tok.name == 'colon':
  559. start = 0
  560. else:
  561. if tokens.get(0).name != 'colon':
  562. return FloatConstant(start_tok.v)
  563. start = int(start_tok.v)
  564. tokens.pop()
  565. if not tokens.get(0).name in ['colon', 'number']:
  566. stop = -1
  567. step = 1
  568. else:
  569. next = tokens.pop()
  570. if next.name == 'colon':
  571. stop = -1
  572. step = int(tokens.pop().v)
  573. else:
  574. stop = int(next.v)
  575. if tokens.get(0).name == 'colon':
  576. tokens.pop()
  577. step = int(tokens.pop().v)
  578. else:
  579. step = 1
  580. return SliceConstant(start, stop, step)
  581. def parse_expression(self, tokens, accept_comma=False):
  582. stack = []
  583. while tokens.remaining():
  584. token = tokens.pop()
  585. if token.name == 'identifier':
  586. if tokens.remaining() and tokens.get(0).name == 'paren_left':
  587. stack.append(self.parse_function_call(token.v, tokens))
  588. elif token.v.strip(' ') == 'ndarray':
  589. stack.append(ArrayClass())
  590. elif token.v.strip(' ') == 'int':
  591. stack.append(DtypeClass('int'))
  592. elif token.v.strip(' ') == 'float':
  593. stack.append(DtypeClass('float'))
  594. else:
  595. stack.append(Variable(token.v.strip(' ')))
  596. elif token.name == 'array_left':
  597. stack.append(ArrayConstant(self.parse_array_const(tokens)))
  598. elif token.name == 'operator':
  599. stack.append(Variable(token.v))
  600. elif token.name == 'number' or token.name == 'colon':
  601. tokens.push()
  602. stack.append(self.parse_number_or_slice(tokens))
  603. elif token.name == 'pipe':
  604. stack.append(RangeConstant(tokens.pop().v))
  605. end = tokens.pop()
  606. assert end.name == 'pipe'
  607. elif token.name == 'paren_left':
  608. stack.append(self.parse_complex_constant(tokens))
  609. elif accept_comma and token.name == 'comma':
  610. continue
  611. else:
  612. tokens.push()
  613. break
  614. if accept_comma:
  615. return stack
  616. stack.reverse()
  617. lhs = stack.pop()
  618. while stack:
  619. op = stack.pop()
  620. assert isinstance(op, Variable)
  621. rhs = stack.pop()
  622. lhs = Operator(lhs, op.name, rhs)
  623. return lhs
  624. def parse_function_call(self, name, tokens):
  625. args = []
  626. tokens.pop() # lparen
  627. while tokens.get(0).name != 'paren_right':
  628. args += self.parse_expression(tokens, accept_comma=True)
  629. return FunctionCall(name, args)
  630. def parse_complex_constant(self, tokens):
  631. r = tokens.pop()
  632. assert r.name == 'number'
  633. assert tokens.pop().name == 'comma'
  634. i = tokens.pop()
  635. assert i.name == 'number'
  636. assert tokens.pop().name == 'paren_right'
  637. return ComplexConstant(r.v, i.v)
  638. def parse_array_const(self, tokens):
  639. elems = []
  640. while True:
  641. token = tokens.pop()
  642. if token.name == 'number':
  643. elems.append(FloatConstant(token.v))
  644. elif token.name == 'array_left':
  645. elems.append(ArrayConstant(self.parse_array_const(tokens)))
  646. elif token.name == 'paren_left':
  647. elems.append(self.parse_complex_constant(tokens))
  648. else:
  649. raise BadToken()
  650. token = tokens.pop()
  651. if token.name == 'array_right':
  652. return elems
  653. assert token.name == 'comma'
  654. def parse_statement(self, tokens):
  655. if (tokens.get(0).name == 'identifier' and
  656. tokens.get(1).name == 'assign'):
  657. lhs = tokens.pop().v
  658. tokens.pop()
  659. rhs = self.parse_expression(tokens)
  660. return Assignment(lhs, rhs)
  661. elif (tokens.get(0).name == 'identifier' and
  662. tokens.get(1).name == 'array_left'):
  663. name = tokens.pop().v
  664. tokens.pop()
  665. index = self.parse_expression(tokens)
  666. tokens.pop()
  667. tokens.pop()
  668. return ArrayAssignment(name, index, self.parse_expression(tokens))
  669. return Execute(self.parse_expression(tokens))
  670. def parse(self, code):
  671. statements = []
  672. for line in code.split("\n"):
  673. if '#' in line:
  674. line = line.split('#', 1)[0]
  675. line = line.strip(" ")
  676. if line:
  677. tokens = self.tokenize(line)
  678. statements.append(self.parse_statement(tokens))
  679. return Code(statements)
  680. def numpy_compile(code):
  681. parser = Parser()
  682. return InterpreterState(parser.parse(code))