Plato on Github
Report Home
classlib/Collections/ArrayedCollection.js
Maintainability
118.05
Lines of code
946
Difficulty
105.01
Estimated Errors
10.60
Function weight
By Complexity
By SLOC
SCScript.install(function(sc) { "use strict"; require("./SequenceableCollection"); var $ = sc.lang.$; var random = sc.libs.random; var mathlib = sc.libs.mathlib; var $nil = $.nil; var $int0 = $.int0; var $int1 = $.int1; sc.lang.klass.refine("ArrayedCollection", function(builder, _) { builder.addMethod("valueOf", function() { return this._.map(function(elem) { return elem.valueOf(); }); }); builder.addMethod("__elem__", function(item) { return item || $nil; }); function throwIfImmutable($this) { if ($this.__immutable) { throw new Error("Attempted write to immutable object."); } } builder.addClassMethod("newClear", { args: "indexedSize=0" }, function($indexedSize) { var $obj; var array, indexedSize, i; $obj = this.new(); indexedSize = $indexedSize.__int__(); array = new Array(indexedSize); for (i = 0; i < indexedSize; ++i) { array[i] = $obj.__elem__(); } $obj._ = array; return $obj; }); // TODO: implements indexedSize builder.addMethod("size", function() { return $.Integer(this._.length); }); // TODO: implements maxSize builder.addMethod("swap", { args: "a; b" }, function($a, $b) { var raw = this._; var a, b, len, tmp; throwIfImmutable(this); a = $a.__int__(); b = $b.__int__(); len = raw.length; if (a < 0 || len <= a || b < 0 || len <= b) { throw new Error("out of index"); } tmp = raw[b]; raw[b] = raw[a]; raw[a] = tmp; return this; }); builder.addMethod("at", { args: "index" }, function($index) { var i; if (Array.isArray($index._)) { return $.Array($index._.map(function($index) { i = $index.__int__(); if (i < 0 || this._.length <= i) { return $nil; } return this._[i]; }, this)); } i = $index.__int__(); return this._[i] || $nil; }); builder.addMethod("clipAt", { args: "index" }, function($index) { var i; if (Array.isArray($index._)) { return $.Array($index._.map(function($index) { i = mathlib.clipIndex($index.__int__(), this._.length); return this._[i]; }, this)); } i = mathlib.clipIndex($index.__int__(), this._.length); return this._[i]; }); builder.addMethod("wrapAt", { args: "index" }, function($index) { var i; if (Array.isArray($index._)) { return $.Array($index._.map(function($index) { var i = mathlib.wrapIndex($index.__int__(), this._.length); return this._[i]; }, this)); } i = mathlib.wrapIndex($index.__int__(), this._.length); return this._[i]; }); builder.addMethod("foldAt", { args: "index" }, function($index) { var i; if (Array.isArray($index._)) { return $.Array($index._.map(function($index) { var i = mathlib.foldIndex($index.__int__(), this._.length); return this._[i]; }, this)); } i = mathlib.foldIndex($index.__int__(), this._.length); return this._[i]; }); builder.addMethod("put", { args: "index; item" }, function($index, $item) { var i; throwIfImmutable(this); if (Array.isArray($index._)) { $index._.forEach(function($index) { var i = $index.__int__(); if (i < 0 || this._.length <= i) { throw new Error("out of index"); } this._[i] = this.__elem__($item); }, this); } else { i = $index.__int__(); if (i < 0 || this._.length <= i) { throw new Error("out of index"); } this._[i] = this.__elem__($item); } return this; }); builder.addMethod("clipPut", { args: "index; item" }, function($index, $item) { throwIfImmutable(this); if (Array.isArray($index._)) { $index._.forEach(function($index) { this._[mathlib.clipIndex($index.__int__(), this._.length)] = this.__elem__($item); }, this); } else { this._[mathlib.clipIndex($index.__int__(), this._.length)] = this.__elem__($item); } return this; }); builder.addMethod("wrapPut", { args: "index; item" }, function($index, $item) { throwIfImmutable(this); if (Array.isArray($index._)) { $index._.forEach(function($index) { this._[mathlib.wrapIndex($index.__int__(), this._.length)] = this.__elem__($item); }, this); } else { this._[mathlib.wrapIndex($index.__int__(), this._.length)] = this.__elem__($item); } return this; }); builder.addMethod("foldPut", { args: "index; item" }, function($index, $item) { throwIfImmutable(this); if (Array.isArray($index._)) { $index._.forEach(function($index) { this._[mathlib.foldIndex($index.__int__(), this._.length)] = this.__elem__($item); }, this); } else { this._[mathlib.foldIndex($index.__int__(), this._.length)] = this.__elem__($item); } return this; }); builder.addMethod("removeAt", { args: "index" }, function($index) { var raw = this._; var index; throwIfImmutable(this); index = $index.__int__(); if (index < 0 || raw.length <= index) { throw new Error("out of index"); } return raw.splice(index, 1)[0]; }); builder.addMethod("takeAt", { args: "index" }, function($index) { var raw = this._; var index, ret, instead; throwIfImmutable(this); index = $index.__int__(); if (index < 0 || raw.length <= index) { throw new Error("out of index"); } ret = raw[index]; instead = raw.pop(); if (index !== raw.length) { raw[index] = instead; } return ret; }); builder.addMethod("indexOf", { args: "item" }, function($item) { var index = this._.indexOf($item); return index === -1 ? $nil : $.Integer(index); }); builder.addMethod("indexOfGreaterThan", { args: "val" }, function($val) { var raw = this._; var val, i, imax = raw.length; val = $val.__num__(); for (i = 0; i < imax; ++i) { if (raw[i].__num__() > val) { return $.Integer(i); } } return $nil; }); builder.addMethod("takeThese", { args: "func" }, function($func) { var raw = this._; var i = 0, $i; $i = $.Integer(i); while (i < raw.length) { if ($func.value(raw[i], $i).__bool__()) { this.takeAt($i); } else { $i = $.Integer(++i); } } return this; }); builder.addMethod("replace", { args: "find; replace" }, function($find, $replace) { var $index, $out, $array; throwIfImmutable(this); $out = $.Array(); $array = this; $find = $find.asArray(); $replace = $replace.asArray(); $.Func(function() { return ($index = $array.find($find)).notNil(); }).while($.Func(function() { $out = $out ["++"] ($array.keep($index)) ["++"] ($replace); $array = $array.drop($index ["+"] ($find.size())); return $array; })); return $out ["++"] ($array); }); builder.addMethod("slotSize", function() { return this.size(); }); builder.addMethod("slotAt", function($index) { return this.at($index); }); builder.addMethod("slotPut", function($index, $value) { return this.put($index, $value); }); builder.addMethod("slotKey", function($index) { return $index; }); builder.addMethod("slotIndex", function() { return $nil; }); builder.addMethod("getSlots", function() { return this.copy(); }); builder.addMethod("setSlots", function($array) { return this.overWrite($array); }); builder.addMethod("atModify", { args: "index; function" }, function($index, $function) { this.put($index, $function.value(this.at($index), $index)); return this; }); builder.addMethod("atInc", { args: "index; inc=1" }, function($index, $inc) { this.put($index, this.at($index).$("+", [ $inc ])); return this; }); builder.addMethod("atDec", { args: "index; dec=1" }, function($index, $dec) { this.put($index, this.at($index).$("-", [ $dec ])); return this; }); builder.addMethod("isArray", sc.TRUE); builder.addMethod("asArray"); builder.addMethod("copyRange", { args: "start; end" }, function($start, $end) { var start, end, instance, raw; if ($start === $nil) { start = 0; } else { start = $start.__int__(); } if ($end === $nil) { end = this._.length; } else { end = $end.__int__(); } raw = this._.slice(start, end + 1); instance = new this.__Spec([]); instance._ = raw; return instance; }); builder.addMethod("copySeries", { args: "first; second; last" }, function($first, $second, $last) { var i, first, second, last, step, instance, raw; raw = []; if ($first === $nil) { first = 0; } else { first = $first.__int__(); } if ($second === $nil) { second = first + 1; } else { second = $second.__int__(); } if ($last === $nil) { last = Infinity; } else { last = $last.__int__(); } last = Math.max(0, Math.min(last, this._.length - 1)); step = second - first; if (step > 0) { for (i = first; i <= last; i += step) { raw.push(this._[i]); } } else if (step < 0) { for (i = first; i >= last; i += step) { raw.push(this._[i]); } } instance = new this.__Spec([]); instance._ = raw; return instance; }); builder.addMethod("putSeries", { args: "first; second; last; value" }, function($first, $second, $last, $value) { var i, first, second, last, step; throwIfImmutable(this); if ($first === $nil) { first = 0; } else { first = $first.__int__(); } if ($second === $nil) { second = first + 1; } else { second = $second.__int__(); } if ($last === $nil) { last = Infinity; } else { last = $last.__int__(); } last = Math.max(0, Math.min(last, this._.length - 1)); step = second - first; $value = this.__elem__($value); if (step > 0) { for (i = first; i <= last; i += step) { this._[i] = $value; } } else if (step < 0) { for (i = first; i >= last; i += step) { this._[i] = $value; } } return this; }); builder.addMethod("add", { args: "item" }, function($item) { throwIfImmutable(this); this._.push(this.__elem__($item)); return this; }); builder.addMethod("addAll", { args: "aCollection" }, function($aCollection) { var $this = this; throwIfImmutable(this); if ($aCollection.isCollection().__bool__()) { $aCollection.do($.Func(function($item) { return $this._.push($this.__elem__($item)); })); } else { this.add($aCollection); } return this; }); builder.addMethod("putEach", { args: "keys; values" }, function($keys, $values) { var keys, values, i, imax; throwIfImmutable(this); $keys = $keys.asArray(); $values = $values.asArray(); keys = $keys._; values = $values._; for (i = 0, imax = keys.length; i < imax; ++i) { this.put(keys[i], this.__elem__(values[i % values.length])); } return this; }); builder.addMethod("extend", { args: "size; item" }, function($size, $item) { var instance, raw, size, i; raw = this._.slice(); size = $size.__int__(); if (raw.length > size) { raw.splice(size); } else if (raw.length < size) { for (i = size - raw.length; i--; ) { raw.push(this.__elem__($item)); } } instance = new this.__Spec([]); instance._ = raw; return instance; }); builder.addMethod("insert", { args: "index; item" }, function($index, $item) { var index; throwIfImmutable(this); index = Math.max(0, $index.__int__()); this._.splice(index, 0, this.__elem__($item)); return this; }); builder.addMethod("move", function($fromIndex, $toIndex) { return this.insert($toIndex, this.removeAt($fromIndex)); }); builder.addMethod("addFirst", { args: "item" }, function($item) { var instance, raw; raw = this._.slice(); raw.unshift(this.__elem__($item)); instance = new this.__Spec([]); instance._ = raw; return instance; }); builder.addMethod("addIfNotNil", { args: "item" }, function($item) { if ($item === $nil) { return this; } return this.addFirst(this.__elem__($item)); }); builder.addMethod("pop", function() { if (this._.length === 0) { return $nil; } throwIfImmutable(this); return this._.pop(); }); builder.addMethod("++", function($anArray) { var instance, raw; raw = this._.slice(); instance = new this.__Spec([]); instance._ = raw; if ($anArray !== $nil) { instance.addAll($anArray); } return instance; }); // TODO: implements overWrite // TODO: implements grow // TODO: implements growClear builder.addMethod("seriesFill", { args: "start; step" }, function($start, $step) { var i, imax; for (i = 0, imax = this._.length; i < imax; ++i) { this.put($.Integer(i), $start); $start = $start.$("+", [ $step ]); } return this; }); builder.addMethod("fill", { args: "value" }, function($value) { var raw, i, imax; throwIfImmutable(this); $value = this.__elem__($value); raw = this._; for (i = 0, imax = raw.length; i < imax; ++i) { raw[i] = $value; } return this; }); builder.addMethod("do", function($function) { sc.lang.iterator.execute( sc.lang.iterator.array$do(this), $function ); return this; }); builder.addMethod("reverseDo", function($function) { sc.lang.iterator.execute( sc.lang.iterator.array$reverseDo(this), $function ); return this; }); builder.addMethod("reverse", function() { var $res = this.copy(); $res._.reverse(); return $res; }); builder.addMethod("windex", function() { var raw = this._; var x, r, i, imax; // <-- _ArrayWindex --> x = 0; r = random.next(); for (i = 0, imax = raw.length; i < imax; ++i) { x += raw[i].__num__(); if (x >= r) { return $.Integer(i); } } return $int0; }); builder.addMethod("normalizeSum", function() { return this ["*"] (this.sum().reciprocal()); }); builder.addMethod("normalize", { args: "min=0.0; max=1.0" }, function($min, $max) { var $minItem, $maxItem; $minItem = this.minItem(); $maxItem = this.maxItem(); return this.collect($.Func(function($el) { return $el.$("linlin", [ $minItem, $maxItem, $min, $max ]); })); }); // TODO: implements asciiPlot // TODO: implements perfectShuffle // TODO: implements performInPlace builder.addMethod("clipExtend", { args: "length" }, function($length) { var last = this._[this._.length - 1] || $nil; return this.extend($length, last); }); builder.addMethod("rank", function() { return $int1 ["+"] (this.first().rank()); }); builder.addMethod("shape", function() { return $.Array([ this.size() ]) ["++"] (this.at($int0).$("shape")); }); builder.addMethod("reshape", function() { var $result; var shape, size, i, imax; shape = _.toArray(arguments); size = 1; for (i = 0, imax = shape.length; i < imax; ++i) { size *= shape[i].__int__(); } $result = this.flat().wrapExtend($.Integer(size)); for (i = imax - 1; i >= 1; --i) { $result = $result.clump(shape[i]); } return $result; }); builder.addMethod("reshapeLike", { args: "another; indexing=\\wrapAt" }, function($another, $indexing) { var $index, $flat; $index = $int0; $flat = this.flat(); return $another.deepCollect($.Integer(0x7FFFFFFF), $.Func(function() { var $item = $flat.perform($indexing, $index); $index = $index.__inc__(); return $item; })); }); // TODO: implements deepCollect // TODO: implements deepDo builder.addMethod("unbubble", { args: "depth=0; levels=1" }, function($depth, $levels) { if ($depth.__num__() <= 0) { if (this.size().__int__() > 1) { return this; } if ($levels.__int__() <= 1) { return this.at($int0); } return this.at($int0).unbubble($depth, $levels.__dec__()); } return this.collect($.Func(function($item) { return $item.unbubble($depth.__dec__()); })); }); builder.addMethod("bubble", { args: "depth=0; levels=1" }, function($depth, $levels) { if ($depth.__int__() <= 0) { if ($levels.__int__() <= 1) { return $.Array([ this ]); } return $.Array([ this.bubble($depth, $levels.__dec__()) ]); } return this.collect($.Func(function($item) { return $item.bubble($depth.__dec__(), $levels); })); }); builder.addMethod("slice", { args: "*cuts" }, function($$cuts) { var $firstCut, $list; var lenOfCuts, cuts; lenOfCuts = $$cuts.size().__int__(); if (lenOfCuts === 0) { return this.copy(); } $firstCut = $$cuts.at($int0); if ($firstCut === $nil) { $list = this.copy(); } else { $list = this.at($firstCut.asArray()); } if (lenOfCuts === 1) { return $list.unbubble(); } cuts = $$cuts._.slice(1); return $list.collect($.Func(function($item) { return $item.$("slice", cuts); })).unbubble(); }); builder.addClassMethod("iota", function() { var $a; var args, product, i, imax, a; args = arguments; product = 1; for (i = 0, imax = args.length; i < imax; ++i) { product *= args[i].__int__(); } a = new Array(product); for (i = 0; i < product; ++i) { a[i] = $.Integer(i); } $a = $.Array(a); return $a.reshape.apply($a, args); }); // TODO: implements asRandomTable // TODO: implements tableRand // TODO: implements msgSize // TODO: implements bundleSize // TODO: implements clumpBundles builder.addMethod("includes", function($item) { return $.Boolean(this._.indexOf($item) !== -1); }); builder.addMethod("asString", function() { return $.String("[ " + this._.map(function($elem) { return $elem.asString().__str__(); }).join(", ") + " ]"); }); /* istanbul ignore next */ builder.addMethod("__sort__", function($function) { throwIfImmutable(this); this._.sort(function($a, $b) { return $function.value($a, $b).__bool__() ? -1 : 1; }); }); }); sc.lang.klass.refine("RawArray", function(builder) { var SCArray = $("Array"); builder.addMethod("archiveAsCompileString", sc.TRUE); builder.addMethod("archiveAsObject", sc.TRUE); builder.addMethod("rate", function() { return $.Symbol("scalar"); }); // TODO: implements readFromStream builder.addMethod("powerset", function() { return this.as(SCArray).powerset(); }); }); sc.lang.klass.define("Int8Array : RawArray", function(builder) { var int8 = new Int8Array(1); builder.addMethod("valueOf", function() { return new Int8Array(this._.map(function($elem) { return $elem.__int__(); })); }); builder.addMethod("__elem__", function(item) { int8[0] = item ? item.__int__() : 0; return $.Integer(int8[0]); }); }); sc.lang.klass.define("Int16Array : RawArray", function(builder) { var int16 = new Int16Array(1); builder.addMethod("valueOf", function() { return new Int16Array(this._.map(function($elem) { return $elem.__int__(); })); }); builder.addMethod("__elem__", function(item) { int16[0] = item ? item.__int__() : 0; return $.Integer(int16[0]); }); }); sc.lang.klass.define("Int32Array : RawArray", function(builder) { var int32 = new Int32Array(1); builder.addMethod("valueOf", function() { return new Int32Array(this._.map(function($elem) { return $elem.__int__(); })); }); builder.addMethod("__elem__", function(item) { int32[0] = item ? item.__int__() : 0; return $.Integer(int32[0]); }); }); sc.lang.klass.define("FloatArray : RawArray", function(builder) { var float32 = new Float32Array(1); builder.addMethod("valueOf", function() { return new Float32Array(this._.map(function($elem) { return $elem.__num__(); })); }); builder.addMethod("__elem__", function(item) { float32[0] = item ? item.__num__() : 0; return $.Float(float32[0]); }); }); sc.lang.klass.define("DoubleArray : RawArray", function(builder) { var float64 = new Float64Array(1); builder.addMethod("valueOf", function() { return new Float64Array(this._.map(function($elem) { return $elem.__num__(); })); }); builder.addMethod("__elem__", function(item) { float64[0] = item ? item.__num__() : 0; return $.Float(float64[0]); }); }); });