slice.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * @constructor
  3. * @param {Object} start
  4. * @param {Object=} stop
  5. * @param {Object=} step
  6. */
  7. Sk.builtin.slice = function slice (start, stop, step) {
  8. Sk.builtin.pyCheckArgs("slice", arguments, 1, 3, false, false);
  9. if ((step !== undefined) && Sk.misceval.isIndex(step) && (Sk.misceval.asIndex(step) === 0)) {
  10. throw new Sk.builtin.ValueError("slice step cannot be zero");
  11. }
  12. if (!(this instanceof Sk.builtin.slice)) {
  13. return new Sk.builtin.slice(start, stop, step);
  14. }
  15. if (stop === undefined && step === undefined) {
  16. stop = start;
  17. start = Sk.builtin.none.none$;
  18. }
  19. if (stop === undefined) {
  20. stop = Sk.builtin.none.none$;
  21. }
  22. if (step === undefined) {
  23. step = Sk.builtin.none.none$;
  24. }
  25. this.start = start;
  26. this.stop = stop;
  27. this.step = step;
  28. this.__class__ = Sk.builtin.slice;
  29. this["$d"] = new Sk.builtin.dict([Sk.builtin.slice$start, this.start,
  30. Sk.builtin.slice$stop, this.stop,
  31. Sk.builtin.slice$step, this.step]);
  32. return this;
  33. };
  34. Sk.abstr.setUpInheritance("slice", Sk.builtin.slice, Sk.builtin.object);
  35. Sk.builtin.slice.prototype["$r"] = function () {
  36. var a = Sk.builtin.repr(this.start).v;
  37. var b = Sk.builtin.repr(this.stop).v;
  38. var c = Sk.builtin.repr(this.step).v;
  39. return new Sk.builtin.str("slice(" + a + ", " + b + ", " + c + ")");
  40. };
  41. Sk.builtin.slice.prototype.tp$richcompare = function (w, op) {
  42. // w not a slice
  43. var t1, t2;
  44. if (!w.__class__ || w.__class__ != Sk.builtin.slice) {
  45. // shortcuts for eq/not
  46. if (op === "Eq") {
  47. return false;
  48. }
  49. if (op === "NotEq") {
  50. return true;
  51. }
  52. // todo; other types should have an arbitrary order
  53. return false;
  54. }
  55. // This is how CPython does it
  56. t1 = new Sk.builtin.tuple([this.start, this.stop, this.step]);
  57. t2 = new Sk.builtin.tuple([w.start, w.stop, w.step]);
  58. return t1.tp$richcompare(t2, op);
  59. };
  60. /* Internal indices function */
  61. Sk.builtin.slice.prototype.slice_indices_ = function (length) {
  62. var start, stop, step;
  63. if (Sk.builtin.checkNone(this.start)) {
  64. start = null;
  65. } else if (Sk.misceval.isIndex(this.start)) {
  66. start = Sk.misceval.asIndex(this.start);
  67. } else {
  68. throw new Sk.builtin.TypeError("slice indices must be integers or None");
  69. }
  70. if (Sk.builtin.checkNone(this.stop)) {
  71. stop = null;
  72. } else if (Sk.misceval.isIndex(this.stop)) {
  73. stop = Sk.misceval.asIndex(this.stop);
  74. } else {
  75. throw new Sk.builtin.TypeError("slice indices must be integers or None");
  76. }
  77. if (Sk.builtin.checkNone(this.step)) {
  78. step = null;
  79. } else if (Sk.misceval.isIndex(this.step)) {
  80. step = Sk.misceval.asIndex(this.step);
  81. } else {
  82. throw new Sk.builtin.TypeError("slice indices must be integers or None");
  83. }
  84. // this seems ugly, better way?
  85. if (step === null) {
  86. step = 1;
  87. }
  88. if (step > 0) {
  89. if (start === null) {
  90. start = 0;
  91. }
  92. if (stop === null) {
  93. stop = length;
  94. }
  95. if (stop > length) {
  96. stop = length;
  97. }
  98. if (start < 0) {
  99. start = length + start;
  100. if (start < 0) {
  101. start = 0;
  102. }
  103. }
  104. if (stop < 0) {
  105. stop = length + stop;
  106. }
  107. } else {
  108. if (start === null) {
  109. start = length - 1;
  110. }
  111. if (start >= length) {
  112. start = length - 1;
  113. }
  114. if (stop === null) {
  115. stop = -1;
  116. } else if (stop < 0) {
  117. stop = length + stop;
  118. if (stop < 0) {
  119. stop = -1;
  120. }
  121. }
  122. if (start < 0) {
  123. start = length + start;
  124. }
  125. }
  126. return [start, stop, step];
  127. };
  128. Sk.builtin.slice.prototype["indices"] = new Sk.builtin.func(function (self, length) {
  129. Sk.builtin.pyCheckArgs("indices", arguments, 2, 2, false, false);
  130. length = Sk.builtin.asnum$(length);
  131. var sss = self.slice_indices_(length);
  132. return new Sk.builtin.tuple([new Sk.builtin.int_(sss[0]),
  133. new Sk.builtin.int_(sss[1]),
  134. new Sk.builtin.int_(sss[2])]);
  135. });
  136. Sk.builtin.slice.prototype.sssiter$ = function (wrt, f) {
  137. var i;
  138. var wrtv = Sk.builtin.asnum$(wrt);
  139. var sss = this.slice_indices_(typeof wrtv === "number" ? wrtv : wrt.v.length);
  140. if (sss[2] > 0) {
  141. for (i = sss[0]; i < sss[1]; i += sss[2]) {
  142. if (f(i, wrtv) === false) {
  143. return;
  144. }
  145. } // wrt or wrtv? RNL
  146. } else {
  147. for (i = sss[0]; i > sss[1]; i += sss[2]) {
  148. if (f(i, wrtv) === false) {
  149. return;
  150. }
  151. } // wrt or wrtv? RNL
  152. }
  153. };
  154. Sk.builtin.slice$start = new Sk.builtin.str("start");
  155. Sk.builtin.slice$stop = new Sk.builtin.str("stop");
  156. Sk.builtin.slice$step = new Sk.builtin.str("step");