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

/pypy/module/micronumpy/compile.py

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