PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/kernel/bootstrap/Enumerator2.rb

https://github.com/MagLev/maglev
Ruby | 689 lines | 599 code | 74 blank | 16 comment | 54 complexity | f64dfe1d0452e9078ebef6c6528d8e56 MD5 | raw file
Possible License(s): LGPL-2.1
  1. module Enumerable
  2. class ObjectEnumerator < Enumerator
  3. # Object enumerator used for lazy enumeration , fix Trac 904
  4. def next(&block)
  5. # return an element of the minor-enumeration
  6. @sub_enum ||= @obj.__send__(@enum_selector, *@extra_args).each
  7. @sub_enum.next(&block)
  8. end
  9. end
  10. class ArrayEnumerator < Enumerator
  11. # ArrayEnumerator also used for String#each_byte
  12. def next
  13. # return an element, @obj[ofs]
  14. arr = @obj
  15. ofs = @ofs
  16. if ofs >= arr.__size
  17. raise StopIteration
  18. end
  19. @ofs = ofs + 1
  20. arr.__at(ofs)
  21. end
  22. end
  23. class StringByteEnumerator < Enumerator
  24. def next
  25. # return an element, @obj[ofs]
  26. str = @obj
  27. ofs = @ofs
  28. if ofs >= str.__size
  29. raise StopIteration
  30. end
  31. @ofs = ofs + 1
  32. str.__at(ofs)
  33. end
  34. end
  35. class StringCharEnumerator < Enumerator
  36. def next
  37. # return an element, @obj[ofs]
  38. str = @obj
  39. ofs = @ofs
  40. if ofs >= str.__size
  41. raise StopIteration
  42. end
  43. @ofs = ofs + 1
  44. ch = str.__at(ofs)
  45. res = ' ' .
  46. res.__at_put(0, ch)
  47. res
  48. end
  49. end
  50. class FirstEnumerator < Enumerator
  51. def next
  52. if ofs > 0
  53. raise StopIteration
  54. end
  55. @ofs = ofs + 1
  56. @obj.each { |o| return o }
  57. raise StopIteration
  58. end
  59. end
  60. class ArrayWithIndexEnumerator < Enumerator
  61. def each_with_index(&block)
  62. unless block_given?
  63. return self
  64. end
  65. @obj.each_with_index(&block)
  66. end
  67. def next
  68. # return an Array [ @obj[ofs], ofs ]
  69. arr = @obj
  70. ofs = @ofs
  71. if ofs >= arr.__size
  72. raise StopIteration
  73. end
  74. @ofs = ofs + 1
  75. [ arr.__at(ofs) , ofs ]
  76. end
  77. end
  78. class ArrayIndexEnumerator < Enumerator
  79. def next
  80. # return the current offset
  81. arr = @obj
  82. ofs = @ofs
  83. if ofs >= arr.__size
  84. raise StopIteration
  85. end
  86. @ofs = ofs + 1
  87. ofs
  88. end
  89. end
  90. class ArrayReverseEnumerator < Enumerator
  91. def initialize(array, enum_sel)
  92. super(array, enum_sel)
  93. @ofs = array.__size - 1
  94. end
  95. def next
  96. # return the element @obj[ofs]
  97. arr = @obj
  98. ofs = @ofs
  99. if ofs < 0
  100. raise StopIteration
  101. end
  102. @ofs = ofs - 1
  103. arr.__at(ofs)
  104. end
  105. def rewind
  106. @ofs = @obj.__size - 1
  107. self
  108. end
  109. end
  110. # ---------------------------------------------
  111. # complex Array enumerators reimplementing more than just the method next
  112. class ArrayCombinationEnumerator < ArrayEnumerator
  113. def initialize(count, array, enum_sel)
  114. super(array, enum_sel)
  115. @count = count
  116. @values = nil
  117. end
  118. def __compute_values
  119. varr = []
  120. cnt = @count
  121. if cnt._equal?(nil)
  122. cnt = @obj.__size
  123. end
  124. @obj.__send__( @enum_selector, cnt ) { |e| varr << e }
  125. @ofs = 0
  126. @values = varr
  127. return varr
  128. end
  129. def next
  130. varr = @values
  131. if varr._equal?(nil)
  132. varr = self.__compute_values
  133. end
  134. ofs = @ofs
  135. if ofs >= varr.__size
  136. raise StopIteration
  137. end
  138. res = varr[ofs]
  139. @ofs = ofs + 1
  140. end
  141. def rewind
  142. @ofs = 0
  143. @values = nil # force recompute
  144. self
  145. end
  146. def each(&block)
  147. cnt = @count
  148. if cnt._equal?(nil)
  149. cnt = @obj.__size
  150. end
  151. @obj.__send__( @enum_selector, cnt, &block)
  152. end
  153. def each_with_object(memo, &block)
  154. cnt = @count
  155. if cnt._equal?(nil)
  156. cnt = @obj.__size
  157. end
  158. @obj.__send__( @enum_selector, cnt) { | elem |
  159. block.call( elem, memo )
  160. }
  161. end
  162. def each_with_index(&block)
  163. cnt = @count
  164. if cnt._equal?(nil)
  165. cnt = @obj.__size
  166. end
  167. n = 0
  168. @obj.__send__( @enum_selector, cnt) { | elem |
  169. block.call( elem , n )
  170. n += 1
  171. }
  172. end
  173. end
  174. class ArrayCycleEnumerator < Enumerator
  175. def initialize(array, repeat_count)
  176. cnt = Maglev::Type.coerce_to(repeat_count, Fixnum , :to_int)
  177. super(array, :cycle)
  178. @cycle_count = cnt
  179. @num_cycles = cnt
  180. end
  181. def next
  182. # return the element @obj[ofs]
  183. arr = @obj
  184. ofs = @ofs
  185. if ofs >= arr.__size
  186. cnt = @cycle_count - 1
  187. @cycle_count = cnt
  188. if cnt <= 0
  189. raise StopIteration
  190. end
  191. ofs = -1 # restart at front of array
  192. end
  193. @ofs = ofs + 1
  194. arr.__at(ofs)
  195. end
  196. def rewind
  197. @ofs = 0
  198. @cycle_count = @num_cycles
  199. self
  200. end
  201. def each(&block)
  202. @obj.cycle(@num_cycles, &block)
  203. end
  204. def each_with_object(memo, &block)
  205. @obj.cycle(@num_cycles) { | elem |
  206. block.call( elem, memo )
  207. }
  208. end
  209. def each_with_index(&block)
  210. lim = @num_cycles
  211. cnt = 0
  212. arr = @obj
  213. sz = arr.__size
  214. while cnt < lim
  215. n = 0
  216. enum_res = arr.each { |elem|
  217. block.call(elem, n)
  218. n += 1
  219. }
  220. if n < sz
  221. return enum_res # break happened in block
  222. end
  223. cnt += 1
  224. end
  225. nil
  226. end
  227. alias with_index each_with_index
  228. alias with_object each_with_object
  229. end
  230. class ArraySelectEnumerator < ArrayEnumerator
  231. def initialize(obj, enum_sel)
  232. super(obj, enum_sel)
  233. @values = nil
  234. end
  235. def __compute_values
  236. varr = []
  237. @obj.each { |e| varr << e }
  238. @ofs = 0
  239. @values = varr
  240. return varr
  241. end
  242. def next
  243. varr = @values
  244. if varr._equal?(nil)
  245. varr = self.__compute_values
  246. end
  247. ofs = @ofs
  248. if ofs >= varr.__size
  249. raise StopIteration
  250. end
  251. res = varr[ofs]
  252. @ofs = ofs + 1
  253. end
  254. def rewind
  255. @ofs = 0
  256. @values = nil # force recompute
  257. self
  258. end
  259. def each(&block)
  260. vals = self.__compute_values
  261. vals.__send__( @enum_selector, &block)
  262. end
  263. def each_with_object(memo, &block)
  264. vals = self.__compute_values
  265. vals.__send__( @enum_selector, @count) { | elem |
  266. block.call( elem, memo )
  267. }
  268. end
  269. def each_with_index(&block)
  270. n = 0
  271. vals = self.__compute_values
  272. vals.__send__( @enum_selector, @count) { | elem |
  273. block.call( elem , n )
  274. n += 1
  275. }
  276. end
  277. end
  278. class DirEnumerator < Enumerator
  279. def next
  280. # return an element, @obj[ofs]
  281. dir = @obj
  282. arr = dir.__entries
  283. ofs = @ofs
  284. if ofs >= arr.__size
  285. raise StopIteration
  286. end
  287. dir.check_closed
  288. @ofs = ofs + 1
  289. arr.__at(ofs)
  290. end
  291. end
  292. class HashEnumerator < Enumerator
  293. def initialize(obj, enum_sel)
  294. super(obj, enum_sel)
  295. @deque_pointer = obj.__head
  296. end
  297. def next
  298. @deque_pointer = @deque_pointer.instance_variable_get :@next
  299. if @deque_pointer.equal?(@obj.__tail)
  300. raise StopIteration
  301. end
  302. return [@deque_pointer.instance_variable_get(:@key), @deque_pointer.instance_variable_get(:@value)]
  303. end
  304. def rewind
  305. @deque_pointer = @obj.__head
  306. self
  307. end
  308. end
  309. class HashKeyEnumerator < HashEnumerator
  310. # used to enumerate either keys or values
  311. def next
  312. if @enum_selector.eql?(:each_value)
  313. return super[1]
  314. elsif @enum_selector.eql?(:each_key)
  315. return super[0]
  316. end
  317. end
  318. end
  319. class NumericEnumerator < Enumerator
  320. def initialize(object, start, last, increm)
  321. @obj = object
  322. @ofs = start
  323. @enum_selector = :each
  324. @extra_args = []
  325. @start = start
  326. @last = last
  327. @inc = increm
  328. end
  329. def rewind
  330. @ofs = @start
  331. self
  332. end
  333. def __next
  334. n = @ofs
  335. if n <= @last
  336. @ofs = n + @inc
  337. return n
  338. end
  339. nil
  340. end
  341. def next
  342. n = self.__next
  343. if n._equal?(nil)
  344. raise StopIteration
  345. end
  346. n
  347. end
  348. def each(&block)
  349. self.rewind
  350. [1].each { |ignore| # this each handles break from the argument block
  351. while true
  352. n = self.__next
  353. if n._equal?(nil)
  354. return @obj
  355. end
  356. block.call(n)
  357. end
  358. }
  359. end
  360. def each_with_index(&block)
  361. self.rewind
  362. [1].each { |ignore| # this each handles break from the argument block
  363. k = 0
  364. while true
  365. n = self.__next
  366. if n._equal?(nil)
  367. return @obj
  368. end
  369. block.call(n, k)
  370. k += 1
  371. end
  372. }
  373. end
  374. def each_with_object(memo, &block)
  375. @obj.__send__( @enum_selector, *@extra_args) { | elem |
  376. block.call( elem , memo )
  377. }
  378. self.rewind
  379. [1].each { |ignore| # this each handles break from the argument block
  380. k = 0
  381. while true
  382. n = self.__next
  383. if n._equal?(nil)
  384. return @obj
  385. end
  386. block.call(n, memo)
  387. k += 1
  388. end
  389. }
  390. end
  391. alias with_index each_with_index
  392. alias with_object each_with_object
  393. end
  394. class NumericDownEnumerator < NumericEnumerator
  395. def __next
  396. n = @ofs
  397. if n >= @last
  398. @ofs = n - @inc
  399. return n
  400. end
  401. nil
  402. end
  403. end
  404. class RangeEnumerator < NumericEnumerator
  405. def initialize(object, enum_sel, increment)
  406. # not using super.initialize
  407. strt = object.begin # aRange.@from
  408. lst = object.end # aRange.@to
  409. @enum_selector = enum_sel
  410. @obj = object
  411. @start = strt
  412. @ofs = strt
  413. @last = lst
  414. @inc = increment
  415. @exclude_end = object.exclude_end?
  416. @extra_args = []
  417. unless @start._isNumeric
  418. unless @exclude_end
  419. @last = @last.succ
  420. end
  421. end
  422. end
  423. def rewind
  424. @ofs = @start
  425. self
  426. end
  427. def __next
  428. current = @ofs
  429. if @start._isNumeric
  430. if @exclude_end
  431. if current >= @last ; return nil; end
  432. else
  433. if current > @last ; return nil; end
  434. end
  435. nxt = current + @inc
  436. else
  437. if current >= @last ; return nil; end
  438. nxt = current.succ
  439. end
  440. @ofs = nxt
  441. return current
  442. end
  443. end
  444. class IoEnumerator < Enumerator
  445. def next
  446. if (anio = @obj).eof?
  447. raise StopIteration
  448. end
  449. sep = @extra_args[0]
  450. res = anio.__next_line(sep)
  451. @ofs += 1
  452. res
  453. end
  454. def rewind
  455. @ofs = 0
  456. @obj.rewind
  457. self
  458. end
  459. end
  460. class IoByteEnumerator < IoEnumerator
  461. def next
  462. if (anio = @obj).eof?
  463. raise StopIteration
  464. end
  465. res = anio.readchar
  466. @ofs += 1
  467. res
  468. end
  469. end
  470. class IoCharEnumerator < IoEnumerator
  471. def next
  472. if (anio = @obj).eof?
  473. raise StopIteration
  474. end
  475. ch = anio.readchar
  476. str = ' '
  477. str[0] = ch
  478. @ofs += 1
  479. str
  480. end
  481. end
  482. class StringEachEnumerator < Enumerator # [
  483. def initialize(obj, enum_sel, separator )
  484. super(obj, enum_sel)
  485. @last = 0
  486. @sep = separator
  487. @idx = separator.size
  488. @extra_args = [ separator ]
  489. end
  490. def next # [
  491. obj = @obj
  492. my_size = obj.__size
  493. sep = @sep
  494. sep_size = sep.__size
  495. newline = sep_size._equal?(0) ? ?\n : sep.__at(sep_size - 1)
  496. last = @last
  497. i = @idx
  498. if sep_size._equal?(0)
  499. while i < my_size
  500. if obj.__at(i)._equal?( ?\n )
  501. if obj.__at(i+=1)._not_equal?( ?\n )
  502. i += 1
  503. next
  504. end
  505. i += 1 while i < my_size && obj.__at(i)._equal?( ?\n )
  506. end
  507. if i > 0 && obj.__at(i-1)._equal?( newline )
  508. line = obj.__at(last, i-last)
  509. @last = i
  510. @idx = i + 1
  511. return line
  512. end
  513. i += 1
  514. end
  515. else
  516. while i < my_size
  517. if i > 0 && obj.__at(i-1)._equal?(newline) &&
  518. (sep_size < 2 || obj.__at_equals( i - sep_siz + 1, sep))
  519. line = obj.__at(last, i-last)
  520. @last = i
  521. @idx = i + 1
  522. return line
  523. end
  524. i += 1
  525. end
  526. end
  527. unless last._equal?(my_size)
  528. line = obj.__at(last, my_size-last+1)
  529. @last = my_size + 1
  530. @idx = my_size + 1
  531. return line
  532. end
  533. raise StopIteration
  534. end # ]
  535. end # ]
  536. class StringGsubEnumerator < Enumerator #
  537. def initialize(obj, enum_sel, regex)
  538. super(obj, enum_sel)
  539. @regex = obj.__get_pattern( regex , true)
  540. end
  541. def next
  542. pos = @ofs
  543. str = @obj
  544. str_siz = str.__size
  545. if pos >= str_siz
  546. raise StopIteration
  547. end
  548. match = @regex.__search(str, pos, nil)
  549. unless match
  550. @ofs = str_siz + 1
  551. raise StopIteration
  552. end
  553. nxt_pos = match.end(0)
  554. if match.begin(0) == nxt_pos
  555. nxt_pos += 1
  556. end
  557. @ofs = nxt_pos
  558. match.__at(0) # the matched substring
  559. end
  560. end # ]
  561. end
  562. Enumerable.__freeze_constants
  563. class Array
  564. # optimize accesses to enumerator classes
  565. ArrayCombinationEnumerator = Enumerable::ArrayCombinationEnumerator
  566. ArrayCycleEnumerator = Enumerable::ArrayCycleEnumerator
  567. ArrayEnumerator = Enumerable::ArrayEnumerator
  568. FirstEnumerator = Enumerable::FirstEnumerator
  569. ArrayIndexEnumerator = Enumerable::ArrayIndexEnumerator
  570. ArrayReverseEnumerator = Enumerable::ArrayReverseEnumerator
  571. ArrayWithIndexEnumerator = Enumerable::ArrayWithIndexEnumerator
  572. end
  573. Array.__freeze_constants
  574. class Dir
  575. DirEnumerator = Enumerable::DirEnumerator
  576. end
  577. Dir.__freeze_constants
  578. class Hash
  579. HashEnumerator = Enumerable::HashEnumerator
  580. HashKeyEnumerator = Enumerable::HashKeyEnumerator
  581. end
  582. Hash.__freeze_constants
  583. class Integer
  584. NumericEnumerator = Enumerable::NumericEnumerator
  585. NumericDownEnumerator = Enumerable::NumericDownEnumerator
  586. end
  587. Integer.__freeze_constants
  588. class Numeric
  589. NumericEnumerator = Enumerable::NumericEnumerator
  590. NumericDownEnumerator = Enumerable::NumericDownEnumerator
  591. end
  592. Numeric.__freeze_constants
  593. class Float
  594. NumericEnumerator = Enumerable::NumericEnumerator
  595. NumericDownEnumerator = Enumerable::NumericDownEnumerator
  596. end
  597. Float.__freeze_constants
  598. class IO
  599. IoEnumerator = Enumerable::IoEnumerator
  600. IoByteEnumerator = Enumerable::IoByteEnumerator
  601. IoCharEnumerator = Enumerable::IoCharEnumerator
  602. end
  603. IO.__freeze_constants
  604. class Range
  605. RangeEnumerator = Enumerable::RangeEnumerator
  606. end
  607. Range.__freeze_constants
  608. class String
  609. StringByteEnumerator = Enumerable::StringByteEnumerator
  610. StringCharEnumerator = Enumerable::StringCharEnumerator
  611. StringEachEnumerator = Enumerable::StringEachEnumerator
  612. ArrayEnumerator = Enumerable::ArrayEnumerator
  613. StringGsubEnumerator = Enumerable::StringGsubEnumerator
  614. end
  615. String.__freeze_constants