From 6f925611ca5fb4e5ecd0980b8597739f5ae29016 Mon Sep 17 00:00:00 2001 From: mohayonao Date: Thu, 1 May 2014 16:34:39 +0900 Subject: [PATCH] improve default arguments in functions - fix delimiter for sc.lang.fn , -> ; - fix default value format - fix codegen - build v0.0.18 --- build/scscript.js | 19133 ++++++++-------- package.json | 2 +- src/sc/lang/classlib/Collections/Array.js | 91 +- .../classlib/Collections/ArrayedCollection.js | 216 +- .../lang/classlib/Collections/Collection.js | 242 +- .../Collections/SequenceableCollection.js | 221 +- src/sc/lang/classlib/Collections/String.js | 19 +- src/sc/lang/classlib/Core/AbstractFunction.js | 97 +- src/sc/lang/classlib/Core/Boolean.js | 26 +- src/sc/lang/classlib/Core/Function.js | 16 +- src/sc/lang/classlib/Core/Nil.js | 51 +- src/sc/lang/classlib/Core/Object.js | 132 +- src/sc/lang/classlib/Core/Ref.js | 10 +- src/sc/lang/classlib/Math/Float.js | 32 +- src/sc/lang/classlib/Math/Integer.js | 82 +- src/sc/lang/classlib/Math/Magnitude.js | 31 +- src/sc/lang/classlib/Math/Number.js | 14 +- src/sc/lang/classlib/Math/SimpleNumber.js | 147 +- src/sc/lang/codegen.js | 23 +- src/sc/lang/compiler_test.js | 225 +- src/sc/lang/fn.js | 91 +- src/sc/lang/fn_test.js | 80 +- src/sc/lang/iterator.js | 20 +- src/sc/lang/klass-utils.js | 15 - src/sc/lang/klass-utils_test.js | 40 - src/sc/lang/parser.js | 97 +- 26 files changed, 10375 insertions(+), 10778 deletions(-) diff --git a/build/scscript.js b/build/scscript.js index b40d76f..6fc04b2 100644 --- a/build/scscript.js +++ b/build/scscript.js @@ -1,7 +1,7 @@ (function(global) { "use strict"; -var sc = { VERSION: "0.0.17" }; +var sc = { VERSION: "0.0.18" }; // src/sc/sc.js (function(sc) { @@ -456,12514 +456,12180 @@ var sc = { VERSION: "0.0.17" }; })(sc); -// src/sc/lang/dollarSC.js +// src/sc/lang/compiler.js (function(sc) { - var $SC = function(name) { - return sc.lang.klass.get(name); - }; + var compiler = {}; - /* istanbul ignore next */ - var shouldBeImplementedInClassLib = function() {}; + compiler.Token = { + CharLiteral: "Char", + EOF: "", + FalseLiteral: "False", + FloatLiteral: "Float", + Identifier: "Identifier", + IntegerLiteral: "Integer", + Keyword: "Keyword", + Label: "Label", + NilLiteral: "Nil", + Punctuator: "Punctuator", + StringLiteral: "String", + SymbolLiteral: "Symbol", + TrueLiteral: "True" + }; - $SC.Class = shouldBeImplementedInClassLib; - $SC.Integer = shouldBeImplementedInClassLib; - $SC.Float = shouldBeImplementedInClassLib; - $SC.Char = shouldBeImplementedInClassLib; - $SC.Array = shouldBeImplementedInClassLib; - $SC.String = shouldBeImplementedInClassLib; - $SC.Function = shouldBeImplementedInClassLib; - $SC.Ref = shouldBeImplementedInClassLib; - $SC.Symbol = shouldBeImplementedInClassLib; - $SC.Boolean = shouldBeImplementedInClassLib; - $SC.True = shouldBeImplementedInClassLib; - $SC.False = shouldBeImplementedInClassLib; - $SC.Nil = shouldBeImplementedInClassLib; + compiler.Syntax = { + AssignmentExpression: "AssignmentExpression", + BinaryExpression: "BinaryExpression", + BlockExpression: "BlockExpression", + CallExpression: "CallExpression", + FunctionExpression: "FunctionExpression", + GlobalExpression: "GlobalExpression", + Identifier: "Identifier", + ListExpression: "ListExpression", + Label: "Label", + Literal: "Literal", + ObjectExpression: "ObjectExpression", + Program: "Program", + ThisExpression: "ThisExpression", + UnaryExpression: "UnaryExpression", + VariableDeclaration: "VariableDeclaration", + VariableDeclarator: "VariableDeclarator" + }; - sc.lang.$SC = $SC; + var Message = compiler.Message = { + ArgumentAlreadyDeclared: "argument '%0' already declared", + InvalidLHSInAssignment: "invalid left-hand side in assignment", + NotImplemented: "not implemented %0", + UnexpectedEOS: "unexpected end of input", + UnexpectedIdentifier: "unexpected identifier", + UnexpectedChar: "unexpected char", + UnexpectedLabel: "unexpected label", + UnexpectedNumber: "unexpected number", + UnexpectedString: "unexpected string", + UnexpectedSymbol: "unexpected symbol", + UnexpectedToken: "unexpected token %0", + VariableAlreadyDeclared: "variable '%0' already declared", + VariableNotDefined: "variable '%0' not defined" + }; -})(sc); + compiler.Keywords = { + var: "keyword", + arg: "keyword", + const: "keyword", + this: "function", + thisThread: "function", + thisProcess: "function", + thisFunction: "function", + thisFunctionDef: "function", + }; -// src/sc/lang/fn.js -(function(sc) { + var Scope = (function() { + function Scope(methods) { + var f = function(parent) { + this.parent = parent; + this.stack = []; + }; - var slice = [].slice; - var $SC = sc.lang.$SC; + function F() {} + F.prototype = Scope; + f.prototype = new F(); - var fn = function(func, def) { - var argNames, remain, wrapper; + Object.keys(methods).forEach(function(key) { + f.prototype[key] = methods[key]; + }); - argNames = def.split(/\s*,\s*/); - if (argNames[argNames.length - 1].charAt(0) === "*") { - remain = !!argNames.pop(); + return f; } - wrapper = function() { - var given, args; - var i, imax; - - given = slice.call(arguments); - args = new Array(argNames.length); + Scope.add = function(type, id, scope) { + var peek = this.stack[this.stack.length - 1]; + var vars, args, declared, stmt, indent; - if (isDictionary(given[given.length - 1])) { - setKeywordArguments(args, argNames, given.pop()); + if (scope) { + vars = scope.vars; + args = scope.args; + declared = scope.declared; + stmt = scope.stmt; + indent = scope.indent; + } else { + vars = peek.vars; + args = peek.args; + declared = peek.declared; + stmt = peek.stmt; + indent = peek.indent; } - for (i = 0, imax = Math.min(argNames.length, given.length); i < imax; ++i) { - args[i] = given[i]; + if (args[id]) { + this.parent.throwError({}, Message.ArgumentAlreadyDeclared, id); } - if (remain) { - args.push($SC.Array(given.slice(argNames.length))); + if (vars[id] && id.charAt(0) !== "_") { + this.parent.throwError({}, Message.VariableAlreadyDeclared, id); } - return func.apply(this, args); + switch (type) { + case "var": + if (!vars[id]) { + this.add_delegate(stmt, id, indent, peek, scope); + vars[id] = true; + delete declared[id]; + } + break; + case "arg": + args[id] = true; + delete declared[id]; + break; + } }; - return wrapper; - }; + Scope.add_delegate = function() { + }; - var isDictionary = function(obj) { - return !!(obj && obj.constructor === Object); - }; + Scope.end = function() { + this.stack.pop(); + }; - var setKeywordArguments = function(args, argNames, dict) { - var keys, name, index; - var i, imax; + Scope.getDeclaredVariable = function() { + var peek = this.stack[this.stack.length - 1]; + var declared = {}; - keys = Object.keys(dict); - for (i = 0, imax = keys.length; i < imax; ++i) { - name = keys[i]; - index = argNames.indexOf(name); - if (index !== -1) { - args[index] = dict[name]; + if (peek) { + Array.prototype.concat.apply([], [ + peek.declared, peek.args, peek.vars + ].map(Object.keys)).forEach(function(key) { + declared[key] = true; + }); } - } - }; - - sc.lang.fn = fn; -})(sc); + return declared; + }; -// src/sc/lang/klass.js -(function(sc) { + Scope.find = function(id) { + var peek = this.stack[this.stack.length - 1]; + return peek.vars[id] || peek.args[id] || peek.declared[id]; + }; - var slice = [].slice; - var $SC = sc.lang.$SC; + Scope.peek = function() { + return this.stack[this.stack.length - 1]; + }; - var klass = {}; - var metaClasses = {}; - var classes = klass.classes = {}; + return Scope; + })(); - var createClassInstance = function(MetaSpec) { - var instance = new SCClass(); - instance._MetaSpec = MetaSpec; - return instance; - }; + compiler.Scope = Scope; - var extend = function(constructor, superMetaClass) { - function F() {} - F.prototype = superMetaClass._Spec.prototype; - constructor.prototype = new F(); + sc.lang.compiler = compiler; - function Meta_F() {} - Meta_F.prototype = superMetaClass._MetaSpec.prototype; + var SCScript = sc.SCScript; - function MetaSpec() {} - MetaSpec.prototype = new Meta_F(); + SCScript.tokenize = function(source, opts) { + opts = opts || /* istanbul ignore next */ {}; + opts.tokens = true; + return sc.lang.parser.parse(source, opts).tokens || /* istanbul ignore next */ []; + }; - constructor.metaClass = createClassInstance(MetaSpec); + SCScript.parse = function(source, opts) { + return sc.lang.parser.parse(source, opts); }; - var def = function(className, constructor, fn, opts) { - var classMethods, instanceMethods, setMethod, spec; + SCScript.compile = function(source, opts) { + var ast = SCScript.parse(source, opts); + return sc.lang.codegen.compile(ast, opts); + }; - classMethods = constructor.metaClass._MetaSpec.prototype; - instanceMethods = constructor.prototype; +})(sc); - setMethod = function(methods, methodName, func) { - var bond; - if (methods.hasOwnProperty(methodName) && !opts.force) { - bond = methods === classMethods ? "." : "#"; - throw new Error( - "sc.lang.klass.refine: " + - className + bond + methodName + " is already defined." - ); - } - methods[methodName] = func; - }; +// src/sc/lang/parser.js +(function(sc) { - if (typeof fn === "function") { - fn(spec = {}, klass.utils); - } else { - spec = fn; - } + var parser = {}; - Object.keys(spec).forEach(function(methodName) { - if (methodName.charCodeAt(0) === 0x24) { // u+0024 is '$' - setMethod(classMethods, methodName.substr(1), spec[methodName]); - } else { - setMethod(instanceMethods, methodName, spec[methodName]); - } - }); - }; + var Token = sc.lang.compiler.Token; + var Syntax = sc.lang.compiler.Syntax; + var Message = sc.lang.compiler.Message; + var Keywords = sc.lang.compiler.Keywords; - var throwIfInvalidArgument = function(constructor, className) { - if (typeof constructor !== "function") { - throw new Error( - "sc.lang.klass.define: " + - "first argument must be a constructor, but got: " + typeof(constructor) - ); - } + var binaryPrecedenceDefaults = { + "?" : 1, + "??" : 1, + "!?" : 1, + "->" : 2, + "||" : 3, + "&&" : 4, + "|" : 5, + "&" : 6, + "==" : 7, + "!=" : 7, + "===": 7, + "!==": 7, + "<" : 8, + ">" : 8, + "<=" : 8, + ">=" : 8, + "<<" : 9, + ">>" : 9, + "+>>": 9, + "+" : 10, + "-" : 10, + "*" : 11, + "/" : 11, + "%" : 11, + "!" : 12, + }; - if (typeof className !== "string") { - throw new Error( - "sc.lang.klass.define: " + - "second argument must be a string, but got: " + String(className) - ); + function char2num(ch) { + var n = ch.charCodeAt(0); + + if (48 <= n && n <= 57) { + return n - 48; } - }; + if (65 <= n && n <= 90) { + return n - 55; + } + return n - 87; // if (97 <= n && n <= 122) + } - var throwIfInvalidClassName = function(className, superClassName) { - var ch0 = className.charCodeAt(0); + function isNumber(ch) { + return "0" <= ch && ch <= "9"; + } - if (ch0 < 0x41 || 0x5a < ch0) { // faster test than !/^[A-Z]/.test(className) - throw new Error( - "sc.lang.klass.define: " + - "classname should be CamelCase, but got '" + className + "'" - ); + var Scope = sc.lang.compiler.Scope({ + begin: function() { + var declared = this.getDeclaredVariable(); + + this.stack.push({ + vars: {}, + args: {}, + declared: declared + }); } + }); - if (metaClasses.hasOwnProperty(className)) { - throw new Error( - "sc.lang.klass.define: " + - "class '" + className + "' is already registered." - ); + function LocationMarker(parser) { + this.parser = parser; + this.marker = [ + parser.index, + parser.lineNumber, + parser.index - parser.lineStart + ]; + } + + LocationMarker.prototype.apply = function(node) { + var parser = this.parser; + var marker = this.marker; + + /* istanbul ignore else */ + if (this.parser.opts.range) { + node.range = [ marker[0], parser.index ]; + } + /* istanbul ignore else */ + if (this.parser.opts.loc) { + node.loc = { + start: { + line: marker[1], + column: marker[2] + }, + end: { + line: parser.lineNumber, + column: parser.index - parser.lineStart + } + }; } + }; - if (className !== "Object") { - if (!metaClasses.hasOwnProperty(superClassName)) { - throw new Error( - "sc.lang.klass.define: " + - "superclass '" + superClassName + "' is not registered." - ); + function SCParser(source, opts) { + /* istanbul ignore next */ + if (typeof source !== "string") { + if (typeof source === "undefined") { + source = ""; } + source = String(source); } + source = source.replace(/\r\n?/g, "\n"); + this.source = source; + this.opts = opts; + this.length = source.length; + this.index = 0; + this.lineNumber = this.length ? 1 : 0; + this.lineStart = 0; + this.reverted = null; + this.scope = new Scope(this); + this.marker = []; + this.tokens = opts.tokens ? [] : null; + this.errors = opts.tolerant ? [] : null; + this.state = { + closedFunction: false, + disallowGenerator: false, + innerElements: false, + immutableList: false, + underscore: [] + }; + } + + SCParser.prototype.parse = function() { + return this.parseProgram(); }; - var buildClass = function(className, constructor) { - var newClass, metaClass; + SCParser.prototype.skipComment = function() { + var source = this.source; + var length = this.length; + var index = this.index; + var ch; - metaClass = constructor.metaClass; + LOOP: while (index < length) { + ch = source.charAt(index); - newClass = new metaClass._MetaSpec(); - newClass._name = className; - newClass._Spec = constructor; - constructor.prototype.__class = newClass; - constructor.prototype.__Spec = constructor; + if (ch === " " || ch === "\t") { + index += 1; + continue; + } - metaClass._Spec = constructor; - metaClass._isMetaClass = true; - metaClass._name = "Meta_" + className; + if (ch === "\n") { + index += 1; + this.lineNumber += 1; + this.lineStart = index; + continue; + } - classes["Meta_" + className] = metaClass; - classes[className] = newClass; + if (ch === "/") { + ch = source.charAt(index + 1); + if (ch === "/") { + index = this.skipLineComment(index + 2); + continue; + } + if (ch === "*") { + index = this.skipBlockComment(index + 2); + continue; + } + } - if (newClass.initClass) { - newClass.initClass(); + break; } - metaClasses[className] = metaClass; + this.index = index; }; - klass.define = function(constructor, className, fn) { - var items, superClassName; + SCParser.prototype.skipLineComment = function(index) { + var source = this.source; + var length = this.length; + var ch; - throwIfInvalidArgument(constructor, className); + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === "\n") { + this.lineNumber += 1; + this.lineStart = index; + break; + } + } - items = className.split(":"); - className = items[0].trim(); - superClassName = (items[1] || "Object").trim(); + return index; + }; - throwIfInvalidClassName(className, superClassName); + SCParser.prototype.skipBlockComment = function(index) { + var source = this.source; + var length = this.length; + var ch, depth; - if (className !== "Object") { - extend(constructor, metaClasses[superClassName]); - } + depth = 1; + while (index < length) { + ch = source.charAt(index); - fn = fn || {}; + if (ch === "\n") { + this.lineNumber += 1; + this.lineStart = index; + } else { + ch = ch + source.charAt(index + 1); + if (ch === "/*") { + depth += 1; + index += 1; + } else if (ch === "*/") { + depth -= 1; + index += 1; + if (depth === 0) { + return index + 1; + } + } + } - def(className, constructor, fn, {}); + index += 1; + } + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); - buildClass(className, constructor); + return index; }; - klass.refine = function(className, fn, opts) { - var constructor; + SCParser.prototype.collectToken = function() { + var loc, token, source, t; - if (!metaClasses.hasOwnProperty(className)) { - throw new Error( - "sc.lang.klass.refine: " + - "class '" + className + "' is not registered." - ); - } + this.skipComment(); - constructor = metaClasses[className]._Spec; + loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; - def(className, constructor, fn, opts || {}); - }; + token = this.advance(); - klass.get = function(name) { - if (!classes[name]) { - throw new Error( - "sc.lang.klass.get: " + - "class '" + name + "' is not registered." - ); + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + + if (token.type !== Token.EOF) { + source = this.source; + t = { + type: token.type, + value: source.slice(token.range[0], token.range[1]) + }; + if (this.opts.range) { + t.range = [ token.range[0], token.range[1] ]; + } + if (this.opts.loc) { + t.loc = loc; + } + this.tokens.push(t); } - return classes[name]; - }; - klass.exists = function(name) { - return !!classes[name]; + return token; }; - // basic classes - function SCObject() { - this._ = this; - } - - function SCClass() { - this._ = this; - this._name = "Class"; - this._Spec = null; - this._isMetaClass = false; - } - - SCObject.metaClass = createClassInstance(function() {}); - klass.define(SCObject, "Object", { - __tag: 1, - __initializeWith__: function(className, args) { - metaClasses[className]._Spec.apply(this, args); - }, - $initClass: function() {} - }); + SCParser.prototype.advance = function() { + var ch, token; - klass.define(SCClass, "Class"); + this.skipComment(); - SCObject.metaClass._MetaSpec.prototype = classes.Class = createClassInstance(); - classes.Class._Spec = SCClass; - classes.Object = new SCObject.metaClass._MetaSpec(); - classes.Object._name = "Object"; - classes.Object._Spec = SCObject.metaClass._Spec; - classes.Object._Spec.prototype.__class = classes.Object; - classes.Object._Spec.prototype.__Spec = classes.Object._Spec; + if (this.length <= this.index) { + return this.EOFToken(); + } - klass.refine("Object", function(spec) { - spec.$new = function() { - if (this._Spec === SCClass) { - return $SC.Nil(); - } - return new this._Spec(slice.call(arguments)); - }; + ch = this.source.charAt(this.index); - spec.class = function() { - return this.__class; - }; + // Symbol literal starts with back slash + if (ch === "\\") { + return this.scanSymbolLiteral(); + } - spec.isClass = function() { - return $SC.False(); - }; + // Char literal starts with dollar + if (ch === "$") { + return this.scanCharLiteral(); + } - spec.isKindOf = function($aClass) { - return $SC.Boolean(this instanceof $aClass._Spec); - }; + // String literal starts with single quote or double quote + if (ch === "'" || ch === "\"") { + return this.scanStringLiteral(); + } - spec.isMemberOf = function($aClass) { - return $SC.Boolean(this.__class === $aClass); - }; + // for partial application + if (ch === "_") { + return this.scanUnderscore(); + } - spec.toString = function() { - var name = this.__class._name; - if (/^[AEIOU]/.test(name)) { - return String("an " + name); - } else { - return String("a " + name); + if (ch === "-") { + token = this.scanNegativeNumericLiteral(); + if (token) { + return token; } - }; + } - spec.valueOf = function() { - return this._; - }; - }); + // Identifier starts with alphabet + if (("A" <= ch && ch <= "Z") || ("a" <= ch && ch <= "z")) { + return this.scanIdentifier(); + } - klass.refine("Class", function(spec) { - spec.name = function() { - return $SC.String(this._name); - }; + // Number literal starts with number + if (isNumber(ch)) { + return this.scanNumericLiteral(); + } - spec.class = function() { - if (this._isMetaClass) { - return classes.Class; - } - return $SC("Meta_" + this._name); - }; + return this.scanPunctuator(); + }; - spec.isClass = function() { - return $SC.True(); - }; + SCParser.prototype.expect = function(value) { + var token = this.lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + this.throwUnexpected(token, value); + } + }; - spec.toString = function() { - return String(this._name); - }; - }); + SCParser.prototype.peek = function() { + var index, lineNumber, lineStart; - sc.lang.klass = klass; + index = this.index; + lineNumber = this.lineNumber; + lineStart = this.lineStart; -})(sc); + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } -// src/sc/lang/klass-constructors.js -(function(sc) { + this.index = index; + this.lineNumber = lineNumber; + this.lineStart = lineStart; + }; - var $SC = sc.lang.$SC; - var klass = sc.lang.klass; + SCParser.prototype.lex = function(saved) { + var that = this; + var token = this.lookahead; - function SCNil() { - this.__initializeWith__("Object"); - this._ = null; - } - klass.define(SCNil, "Nil", { - __tag: 773 - }); + if (saved) { + saved = [ this.lookahead, this.index, this.lineNumber, this.lineStart ]; + } - function SCSymbol() { - this.__initializeWith__("Object"); - this._ = ""; - } - klass.define(SCSymbol, "Symbol", { - __tag: 1027 - }); + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; - function SCBoolean() { - this.__initializeWith__("Object"); - } - klass.define(SCBoolean, "Boolean"); + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } - function SCTrue() { - this.__initializeWith__("Boolean"); - this._ = true; - } - klass.define(SCTrue, "True : Boolean", { - __tag: 775 - }); + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; - function SCFalse() { - this.__initializeWith__("Boolean"); - this._ = false; - } - klass.define(SCFalse, "False : Boolean", { - __tag: 774 - }); + if (saved) { + token.restore = function() { + that.lookahead = saved[0]; + that.index = saved[1]; + that.lineNumber = saved[2]; + that.lineStart = saved[3]; + if (that.tokens) { + that.tokens.pop(); + } + }; + } - function SCMagnitude() { - this.__initializeWith__("Object"); - } - klass.define(SCMagnitude, "Magnitude"); + return token; + }; - function SCChar() { - this.__initializeWith__("Magnitude"); - this._ = "\0"; - } - klass.define(SCChar, "Char : Magnitude", { - __tag: 1028 - }); + SCParser.prototype.EOFToken = function() { + return { + type: Token.EOF, + value: "", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ this.index, this.index ] + }; + }; - function SCNumber() { - this.__initializeWith__("Magnitude"); - } - klass.define(SCNumber, "Number : Magnitude"); + SCParser.prototype.scanCharLiteral = function() { + var start, value; - function SCSimpleNumber() { - this.__initializeWith__("Number"); - } - klass.define(SCSimpleNumber, "SimpleNumber : Number"); + start = this.index; + value = this.source.charAt(this.index + 1); - function SCInteger() { - this.__initializeWith__("SimpleNumber"); - this._ = 0; - } - klass.define(SCInteger, "Integer : SimpleNumber", { - __tag: 770 - }); + this.index += 2; - function SCFloat() { - this.__initializeWith__("SimpleNumber"); - this._ = 0.0; - } - klass.define(SCFloat, "Float : SimpleNumber", { - __tag: 777 - }); + return { + type : Token.CharLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; - function SCCollection() { - this.__initializeWith__("Object"); - } - klass.define(SCCollection, "Collection"); + SCParser.prototype.scanIdentifier = function() { + var source = this.source.slice(this.index); + var start = this.index; + var value, type; - function SCSequenceableCollection() { - this.__initializeWith__("Collection"); - } - klass.define(SCSequenceableCollection, "SequenceableCollection : Collection"); + value = /^[a-zA-Z][a-zA-Z0-9_]*/.exec(source)[0]; - function SCArrayedCollection() { - this.__initializeWith__("SequenceableCollection"); - this._immutable = false; - this._ = []; - } - klass.define(SCArrayedCollection, "ArrayedCollection : SequenceableCollection"); + this.index += value.length; - function SCRawArray() { - this.__initializeWith__("ArrayedCollection"); - } - klass.define(SCRawArray, "RawArray : ArrayedCollection"); + if (this.source.charAt(this.index) === ":") { + this.index += 1; + return { + type: Token.Label, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + } else if (this.isKeyword(value)) { + type = Token.Keyword; + } else { + switch (value) { + case "inf": + type = Token.FloatLiteral; + value = "Infinity"; + break; + case "pi": + type = Token.FloatLiteral; + value = String(Math.PI); + break; + case "nil": + type = Token.NilLiteral; + value = "null"; + break; + case "true": + type = Token.TrueLiteral; + break; + case "false": + type = Token.FalseLiteral; + break; + default: + type = Token.Identifier; + break; + } + } - function SCArray() { - this.__initializeWith__("ArrayedCollection"); - } - klass.define(SCArray, "Array : ArrayedCollection", { - __tag: 11 - }); + return { + type: type, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + }; - function SCString(value) { - this.__initializeWith__("RawArray"); - this._ = value; - } - klass.define(SCString, "String : RawArray", { - __tag: 1034 - }); + SCParser.prototype.scanNumericLiteral = function(neg) { + return this.scanNAryNumberLiteral(neg) || this.scanDecimalNumberLiteral(neg); + }; - function SCAbstractFunction() { - this.__initializeWith__("Object"); - } - klass.define(SCAbstractFunction, "AbstractFunction"); + SCParser.prototype.scanNegativeNumericLiteral = function() { + var token, ch1, ch2, ch3; + var start, value = null; - function SCFunction() { - this.__initializeWith__("AbstractFunction"); - // istanbul ignore next - this._ = function() {}; - } - klass.define(SCFunction, "Function : AbstractFunction", { - __tag: 12 - }); + start = this.index; + ch1 = this.source.charAt(this.index + 1); - // $SC - var $nil = new SCNil(); - var $true = new SCTrue(); - var $false = new SCFalse(); - var $integers = {}; - var $floats = {}; - var $symbols = {}; - var $chars = {}; + if (isNumber(ch1)) { + this.index += 1; + token = this.scanNumericLiteral(true); + token.range[0] = start; + return token; + } - $SC.Nil = function() { - return $nil; - }; + ch2 = this.source.charAt(this.index + 2); + ch3 = this.source.charAt(this.index + 3); - $SC.Boolean = function($value) { - return $value ? $true : $false; - }; + if (ch1 + ch2 === "pi") { + this.index += 3; + value = String(-Math.PI); + } else if (ch1 + ch2 + ch3 === "inf") { + this.index += 4; + value = "-Infinity"; + } - $SC.True = function() { - return $true; - }; + if (value !== null) { + return { + type : Token.FloatLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } - $SC.False = function() { - return $false; + return null; }; - $SC.Integer = function(value) { - var instance; + SCParser.prototype.scanNAryNumberLiteral = function(neg) { + var re, start, items; + var base, integer, frac, pi; + var value, type; - if (!global.isFinite(value)) { - return $SC.Float(+value); + re = /^(\d+)r((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+)(?:\.((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+))?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + if (!items) { + return; } - value = value|0; + base = items[1].replace(/^0+(?=\d)/g, "")|0; + integer = items[2].replace(/(^0+(?=\d)|_)/g, ""); + frac = items[3] && items[3].replace(/_/g, ""); - if (!$integers.hasOwnProperty(value)) { - instance = new SCInteger(); - instance._ = value; - $integers[value] = instance; + if (!frac && base < 26 && integer.substr(-2) === "pi") { + integer = integer.substr(0, integer.length - 2); + pi = true; } - return $integers[value]; - }; - - $SC.Float = function(value) { - var instance; + type = Token.IntegerLiteral; + value = this.calcNBasedInteger(integer, base); - value = +value; + if (frac) { + type = Token.FloatLiteral; + value += this.calcNBasedFrac(frac, base); + } - if (!$floats.hasOwnProperty(value)) { - instance = new SCFloat(); - instance._ = value; - $floats[value] = instance; + if (neg) { + value *= -1; } - return $floats[value]; - }; + if (pi) { + type = Token.FloatLiteral; + value = value * Math.PI; + } - $SC.Symbol = function(value) { - var instance; - if (!$symbols.hasOwnProperty(value)) { - instance = new SCSymbol(); - instance._ = value; - $symbols[value] = instance; + if (type === Token.FloatLiteral && value === (value|0)) { + value = value + ".0"; + } else { + value = String(value); } - return $symbols[value]; - }; - $SC.Char = function(value) { - var instance; + this.index += items[0].length; - value = String(value).charAt(0); + return { + type : type, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; - if (!$chars.hasOwnProperty(value)) { - instance = new SCChar(); - instance._ = value; - $chars[value] = instance; + SCParser.prototype.char2num = function(ch, base) { + var x = char2num(ch, base); + if (x >= base) { + this.throwError({}, Message.UnexpectedToken, ch); } - - return $chars[value]; + return x; }; - $SC.Array = function(value, immutable) { - var instance = new SCArray(); - instance._ = value || []; - instance._immutable = !!immutable; - return instance; - }; + SCParser.prototype.calcNBasedInteger = function(integer, base) { + var value, i, imax; - $SC.String = function(value, immutable) { - var instance = new SCString(); - instance._ = String(value).split("").map($SC.Char); - instance._immutable = !!immutable; - return instance; - }; + for (i = value = 0, imax = integer.length; i < imax; ++i) { + value *= base; + value += this.char2num(integer[i], base); + } - $SC.Function = function(value) { - var instance = new SCFunction(); - instance._ = value; - return instance; + return value; }; -})(sc); - -// src/sc/lang/klass-utils.js -(function(sc) { - - var $SC = sc.lang.$SC; - var klass = sc.lang.klass; + SCParser.prototype.calcNBasedFrac = function(frac, base) { + var value, i, imax; - var utils = { - BOOL: function(a) { - return a.__bool__(); - }, - $nil : $SC.Nil(), - $true : $SC.True(), - $false: $SC.False(), - $int_0: $SC.Integer(0), - $int_1: $SC.Integer(1), - nop: function() { - return this; - }, - alwaysReturn$nil : $SC.Nil, - alwaysReturn$true : $SC.True, - alwaysReturn$false: $SC.False, - alwaysReturn$int_0: function() { - return utils.$int_0; - }, - alwaysReturn$int_1: function() { - return utils.$int_1; - }, - defaultValue$Nil: function($obj) { - return $obj || utils.$nil; - }, - defaultValue$Boolean: function($obj, value) { - return $obj || $SC.Boolean(value); - }, - defaultValue$Integer: function($obj, value) { - return $obj || $SC.Integer(value); - }, - defaultValue$Float: function($obj, value) { - return $obj || $SC.Float(value); - }, - defaultValue$Symbol: function($obj, value) { - return $obj || $SC.Symbol(value); - }, - getMethod: function(className, methodName) { - return klass.get(className)._Spec.prototype[methodName]; + for (i = value = 0, imax = frac.length; i < imax; ++i) { + value += this.char2num(frac[i], base) * Math.pow(base, -(i + 1)); } - }; - - klass.utils = utils; -})(sc); + return value; + }; -// src/sc/lang/iterator.js -(function(sc) { + SCParser.prototype.scanDecimalNumberLiteral = function(neg) { + var re, start, items, integer, frac, pi; + var value, type; - var iterator = {}; - var $SC = sc.lang.$SC; - var utils = sc.lang.klass.utils; - var $nil = utils.$nil; - var $int_0 = utils.$int_0; - var $int_1 = utils.$int_1; - var BOOL = utils.BOOL; + re = /^((?:\d(?:_(?=\d))?)+((?:\.(?:\d(?:_(?=\d))?)+)?(?:e[-+]?(?:\d(?:_(?=\d))?)+)?))(pi)?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); - var __stop__ = function() { - return null; - }; + integer = items[1]; + frac = items[2]; + pi = items[3]; - var nop_iter = { - next: __stop__ - }; + type = (frac || pi) ? Token.FloatLiteral : Token.IntegerLiteral; + value = +integer.replace(/(^0+(?=\d)|_)/g, ""); - var one_shot_iter = function(value) { - var iter = { - next: function() { - iter.next = __stop__; - return value; - } - }; - return iter; - }; + if (neg) { + value *= -1; + } - // TODO: async function - iterator.execute = function(iter, $function) { - var $item, ret, i = 0; - $function = utils.defaultValue$Nil($function); + if (pi) { + value = value * Math.PI; + } - while (($item = iter.next()) !== null) { - if (Array.isArray($item)) { - ret = $function.value($item[0], $item[1]); - } else { - ret = $function.value($item, $SC.Integer(i++)); - } - if (ret === 65535) { - break; - } + if (type === Token.FloatLiteral && value === (value|0)) { + value = value + ".0"; + } else { + value = String(value); } - }; - iterator.object$do = one_shot_iter; + this.index += items[0].length; - iterator.function$while = function($function) { - var iter = { - next: function() { - if (BOOL($function.value())) { - return [ $nil, $nil ]; - } - iter.next = __stop__; - return null; - } + return { + type : type, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] }; - - return iter; }; - var sc_incremental_iter = function($start, $end, $step) { - var $i = $start, iter = { - next: function() { - var $ret = $i; - $i = $i ["+"] ($step); - if ($i > $end) { - iter.next = __stop__; - } - return $ret; - } - }; - return iter; - }; + SCParser.prototype.scanPunctuator = function() { + var re, start, items; - var sc_decremental_iter = function($start, $end, $step) { - var $i = $start, iter = { - next: function() { - var $ret = $i; - $i = $i ["+"] ($step); - if ($i < $end) { - iter.next = __stop__; - } - return $ret; - } - }; - return iter; - }; + re = /^(\.{1,3}|[(){}[\]:;,~#`]|[-+*\/%<=>!?&|@]+)/; + start = this.index; + items = re.exec(this.source.slice(this.index)); - var sc_numeric_iter = function($start, $end, $step) { - if ($start.valueOf() === $end.valueOf()) { - return one_shot_iter($start); - } else if ($start < $end && $step > 0) { - return sc_incremental_iter($start, $end, $step); - } else if ($start > $end && $step < 0) { - return sc_decremental_iter($start, $end, $step); + if (items) { + this.index += items[0].length; + return { + type : Token.Punctuator, + value: items[0], + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; } - return nop_iter; - }; - iterator.number$do = function($end) { - var $start, $step; + this.throwError({}, Message.UnexpectedToken, this.source.charAt(this.index)); - $start = $int_0; - $end = $end.__dec__(); - $step = $int_1; + this.index = this.length; - return sc_numeric_iter($start, $end, $step); + return this.EOFToken(); }; - iterator.number$reverseDo = function($start) { - var $end, $step; - - $start = $start.__dec__(); - $end = $int_0; - $step = $SC.Integer(-1); + SCParser.prototype.scanStringLiteral = function() { + var source, start; + var length, index; + var quote, ch, value, type; - return sc_numeric_iter($start, $end, $step); - }; + source = this.source; + length = this.length; + index = start = this.index; + quote = source.charAt(start); + type = (quote === '"') ? Token.StringLiteral : Token.SymbolLiteral; - iterator.number$for = function($start, $end) { - var $step; - $end = utils.defaultValue$Nil($end); + index += 1; + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === quote) { + value = source.substr(start + 1, index - start - 2); + value = value.replace(/\n/g, "\\n"); + this.index = index; + return { + type : type, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } else if (ch === "\n") { + this.lineNumber += 1; + this.lineStart = index; + } else if (ch === "\\") { + index += 1; + } + } - $step = ($start <= $end) ? $int_1 : $SC.Integer(-1); + this.index = index; + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); - return sc_numeric_iter($start, $end, $step); + return this.EOFToken(); }; - iterator.number$forBy = function($start, $end, $step) { - $end = utils.defaultValue$Nil($end); - $step = utils.defaultValue$Nil($step); + SCParser.prototype.scanSymbolLiteral = function() { + var re, start, items; + var value; - return sc_numeric_iter($start, $end, $step); - }; + re = /^\\([a-z_]\w*)?/i; + start = this.index; + items = re.exec(this.source.slice(this.index)); - iterator.number$forSeries = function($start, $second, $last) { - var $end, $step; + value = items[1]; - $second = utils.defaultValue$Nil($second); - $end = utils.defaultValue$Nil($last); - $step = $second ["-"] ($start); + this.index += items[0].length; - return sc_numeric_iter($start, $end, $step); + return { + type : Token.SymbolLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; }; - var js_incremental_iter = function(start, end, step, type) { - var i = start, iter = { - next: function() { - var ret = i; - i += step; - if (i > end) { - iter.next = __stop__; - } - return type(ret); - } + SCParser.prototype.scanUnderscore = function() { + var start = this.index; + + this.index += 1; + + return { + type: Token.Identifier, + value: "_", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] }; - return iter; }; - var js_decremental_iter = function(start, end, step, type) { - var i = start, iter = { - next: function() { - var ret = i; - i += step; - if (i < end) { - iter.next = __stop__; - } - return type(ret); - } + SCParser.prototype.createAssignmentExpression = function(operator, left, right, remain) { + var node = { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right }; - return iter; + if (remain) { + node.remain = remain; + } + return node; }; - var js_numeric_iter = function(start, end, step, type) { - if (start === end) { - return one_shot_iter(type(start)); - } else if (start < end && step > 0) { - return js_incremental_iter(start, end, step, type); - } else if (start > end && step < 0) { - return js_decremental_iter(start, end, step, type); + SCParser.prototype.createBinaryExpression = function(operator, left, right) { + var node = { + type: Syntax.BinaryExpression, + operator: operator.value, + left: left, + right: right + }; + if (operator.adverb) { + node.adverb = operator.adverb; } - return nop_iter; + return node; }; - var js_numeric_iter$do = function($endval, type) { - var end = type($endval.__num__()).valueOf(); - return js_numeric_iter(0, end - 1, +1, type); + SCParser.prototype.createBlockExpression = function(body) { + return { + type: Syntax.BlockExpression, + body: body + }; }; - var js_numeric_iter$reverseDo = function($startval, type) { - var start = type($startval.__num__()).valueOf(); - var end = (start|0) - start; - return js_numeric_iter(start - 1, end, -1, type); - }; + SCParser.prototype.createCallExpression = function(callee, method, args, stamp) { + var node; - var js_numeric_iter$for = function($startval, $endval, type) { - $startval = utils.defaultValue$Nil($startval); - $endval = utils.defaultValue$Nil($endval); + node = { + type: Syntax.CallExpression, + callee: callee, + method: method, + args : args, + }; - var start = type($startval.__num__()).valueOf(); - var end = type($endval .__num__()).valueOf(); - var step = (start <= end) ? +1 : -1; + if (stamp) { + node.stamp = stamp; + } - return js_numeric_iter(start, end, step, type); + return node; }; - var js_numeric_iter$forBy = function($startval, $endval, $stepval, type) { - $endval = utils.defaultValue$Nil($endval); - $stepval = utils.defaultValue$Nil($stepval); - - var start = type($startval.__num__()).valueOf(); - var end = type($endval .__num__()).valueOf(); - var step = type($stepval .__num__()).valueOf(); - - return js_numeric_iter(start, end, step, type); + SCParser.prototype.createGlobalExpression = function(id) { + return { + type: Syntax.GlobalExpression, + id: id + }; }; - var js_numeric_iter$forSeries = function($startval, $second, $last, type) { - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); - - var start = type($startval.__num__()).valueOf(); - var second = type($second .__num__()).valueOf(); - var end = type($last .__num__()).valueOf(); - var step = second - start; + SCParser.prototype.createFunctionExpression = function(args, body, closed, partial, blocklist) { + var node; - return js_numeric_iter(start, end, step, type); + node = { + type: Syntax.FunctionExpression, + body: body + }; + if (args) { + node.args = args; + } + if (closed) { + node.closed = true; + } + if (partial) { + node.partial = true; + } + if (blocklist) { + node.blocklist = true; + } + return node; }; - iterator.integer$do = function($endval) { - return js_numeric_iter$do($endval, $SC.Integer); + SCParser.prototype.createIdentifier = function(name) { + return { + type: Syntax.Identifier, + name: name + }; }; - iterator.integer$reverseDo = function($startval) { - return js_numeric_iter$reverseDo($startval, $SC.Integer); + SCParser.prototype.createLabel = function(name) { + return { + type: Syntax.Label, + name: name + }; }; - iterator.integer$for = function($startval, $endval) { - return js_numeric_iter$for($startval, $endval, $SC.Integer); + SCParser.prototype.createListExpression = function(elements, immutable) { + var node = { + type: Syntax.ListExpression, + elements: elements + }; + if (immutable) { + node.immutable = !!immutable; + } + return node; }; - iterator.integer$forBy = function($startval, $endval, $stepval) { - return js_numeric_iter$forBy($startval, $endval, $stepval, $SC.Integer); + SCParser.prototype.createLiteral = function(token) { + return { + type: Syntax.Literal, + value: token.value, + valueType: token.type + }; }; - iterator.integer$forSeries = function($startval, $second, $last) { - return js_numeric_iter$forSeries($startval, $second, $last, $SC.Integer); + SCParser.prototype.createLocationMarker = function() { + if (this.opts.loc || this.opts.range) { + this.skipComment(); + return new LocationMarker(this); + } }; - iterator.float$do = function($endval) { - return js_numeric_iter$do($endval, $SC.Float); + SCParser.prototype.createObjectExpression = function(elements) { + return { + type: Syntax.ObjectExpression, + elements: elements + }; }; - iterator.float$reverseDo = function($startval) { - return js_numeric_iter$reverseDo($startval, $SC.Float); + SCParser.prototype.createProgram = function(body) { + return { + type: Syntax.Program, + body: body + }; }; - iterator.float$for = function($startval, $endval) { - return js_numeric_iter$for($startval, $endval, $SC.Float); + SCParser.prototype.createThisExpression = function(name) { + return { + type: Syntax.ThisExpression, + name: name + }; }; - iterator.float$forBy = function($startval, $endval, $stepval) { - return js_numeric_iter$forBy($startval, $endval, $stepval, $SC.Float); + SCParser.prototype.createUnaryExpression = function(operator, arg) { + return { + type: Syntax.UnaryExpression, + operator: operator, + arg: arg + }; }; - iterator.float$forSeries = function($startval, $second, $last) { - return js_numeric_iter$forSeries($startval, $second, $last, $SC.Float); + SCParser.prototype.createVariableDeclaration = function(declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; }; - var list_iter = function(list) { - var i = 0, iter = { - next: function() { - var $ret = list[i++]; - if (i >= list.length) { - iter.next = __stop__; - } - return $ret; - } + SCParser.prototype.createVariableDeclarator = function(id, init) { + var node = { + type: Syntax.VariableDeclarator, + id: id }; - return iter; + if (init) { + node.init = init; + } + return node; }; - var js_array_iter = function(list) { - if (list.length) { - return list_iter(list); + SCParser.prototype.isClassName = function(node) { + var name, ch; + + if (node.type === Syntax.Identifier) { + name = node.value || node.name; + ch = name.charAt(0); + return "A" <= ch && ch <= "Z"; } - return nop_iter; - }; - iterator.array$do = function($array) { - return js_array_iter($array._.slice()); + return false; }; - iterator.array$reverseDo = function($array) { - return js_array_iter($array._.slice().reverse()); + SCParser.prototype.isKeyword = function(value) { + return !!Keywords[value] || false; }; - sc.lang.iterator = iterator; - -})(sc); + SCParser.prototype.isLeftHandSide = function(expr) { + switch (expr.type) { + case Syntax.Identifier: + case Syntax.GlobalExpression: + return true; + } + return false; + }; -// src/sc/lang/classlib.js -(function(sc) { + SCParser.prototype._match = function(value, type) { + var token = this.lookahead; + return token.type === type && token.value === value; + }; - sc.lang.classlib = {}; + SCParser.prototype.match = function(value) { + return this._match(value, Token.Punctuator); + }; -})(sc); + SCParser.prototype.matchKeyword = function(value) { + return this._match(value, Token.Keyword); + }; -// src/sc/lang/classlib/Core/Object.js -(function(sc) { + SCParser.prototype.matchAny = function(list) { + var value, i, imax; - var slice = [].slice; - var $SC = sc.lang.$SC; - var fn = sc.lang.fn; + if (this.lookahead.type === Token.Punctuator) { + value = this.lookahead.value; + for (i = 0, imax = list.length; i < imax; ++i) { + if (list[i] === value) { + return value; + } + } + } - sc.lang.klass.refine("Object", function(spec, utils) { - var BOOL = utils.BOOL; - var $nil = utils.$nil; - var $true = utils.$true; - var $false = utils.$false; - var $int_1 = utils.$int_1; - var SCArray = $SC("Array"); + return null; + }; - spec.__num__ = function() { - throw new Error("Wrong Type"); - }; + SCParser.prototype.withScope = function(fn) { + var result; - spec.__int__ = function() { - return this.__num__()|0; - }; + this.scope.begin(); + result = fn.call(this); + this.scope.end(); - spec.__bool__ = function() { - throw new Error("Wrong Type"); - }; + return result; + }; - spec.__sym__ = function() { - throw new Error("Wrong Type"); - }; + // 1. Program + SCParser.prototype.parseProgram = function() { + var node; - spec.__str__ = function() { - return String(this); - }; + this.skipComment(); + this.markStart(); + this.peek(); - // TODO: implements $new - // TODO: implements $newCopyArgs + node = this.withScope(function() { + var body; - spec.$newFrom = function() { - return this._doesNotUnderstand("newFrom"); - }; + body = this.parseFunctionBody(""); + if (body.length === 1 && body[0].type === Syntax.BlockExpression) { + body = body[0].body; + } - // TODO: implements dump - // TODO: implements post - // TODO: implements postln - // TODO: implements postc - // TODO: implements postcln - // TODO: implements postcs - // TODO: implements totalFree - // TODO: implements largestFreeBlock - // TODO: implements gcDumpGrey - // TODO: implements gcDumpSet - // TODO: implements gcInfo - // TODO: implements gcSanity - // TODO: implements canCallOS + return this.createProgram(body); + }); - spec.size = utils.alwaysReturn$int_0; - spec.indexedSize = utils.alwaysReturn$int_0; - spec.flatSize = utils.alwaysReturn$int_1; + return this.markEnd(node); + }; - spec.do = function($function) { - $function = utils.defaultValue$Nil($function); + // 2. Function + // 2.1 Function Expression + SCParser.prototype.parseFunctionExpression = function(closed, blocklist) { + var node; - sc.lang.iterator.execute( - sc.lang.iterator.object$do(this), - $function - ); + node = this.withScope(function() { + var args, body; - return this; - }; + if (this.match("|")) { + args = this.parseFunctionArgument("|"); + } else if (this.matchKeyword("arg")) { + args = this.parseFunctionArgument(";"); + } + body = this.parseFunctionBody("}"); - spec.generate = function($function, $state) { - $state = utils.defaultValue$Nil($state); + return this.createFunctionExpression(args, body, closed, false, blocklist); + }); - this.do($function); + return node; + }; - return $state; - }; + // 2.2 Function Argument + SCParser.prototype.parseFunctionArgument = function(expect) { + var args = { list: [] }, lookahead; - // already defined: class - // already defined: isKindOf - // already defined: isMemberOf + this.lex(); - spec.respondsTo = function($aSymbol) { - $aSymbol = utils.defaultValue$Nil($aSymbol); - return $SC.Boolean(typeof this[$aSymbol.__sym__()] === "function"); - }; + if (!this.match("...")) { + do { + args.list.push(this.parseFunctionArgumentElement()); + if (!this.match(",")) { + break; + } + this.lex(); + } while (this.lookahead.type !== Token.EOF); + } - // TODO: implements performMsg + if (this.match("...")) { + this.lex(); + lookahead = this.lookahead; + args.remain = this.parseVariableIdentifier(); + this.scope.add("arg", args.remain.name); + } - spec.perform = function($selector) { - var selector, method; - $selector = utils.defaultValue$Nil($selector); + this.expect(expect); - selector = $selector.__sym__(); - method = this[selector]; + return args; + }; - if (method) { - return method.apply(this, slice.call(arguments, 1)); - } + SCParser.prototype._parseArgVarElement = function(type, method) { + var init = null, id; - throw new Error("Message '" + selector + "' not understood."); - }; + this.skipComment(); + this.markStart(); + id = this.parseVariableIdentifier(); + this.scope.add(type, id.name); - spec.performList = function($selector, $arglist) { - var selector, method; - $selector = utils.defaultValue$Nil($selector); - $arglist = utils.defaultValue$Nil($arglist); + if (this.match("=")) { + this.lex(); + init = this[method](); + } - selector = $selector.__sym__(); - method = this[selector]; + return this.markEnd(this.createVariableDeclarator(id, init)); + }; - if (method) { - return method.apply(this, $arglist.asArray()._); - } + SCParser.prototype.parseFunctionArgumentElement = function() { + var node = this._parseArgVarElement("arg", "parseArgumentableValue"); - throw new Error("Message '" + selector + "' not understood."); - }; + if (node.init && !isValidArgumentValue(node.init)) { + this.throwUnexpected(this.lookahead); + } - spec.functionPerformList = utils.nop; + return node; + }; - // TODO: implements superPerform - // TODO: implements superPerformList - // TODO: implements tryPerform - // TODO: implements multiChannelPerform - // TODO: implements performWithEnvir - // TODO: implements performKeyValuePairs + // 2.3 Function Body + SCParser.prototype.parseFunctionBody = function(match) { + var elements = []; - var copy = function(obj) { - var copied = obj; + while (this.matchKeyword("var")) { + elements.push(this.parseVariableDeclaration()); + } - if (Array.isArray(obj)) { - copied = obj.slice(); - } else if (obj && obj.constructor === Object) { - copied = {}; - Object.keys(obj).forEach(function(key) { - copied[key] = obj[key]; - }); + while (this.lookahead.type !== Token.EOF && !this.match(match)) { + elements.push(this.parseExpression()); + if (this.lookahead.type !== Token.EOF && !this.match(match)) { + this.expect(";"); + } else { + break; } + } - return copied; - }; - - spec.copy = function() { - return this.shallowCopy(); - }; + return elements; + }; - // TODO: implements contentsCopy + // 3. Variable Declarations + SCParser.prototype.parseVariableDeclaration = function() { + var declaration; - spec.shallowCopy = function() { - var a = new this.__class._Spec(); + this.skipComment(); + this.markStart(); - Object.keys(this).forEach(function(key) { - a[key] = copy(this[key]); - }, this); + this.lex(); // var - if (this._ === this) { - a._ = a; - } + declaration = this.markEnd( + this.createVariableDeclaration( + this.parseVariableDeclarationList(), "var" + ) + ); - return a; - }; + this.expect(";"); - // TODO: implements copyImmutable - // TODO: implements deepCopy + return declaration; + }; - spec.dup = function($n) { - var $this = this; - var $array, i, imax; + SCParser.prototype.parseVariableDeclarationList = function() { + var list = []; - $n = utils.defaultValue$Integer($n, 2); - if (BOOL($n.isSequenceableCollection())) { - return SCArray.fillND($n, $SC.Function(function() { - return $this.copy(); - })); + do { + list.push(this.parseVariableDeclarationElement()); + if (!this.match(",")) { + break; } + this.lex(); + } while (this.lookahead.type !== Token.EOF); - $array = SCArray.new($n); - for (i = 0, imax = $n.__int__(); i < imax; ++i) { - $array.add(this.copy()); - } + return list; + }; - return $array; - }; + SCParser.prototype.parseVariableDeclarationElement = function() { + return this._parseArgVarElement("var", "parseAssignmentExpression"); + }; - spec["!"] = function($n) { - return this.dup($n); - }; + // 4. Expression + SCParser.prototype.parseExpression = function(node) { + return this.parseAssignmentExpression(node); + }; - spec.poll = function() { - return this.value(); - }; + // 4.1 Expressions + SCParser.prototype.parseExpressions = function(node) { + var nodes = []; - spec.value = utils.nop; - spec.valueArray = utils.nop; - spec.valueEnvir = utils.nop; - spec.valueArrayEnvir = utils.nop; + if (node) { + nodes.push(node); + this.lex(); + } - spec["=="] = function($obj) { - return this ["==="] ($obj); - }; + while (this.lookahead.type !== Token.EOF && !this.matchAny([ ",", ")", "]", ".." ])) { + this.skipComment(); + this.markStart(); + node = this.parseAssignmentExpression(); + this.markEnd(node); + nodes.push(node); + if (this.match(";")) { + this.lex(); + } + } - spec["!="] = function($obj) { - return (this ["=="] ($obj)).not(); - }; + if (nodes.length === 0) { + this.throwUnexpected(this.lookahead); + } - spec["==="] = function($obj) { - return $SC.Boolean(this === $obj); - }; + return nodes.length === 1 ? nodes[0] : nodes; + }; - spec["!=="] = function($obj) { - return $SC.Boolean(this !== $obj); - }; + // 4.2 Assignment Expression + SCParser.prototype.parseAssignmentExpression = function(node) { + var token; - // TODO: implements equals - // TODO: implements compareObject - // TODO: implements instVarHash - // TODO: implements basicHash - // TODO: implements hash - // TODO: implements identityHash + if (node) { + return this.parsePartialExpression(node); + } - spec["->"] = function($obj) { - return $SC("Association").new(this, $obj); - }; + this.skipComment(); + this.markStart(); - spec.next = utils.nop; - spec.reset = utils.nop; + if (this.match("#")) { + token = this.lex(true); + if (this.matchAny([ "[", "{" ])) { + token.restore(); + } else { + node = this.parseDestructuringAssignmentExpression(); + } + } - spec.first = function($inval) { - $inval = utils.defaultValue$Nil($inval); + if (!node) { + node = this.parseSimpleAssignmentExpression(); + } - this.reset(); - return this.next($inval); - }; + return this.markEnd(node); + }; - spec.iter = function() { - return $SC("OneShotStream").new(this); - }; + SCParser.prototype.parseDestructuringAssignmentExpression = function() { + var node, left, right, token; - spec.stop = utils.nop; - spec.free = utils.nop; - spec.clear = utils.nop; - spec.removedFromScheduler = utils.nop; - spec.isPlaying = utils.alwaysReturn$false; + left = this.parseDestructuringAssignmentLeft(); + token = this.lookahead; + this.expect("="); - spec.embedInStream = function() { - return this.yield(); - }; + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left.list, right, left.remain + ); - // TODO: implements cyc - // TODO: implements fin - // TODO: implements repeat - // TODO: implements loop + return node; + }; - spec.asStream = utils.nop; + SCParser.prototype.parseSimpleAssignmentExpression = function() { + var node, left, right, token; - // TODO: implements streamArg + node = left = this.parsePartialExpression(); - spec.eventAt = utils.alwaysReturn$nil; + if (this.match("=")) { + if (node.type === Syntax.CallExpression) { + token = this.lex(); + right = this.parseAssignmentExpression(); + left.method.name = this.getAssignMethod(left.method.name); + left.args.list = node.args.list.concat(right); + /* istanbul ignore else */ + if (this.opts.range) { + left.range[1] = this.index; + } + /* istanbul ignore else */ + if (this.opts.loc) { + left.loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + } + node = left; + } else { + // TODO: fix + if (!this.isLeftHandSide(left)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } - spec.composeEvents = function($event) { - $event = utils.defaultValue$Nil($event); - return $event.copy(); - }; + token = this.lex(); + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left, right + ); + } + } - spec.finishEvent = utils.nop; - spec.atLimit = utils.alwaysReturn$false; - spec.isRest = utils.alwaysReturn$false; - spec.threadPlayer = utils.nop; - spec.threadPlayer_ = utils.nop; - spec["?"] = utils.nop; - spec["??"] = utils.nop; + return node; + }; - spec["!?"] = function($obj) { - $obj = utils.defaultValue$Nil($obj); - return $obj.value(this); - }; + SCParser.prototype.getAssignMethod = function(methodName) { + switch (methodName) { + case "at": + return "put"; + case "copySeries": + return "putSeries"; + } + return methodName + "_"; + }; - spec.isNil = utils.alwaysReturn$false; - spec.notNil = utils.alwaysReturn$true; - spec.isNumber = utils.alwaysReturn$false; - spec.isInteger = utils.alwaysReturn$false; - spec.isFloat = utils.alwaysReturn$false; - spec.isSequenceableCollection = utils.alwaysReturn$false; - spec.isCollection = utils.alwaysReturn$false; - spec.isArray = utils.alwaysReturn$false; - spec.isString = utils.alwaysReturn$false; - spec.containsSeqColl = utils.alwaysReturn$false; - spec.isValidUGenInput = utils.alwaysReturn$false; - spec.isException = utils.alwaysReturn$false; - spec.isFunction = utils.alwaysReturn$false; + SCParser.prototype.parseDestructuringAssignmentLeft = function() { + var params = { list: [] }, element; - spec.matchItem = function($item) { - $item = utils.defaultValue$Nil($item); - return this ["==="] ($item); - }; + do { + element = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(element)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + params.list.push(element); + if (this.match(",")) { + this.lex(); + } else if (this.match("...")) { + this.lex(); + params.remain = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(params.remain)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + break; + } + } while (this.lookahead.type !== Token.EOF && !this.match("=")); - spec.trueAt = utils.alwaysReturn$false; + return params; + }; - spec.falseAt = function($key) { - $key = utils.defaultValue$Nil($key); - return this.trueAt($key).not(); - }; + // 4.3 Partial Expression + SCParser.prototype.parsePartialExpression = function(node) { + var underscore, x, y; - // TODO: implements pointsTo - // TODO: implements mutable - // TODO: implements frozen - // TODO: implements halt - // TODO: implements primitiveFailed - // TODO: implements reportError - // TODO: implements subclassResponsibility - spec._subclassResponsibility = function(methodName) { - throw new Error("RECEIVER " + String(this) + ": " + - "'" + methodName + "' should have been implemented by subclass"); - }; + if (this.state.innerElements) { + node = this.parseBinaryExpression(node); + } else { + underscore = this.state.underscore; + this.state.underscore = []; - // TODO: implements doesNotUnderstand - spec._doesNotUnderstand = function(methodName) { - throw new Error("RECEIVER " + this.__str__() + ": " + - "Message '" + methodName + "' not understood."); - }; + node = this.parseBinaryExpression(node); - // TODO: implements shouldNotImplement - // TODO: implements outOfContextReturn - // TODO: implements immutableError - // TODO: implements deprecated - // TODO: implements mustBeBoolean - // TODO: implements notYetImplemented - // TODO: implements dumpBackTrace - // TODO: implements getBackTrace - // TODO: implements throw + if (this.state.underscore.length) { + node = this.withScope(function() { + var args, i, imax; - spec.species = function() { - return this.class(); - }; + args = new Array(this.state.underscore.length); + for (i = 0, imax = args.length; i < imax; ++i) { + x = this.state.underscore[i]; + y = this.createVariableDeclarator(x); + /* istanbul ignore else */ + if (x.range) { + y.range = x.range; + } + /* istanbul ignore else */ + if (x.loc) { + y.loc = x.loc; + } + args[i] = y; + this.scope.add("arg", this.state.underscore[i].name); + } - spec.asCollection = function() { - return $SC.Array([ this ]); - }; + return this.createFunctionExpression( + { list: args }, [ node ], false, true, false + ); + }); + } - spec.asSymbol = function() { - return this.asString().asSymbol(); - }; + this.state.underscore = underscore; + } - spec.asString = function() { - return $SC.String(String(this)); - }; + return node; + }; - // TODO: implements asCompileString - // TODO: implements cs - // TODO: implements printClassNameOn - // TODO: implements printOn - // TODO: implements storeOn - // TODO: implements storeParamsOn - // TODO: implements simplifyStoreArgs - // TODO: implements storeArgs - // TODO: implements storeModifiersOn + // 4.4 Conditional Expression + // 4.5 Binary Expression + SCParser.prototype.parseBinaryExpression = function(node) { + var marker, left, token, prec; - spec.as = function($aSimilarClass) { - $aSimilarClass = utils.defaultValue$Nil($aSimilarClass); - return $aSimilarClass.newFrom(this); - }; + this.skipComment(); - spec.dereference = utils.nop; + marker = this.createLocationMarker(); + left = this.parseUnaryExpression(node); + token = this.lookahead; - spec.reference = function() { - return $SC.Ref(this); - }; + prec = this.binaryPrecedence(token); + if (prec === 0) { + if (node) { + return this.parseUnaryExpression(node); + } + return left; + } + this.lex(); - spec.asRef = function() { - return $SC.Ref(this); - }; + token.prec = prec; + token.adverb = this.parseAdverb(); - spec.asArray = function() { - return this.asCollection().asArray(); - }; + return this.sortByBinaryPrecedence(left, token, marker); + }; - spec.asSequenceableCollection = function() { - return this.asArray(); - }; + SCParser.prototype.sortByBinaryPrecedence = function(left, operator, marker) { + var expr; + var prec, token; + var markers, i; + var right, stack; - spec.rank = utils.alwaysReturn$int_0; + markers = [ marker, this.createLocationMarker() ]; + right = this.parseUnaryExpression(); - spec.deepCollect = function($depth, $function, $index, $rank) { - $function = utils.defaultValue$Nil($function); - return $function.value(this, $index, $rank); - }; + stack = [ left, operator, right ]; - spec.deepDo = function($depth, $function, $index, $rank) { - $function = utils.defaultValue$Nil($function); - $function.value(this, $index, $rank); - return this; - }; + while ((prec = this.binaryPrecedence(this.lookahead)) > 0) { + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop(); + left = stack.pop(); + expr = this.createBinaryExpression(operator, left, right); + markers.pop(); - spec.slice = utils.nop; - spec.shape = utils.alwaysReturn$nil; - spec.unbubble = utils.nop; + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + stack.push(expr); + markers.push(marker); + } - spec.bubble = function($depth, $levels) { - var levels, a; - $levels = utils.defaultValue$Integer($levels, 1); + // Shift. + token = this.lex(); + token.prec = prec; + token.adverb = this.parseAdverb(); - levels = $levels.__int__(); - if (levels <= 1) { - a = [ this ]; - } else { - a = [ - this.bubble($depth, $SC.Integer(levels - 1)) - ]; + stack.push(token); + markers.push(this.createLocationMarker()); + expr = this.parseUnaryExpression(); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = this.createBinaryExpression(stack[i - 1], stack[i - 2], expr); + i -= 2; + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); } + } - return $SC.Array(a); - }; + return expr; + }; - spec.obtain = function($index, $default) { - $index = utils.defaultValue$Nil($index); - $default = utils.defaultValue$Nil($default); + SCParser.prototype.binaryPrecedence = function(token) { + var table, prec = 0; - if ($index.__num__() === 0) { - return this; + if (this.opts.binaryPrecedence) { + if (typeof this.opts.binaryPrecedence === "object") { + table = this.opts.binaryPrecedence; } else { - return $default; + table = binaryPrecedenceDefaults; } - }; + } else { + table = {}; + } + switch (token.type) { + case Token.Punctuator: + if (token.value !== "=") { + if (table.hasOwnProperty(token.value)) { + prec = table[token.value]; + } else if (/^[-+*\/%<=>!?&|@]+$/.test(token.value)) { + prec = 255; + } + } + break; + case Token.Label: + prec = 255; + break; + } + + return prec; + }; - spec.instill = function($index, $item, $default) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + SCParser.prototype.parseAdverb = function() { + var adverb, lookahead; - if ($index.__num__() === 0) { - return $item; - } else { - return this.asArray().instill($index, $item, $default); - } - }; + if (this.match(".")) { + this.lex(); - spec.addFunc = fn(function($$functions) { - return $SC("FunctionList").new(this ["++"] ($$functions)); - }, "*functions"); + lookahead = this.lookahead; + adverb = this.parsePrimaryExpression(); - spec.removeFunc = function($function) { - if (this === $function) { - return $nil; + if (adverb.type === Syntax.Literal) { + return adverb; } - return this; - }; - spec.replaceFunc = function($find, $replace) { - $replace = utils.defaultValue$Nil($replace); - if (this === $find) { - return $replace; + if (adverb.type === Syntax.Identifier) { + adverb.type = Syntax.Literal; + adverb.value = adverb.name; + adverb.valueType = Token.SymbolLiteral; + delete adverb.name; + return adverb; } - return this; - }; - // TODO: implements addFuncTo - // TODO: implements removeFuncFrom + this.throwUnexpected(lookahead); + } - spec.while = function($body) { - var $this = this; - $body = utils.defaultValue$Nil($body); + return null; + }; - $SC.Function(function() { - return $this.value(); - }).while($SC.Function(function() { - return $body.value(); - })); + // 4.6 Unary Expressions + SCParser.prototype.parseUnaryExpression = function(node) { + var token, expr; - return this; - }; + this.markStart(); - spec.switch = function() { - var args, i, imax; + if (this.match("`")) { + token = this.lex(); + expr = this.parseUnaryExpression(); + expr = this.createUnaryExpression(token.value, expr); + } else { + expr = this.parseLeftHandSideExpression(node); + } - args = slice.call(arguments); - for (i = 0, imax = args.length >> 1; i < imax; i++) { - if (BOOL(this ["=="] (args[i * 2]))) { - return args[i * 2 + 1].value(); - } - } + return this.markEnd(expr); + }; - if (args.length % 2 === 1) { - return args[args.length - 1].value(); - } + // 4.7 LeftHandSide Expressions + SCParser.prototype.parseLeftHandSideExpression = function(node) { + var marker, expr, prev, lookahead; + var blocklist, stamp; - return $nil; - }; + this.skipComment(); - spec.yield = function() { - // TODO: implements yield - }; + marker = this.createLocationMarker(); + expr = this.parsePrimaryExpression(node); - // TODO: implements alwaysYield - // TODO: implements yieldAndReset - // TODO: implements idle - // TODO: implements $initClass - // TODO: implements dependants - // TODO: implements changed - // TODO: implements addDependant - // TODO: implements removeDependant - // TODO: implements release - // TODO: implements releaseDependants - // TODO: implements update - // TODO: implements addUniqueMethod - // TODO: implements removeUniqueMethods - // TODO: implements removeUniqueMethod - // TODO: implements inspect - // TODO: implements inspectorClass - // TODO: implements inspector - // TODO: implements crash - // TODO: implements stackDepth - // TODO: implements dumpStack - // TODO: implements dumpDetailedBackTrace - // TODO: implements freeze + blocklist = false; - spec["&"] = function($that) { - return this.bitAnd($that); - }; + while ((stamp = this.matchAny([ "(", "{", "#", "[", "." ])) !== null) { + lookahead = this.lookahead; + if ((prev === "{" && (stamp !== "#" && stamp !== "{")) || (prev === "(" && stamp === "(")) { + this.throwUnexpected(lookahead); + } + switch (stamp) { + case "(": + expr = this.parseLeftHandSideParenthesis(expr); + break; + case "#": + expr = this.parseLeftHandSideClosedBrace(expr); + break; + case "{": + expr = this.parseLeftHandSideBrace(expr); + break; + case "[": + expr = this.parseLeftHandSideBracket(expr); + break; + case ".": + expr = this.parseLeftHandSideDot(expr); + break; + } - spec["|"] = function($that) { - return this.bitOr($that); - }; + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + prev = stamp; + } - spec["%"] = function($that) { - return this.mod($that); - }; + return expr; + }; - spec["**"] = function($that) { - return this.pow($that); - }; + SCParser.prototype.parseLeftHandSideParenthesis = function(expr) { + if (this.isClassName(expr)) { + return this.parseLeftHandSideClassNew(expr); + } - spec["<<"] = function($that) { - return this.leftShift($that); - }; + return this.parseLeftHandSideMethodCall(expr); + }; - spec[">>"] = function($that) { - return this.rightShift($that); - }; + SCParser.prototype.parseLeftHandSideClassNew = function(expr) { + var method, args; - spec["+>>"] = function($that) { - return this.unsignedRightShift($that); - }; + method = this.markTouch(this.createIdentifier("new")); + args = this.parseCallArgument(); - spec[" 0.max(1) + return this.createCallExpression(expr, method, args, "("); + }; - return this; - }; + SCParser.prototype.parseLeftHandSideClosedBrace = function(expr) { + this.lex(); + if (!this.match("{")) { + this.throwUnexpected(this.lookahead); + } - spec.fuzzyEqual = function($that, $precision) { - $that = utils.defaultValue$Nil($that); - $precision = utils.defaultValue$Float($precision, 1.0); + this.state.closedFunction = true; + expr = this.parseLeftHandSideBrace(expr); + this.state.closedFunction = false; - return $SC.Float(0.0).max( - $SC.Float(1.0) ["-"] ( - (this ["-"] ($that).abs()) ["/"] ($precision) - ) - ); - }; + return expr; + }; - spec.isUGen = utils.alwaysReturn$false; - spec.numChannels = utils.alwaysReturn$int_1; + SCParser.prototype.parseLeftHandSideBrace = function(expr) { + var method, lookahead, disallowGenerator, node; - spec.pair = function($that) { - $that = utils.defaultValue$Nil($that); - return $SC.Array([ this, $that ]); - }; + if (expr.type === Syntax.CallExpression && expr.stamp && expr.stamp !== "(") { + this.throwUnexpected(this.lookahead); + } + if (expr.type === Syntax.Identifier) { + if (this.isClassName(expr)) { + method = this.markTouch(this.createIdentifier("new")); + expr = this.createCallExpression(expr, method, { list: [] }, "{"); + } else { + expr = this.createCallExpression(null, expr, { list: [] }); + } + } + lookahead = this.lookahead; + disallowGenerator = this.state.disallowGenerator; + this.state.disallowGenerator = true; + node = this.parseBraces(true); + this.state.disallowGenerator = disallowGenerator; - spec.pairs = function($that) { - var $list; - $that = utils.defaultValue$Nil($that); + // TODO: refactoring + if (expr.callee === null) { + expr.callee = node; + node = expr; + } else { + expr.args.list.push(node); + } - $list = $SC.Array(); - this.asArray().do($SC.Function(function($a) { - $that.asArray().do($SC.Function(function($b) { - $list = $list.add($a.asArray() ["++"] ($b)); - })); - })); + return expr; + }; - return $list; - }; + SCParser.prototype.parseLeftHandSideBracket = function(expr) { + if (expr.type === Syntax.CallExpression && expr.stamp === "(") { + this.throwUnexpected(this.lookahead); + } - spec.awake = function($beats) { - return this.next($beats); - }; + if (this.isClassName(expr)) { + expr = this.parseLeftHandSideNewFrom(expr); + } else { + expr = this.parseLeftHandSideListAt(expr); + } - spec.beats_ = utils.nop; - spec.clock_ = utils.nop; + return expr; + }; - spec.performBinaryOpOnSomething = function($aSelector) { - var aSelector; - $aSelector = utils.defaultValue$Nil($aSelector); + SCParser.prototype.parseLeftHandSideNewFrom = function(expr) { + var node, method; - aSelector = $aSelector.__sym__(); - if (aSelector === "==") { - return $false; - } - if (aSelector === "!=") { - return $true; - } + method = this.markTouch(this.createIdentifier("newFrom")); - throw new Error("binary operator '" + aSelector + "' failed."); - }; + this.skipComment(); + this.markStart(); - spec.performBinaryOpOnSimpleNumber = function($aSelector, $thig, $adverb) { - return this.performBinaryOpOnSomething($aSelector, $thig, $adverb); - }; + node = this.markEnd(this.parseListInitialiser()); - spec.performBinaryOpOnSignal = spec.performBinaryOpOnSimpleNumber; - spec.performBinaryOpOnComplex = spec.performBinaryOpOnSimpleNumber; - spec.performBinaryOpOnSeqColl = spec.performBinaryOpOnSimpleNumber; - spec.performBinaryOpOnUGen = spec.performBinaryOpOnSimpleNumber; + return this.createCallExpression(expr, method, { list: [ node ] }, "["); + }; - // TODO: implements writeDefFile + SCParser.prototype.parseLeftHandSideListAt = function(expr) { + var indexes, method; - spec.isInputUGen = utils.alwaysReturn$false; - spec.isOutputUGen = utils.alwaysReturn$false; - spec.isControlUGen = utils.alwaysReturn$false; - spec.source = utils.nop; - spec.asUGenInput = utils.nop; - spec.asControlInput = utils.nop; + method = this.markTouch(this.createIdentifier("at")); - spec.asAudioRateInput = function() { - if (this.rate().__sym__() !== "audio") { - return $SC("K2A").ar(this); + indexes = this.parseListIndexer(); + if (indexes) { + if (indexes.length === 3) { + method.name = "copySeries"; } - return this; - }; + } else { + this.throwUnexpected(this.lookahead); + } - // TODO: implements slotSize - // TODO: implements slotAt - // TODO: implements slotPut - // TODO: implements slotKey - // TODO: implements slotIndex - // TODO: implements slotsDo - // TODO: implements slotValuesDo - // TODO: implements getSlots - // TODO: implements setSlots - // TODO: implements instVarSize - // TODO: implements instVarAt - // TODO: implements instVarPut - // TODO: implements writeArchive - // TODO: implements $readArchive - // TODO: implements asArchive - // TODO: implements initFromArchive - // TODO: implements archiveAsCompileString - // TODO: implements archiveAsObject - // TODO: implements checkCanArchive - // TODO: implements writeTextArchive - // TODO: implements $readTextArchive - // TODO: implements asTextArchive - // TODO: implements getContainedObjects - // TODO: implements writeBinaryArchive - // TODO: implements $readBinaryArchive - // TODO: implements asBinaryArchive - // TODO: implements genNext - // TODO: implements genCurrent - // TODO: implements $classRedirect - // TODO: implements help - }); + return this.createCallExpression(expr, method, { list: indexes }, "["); + }; -})(sc); + SCParser.prototype.parseLeftHandSideDot = function(expr) { + var method, args; -// src/sc/lang/classlib/Core/AbstractFunction.js -(function(sc) { + this.lex(); - var $SC = sc.lang.$SC; - var fn = sc.lang.fn; - var utils = sc.lang.klass.utils; + if (this.match("(")) { + // expr.() + return this.parseLeftHandSideDotValue(expr); + } else if (this.match("[")) { + // expr.[0] + return this.parseLeftHandSideDotBracket(expr); + } - sc.lang.klass.refine("AbstractFunction", function(spec, utils) { - spec.composeUnaryOp = function($aSelector) { - return $SC("UnaryOpFunction").new($aSelector, this); - }; + method = this.parseProperty(); + if (this.match("(")) { + // expr.method(args) + args = this.parseCallArgument(); + return this.createCallExpression(expr, method, args); + } - spec.composeBinaryOp = function($aSelector, $something, $adverb) { - return $SC("BinaryOpFunction").new($aSelector, this, $something, $adverb); - }; + // expr.method + return this.createCallExpression(expr, method, { list: [] }); + }; - spec.reverseComposeBinaryOp = function($aSelector, $something, $adverb) { - return $SC("BinaryOpFunction").new($aSelector, $something, this, $adverb); - }; + SCParser.prototype.parseLeftHandSideDotValue = function(expr) { + var method, args; - spec.composeNAryOp = function($aSelector, $anArgList) { - return $SC("NAryOpFunction").new($aSelector, this, $anArgList); - }; + method = this.markTouch(this.createIdentifier("value")); + args = this.parseCallArgument(); - spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber, $adverb) { - return this.reverseComposeBinaryOp($aSelector, $aNumber, $adverb); - }; + return this.createCallExpression(expr, method, args, "."); + }; - spec.performBinaryOpOnSignal = function($aSelector, $aSignal, $adverb) { - return this.reverseComposeBinaryOp($aSelector, $aSignal, $adverb); - }; + SCParser.prototype.parseLeftHandSideDotBracket = function(expr) { + var save, method; - spec.performBinaryOpOnComplex = function($aSelector, $aComplex, $adverb) { - return this.reverseComposeBinaryOp($aSelector, $aComplex, $adverb); - }; + save = expr; + method = this.markTouch(this.createIdentifier("value")); + expr = this.markTouch(this.createCallExpression(expr, method, { list: [] }, ".")); - spec.performBinaryOpOnSeqColl = function($aSelector, $aSeqColl, $adverb) { - return this.reverseComposeBinaryOp($aSelector, $aSeqColl, $adverb); - }; + /* istanbul ignore else */ + if (this.opts.range) { + expr.range[0] = save.range[0]; + } - spec.neg = function() { - return this.composeUnaryOp($SC.Symbol("neg")); - }; + /* istanbul ignore else */ + if (this.opts.loc) { + expr.loc.start = save.loc.start; + } - spec.reciprocal = function() { - return this.composeUnaryOp($SC.Symbol("reciprocal")); - }; + return this.parseLeftHandSideListAt(expr); + }; - spec.bitNot = function() { - return this.composeUnaryOp($SC.Symbol("bitNot")); - }; + SCParser.prototype.parseCallArgument = function() { + var args, node, hasKeyword, lookahead; - spec.abs = function() { - return this.composeUnaryOp($SC.Symbol("abs")); - }; + args = { list: [] }; + hasKeyword = false; - spec.asFloat = function() { - return this.composeUnaryOp($SC.Symbol("asFloat")); - }; + this.expect("("); - spec.asInteger = function() { - return this.composeUnaryOp($SC.Symbol("asInteger")); - }; + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + lookahead = this.lookahead; + if (!hasKeyword) { + if (this.match("*")) { + this.lex(); + args.expand = this.parseExpressions(); + hasKeyword = true; + } else if (lookahead.type === Token.Label) { + this.parseCallArgumentKeyword(args); + hasKeyword = true; + } else { + node = this.parseExpressions(); + args.list.push(node); + } + } else { + if (lookahead.type !== Token.Label) { + this.throwUnexpected(lookahead); + } + this.parseCallArgumentKeyword(args); + } + if (this.match(")")) { + break; + } + this.expect(","); + } - spec.ceil = function() { - return this.composeUnaryOp($SC.Symbol("ceil")); - }; + this.expect(")"); - spec.floor = function() { - return this.composeUnaryOp($SC.Symbol("floor")); - }; + return args; + }; - spec.frac = function() { - return this.composeUnaryOp($SC.Symbol("frac")); - }; + SCParser.prototype.parseCallArgumentKeyword = function(args) { + var key, value; - spec.sign = function() { - return this.composeUnaryOp($SC.Symbol("sign")); - }; + key = this.lex().value; + value = this.parseExpressions(); + if (!args.keywords) { + args.keywords = {}; + } + args.keywords[key] = value; + }; - spec.squared = function() { - return this.composeUnaryOp($SC.Symbol("squared")); - }; + SCParser.prototype.parseListIndexer = function() { + var node = null; - spec.cubed = function() { - return this.composeUnaryOp($SC.Symbol("cubed")); - }; + this.expect("["); - spec.sqrt = function() { - return this.composeUnaryOp($SC.Symbol("sqrt")); - }; + if (!this.match("]")) { + if (this.match("..")) { + // [..last] / [..] + node = this.parseListIndexerWithoutFirst(); + } else { + // [first] / [first..last] / [first, second..last] + node = this.parseListIndexerWithFirst(); + } + } - spec.exp = function() { - return this.composeUnaryOp($SC.Symbol("exp")); - }; + this.expect("]"); - spec.midicps = function() { - return this.composeUnaryOp($SC.Symbol("midicps")); - }; + if (node === null) { + this.throwUnexpected({ value: "]" }); + } - spec.cpsmidi = function() { - return this.composeUnaryOp($SC.Symbol("cpsmidi")); - }; + return node; + }; - spec.midiratio = function() { - return this.composeUnaryOp($SC.Symbol("midiratio")); - }; + SCParser.prototype.parseListIndexerWithoutFirst = function() { + var last; - spec.ratiomidi = function() { - return this.composeUnaryOp($SC.Symbol("ratiomidi")); - }; + this.lex(); - spec.ampdb = function() { - return this.composeUnaryOp($SC.Symbol("ampdb")); - }; + if (!this.match("]")) { + last = this.parseExpressions(); - spec.dbamp = function() { - return this.composeUnaryOp($SC.Symbol("dbamp")); - }; + // [..last] + return [ null, null, last ]; + } - spec.octcps = function() { - return this.composeUnaryOp($SC.Symbol("octcps")); - }; + // [..] + return [ null, null, null ]; + }; - spec.cpsoct = function() { - return this.composeUnaryOp($SC.Symbol("cpsoct")); - }; + SCParser.prototype.parseListIndexerWithFirst = function() { + var first = null; - spec.log = function() { - return this.composeUnaryOp($SC.Symbol("log")); - }; + if (!this.match(",")) { + first = this.parseExpressions(); + } else { + this.throwUnexpected(this.lookahead); + } - spec.log2 = function() { - return this.composeUnaryOp($SC.Symbol("log2")); - }; + if (this.match("..")) { + return this.parseListIndexerWithoutSecond(first); + } else if (this.match(",")) { + return this.parseListIndexerWithSecond(first); + } - spec.log10 = function() { - return this.composeUnaryOp($SC.Symbol("log10")); - }; + // [first] + return [ first ]; + }; - spec.sin = function() { - return this.composeUnaryOp($SC.Symbol("sin")); - }; + SCParser.prototype.parseListIndexerWithoutSecond = function(first) { + var last = null; - spec.cos = function() { - return this.composeUnaryOp($SC.Symbol("cos")); - }; + this.lex(); - spec.tan = function() { - return this.composeUnaryOp($SC.Symbol("tan")); - }; + if (!this.match("]")) { + last = this.parseExpressions(); + } - spec.asin = function() { - return this.composeUnaryOp($SC.Symbol("asin")); - }; + // [first..last] + return [ first, null, last ]; + }; - spec.acos = function() { - return this.composeUnaryOp($SC.Symbol("acos")); - }; + SCParser.prototype.parseListIndexerWithSecond = function(first) { + var second, last = null; - spec.atan = function() { - return this.composeUnaryOp($SC.Symbol("atan")); - }; + this.lex(); - spec.sinh = function() { - return this.composeUnaryOp($SC.Symbol("sinh")); - }; + second = this.parseExpressions(); + if (this.match("..")) { + this.lex(); + if (!this.match("]")) { + last = this.parseExpressions(); + } + } else { + this.throwUnexpected(this.lookahead); + } - spec.cosh = function() { - return this.composeUnaryOp($SC.Symbol("cosh")); - }; + // [first, second..last] + return [ first, second, last ]; + }; - spec.tanh = function() { - return this.composeUnaryOp($SC.Symbol("tanh")); - }; + SCParser.prototype.parseProperty = function() { + var token; - spec.rand = function() { - return this.composeUnaryOp($SC.Symbol("rand")); - }; + this.skipComment(); + this.markStart(); + token = this.lex(); - spec.rand2 = function() { - return this.composeUnaryOp($SC.Symbol("rand2")); - }; + if (token.type !== Token.Identifier || this.isClassName(token)) { + this.throwUnexpected(token); + } - spec.linrand = function() { - return this.composeUnaryOp($SC.Symbol("linrand")); - }; + return this.markEnd(this.createIdentifier(token.value)); + }; - spec.bilinrand = function() { - return this.composeUnaryOp($SC.Symbol("bilinrand")); - }; + // 4.8 Primary Expressions + SCParser.prototype.parseArgumentableValue = function() { + var expr, stamp; - spec.sum3rand = function() { - return this.composeUnaryOp($SC.Symbol("sum3rand")); - }; + this.skipComment(); + this.markStart(); - spec.distort = function() { - return this.composeUnaryOp($SC.Symbol("distort")); - }; + stamp = this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type; - spec.softclip = function() { - return this.composeUnaryOp($SC.Symbol("softclip")); - }; + switch (stamp) { + case "#": + expr = this.parsePrimaryHashedExpression(); + break; + case Token.CharLiteral: + case Token.FloatLiteral: + case Token.FalseLiteral: + case Token.IntegerLiteral: + case Token.NilLiteral: + case Token.SymbolLiteral: + case Token.TrueLiteral: + expr = this.createLiteral(this.lex()); + break; + } - spec.coin = function() { - return this.composeUnaryOp($SC.Symbol("coin")); - }; + if (!expr) { + expr = {}; + this.throwUnexpected(this.lex()); + } - spec.even = function() { - return this.composeUnaryOp($SC.Symbol("even")); - }; + return this.markEnd(expr); + }; - spec.odd = function() { - return this.composeUnaryOp($SC.Symbol("odd")); - }; + SCParser.prototype.parsePrimaryExpression = function(node) { + var expr, stamp; - spec.rectWindow = function() { - return this.composeUnaryOp($SC.Symbol("rectWindow")); - }; + if (node) { + return node; + } - spec.hanWindow = function() { - return this.composeUnaryOp($SC.Symbol("hanWindow")); - }; + this.skipComment(); + this.markStart(); - spec.welWindow = function() { - return this.composeUnaryOp($SC.Symbol("welWindow")); - }; + if (this.match("~")) { + this.lex(); + expr = this.createGlobalExpression(this.parseIdentifier()); + } else { + stamp = this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type; + switch (stamp) { + case "(": + expr = this.parseParentheses(); + break; + case "{": + expr = this.parseBraces(); + break; + case "[": + expr = this.parseListInitialiser(); + break; + case Token.Keyword: + expr = this.parsePrimaryKeywordExpression(); + break; + case Token.Identifier: + expr = this.parsePrimaryIdentifier(); + break; + case Token.StringLiteral: + expr = this.parsePrimaryStringExpression(); + break; + default: + // case "#": + // case Token.CharLiteral: + // case Token.FloatLiteral: + // case Token.FalseLiteral: + // case Token.IntegerLiteral: + // case Token.NilLiteral: + // case Token.SymbolLiteral: + // case Token.TrueLiteral: + expr = this.parseArgumentableValue(stamp); + break; + } + } - spec.triWindow = function() { - return this.composeUnaryOp($SC.Symbol("triWindow")); - }; + return this.markEnd(expr); + }; - spec.scurve = function() { - return this.composeUnaryOp($SC.Symbol("scurve")); - }; + SCParser.prototype.parsePrimaryHashedExpression = function() { + var expr, lookahead; - spec.ramp = function() { - return this.composeUnaryOp($SC.Symbol("ramp")); - }; + lookahead = this.lookahead; - spec.isPositive = function() { - return this.composeUnaryOp($SC.Symbol("isPositive")); - }; + this.lex(); - spec.isNegative = function() { - return this.composeUnaryOp($SC.Symbol("isNegative")); - }; + switch (this.matchAny([ "[", "{" ])) { + case "[": + expr = this.parsePrimaryImmutableListExpression(lookahead); + break; + case "{": + expr = this.parsePrimaryClosedFunctionExpression(); + break; + default: + expr = {}; + this.throwUnexpected(this.lookahead); + break; + } - spec.isStrictlyPositive = function() { - return this.composeUnaryOp($SC.Symbol("isStrictlyPositive")); - }; + return expr; + }; - spec.rho = function() { - return this.composeUnaryOp($SC.Symbol("rho")); - }; + SCParser.prototype.parsePrimaryImmutableListExpression = function(lookahead) { + var expr; - spec.theta = function() { - return this.composeUnaryOp($SC.Symbol("theta")); - }; + if (this.state.immutableList) { + this.throwUnexpected(lookahead); + } - spec.rotate = function($function) { - return this.composeBinaryOp($SC.Symbol("rotate"), $function); - }; + this.state.immutableList = true; + expr = this.parseListInitialiser(); + this.state.immutableList = false; - spec.dist = function($function) { - return this.composeBinaryOp($SC.Symbol("dist"), $function); - }; + return expr; + }; - spec["+"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("+"), $function, $adverb); - }; + SCParser.prototype.parsePrimaryClosedFunctionExpression = function() { + var expr, disallowGenerator, closedFunction; - spec["-"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("-"), $function, $adverb); - }; + disallowGenerator = this.state.disallowGenerator; + closedFunction = this.state.closedFunction; - spec["*"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("*"), $function, $adverb); - }; + this.state.disallowGenerator = true; + this.state.closedFunction = true; + expr = this.parseBraces(); + this.state.closedFunction = closedFunction; + this.state.disallowGenerator = disallowGenerator; - spec["/"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("/"), $function, $adverb); - }; + return expr; + }; - spec.div = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("div"), $function, $adverb); - }; - - spec.mod = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("mod"), $function, $adverb); - }; - - spec.pow = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("pow"), $function, $adverb); - }; + SCParser.prototype.parsePrimaryKeywordExpression = function() { + if (Keywords[this.lookahead.value] === "keyword") { + this.throwUnexpected(this.lookahead); + } - spec.min = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("min"), $function, $adverb); - }; + return this.createThisExpression(this.lex().value); + }; - spec.max = function($function, $adverb) { - $function = utils.defaultValue$Integer($function, 0); - return this.composeBinaryOp($SC.Symbol("max"), $function, $adverb); - }; + SCParser.prototype.parsePrimaryIdentifier = function() { + var expr, lookahead; - spec["<"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("<"), $function, $adverb); - }; + lookahead = this.lookahead; - spec["<="] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("<="), $function, $adverb); - }; + expr = this.parseIdentifier(); - spec[">"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol(">"), $function, $adverb); - }; + if (expr.name === "_") { + expr.name = "$_" + this.state.underscore.length.toString(); + this.state.underscore.push(expr); + } - spec[">="] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol(">="), $function, $adverb); - }; + return expr; + }; - spec.bitAnd = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("bitAnd"), $function, $adverb); - }; + SCParser.prototype.isInterpolatedString = function(value) { + var re = /(^|[^\x5c])#\{/; + return re.test(value); + }; - spec.bitOr = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("bitOr"), $function, $adverb); - }; + SCParser.prototype.parsePrimaryStringExpression = function() { + var token; - spec.bitXor = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("bitXor"), $function, $adverb); - }; + token = this.lex(); - spec.bitHammingDistance = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("bitHammingDistance"), $function, $adverb); - }; + if (this.isInterpolatedString(token.value)) { + return this.parseInterpolatedString(token.value); + } - spec.lcm = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("lcm"), $function, $adverb); - }; + return this.createLiteral(token); + }; - spec.gcd = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("gcd"), $function, $adverb); - }; + SCParser.prototype.parseInterpolatedString = function(value) { + var len, items; + var index1, index2, code, parser; - spec.round = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("round"), $function, $adverb); - }; + len = value.length; + items = []; - spec.roundUp = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("roundUp"), $function, $adverb); - }; + index1 = 0; - spec.trunc = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("trunc"), $function, $adverb); - }; + do { + index2 = findString$InterpolatedString(value, index1); + if (index2 >= len) { + break; + } + code = value.substr(index1, index2 - index1); + if (code) { + items.push('"' + code + '"'); + } - spec.atan2 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("atan2"), $function, $adverb); - }; + index1 = index2 + 2; + index2 = findExpression$InterpolatedString(value, index1, items); - spec.hypot = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("hypot"), $function, $adverb); - }; + code = value.substr(index1, index2 - index1); + if (code) { + items.push("(" + code + ").asString"); + } - spec.hypotApx = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("hypotApx"), $function, $adverb); - }; + index1 = index2 + 1; + } while (index1 < len); - spec.leftShift = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("leftShift"), $function, $adverb); - }; + if (index1 < len) { + items.push('"' + value.substr(index1) + '"'); + } - spec.rightShift = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("rightShift"), $function, $adverb); - }; + code = items.join("++"); + parser = new SCParser(code, {}); + parser.peek(); - spec.unsignedRightShift = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("unsignedRightShift"), $function, $adverb); - }; + return parser.parseExpression(); + }; - spec.ring1 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("ring1"), $function, $adverb); - }; + var findString$InterpolatedString = function(value, index) { + var len, ch; - spec.ring2 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("ring2"), $function, $adverb); - }; + len = value.length; - spec.ring3 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("ring3"), $function, $adverb); - }; + while (index < len) { + ch = value.charAt(index); + if (ch === "#") { + if (value.charAt(index + 1) === "{") { + break; + } + } else if (ch === "\\") { + index += 1; + } + index += 1; + } - spec.ring4 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("ring4"), $function, $adverb); - }; + return index; + }; - spec.difsqr = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("difsqr"), $function, $adverb); - }; + var findExpression$InterpolatedString = function(value, index) { + var len, depth, ch; - spec.sumsqr = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("sumsqr"), $function, $adverb); - }; + len = value.length; - spec.sqrsum = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("sqrsum"), $function, $adverb); - }; + depth = 0; + while (index < len) { + ch = value.charAt(index); + if (ch === "}") { + if (depth === 0) { + break; + } + depth -= 1; + } else if (ch === "{") { + depth += 1; + } + index += 1; + } - spec.sqrdif = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("sqrdif"), $function, $adverb); - }; + return index; + }; - spec.absdif = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("absdif"), $function, $adverb); - }; + // ( ... ) + SCParser.prototype.parseParentheses = function() { + var marker, expr, generator, items; - spec.thresh = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("thresh"), $function, $adverb); - }; + this.skipComment(); - spec.amclip = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("amclip"), $function, $adverb); - }; + marker = this.createLocationMarker(); + this.expect("("); - spec.scaleneg = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("scaleneg"), $function, $adverb); - }; + if (this.match(":")) { + this.lex(); + generator = true; + } - spec.clip2 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("clip2"), $function, $adverb); - }; + if (this.lookahead.type === Token.Label) { + expr = this.parseObjectInitialiser(); + } else if (this.matchKeyword("var")) { + expr = this.withScope(function() { + var body; + body = this.parseFunctionBody(")"); + return this.createBlockExpression(body); + }); + } else if (this.match("..")) { + expr = this.parseSeriesInitialiser(null, generator); + } else if (this.match(")")) { + expr = this.createObjectExpression([]); + } else { + items = this.parseParenthesesGuess(generator, marker); + expr = items[0]; + marker = items[1]; + } - spec.fold2 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("fold2"), $function, $adverb); - }; + this.expect(")"); - spec.wrap2 = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("wrap2"), $function, $adverb); - }; + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } - spec.excess = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("excess"), $function, $adverb); - }; + return expr; + }; - spec.firstArg = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("firstArg"), $function, $adverb); - }; + SCParser.prototype.parseParenthesesGuess = function(generator, marker) { + var node, expr; - spec.rrand = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("rrand"), $function, $adverb); - }; + node = this.parseExpression(); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseSeriesInitialiser(node, generator); + } else if (this.match(":")) { + expr = this.parseObjectInitialiser(node); + } else if (this.match(";")) { + expr = this.parseExpressions(node); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseSeriesInitialiser(expr, generator); + } + marker = null; + } else { + expr = this.parseExpression(node); + marker = null; + } - spec.exprand = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("exprand"), $function, $adverb); - }; + return [ expr, marker ]; + }; - spec["@"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("@"), $function, $adverb); - }; + SCParser.prototype.parseObjectInitialiser = function(node) { + var elements = [], innerElements; - spec.real = utils.nop; - spec.imag = function() { - return $SC.Float(0.0); - }; + innerElements = this.state.innerElements; + this.state.innerElements = true; - spec["||"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("||"), $function, $adverb); - }; + if (node) { + this.expect(":"); + } else { + node = this.parseLabelAsSymbol(); + } + elements.push(node, this.parseExpression()); - spec["&&"] = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("&&"), $function, $adverb); - }; + if (this.match(",")) { + this.lex(); + } - spec.xor = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("xor"), $function, $adverb); - }; + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + if (this.lookahead.type === Token.Label) { + node = this.parseLabelAsSymbol(); + } else { + node = this.parseExpression(); + this.expect(":"); + } + elements.push(node, this.parseExpression()); + if (!this.match(")")) { + this.expect(","); + } + } - spec.nand = function($function, $adverb) { - return this.composeBinaryOp($SC.Symbol("nand"), $function, $adverb); - }; + this.state.innerElements = innerElements; - spec.not = function() { - return this.composeUnaryOp($SC.Symbol("not")); - }; + return this.createObjectExpression(elements); + }; - spec.ref = function() { - return this.composeUnaryOp($SC.Symbol("asRef")); - }; + SCParser.prototype.parseSeriesInitialiser = function(node, generator) { + var method, innerElements; + var items = []; - spec.clip = function($lo, $hi) { - return this.composeNAryOp($SC.Symbol("clip"), $SC.Array([ $lo, $hi ])); - }; + innerElements = this.state.innerElements; + this.state.innerElements = true; - spec.wrap = function($lo, $hi) { - return this.composeNAryOp($SC.Symbol("wrap"), $SC.Array([ $lo, $hi ])); - }; + method = this.markTouch(this.createIdentifier( + generator ? "seriesIter" : "series" + )); - spec.fold = function($lo, $hi) { - return this.composeNAryOp($SC.Symbol("fold"), $SC.Array([ $lo, $hi ])); - }; + if (node === null) { + // (..), (..last) + items = this.parseSeriesInitialiserWithoutFirst(generator); + } else { + items = this.parseSeriesInitialiserWithFirst(node, generator); + } - spec.blend = function($that, $blendFrac) { - $blendFrac = utils.defaultValue$Float($blendFrac, 0.5); - return this.composeNAryOp( - $SC.Symbol("blend"), $SC.Array([ $that, $blendFrac ]) - ); - }; + this.state.innerElements = innerElements; - spec.linlin = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("linlin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) - ); - }; + return this.createCallExpression(items.shift(), method, { list: items }); + }; - spec.linexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("linexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) - ); - }; + SCParser.prototype.parseSeriesInitialiserWithoutFirst = function(generator) { + var first, last = null; - spec.explin = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("explin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) - ); - }; + // (..last) + first = this.markTouch({ + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral + }); - spec.expexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("expexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) - ); - }; + this.expect(".."); + if (this.match(")")) { + if (!generator) { + this.throwUnexpected(this.lookahead); + } + } else { + last = this.parseExpressions(); + } - spec.lincurve = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("lincurve"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) - ); - }; + return [ first, null, last ]; + }; - spec.curvelin = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("curvelin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) - ); - }; + SCParser.prototype.parseSeriesInitialiserWithFirst = function(node, generator) { + var first, second = null, last = null; - spec.bilin = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("bilin"), $SC.Array([ - $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip - ]) - ); - }; + first = node; + if (this.match(",")) { + // (first, second .. last) + this.lex(); + second = this.parseExpressions(); + if (Array.isArray(second) && second.length === 0) { + this.throwUnexpected(this.lookahead); + } + this.expect(".."); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } else { + // (first..last) + this.lex(); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } - spec.biexp = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); - return this.composeNAryOp( - $SC.Symbol("biexp"), $SC.Array([ - $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip - ]) - ); - }; + return [ first, second, last ]; + }; - spec.moddif = function($function, $mod) { - $function = utils.defaultValue$Float($function, 0.0); - $mod = utils.defaultValue$Float($mod , 1.0); - return this.composeNAryOp( - $SC.Symbol("moddif"), $SC.Array([ $function, $mod ]) - ); - }; + SCParser.prototype.parseListInitialiser = function() { + var elements, innerElements; - spec.degreeToKey = function($scale, $stepsPerOctave) { - $stepsPerOctave = utils.defaultValue$Integer($stepsPerOctave, 12); - return this.composeNAryOp( - $SC.Symbol("degreeToKey"), $SC.Array([ $scale, $stepsPerOctave ]) - ); - }; + elements = []; - spec.degrad = function() { - return this.composeUnaryOp($SC.Symbol("degrad")); - }; + innerElements = this.state.innerElements; + this.state.innerElements = true; - spec.raddeg = function() { - return this.composeUnaryOp($SC.Symbol("raddeg")); - }; + this.expect("["); - spec.applyTo = function() { - return this.value.apply(this, arguments); - }; + while (this.lookahead.type !== Token.EOF && !this.match("]")) { + if (this.lookahead.type === Token.Label) { + elements.push(this.parseLabelAsSymbol(), this.parseExpression()); + } else { + elements.push(this.parseExpression()); + if (this.match(":")) { + this.lex(); + elements.push(this.parseExpression()); + } + } + if (!this.match("]")) { + this.expect(","); + } + } - // TODO: implements <> - // TODO: implements sampled + this.expect("]"); - spec.asUGenInput = function($for) { - return this.value($for); - }; + this.state.innerElements = innerElements; - spec.asAudioRateInput = function($for) { - var $result; + return this.createListExpression(elements, this.state.immutableList); + }; - $result = this.value($for); + // { ... } + SCParser.prototype.parseBraces = function(blocklist) { + var expr; - if ($result.rate().__sym__() !== "audio") { - return $SC("K2A").ar($result); + this.skipComment(); + this.markStart(); + + this.expect("{"); + + if (this.match(":")) { + if (!this.state.disallowGenerator) { + this.lex(); + expr = this.parseGeneratorInitialiser(); + } else { + expr = {}; + this.throwUnexpected(this.lookahead); } + } else { + expr = this.parseFunctionExpression(this.state.closedFunction, blocklist); + } - return $result; - }; + this.expect("}"); - spec.asControlInput = function() { - return this.value(); - }; - - spec.isValidUGenInput = utils.alwaysReturn$true; - }); - - function SCUnaryOpFunction(args) { - this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); - } - - sc.lang.klass.define(SCUnaryOpFunction, "UnaryOpFunction : AbstractFunction", function(spec) { - - spec.value = function() { - var $a = this.$a; - return $a.value.apply($a, arguments).perform(this.$selector); - }; - - spec.valueArray = function($args) { - return this.$a.valueArray($args).perform(this.$selector); - }; + return this.markEnd(expr); + }; - // TODO: implements valueEnvir - // TODO: implements valueArrayEnvir + SCParser.prototype.parseGeneratorInitialiser = function() { + this.throwError({}, Message.NotImplemented, "generator literal"); - spec.functionPerformList = function($selector, $arglist) { - return this.performList($selector, $arglist); - }; + this.parseExpression(); + this.expect(","); - // TODO: implements storeOn - }); + while (this.lookahead.type !== Token.EOF && !this.match("}")) { + this.parseExpression(); + if (!this.match("}")) { + this.expect(","); + } + } - function SCBinaryOpFunction(args) { - this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); - this.$b = utils.defaultValue$Nil(args[2]); - this.$adverb = utils.defaultValue$Nil(args[3]); - } + return this.createLiteral({ value: "null", valueType: Token.NilLiteral }); + }; - sc.lang.klass.define(SCBinaryOpFunction, "BinaryOpFunction : AbstractFunction", function(spec) { + SCParser.prototype.parseLabel = function() { + this.skipComment(); + this.markStart(); + return this.markEnd(this.createLabel(this.lex().value)); + }; - spec.value = function() { - return this.$a.value.apply(this.$a, arguments) - .perform(this.$selector, this.$b.value.apply(this.$b, arguments), this.$adverb); - }; + SCParser.prototype.parseLabelAsSymbol = function() { + var label, node; - spec.valueArray = function($args) { - return this.$a.valueArray($args) - .perform(this.$selector, this.$b.valueArray($args, arguments), this.$adverb); + label = this.parseLabel(); + node = { + type: Syntax.Literal, + value: label.name, + valueType: Token.SymbolLiteral }; - // TODO: implements valueEnvir - // TODO: implements valueArrayEnvir + /* istanbul ignore else */ + if (label.range) { + node.range = label.range; + } + /* istanbul ignore else */ + if (label.loc) { + node.loc = label.loc; + } - spec.functionPerformList = function($selector, $arglist) { - return this.performList($selector, $arglist); - }; + return node; + }; - // TODO: implements storeOn - }); + SCParser.prototype.parseIdentifier = function() { + var expr; - function SCNAryOpFunction(args) { - this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); - this.$arglist = utils.defaultValue$Nil(args[2]); - } + this.skipComment(); + this.markStart(); - sc.lang.klass.define(SCNAryOpFunction, "NAryOpFunction : AbstractFunction", function(spec) { + if (this.lookahead.type !== Syntax.Identifier) { + this.throwUnexpected(this.lookahead); + } - spec.value = function() { - var args = arguments; - return this.$a.value.apply(this.$a, args) - .performList(this.$selector, this.$arglist.collect($SC.Function(function($_) { - return $_.value.apply($_, args); - }))); - }; + expr = this.lex(); - spec.valueArray = function($args) { - return this.$a.valueArray($args) - .performList(this.$selector, this.$arglist.collect($SC.Function(function($_) { - return $_.valueArray($args); - }))); - }; + return this.markEnd(this.createIdentifier(expr.value)); + }; - // TODO: implements valueEnvir - // TODO: implements valueArrayEnvir + SCParser.prototype.parseVariableIdentifier = function() { + var token, value, ch; - spec.functionPerformList = function($selector, $arglist) { - return this.performList($selector, $arglist); - }; + this.skipComment(); + this.markStart(); - // TODO: implements storeOn - }); + token = this.lex(); + value = token.value; - function SCFunctionList(args) { - this.__initializeWith__("AbstractFunction"); - this.$array = utils.defaultValue$Nil(args[0]); - this._flopped = false; - } + if (token.type !== Token.Identifier) { + this.throwUnexpected(token); + } else { + ch = value.charAt(0); + if (("A" <= ch && ch <= "Z") || ch === "_") { + this.throwUnexpected(token); + } + } - sc.lang.klass.define(SCFunctionList, "FunctionList : AbstractFunction", function(spec, utils) { - var $int_0 = utils.$int_0; + return this.markEnd(this.createIdentifier(value)); + }; - spec.array = function() { - return this.$array; - }; + SCParser.prototype.markStart = function() { + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.push( + this.index - this.lineStart, + this.lineNumber + ); + } + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.push( + this.index + ); + } + }; - spec.array_ = function($value) { - $value = utils.defaultValue$Nil($value); - this.$array = $value; - return this; - }; + SCParser.prototype.markEnd = function(node) { + if (Array.isArray(node) || node.range || node.loc) { + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.pop(); + } + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.pop(); + this.marker.pop(); + } + } else { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.marker.pop(), this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.marker.pop(), + column: this.marker.pop() + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + } + return node; + }; - spec.flopped = function() { - return $SC.Boolean(this._flopped); - }; + SCParser.prototype.markTouch = function(node) { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.index, this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + return node; + }; - spec.addFunc = fn(function($$functions) { - if (this._flopped) { - throw new Error("cannot add a function to a flopped FunctionList"); - } + SCParser.prototype.throwError = function(token, messageFormat) { + var args, message; + var error, index, lineNumber, column; + var prev; - this.$array = this.$array.addAll($$functions); + args = Array.prototype.slice.call(arguments, 2); + message = messageFormat.replace(/%(\d)/g, function(whole, index) { + return args[index]; + }); - return this; - }, "*functions"); + if (typeof token.lineNumber === "number") { + index = token.range[0]; + lineNumber = token.lineNumber; + column = token.range[0] - token.lineStart + 1; + } else { + index = this.index; + lineNumber = this.lineNumber; + column = this.index - this.lineStart + 1; + } - spec.removeFunc = function($function) { - this.$array.remove($function); + error = new Error("Line " + lineNumber + ": " + message); + error.index = index; + error.lineNumber = lineNumber; + error.column = column; + error.description = message; - if (this.$array.size() < 2) { - return this.$array.at($int_0); + if (this.errors) { + prev = this.errors[this.errors.length - 1]; + if (!(prev && error.index <= prev.index)) { + this.errors.push(error); } + } else { + throw error; + } + }; - return this; - }; + SCParser.prototype.throwUnexpected = function(token) { + switch (token.type) { + case Token.EOF: + this.throwError(token, Message.UnexpectedEOS); + break; + case Token.FloatLiteral: + case Token.IntegerLiteral: + this.throwError(token, Message.UnexpectedNumber); + break; + case Token.CharLiteral: + this.throwError(token, Message.UnexpectedChar); + break; + case Token.StringLiteral: + this.throwError(token, Message.UnexpectedString); + break; + case Token.SymbolLiteral: + this.throwError(token, Message.UnexpectedSymbol); + break; + case Token.Identifier: + this.throwError(token, Message.UnexpectedIdentifier); + break; + default: + this.throwError(token, Message.UnexpectedToken, token.value); + break; + } + }; - spec.replaceFunc = function($find, $replace) { - this.$array = this.$array.replace($find, $replace); - return this; - }; + function isValidArgumentValue(node) { + if (node.type === Syntax.Literal) { + return true; + } + if (node.type === Syntax.ListExpression) { + return node.elements.every(function(node) { + return node.type === Syntax.Literal; + }); + } - spec.value = function() { - var $res, args = arguments; + return false; + } - $res = this.$array.collect($SC.Function(function($_) { - return $_.value.apply($_, args); - })); + parser.parse = function(source, opts) { + var instance, ast; - return this._flopped ? $res.flop() : $res; - }; + opts = opts || /* istanbul ignore next */ {}; - spec.valueArray = function($args) { - var $res; + instance = new SCParser(source, opts); + ast = instance.parse(); - $res = this.$array.collect($SC.Function(function($_) { - return $_.valueArray($args); - })); + if (!!opts.tokens && typeof instance.tokens !== "undefined") { + ast.tokens = instance.tokens; + } + if (!!opts.tolerant && typeof instance.errors !== "undefined") { + ast.errors = instance.errors; + } - return this._flopped ? $res.flop() : $res; - }; + return ast; + }; - // TODO: implements valueEnvir - // TODO: implements valueArrayEnvir + sc.lang.parser = parser; - spec.do = function($function) { - this.$array.do($function); - return this; - }; +})(sc); - spec.flop = function() { - if (!this._flopped) { - this.$array = this.$array.collect($SC.Function(function($_) { - return $_.flop(); - })); - } - this._flopped = true; +// src/sc/lang/dollarSC.js +(function(sc) { - return this; - }; + var $SC = function(name) { + return sc.lang.klass.get(name); + }; - // TODO: implements envirFlop + /* istanbul ignore next */ + var shouldBeImplementedInClassLib = function() {}; - spec.storeArgs = function() { - return $SC.Array([ this.$array ]); - }; + $SC.Class = shouldBeImplementedInClassLib; + $SC.Integer = shouldBeImplementedInClassLib; + $SC.Float = shouldBeImplementedInClassLib; + $SC.Char = shouldBeImplementedInClassLib; + $SC.Array = shouldBeImplementedInClassLib; + $SC.String = shouldBeImplementedInClassLib; + $SC.Function = shouldBeImplementedInClassLib; + $SC.Ref = shouldBeImplementedInClassLib; + $SC.Symbol = shouldBeImplementedInClassLib; + $SC.Boolean = shouldBeImplementedInClassLib; + $SC.True = shouldBeImplementedInClassLib; + $SC.False = shouldBeImplementedInClassLib; + $SC.Nil = shouldBeImplementedInClassLib; - }); + sc.lang.$SC = $SC; })(sc); -// src/sc/lang/classlib/Streams/Stream.js +// src/sc/lang/fn.js (function(sc) { - function SCStream() { - this.__initializeWith__("AbstractFunction"); - } - - sc.lang.klass.define(SCStream, "Stream : AbstractFunction", function() { - // TODO: implements parent - // TODO: implements next - // TODO: implements iter - // TODO: implements value - // TODO: implements valueArray - // TODO: implements nextN - // TODO: implements all - // TODO: implements put - // TODO: implements putN - // TODO: implements putAll - // TODO: implements do - // TODO: implements subSample - // TODO: implements loop - // TODO: implements generate - // TODO: implements collect - // TODO: implements reject - // TODO: implements select - // TODO: implements dot - // TODO: implements interlace - // TODO: implements ++ - // TODO: implements appendStream - // TODO: implements collate - // TODO: implements <> - // TODO: implements composeUnaryOp - // TODO: implements composeBinaryOp - // TODO: implements reverseComposeBinaryOp - // TODO: implements composeNAryOp - // TODO: implements embedInStream - // TODO: implements while - // TODO: implements asEventStreamPlayer - // TODO: implements play - // TODO: implements trace - // TODO: implements constrain - // TODO: implements repeat - }); - - function SCPauseStream() { - this.__initializeWith__("Stream"); - } + var slice = [].slice; + var $SC = sc.lang.$SC; - sc.lang.klass.define(SCPauseStream, "PauseStream : Stream", function() { - // TODO: implements stream - // TODO: implements originalStream - // TODO: implements clock - // TODO: implements nextBeat - // TODO: implements streamHasEnded - // TODO: implements streamHasEnded_ + var _getDefaultValue = function(value) { + var ch; - // TODO: implements isPlaying - // TODO: implements play - // TODO: implements reset - // TODO: implements stop - // TODO: implements prStop - // TODO: implements removedFromScheduler - // TODO: implements streamError - // TODO: implements wasStopped - // TODO: implements canPause - // TODO: implements pause - // TODO: implements resume - // TODO: implements refresh - // TODO: implements start - // TODO: implements stream_ - // TODO: implements next - // TODO: implements awake - // TODO: implements threadPlayer - }); + switch (value) { + case "nil": + return $SC.Nil(); + case "true": + return $SC.True(); + case "false": + return $SC.False(); + case "inf": + return $SC.Float(Infinity); + case "-inf": + return $SC.Float(-Infinity); + } - function SCTask() { - this.__initializeWith__("PauseStream"); - } + ch = value.charAt(0); + switch (ch) { + case "$": + return $SC.Char(value.charAt(1)); + case "\\": + return $SC.Symbol(value.substr(1)); + } - sc.lang.klass.define(SCTask, "Task : PauseStream", function() { - // TODO: implements storeArgs - }); + if (value.indexOf(".") !== -1) { + return $SC.Float(+value); + } -})(sc); + return $SC.Integer(+value); + }; -// src/sc/lang/classlib/Math/Magnitude.js -(function(sc) { + var getDefaultValue = function(value) { + if (value.charAt(0) === "[") { + return $SC.Array(value.slice(1, -2).split(",").map(function(value) { + return _getDefaultValue(value.trim()); + })); + } + return _getDefaultValue(value); + }; - var $SC = sc.lang.$SC; + var fn = function(func, def) { + var argItems, argNames, argVals; + var remain, wrapper; - sc.lang.klass.refine("Magnitude", function(spec, utils) { - spec["=="] = function($aMagnitude) { - return $SC.Boolean(this.valueOf() === $aMagnitude.valueOf()); - }; + argItems = def.split(/\s*;\s*/); + if (argItems[argItems.length - 1].charAt(0) === "*") { + remain = !!argItems.pop(); + } - spec["!="] = function($aMagnitude) { - return $SC.Boolean(this.valueOf() !== $aMagnitude.valueOf()); - }; + argNames = new Array(argItems.length); + argVals = new Array(argItems.length); - spec.hash = function() { - return this._subclassResponsibility("hash"); - }; + argItems.forEach(function(items, i) { + items = items.split("="); + argNames[i] = items[0].trim(); + argVals [i] = getDefaultValue(items[1] || "nil"); + }); - spec["<"] = function($aMagnitude) { - return $SC.Boolean(this < $aMagnitude); - }; + wrapper = function() { + var given, args; - spec[">"] = function($aMagnitude) { - return $SC.Boolean(this > $aMagnitude); - }; + given = slice.call(arguments); + args = argVals.slice(); - spec["<="] = function($aMagnitude) { - return $SC.Boolean(this <= $aMagnitude); - }; + if (isDictionary(given[given.length - 1])) { + setKeywordArguments(args, argNames, given.pop()); + } - spec[">="] = function($aMagnitude) { - return $SC.Boolean(this >= $aMagnitude); - }; + copy(args, given, Math.min(argNames.length, given.length)); - spec.exclusivelyBetween = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - return $SC.Boolean($lo < this && this < $hi); - }; + if (remain) { + args.push($SC.Array(given.slice(argNames.length))); + } - spec.inclusivelyBetween = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - return $SC.Boolean($lo <= this && this <= $hi); + return func.apply(this, args); }; - spec.min = function($aMagnitude) { - $aMagnitude = utils.defaultValue$Nil($aMagnitude); - return this <= $aMagnitude ? this : $aMagnitude; - }; + wrapper._argNames = argNames; + wrapper._argVals = argVals; - spec.max = function($aMagnitude) { - $aMagnitude = utils.defaultValue$Nil($aMagnitude); - return this >= $aMagnitude ? this : $aMagnitude; - }; + return wrapper; + }; - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - return this <= $lo ? $lo : this >= $hi ? $hi : this; - }; - }); + var isDictionary = function(obj) { + return !!(obj && obj.constructor === Object); + }; -})(sc); + var copy = function(args, given, length) { + for (var i = 0; i < length; ++i) { + if (given[i]) { + args[i] = given[i]; + } + } + }; -// src/sc/lang/classlib/Math/Number.js -(function(sc) { - - var $SC = sc.lang.$SC; - var iterator = sc.lang.iterator; + var setKeywordArguments = function(args, argNames, dict) { + Object.keys(dict).forEach(function(key) { + var index = argNames.indexOf(key); + if (index !== -1) { + args[index] = dict[key]; + } + }); + }; - sc.lang.klass.refine("Number", function(spec, utils) { - spec.isNumber = utils.alwaysReturn$true; + sc.lang.fn = fn; - spec["+"] = function() { - return this._subclassResponsibility("+"); - }; +})(sc); - spec["-"] = function() { - return this._subclassResponsibility("-"); - }; +// src/sc/lang/klass.js +(function(sc) { - spec["*"] = function() { - return this._subclassResponsibility("*"); - }; + var slice = [].slice; + var $SC = sc.lang.$SC; - spec["/"] = function() { - return this._subclassResponsibility("/"); - }; + var klass = {}; + var metaClasses = {}; + var classes = klass.classes = {}; - spec.mod = function() { - return this._subclassResponsibility("mod"); - }; + var createClassInstance = function(MetaSpec) { + var instance = new SCClass(); + instance._MetaSpec = MetaSpec; + return instance; + }; - spec.div = function() { - return this._subclassResponsibility("div"); - }; + var extend = function(constructor, superMetaClass) { + function F() {} + F.prototype = superMetaClass._Spec.prototype; + constructor.prototype = new F(); - spec.pow = function() { - return this._subclassResponsibility("pow"); - }; + function Meta_F() {} + Meta_F.prototype = superMetaClass._MetaSpec.prototype; - spec.performBinaryOpOnSeqColl = function($aSelector, $aSeqColl, $adverb) { - var $this = this; - $aSeqColl = utils.defaultValue$Nil($aSeqColl); + function MetaSpec() {} + MetaSpec.prototype = new Meta_F(); - return $aSeqColl.collect($SC.Function(function($item) { - return $item.perform($aSelector, $this, $adverb); - })); - }; + constructor.metaClass = createClassInstance(MetaSpec); + }; - // TODO: implements performBinaryOpOnPoint + var def = function(className, constructor, fn, opts) { + var classMethods, instanceMethods, setMethod, spec; - spec.rho = utils.nop; + classMethods = constructor.metaClass._MetaSpec.prototype; + instanceMethods = constructor.prototype; - spec.theta = function() { - return $SC.Float(0.0); + setMethod = function(methods, methodName, func) { + var bond; + if (methods.hasOwnProperty(methodName) && !opts.force) { + bond = methods === classMethods ? "." : "#"; + throw new Error( + "sc.lang.klass.refine: " + + className + bond + methodName + " is already defined." + ); + } + methods[methodName] = func; }; - spec.real = utils.nop; + if (typeof fn === "function") { + fn(spec = {}, klass.utils); + } else { + spec = fn; + } - spec.imag = function() { - return $SC.Float(0.0); - }; + Object.keys(spec).forEach(function(methodName) { + if (methodName.charCodeAt(0) === 0x24) { // u+0024 is '$' + setMethod(classMethods, methodName.substr(1), spec[methodName]); + } else { + setMethod(instanceMethods, methodName, spec[methodName]); + } + }); + }; - // TODO: implements @ - // TODO: implements complex - // TODO: implements polar + var throwIfInvalidArgument = function(constructor, className) { + if (typeof constructor !== "function") { + throw new Error( + "sc.lang.klass.define: " + + "first argument must be a constructor, but got: " + typeof(constructor) + ); + } - spec.for = function($endValue, $function) { - iterator.execute( - iterator.number$for(this, $endValue), - $function + if (typeof className !== "string") { + throw new Error( + "sc.lang.klass.define: " + + "second argument must be a string, but got: " + String(className) ); - return this; - }; + } + }; - spec.forBy = function($endValue, $stepValue, $function) { - iterator.execute( - iterator.number$forBy(this, $endValue, $stepValue), - $function + var throwIfInvalidClassName = function(className, superClassName) { + var ch0 = className.charCodeAt(0); + + if (ch0 < 0x41 || 0x5a < ch0) { // faster test than !/^[A-Z]/.test(className) + throw new Error( + "sc.lang.klass.define: " + + "classname should be CamelCase, but got '" + className + "'" ); - return this; - }; + } - spec.forSeries = function($second, $last, $function) { - iterator.execute( - iterator.number$forSeries(this, $second, $last), - $function + if (metaClasses.hasOwnProperty(className)) { + throw new Error( + "sc.lang.klass.define: " + + "class '" + className + "' is already registered." ); - return this; - }; - }); + } -})(sc); + if (className !== "Object") { + if (!metaClasses.hasOwnProperty(superClassName)) { + throw new Error( + "sc.lang.klass.define: " + + "superclass '" + superClassName + "' is not registered." + ); + } + } + }; -// src/sc/lang/classlib/Math/SimpleNumber.js -(function(sc) { + var buildClass = function(className, constructor) { + var newClass, metaClass; - var $SC = sc.lang.$SC; - var rand = sc.libs.random; + metaClass = constructor.metaClass; - function prOpSimpleNumber(selector, func) { - return function($aNumber, $adverb) { - var tag = $aNumber.__tag; + newClass = new metaClass._MetaSpec(); + newClass._name = className; + newClass._Spec = constructor; + constructor.prototype.__class = newClass; + constructor.prototype.__Spec = constructor; - switch (tag) { - case 770: - case 777: - return $SC.Boolean(func(this._, $aNumber._)); - } + metaClass._Spec = constructor; + metaClass._isMetaClass = true; + metaClass._name = "Meta_" + className; - if ($aNumber.isSequenceableCollection().valueOf()) { - return $aNumber.performBinaryOpOnSimpleNumber( - $SC.Symbol(selector), this, $adverb - ); - } + classes["Meta_" + className] = metaClass; + classes[className] = newClass; - return $SC.False(); - }; - } + if (newClass.initClass) { + newClass.initClass(); + } - sc.lang.klass.refine("SimpleNumber", function(spec, utils) { - var $nil = utils.$nil; - var $int_0 = utils.$int_0; - var $int_1 = utils.$int_1; - var SCArray = $SC("Array"); + metaClasses[className] = metaClass; + }; - spec.__newFrom__ = $SC.Float; + klass.define = function(constructor, className, fn) { + var items, superClassName; - spec.__bool__ = function() { - return this._ !== 0; - }; + throwIfInvalidArgument(constructor, className); - spec.__dec__ = function() { - return this.__newFrom__(this._ - 1); - }; + items = className.split(":"); + className = items[0].trim(); + superClassName = (items[1] || "Object").trim(); - spec.__inc__ = function() { - return this.__newFrom__(this._ + 1); - }; + throwIfInvalidClassName(className, superClassName); - spec.__int__ = function() { - if (!isFinite(this._)) { - return this._; - } - return this._|0; - }; + if (className !== "Object") { + extend(constructor, metaClasses[superClassName]); + } - spec.__num__ = function() { - return this._; - }; + fn = fn || {}; - spec.isValidUGenInput = function() { - return $SC.Boolean(!isNaN(this._)); - }; + def(className, constructor, fn, {}); - spec.numChannels = utils.alwaysReturn$int_1; + buildClass(className, constructor); + }; - spec.magnitude = function() { - return this.abs(); - }; + klass.refine = function(className, fn, opts) { + var constructor; - spec.angle = function() { - return $SC.Float(this._ >= 0 ? 0 : Math.PI); - }; + if (!metaClasses.hasOwnProperty(className)) { + throw new Error( + "sc.lang.klass.refine: " + + "class '" + className + "' is not registered." + ); + } - spec.neg = function() { - return this.__newFrom__(-this._); - }; + constructor = metaClasses[className]._Spec; - // bitNot: implemented by subclass + def(className, constructor, fn, opts || {}); + }; - spec.abs = function() { - return this.__newFrom__(Math.abs(this._)); - }; + klass.get = function(name) { + if (!classes[name]) { + throw new Error( + "sc.lang.klass.get: " + + "class '" + name + "' is not registered." + ); + } + return classes[name]; + }; - spec.ceil = function() { - return this.__newFrom__(Math.ceil(this._)); - }; + klass.exists = function(name) { + return !!classes[name]; + }; - spec.floor = function() { - return this.__newFrom__(Math.floor(this._)); - }; + // basic classes + function SCObject() { + this._ = this; + } - spec.frac = function() { - var a = this._; + function SCClass() { + this._ = this; + this._name = "Class"; + this._Spec = null; + this._isMetaClass = false; + } - if (a < 0) { - return this.__newFrom__(1 + (a - (a|0))); - } - return this.__newFrom__(a - (a|0)); - }; + SCObject.metaClass = createClassInstance(function() {}); + klass.define(SCObject, "Object", { + __tag: 1, + __initializeWith__: function(className, args) { + metaClasses[className]._Spec.apply(this, args); + }, + $initClass: function() {} + }); - spec.sign = function() { - var a = this._; - return this.__newFrom__( - a > 0 ? 1 : a === 0 ? 0 : -1 - ); - }; + klass.define(SCClass, "Class"); - spec.squared = function() { - return this.__newFrom__(this._ * this._); - }; + SCObject.metaClass._MetaSpec.prototype = classes.Class = createClassInstance(); + classes.Class._Spec = SCClass; + classes.Object = new SCObject.metaClass._MetaSpec(); + classes.Object._name = "Object"; + classes.Object._Spec = SCObject.metaClass._Spec; + classes.Object._Spec.prototype.__class = classes.Object; + classes.Object._Spec.prototype.__Spec = classes.Object._Spec; - spec.cubed = function() { - return this.__newFrom__(this._ * this._ * this._); + klass.refine("Object", function(spec) { + spec.$new = function() { + if (this._Spec === SCClass) { + return $SC.Nil(); + } + return new this._Spec(slice.call(arguments)); }; - spec.sqrt = function() { - return $SC.Float(Math.sqrt(this._)); + spec.class = function() { + return this.__class; }; - spec.exp = function() { - return $SC.Float(Math.exp(this._)); + spec.isClass = function() { + return $SC.False(); }; - spec.reciprocal = function() { - return $SC.Float(1 / this._); + spec.isKindOf = function($aClass) { + return $SC.Boolean(this instanceof $aClass._Spec); }; - spec.midicps = function() { - return $SC.Float( - 440 * Math.pow(2, (this._ - 69) * 1/12) - ); + spec.isMemberOf = function($aClass) { + return $SC.Boolean(this.__class === $aClass); }; - spec.cpsmidi = function() { - return $SC.Float( - Math.log(Math.abs(this._) * 1/440) * Math.LOG2E * 12 + 69 - ); + spec.toString = function() { + var name = this.__class._name; + if (/^[AEIOU]/.test(name)) { + return String("an " + name); + } else { + return String("a " + name); + } }; - spec.midiratio = function() { - return $SC.Float( - Math.pow(2, this._ * 1/12) - ); + spec.valueOf = function() { + return this._; }; + }); - spec.ratiomidi = function() { - return $SC.Float( - Math.log(Math.abs(this._)) * Math.LOG2E * 12 - ); + klass.refine("Class", function(spec) { + spec.name = function() { + return $SC.String(this._name); }; - spec.ampdb = function() { - return $SC.Float( - Math.log(this._) * Math.LOG10E * 20 - ); + spec.class = function() { + if (this._isMetaClass) { + return classes.Class; + } + return $SC("Meta_" + this._name); }; - spec.dbamp = function() { - return $SC.Float( - Math.pow(10, this._ * 0.05) - ); + spec.isClass = function() { + return $SC.True(); }; - spec.octcps = function() { - return $SC.Float( - 440 * Math.pow(2, this._ - 4.75) - ); + spec.toString = function() { + return String(this._name); }; + }); - spec.cpsoct = function() { - return $SC.Float( - Math.log(Math.abs(this._) * 1/440) * Math.LOG2E + 4.75 - ); - }; + sc.lang.klass = klass; - spec.log = function() { - return $SC.Float(Math.log(this._)); - }; +})(sc); - spec.log2 = function() { - return $SC.Float(Math.log(Math.abs(this._)) * Math.LOG2E); - }; +// src/sc/lang/klass-constructors.js +(function(sc) { - spec.log10 = function() { - return $SC.Float(Math.log(this._) * Math.LOG10E); - }; + var $SC = sc.lang.$SC; + var klass = sc.lang.klass; - spec.sin = function() { - return $SC.Float(Math.sin(this._)); - }; + function SCNil() { + this.__initializeWith__("Object"); + this._ = null; + } + klass.define(SCNil, "Nil", { + __tag: 773 + }); - spec.cos = function() { - return $SC.Float(Math.cos(this._)); - }; + function SCSymbol() { + this.__initializeWith__("Object"); + this._ = ""; + } + klass.define(SCSymbol, "Symbol", { + __tag: 1027 + }); - spec.tan = function() { - return $SC.Float(Math.tan(this._)); - }; + function SCBoolean() { + this.__initializeWith__("Object"); + } + klass.define(SCBoolean, "Boolean"); - spec.asin = function() { - return $SC.Float(Math.asin(this._)); - }; + function SCTrue() { + this.__initializeWith__("Boolean"); + this._ = true; + } + klass.define(SCTrue, "True : Boolean", { + __tag: 775 + }); - spec.acos = function() { - return $SC.Float(Math.acos(this._)); - }; + function SCFalse() { + this.__initializeWith__("Boolean"); + this._ = false; + } + klass.define(SCFalse, "False : Boolean", { + __tag: 774 + }); - spec.atan = function() { - return $SC.Float(Math.atan(this._)); - }; + function SCMagnitude() { + this.__initializeWith__("Object"); + } + klass.define(SCMagnitude, "Magnitude"); - function _sinh(a) { - return (Math.pow(Math.E, a) - Math.pow(Math.E, -a)) * 0.5; - } + function SCChar() { + this.__initializeWith__("Magnitude"); + this._ = "\0"; + } + klass.define(SCChar, "Char : Magnitude", { + __tag: 1028 + }); - spec.sinh = function() { - return $SC.Float(_sinh(this._)); - }; + function SCNumber() { + this.__initializeWith__("Magnitude"); + } + klass.define(SCNumber, "Number : Magnitude"); - function _cosh(a) { - return (Math.pow(Math.E, a) + Math.pow(Math.E, -a)) * 0.5; - } + function SCSimpleNumber() { + this.__initializeWith__("Number"); + } + klass.define(SCSimpleNumber, "SimpleNumber : Number"); - spec.cosh = function() { - return $SC.Float(_cosh(this._)); - }; + function SCInteger() { + this.__initializeWith__("SimpleNumber"); + this._ = 0; + } + klass.define(SCInteger, "Integer : SimpleNumber", { + __tag: 770 + }); - spec.tanh = function() { - return $SC.Float(_sinh(this._) / _cosh(this._)); - }; + function SCFloat() { + this.__initializeWith__("SimpleNumber"); + this._ = 0.0; + } + klass.define(SCFloat, "Float : SimpleNumber", { + __tag: 777 + }); - spec.rand = function() { - return this.__newFrom__( - rand.next() * this._ - ); - }; - - spec.rand2 = function() { - return this.__newFrom__( - (rand.next() * 2 - 1) * this._ - ); - }; + function SCCollection() { + this.__initializeWith__("Object"); + } + klass.define(SCCollection, "Collection"); - spec.linrand = function() { - return this.__newFrom__( - Math.min(rand.next(), rand.next()) * this._ - ); - }; + function SCSequenceableCollection() { + this.__initializeWith__("Collection"); + } + klass.define(SCSequenceableCollection, "SequenceableCollection : Collection"); - spec.bilinrand = function() { - return this.__newFrom__( - (rand.next() - rand.next()) * this._ - ); - }; + function SCArrayedCollection() { + this.__initializeWith__("SequenceableCollection"); + this._immutable = false; + this._ = []; + } + klass.define(SCArrayedCollection, "ArrayedCollection : SequenceableCollection"); - spec.sum3rand = function() { - return this.__newFrom__( - (rand.next() + rand.next() + rand.next() - 1.5) * 2/3 * this._ - ); - }; + function SCRawArray() { + this.__initializeWith__("ArrayedCollection"); + } + klass.define(SCRawArray, "RawArray : ArrayedCollection"); - spec.distort = function() { - return $SC.Float( - this._ / (1 + Math.abs(this._)) - ); - }; + function SCArray() { + this.__initializeWith__("ArrayedCollection"); + } + klass.define(SCArray, "Array : ArrayedCollection", { + __tag: 11 + }); - spec.softclip = function() { - var a = this._, abs_a = Math.abs(a); - return $SC.Float(abs_a <= 0.5 ? a : (abs_a - 0.25) / a); - }; + function SCString(value) { + this.__initializeWith__("RawArray"); + this._ = value; + } + klass.define(SCString, "String : RawArray", { + __tag: 1034 + }); - spec.coin = function() { - return $SC.Boolean(rand.next() < this._); - }; + function SCAbstractFunction() { + this.__initializeWith__("Object"); + } + klass.define(SCAbstractFunction, "AbstractFunction"); - spec.isPositive = function() { - return $SC.Boolean(this._ >= 0); - }; + function SCFunction() { + this.__initializeWith__("AbstractFunction"); + // istanbul ignore next + this._ = function() {}; + } + klass.define(SCFunction, "Function : AbstractFunction", { + __tag: 12 + }); - spec.isNegative = function() { - return $SC.Boolean(this._ < 0); - }; + // $SC + var $nil = new SCNil(); + var $true = new SCTrue(); + var $false = new SCFalse(); + var $integers = {}; + var $floats = {}; + var $symbols = {}; + var $chars = {}; - spec.isStrictlyPositive = function() { - return $SC.Boolean(this._ > 0); - }; + $SC.Nil = function() { + return $nil; + }; - spec.isNaN = function() { - return $SC.Boolean(isNaN(this._)); - }; + $SC.Boolean = function($value) { + return $value ? $true : $false; + }; - spec.asBoolean = function() { - return $SC.Boolean(this._ > 0); - }; + $SC.True = function() { + return $true; + }; - spec.booleanValue = function() { - return $SC.Boolean(this._ > 0); - }; + $SC.False = function() { + return $false; + }; - spec.binaryValue = function() { - return this._ > 0 ? $int_1 : $int_0; - }; + $SC.Integer = function(value) { + var instance; - spec.rectWindow = function() { - var a = this._; - if (a < 0 || 1 < a) { - return $SC.Float(0); - } - return $SC.Float(1); - }; + if (!global.isFinite(value)) { + return $SC.Float(+value); + } - spec.hanWindow = function() { - var a = this._; - if (a < 0 || 1 < a) { - return $SC.Float(0); - } - return $SC.Float(0.5 - 0.5 * Math.cos(a * 2 * Math.PI)); - }; + value = value|0; - spec.welWindow = function() { - var a = this._; - if (a < 0 || 1 < a) { - return $SC.Float(0); - } - return $SC.Float(Math.sin(a * Math.PI)); - }; + if (!$integers.hasOwnProperty(value)) { + instance = new SCInteger(); + instance._ = value; + $integers[value] = instance; + } - spec.triWindow = function() { - var a = this._; - if (a < 0 || 1 < a) { - return $SC.Float(0); - } - if (a < 0.5) { - return $SC.Float(2 * a); - } - return $SC.Float(-2 * a + 2); - }; + return $integers[value]; + }; - spec.scurve = function() { - var a = this._; - if (a <= 0) { - return $SC.Float(0); - } - if (1 <= a) { - return $SC.Float(1); - } - return $SC.Float(a * a * (3 - 2 * a)); - }; + $SC.Float = function(value) { + var instance; - spec.ramp = function() { - var a = this._; - if (a <= 0) { - return $SC.Float(0); - } - if (1 <= a) { - return $SC.Float(1); - } - return $SC.Float(a); - }; + value = +value; - // +: implemented by subclass - // -: implemented by subclass - // *: implemented by subclass - // /: implemented by subclass - // mod: implemented by subclass - // div: implemented by subclass - // pow: implemented by subclass - // min: implemented by subclass - // max: implemented by subclass - // bitAnd: implemented by subclass - // bitOr : implemented by subclass - // bitXor: implemented by subclass + if (!$floats.hasOwnProperty(value)) { + instance = new SCFloat(); + instance._ = value; + $floats[value] = instance; + } - spec.bitTest = function($bit) { - $bit = utils.defaultValue$Nil($bit); - return $SC.Boolean( - this.bitAnd($int_1.leftShift($bit)).valueOf() !== 0 - ); - }; + return $floats[value]; + }; - // lcm : implemented by subclass - // gcd : implemented by subclass - // round : implemented by subclass - // roundUp : implemented by subclass - // trunc : implemented by subclass - // atan2 : implemented by subclass - // hypot : implemented by subclass - // hypotApx: implemented by subclass - // leftShift : implemented by subclass - // rightShift : implemented by subclass - // unsignedRightShift: implemented by subclass - // ring1 : implemented by subclass - // ring2 : implemented by subclass - // ring3 : implemented by subclass - // ring4 : implemented by subclass - // difsqr: implemented by subclass - // sumsqr: implemented by subclass - // sqrsum: implemented by subclass - // sqrdif: implemented by subclass - // absdif: implemented by subclass - // thresh: implemented by subclass - // amclip: implemented by subclass - // clip2 : implemented by subclass - // fold2 : implemented by subclass - // wrap2 : implemented by subclass - // excess: implemented by subclass - // firstArg: implemented by subclass - // rrand : implemented by subclass - // exprand : implemented by subclass + $SC.Symbol = function(value) { + var instance; + if (!$symbols.hasOwnProperty(value)) { + instance = new SCSymbol(); + instance._ = value; + $symbols[value] = instance; + } + return $symbols[value]; + }; - spec["=="] = function($aNumber) { - return $SC.Boolean(this._ === $aNumber._); - }; + $SC.Char = function(value) { + var instance; - spec["!="] = function($aNumber) { - return $SC.Boolean(this._ !== $aNumber._); - }; + value = String(value).charAt(0); - spec["<"] = prOpSimpleNumber("<", function(a, b) { - return a < b; - }); - spec[">"] = prOpSimpleNumber(">", function(a, b) { - return a > b; - }); - spec["<="] = prOpSimpleNumber("<=", function(a, b) { - return a <= b; - }); - spec[">="] = prOpSimpleNumber(">=", function(a, b) { - return a >= b; - }); + if (!$chars.hasOwnProperty(value)) { + instance = new SCChar(); + instance._ = value; + $chars[value] = instance; + } - spec.equalWithPrecision = function($that, $precision) { - $that = utils.defaultValue$Nil($that); - $precision = utils.defaultValue$Float($precision, 0.0001); - return this.absdif($that) ["<"] ($precision); - }; + return $chars[value]; + }; - // TODO: implements hash + $SC.Array = function(value, immutable) { + var instance = new SCArray(); + instance._ = value || []; + instance._immutable = !!immutable; + return instance; + }; - spec.asInteger = function() { - return $SC.Integer(this._); - }; + $SC.String = function(value, immutable) { + var instance = new SCString(); + instance._ = String(value).split("").map($SC.Char); + instance._immutable = !!immutable; + return instance; + }; - spec.asFloat = function() { - return $SC.Float(this._); - }; + $SC.Function = function(value) { + var instance = new SCFunction(); + instance._ = value; + return instance; + }; - // TODO: implements asComplex - // TODO: implements asRect +})(sc); - spec.degrad = function() { - return $SC.Float(this._ * Math.PI / 180); - }; +// src/sc/lang/klass-utils.js +(function(sc) { - spec.raddeg = function() { - return $SC.Float(this._ * 180 / Math.PI); - }; + var $SC = sc.lang.$SC; + var klass = sc.lang.klass; - // TODO: implements performBinaryOpOnSimpleNumber - // TODO: implements performBinaryOpOnComplex - // TODO: implements performBinaryOpOnSignal + var utils = { + BOOL: function(a) { + return a.__bool__(); + }, + $nil : $SC.Nil(), + $true : $SC.True(), + $false: $SC.False(), + $int_0: $SC.Integer(0), + $int_1: $SC.Integer(1), + nop: function() { + return this; + }, + alwaysReturn$nil : $SC.Nil, + alwaysReturn$true : $SC.True, + alwaysReturn$false: $SC.False, + alwaysReturn$int_0: function() { + return utils.$int_0; + }, + alwaysReturn$int_1: function() { + return utils.$int_1; + }, + getMethod: function(className, methodName) { + return klass.get(className)._Spec.prototype[methodName]; + } + }; - spec.nextPowerOfTwo = function() { - return $SC.Float( - Math.pow(2, Math.ceil(Math.log(this._) / Math.log(2))) - ); - }; + klass.utils = utils; - spec.nextPowerOf = function($base) { - $base = utils.defaultValue$Nil($base); - return $base.pow( - (this.log() ["/"] ($base.log())).ceil() - ); - }; +})(sc); - spec.nextPowerOfThree = function() { - return $SC.Float( - Math.pow(3, Math.ceil(Math.log(this._) / Math.log(3))) - ); - }; +// src/sc/lang/iterator.js +(function(sc) { - spec.previousPowerOf = function($base) { - $base = utils.defaultValue$Nil($base); - return $base.pow( - (this.log() ["/"] ($base.log())).ceil().__dec__() - ); - }; + var iterator = {}; + var $SC = sc.lang.$SC; + var utils = sc.lang.klass.utils; + var $nil = utils.$nil; + var $int_0 = utils.$int_0; + var $int_1 = utils.$int_1; + var BOOL = utils.BOOL; - spec.quantize = function($quantum, $tolerance, $strength) { - var $round, $diff; - $quantum = utils.defaultValue$Float($quantum, 1.0); - $tolerance = utils.defaultValue$Float($tolerance, 0.05); - $strength = utils.defaultValue$Float($strength, 1.0); + var __stop__ = function() { + return null; + }; - $round = this.round($quantum); - $diff = $round ["-"] (this); + var nop_iter = { + next: __stop__ + }; - if ($diff.abs() < $tolerance) { - return this ["+"] ($strength ["*"] ($diff)); + var one_shot_iter = function(value) { + var iter = { + next: function() { + iter.next = __stop__; + return value; } - - return this; }; + return iter; + }; - spec.linlin = function($inMin, $inMax, $outMin, $outMax, $clip) { - var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); - - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + // TODO: async function + iterator.execute = function(iter, $function) { + var $item, ret, i = 0; - if ($res === null) { - // (this-inMin)/(inMax-inMin) * (outMax-outMin) + outMin; - $res = ((this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)) - ["*"] ($outMax ["-"] ($outMin)) ["+"] ($outMin)); + while (($item = iter.next()) !== null) { + if (Array.isArray($item)) { + ret = $function.value($item[0], $item[1]); + } else { + ret = $function.value($item, $SC.Integer(i++)); + } + if (ret === 65535) { + break; } + } + }; - return $res; - }; + iterator.object$do = one_shot_iter; - spec.linexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + iterator.function$while = function($function) { + var iter = { + next: function() { + if (BOOL($function.value())) { + return [ $nil, $nil ]; + } + iter.next = __stop__; + return null; + } + }; - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + return iter; + }; - if ($res === null) { - // Math.pow(outMax/outMin, (this-inMin)/(inMax-inMin)) * outMin; - $res = $outMax ["/"] ($outMin).pow( - (this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)) - ) ["*"] ($outMin); + var sc_incremental_iter = function($start, $end, $step) { + var $i = $start, iter = { + next: function() { + var $ret = $i; + $i = $i ["+"] ($step); + if ($i > $end) { + iter.next = __stop__; + } + return $ret; } + }; + return iter; + }; - return $res; + var sc_decremental_iter = function($start, $end, $step) { + var $i = $start, iter = { + next: function() { + var $ret = $i; + $i = $i ["+"] ($step); + if ($i < $end) { + iter.next = __stop__; + } + return $ret; + } }; + return iter; + }; - spec.explin = function($inMin, $inMax, $outMin, $outMax, $clip) { - var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + var sc_numeric_iter = function($start, $end, $step) { + if ($start.valueOf() === $end.valueOf()) { + return one_shot_iter($start); + } else if ($start < $end && $step > 0) { + return sc_incremental_iter($start, $end, $step); + } else if ($start > $end && $step < 0) { + return sc_decremental_iter($start, $end, $step); + } + return nop_iter; + }; - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + iterator.number$do = function($end) { + var $start, $step; - if ($res === null) { - // (((Math.log(this/inMin)) / (Math.log(inMax/inMin))) * (outMax-outMin)) + outMin; - $res = ((this ["/"] ($inMin).log() ["/"] ($inMax ["/"] ($inMin).log()) - ["*"] ($outMax ["-"] ($outMin))) ["+"] ($outMin)); - } + $start = $int_0; + $end = $end.__dec__(); + $step = $int_1; - return $res; - }; + return sc_numeric_iter($start, $end, $step); + }; - spec.expexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + iterator.number$reverseDo = function($start) { + var $end, $step; - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + $start = $start.__dec__(); + $end = $int_0; + $step = $SC.Integer(-1); - if ($res === null) { - // Math.pow(outMax/outMin, Math.log(this/inMin) / Math.log(inMax/inMin)) * outMin; - $res = $outMax ["/"] ($outMin).pow( - this ["/"] ($inMin).log() ["/"] ($inMax ["/"] ($inMin).log()) - ) ["*"] ($outMin); - } + return sc_numeric_iter($start, $end, $step); + }; - return $res; - }; + iterator.number$for = function($start, $end) { + var $step; - spec.lincurve = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - var $res = null, $grow, $a, $b, $scaled; - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + $step = ($start <= $end) ? $int_1 : $SC.Integer(-1); - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + return sc_numeric_iter($start, $end, $step); + }; - if ($res === null) { - if (Math.abs($curve.valueOf()) < 0.001) { - $res = this.linlin($inMin, $inMax, $outMin, $outMax); - } else { - $grow = $curve.exp(); - $a = $outMax ["-"] ($outMin) ["/"] ($SC.Float(1.0) ["-"] ($grow)); - $b = $outMin ["+"] ($a); - $scaled = (this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)); + iterator.number$forBy = function($start, $end, $step) { + return sc_numeric_iter($start, $end, $step); + }; - $res = $b ["-"] ($a ["*"] ($grow.pow($scaled))); + iterator.number$forSeries = function($start, $second, $last) { + var $step; + + $step = $second ["-"] ($start); + + return sc_numeric_iter($start, $last, $step); + }; + + var js_incremental_iter = function(start, end, step, type) { + var i = start, iter = { + next: function() { + var ret = i; + i += step; + if (i > end) { + iter.next = __stop__; } + return type(ret); } + }; + return iter; + }; - return $res; + var js_decremental_iter = function(start, end, step, type) { + var i = start, iter = { + next: function() { + var ret = i; + i += step; + if (i < end) { + iter.next = __stop__; + } + return type(ret); + } }; + return iter; + }; - spec.curvelin = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - var $res = null, $grow, $a, $b; - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + var js_numeric_iter = function(start, end, step, type) { + if (start === end) { + return one_shot_iter(type(start)); + } else if (start < end && step > 0) { + return js_incremental_iter(start, end, step, type); + } else if (start > end && step < 0) { + return js_decremental_iter(start, end, step, type); + } + return nop_iter; + }; - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + var js_numeric_iter$do = function($endval, type) { + var end = type($endval.__num__()).valueOf(); + return js_numeric_iter(0, end - 1, +1, type); + }; - if ($res === null) { - if (Math.abs($curve.valueOf()) < 0.001) { - $res = this.linlin($inMin, $inMax, $outMin, $outMax); - } else { - $grow = $curve.exp(); - $a = $inMax ["-"] ($inMin) ["/"] ($SC.Float(1.0) ["-"] ($grow)); - $b = $inMin ["+"] ($a); + var js_numeric_iter$reverseDo = function($startval, type) { + var start = type($startval.__num__()).valueOf(); + var end = (start|0) - start; + return js_numeric_iter(start - 1, end, -1, type); + }; - $res = ((($b ["-"] (this)) ["/"] ($a)).log() - ["*"] ($outMax ["-"] ($outMin)) ["/"] ($curve) ["+"] ($outMin)); - } - } + var js_numeric_iter$for = function($startval, $endval, type) { + var start = type($startval.__num__()).valueOf(); + var end = type($endval .__num__()).valueOf(); + var step = (start <= end) ? +1 : -1; - return $res; - }; + return js_numeric_iter(start, end, step, type); + }; - spec.bilin = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - var $res = null; - $inCenter = utils.defaultValue$Nil($inCenter); - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outCenter = utils.defaultValue$Nil($outCenter); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + var js_numeric_iter$forBy = function($startval, $endval, $stepval, type) { + var start = type($startval.__num__()).valueOf(); + var end = type($endval .__num__()).valueOf(); + var step = type($stepval .__num__()).valueOf(); - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + return js_numeric_iter(start, end, step, type); + }; - if ($res === null) { - if (this >= $inCenter) { - $res = this.linlin($inCenter, $inMax, $outCenter, $outMax, $SC.Symbol("none")); - } else { - $res = this.linlin($inMin, $inCenter, $outMin, $outCenter, $SC.Symbol("none")); - } - } + var js_numeric_iter$forSeries = function($startval, $second, $last, type) { + var start = type($startval.__num__()).valueOf(); + var second = type($second .__num__()).valueOf(); + var end = type($last .__num__()).valueOf(); + var step = second - start; - return $res; - }; + return js_numeric_iter(start, end, step, type); + }; - spec.biexp = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - var $res = null; - $inCenter = utils.defaultValue$Nil($inCenter); - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outCenter = utils.defaultValue$Nil($outCenter); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + iterator.integer$do = function($endval) { + return js_numeric_iter$do($endval, $SC.Integer); + }; - $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + iterator.integer$reverseDo = function($startval) { + return js_numeric_iter$reverseDo($startval, $SC.Integer); + }; - if ($res === null) { - if (this >= $inCenter) { - $res = this.explin($inCenter, $inMax, $outCenter, $outMax, $SC.Symbol("none")); - } else { - $res = this.explin($inMin, $inCenter, $outMin, $outCenter, $SC.Symbol("none")); - } - } + iterator.integer$for = function($startval, $endval) { + return js_numeric_iter$for($startval, $endval, $SC.Integer); + }; - return $res; - }; + iterator.integer$forBy = function($startval, $endval, $stepval) { + return js_numeric_iter$forBy($startval, $endval, $stepval, $SC.Integer); + }; - spec.moddif = function($aNumber, $mod) { - var $diff, $modhalf; - $aNumber = utils.defaultValue$Float($aNumber, 0.0); - $mod = utils.defaultValue$Float($mod , 1.0); + iterator.integer$forSeries = function($startval, $second, $last) { + return js_numeric_iter$forSeries($startval, $second, $last, $SC.Integer); + }; - $diff = this.absdif($aNumber) ["%"] ($mod); - $modhalf = $mod ["*"] ($SC.Float(0.5)); + iterator.float$do = function($endval) { + return js_numeric_iter$do($endval, $SC.Float); + }; - return $modhalf ["-"] ($diff.absdif($modhalf)); - }; + iterator.float$reverseDo = function($startval) { + return js_numeric_iter$reverseDo($startval, $SC.Float); + }; - spec.lcurve = function($a, $m, $n, $tau) { - var $rTau, $x; - $a = utils.defaultValue$Float($a, 1.0); - $m = utils.defaultValue$Float($m, 0.0); - $n = utils.defaultValue$Float($n, 1.0); - $tau = utils.defaultValue$Float($tau, 1.0); + iterator.float$for = function($startval, $endval) { + return js_numeric_iter$for($startval, $endval, $SC.Float); + }; - $x = this.neg(); + iterator.float$forBy = function($startval, $endval, $stepval) { + return js_numeric_iter$forBy($startval, $endval, $stepval, $SC.Float); + }; - if ($tau.__num__() === 1.0) { - // a * (m * exp(x) + 1) / (n * exp(x) + 1) - return $a ["*"] ( - $m ["*"] ($x.exp()).__inc__() - ) ["/"] ( - $n ["*"] ($x.exp()).__inc__() - ); - } else { - $rTau = $tau.reciprocal(); - return $a ["*"] ( - $m ["*"] ($x.exp()) ["*"] ($rTau).__inc__() - ) ["/"] ( - $n ["*"] ($x.exp()) ["*"] ($rTau).__inc__() - ); + iterator.float$forSeries = function($startval, $second, $last) { + return js_numeric_iter$forSeries($startval, $second, $last, $SC.Float); + }; + + var list_iter = function(list) { + var i = 0, iter = { + next: function() { + var $ret = list[i++]; + if (i >= list.length) { + iter.next = __stop__; + } + return $ret; } }; + return iter; + }; - spec.gauss = function($standardDeviation) { - $standardDeviation = utils.defaultValue$Nil($standardDeviation); - // ^((((-2*log(1.0.rand)).sqrt * sin(2pi.rand)) * standardDeviation) + this) - return ($SC.Float(-2.0) ["*"] ($SC.Float(1.0).rand().log()).sqrt() ["*"] ( - $SC.Float(2 * Math.PI).rand().sin() - ) ["*"] ($standardDeviation)) ["+"] (this); - }; + var js_array_iter = function(list) { + if (list.length) { + return list_iter(list); + } + return nop_iter; + }; - spec.gaussCurve = function($a, $b, $c) { - $a = utils.defaultValue$Float($a, 1.0); - $b = utils.defaultValue$Float($b, 0.0); - $c = utils.defaultValue$Float($c, 1.0); + iterator.array$do = function($array) { + return js_array_iter($array._.slice()); + }; - // ^a * (exp(squared(this - b) / (-2.0 * squared(c)))) - return $a ["*"] (( - (this ["-"] ($b).squared()) ["/"] ($SC.Float(-2.0) ["*"] ($c.squared())) - ).exp()); - }; + iterator.array$reverseDo = function($array) { + return js_array_iter($array._.slice().reverse()); + }; - // TODO: implements asPoint - // TODO: implements asWarp + sc.lang.iterator = iterator; - spec.wait = function() { - return this.yield(); - }; +})(sc); - // TODO: implements waitUntil - // TODO: implements sleep - // TODO: implements printOn - // TODO: implements storeOn +// src/sc/lang/classlib.js +(function(sc) { - spec.rate = function() { - return $SC.Symbol("scalar"); + sc.lang.classlib = {}; + +})(sc); + +// src/sc/lang/classlib/Core/Object.js +(function(sc) { + + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + + sc.lang.klass.refine("Object", function(spec, utils) { + var BOOL = utils.BOOL; + var $nil = utils.$nil; + var $true = utils.$true; + var $false = utils.$false; + var $int_1 = utils.$int_1; + var SCArray = $SC("Array"); + + spec.__num__ = function() { + throw new Error("Wrong Type"); }; - spec.asAudioRateInput = function() { - if (this._ === 0) { - return $SC("Silent").ar(); - } - return $SC("DC").ar(this); + spec.__int__ = function() { + return this.__num__()|0; }; - spec.madd = function($mul, $add) { - $mul = utils.defaultValue$Nil($mul); - $add = utils.defaultValue$Nil($add); + spec.__bool__ = function() { + throw new Error("Wrong Type"); + }; - return (this ["*"] ($mul)) ["+"] ($add); + spec.__sym__ = function() { + throw new Error("Wrong Type"); }; - spec.lag = utils.nop; - spec.lag2 = utils.nop; - spec.lag3 = utils.nop; - spec.lagud = utils.nop; - spec.lag2ud = utils.nop; - spec.lag3ud = utils.nop; - spec.varlag = utils.nop; - spec.slew = utils.nop; + spec.__str__ = function() { + return String(this); + }; - // TODO: implements writeInputSpec + // TODO: implements $new + // TODO: implements $newCopyArgs - spec.series = function($second, $last) { - var $step; - var last, step, size; - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); + spec.$newFrom = function() { + return this._doesNotUnderstand("newFrom"); + }; - if ($second === $nil) { - if (this.valueOf() < $last.valueOf()) { - $second = this.__inc__(); - } else { - $second = this.__dec__(); - } - } - $step = $second ["-"] (this); + // TODO: implements dump + // TODO: implements post + // TODO: implements postln + // TODO: implements postc + // TODO: implements postcln + // TODO: implements postcs + // TODO: implements totalFree + // TODO: implements largestFreeBlock + // TODO: implements gcDumpGrey + // TODO: implements gcDumpSet + // TODO: implements gcInfo + // TODO: implements gcSanity + // TODO: implements canCallOS - last = $last.__num__(); - step = $step.__num__(); - size = (Math.floor((last - this._) / step + 0.001)|0) + 1; + spec.size = utils.alwaysReturn$int_0; + spec.indexedSize = utils.alwaysReturn$int_0; + spec.flatSize = utils.alwaysReturn$int_1; - return SCArray.series($SC.Integer(size), this, $step); + spec.do = function($function) { + sc.lang.iterator.execute( + sc.lang.iterator.object$do(this), + $function + ); + + return this; }; - // TODO: implements seriesIter - // TODO: implements degreeToKey - // TODO: implements keyToDegree - // TODO: implements nearestInList - // TODO: implements nearestInScale - // TODO: implements partition - // TODO: implements nextTimeOnGrid - // TODO: implements playAndDelta - // TODO: implements asQuant - // TODO: implements asTimeString - // TODO: implements asFraction - // TODO: implements asBufWithValues - // TODO: implements schedBundleArrayOnClock + spec.generate = fn(function($function, $state) { + this.do($function); - spec.shallowCopy = utils.nop; - }); + return $state; + }, "function; state"); - function clip_for_map($this, $inMin, $inMax, $outMin, $outMax, $clip) { + // already defined: class + // already defined: isKindOf + // already defined: isMemberOf - switch ($clip.__sym__()) { - case "minmax": - if ($this <= $inMin) { - return $outMin; - } - if ($this >= $inMax) { - return $outMax; - } - break; - case "min": - if ($this <= $inMin) { - return $outMin; - } - break; - case "max": - if ($this >= $inMax) { - return $outMax; - } - break; - } + spec.respondsTo = fn(function($aSymbol) { + return $SC.Boolean(typeof this[$aSymbol.__sym__()] === "function"); + }, "aSymbol"); - return null; - } + // TODO: implements performMsg -})(sc); + spec.perform = function($selector) { + var selector, method; -// src/sc/lang/classlib/Math/bop.js -(function(sc) { + selector = $selector.__sym__(); + method = this[selector]; - var $SC = sc.lang.$SC; - var mathlib = sc.libs.mathlib; + if (method) { + return method.apply(this, slice.call(arguments, 1)); + } - sc.lang.classlib.bop = function(selector, type1, type2) { - var func = mathlib[selector]; + throw new Error("Message '" + selector + "' not understood."); + }; - return function($aNumber, $adverb) { - var tag = $aNumber.__tag; + spec.performList = function($selector, $arglist) { + var selector, method; - switch (tag) { - case 770: - return type1(func(this._, $aNumber._)); - case 777: - return type2(func(this._, $aNumber._)); + selector = $selector.__sym__(); + method = this[selector]; + + if (method) { + return method.apply(this, $arglist.asArray()._); } - return $aNumber.performBinaryOpOnSimpleNumber( - $SC.Symbol(selector), this, $adverb - ); + throw new Error("Message '" + selector + "' not understood."); }; - }; - -})(sc); - -// src/sc/lang/classlib/Math/Integer.js -(function(sc) { - var $SC = sc.lang.$SC; - var iterator = sc.lang.iterator; - var mathlib = sc.libs.mathlib; + spec.functionPerformList = utils.nop; - sc.lang.klass.refine("Integer", function(spec, utils) { - var $nil = utils.$nil; - var $int_1 = utils.$int_1; - var SCArray = $SC("Array"); + // TODO: implements superPerform + // TODO: implements superPerformList + // TODO: implements tryPerform + // TODO: implements multiChannelPerform + // TODO: implements performWithEnvir + // TODO: implements performKeyValuePairs - spec.__newFrom__ = $SC.Integer; + var copy = function(obj) { + var copied = obj; - spec.__int__ = function() { - return this._; - }; + if (Array.isArray(obj)) { + copied = obj.slice(); + } else if (obj && obj.constructor === Object) { + copied = {}; + Object.keys(obj).forEach(function(key) { + copied[key] = obj[key]; + }); + } - spec.toString = function() { - return String("" + this._); + return copied; }; - spec.$new = function() { - throw new Error("Integer.new is illegal, should use literal."); + spec.copy = function() { + return this.shallowCopy(); }; - spec.isInteger = utils.alwaysReturn$true; - - // TODO: implements hash + // TODO: implements contentsCopy - [ - [ "+", $SC.Integer, $SC.Float ], - [ "-", $SC.Integer, $SC.Float ], - [ "*", $SC.Integer, $SC.Float ], - [ "/", $SC.Float , $SC.Float ], - [ "mod" , $SC.Integer, $SC.Float ], - [ "div" , $SC.Integer, $SC.Integer ], - [ "pow" , $SC.Float , $SC.Float ], - [ "min" , $SC.Integer, $SC.Float ], - [ "max" , $SC.Integer, $SC.Float ], - [ "bitAnd" , $SC.Integer, $SC.Float ], - [ "bitOr" , $SC.Integer, $SC.Float ], - [ "bitXor" , $SC.Integer, $SC.Float ], - [ "lcm" , $SC.Integer, $SC.Float ], - [ "gcd" , $SC.Integer, $SC.Float ], - [ "round" , $SC.Integer, $SC.Float ], - [ "roundUp" , $SC.Integer, $SC.Float ], - [ "trunc" , $SC.Integer, $SC.Float ], - [ "atan2" , $SC.Float , $SC.Float ], - [ "hypot" , $SC.Float , $SC.Float ], - [ "hypotApx", $SC.Float , $SC.Float ], - [ "leftShift" , $SC.Integer, $SC.Float ], - [ "rightShift" , $SC.Integer, $SC.Float ], - [ "unsignedRightShift", $SC.Integer, $SC.Float ], - [ "ring1" , $SC.Integer, $SC.Float ], - [ "ring2" , $SC.Integer, $SC.Float ], - [ "ring3" , $SC.Integer, $SC.Float ], - [ "ring4" , $SC.Integer, $SC.Float ], - [ "difsqr" , $SC.Integer, $SC.Float ], - [ "sumsqr" , $SC.Integer, $SC.Float ], - [ "sqrsum" , $SC.Integer, $SC.Float ], - [ "sqrdif" , $SC.Integer, $SC.Float ], - [ "absdif" , $SC.Integer, $SC.Float ], - [ "thresh" , $SC.Integer, $SC.Integer ], - [ "amclip" , $SC.Integer, $SC.Float ], - [ "scaleneg", $SC.Integer, $SC.Float ], - [ "clip2" , $SC.Integer, $SC.Float ], - [ "fold2" , $SC.Integer, $SC.Float ], - [ "excess" , $SC.Integer, $SC.Float ], - [ "firstArg", $SC.Integer, $SC.Integer ], - [ "rrand" , $SC.Integer, $SC.Float ], - [ "exprand" , $SC.Float , $SC.Float ], - ].forEach(function(items) { - spec[items[0]] = sc.lang.classlib.bop.apply(null, items); - }); + spec.shallowCopy = function() { + var a = new this.__class._Spec(); - spec.wrap2 = function($aNumber, $adverb) { - var tag = $aNumber.__tag; + Object.keys(this).forEach(function(key) { + a[key] = copy(this[key]); + }, this); - switch (tag) { - case 770: - return $SC.Integer(mathlib.iwrap(this._, -$aNumber._, $aNumber._)); - case 777: - return $SC.Float(mathlib.wrap2(this._, $aNumber._)); + if (this._ === this) { + a._ = a; } - return $aNumber.performBinaryOpOnSimpleNumber( - $SC.Symbol("wrap2"), this, $adverb - ); + return a; }; - spec.rrand = function($aNumber, $adverb) { - var tag = $aNumber.__tag; + // TODO: implements copyImmutable + // TODO: implements deepCopy - switch (tag) { - case 770: - return $SC.Integer(Math.round(mathlib.rrand(this._, $aNumber._))); - case 777: - return $SC.Float(mathlib.rrand(this._, $aNumber._)); + spec.dup = fn(function($n) { + var $this = this; + var $array, i, imax; + + if (BOOL($n.isSequenceableCollection())) { + return SCArray.fillND($n, $SC.Function(function() { + return $this.copy(); + })); } - return $aNumber.performBinaryOpOnSimpleNumber( - $SC.Symbol("rrand"), this, $adverb - ); - }; + $array = SCArray.new($n); + for (i = 0, imax = $n.__int__(); i < imax; ++i) { + $array.add(this.copy()); + } - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + return $array; + }, "n=2"); - // <-- _ClipInt --> - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } - if ($lo.__tag === 770 && $hi.__tag === 770) { - return $SC.Integer( - mathlib.clip(this._, $lo.__int__(), $hi.__int__()) - ); - } - - return $SC.Float( - mathlib.clip(this._, $lo.__num__(), $hi.__num__()) - ); + spec["!"] = function($n) { + return this.dup($n); }; - spec.wrap = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - - // <-- _WrapInt --> - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } - if ($lo.__tag === 770 && $hi.__tag === 770) { - return $SC.Integer( - mathlib.iwrap(this._, $lo.__int__(), $hi.__int__()) - ); - } - - return $SC.Float( - mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) - ); + spec.poll = function() { + return this.value(); }; - spec.fold = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - - // <-- _FoldInt --> - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } - if ($lo.__tag === 770 && $hi.__tag === 770) { - return $SC.Integer( - mathlib.ifold(this._, $lo.__int__(), $hi.__int__()) - ); - } + spec.value = utils.nop; + spec.valueArray = utils.nop; + spec.valueEnvir = utils.nop; + spec.valueArrayEnvir = utils.nop; - return $SC.Float( - mathlib.fold(this._, $lo.__num__(), $hi.__num__()) - ); + spec["=="] = function($obj) { + return this ["==="] ($obj); }; - spec.even = function() { - return $SC.Boolean(!(this._ & 1)); + spec["!="] = function($obj) { + return (this ["=="] ($obj)).not(); }; - spec.odd = function() { - return $SC.Boolean(!!(this._ & 1)); + spec["==="] = function($obj) { + return $SC.Boolean(this === $obj); }; - spec.xrand = function($exclude) { - $exclude = utils.defaultValue$Integer($exclude, 0); - return ($exclude ["+"] (this.__dec__().rand()) ["+"] ($int_1)) ["%"] (this); + spec["!=="] = function($obj) { + return $SC.Boolean(this !== $obj); }; - spec.xrand2 = function($exclude) { - var raw, res; - $exclude = utils.defaultValue$Integer($exclude, 0); + // TODO: implements equals + // TODO: implements compareObject + // TODO: implements instVarHash + // TODO: implements basicHash + // TODO: implements hash + // TODO: implements identityHash - raw = this._; - res = (mathlib.rand((2 * raw))|0) - raw; + spec["->"] = function($obj) { + return $SC("Association").new(this, $obj); + }; - if (res === $exclude._) { - return this; - } + spec.next = utils.nop; + spec.reset = utils.nop; - return $SC.Integer(res); + spec.first = fn(function($inval) { + this.reset(); + return this.next($inval); + }, "inval"); + + spec.iter = function() { + return $SC("OneShotStream").new(this); }; - spec.degreeToKey = function($scale, $stepsPerOctave) { - $scale = utils.defaultValue$Nil($scale); - $stepsPerOctave = utils.defaultValue$Integer($stepsPerOctave, 12); + spec.stop = utils.nop; + spec.free = utils.nop; + spec.clear = utils.nop; + spec.removedFromScheduler = utils.nop; + spec.isPlaying = utils.alwaysReturn$false; - return $scale.performDegreeToKey(this, $stepsPerOctave); + spec.embedInStream = function() { + return this.yield(); }; - spec.do = function($function) { - iterator.execute( - iterator.integer$do(this), - $function - ); - return this; - }; + // TODO: implements cyc + // TODO: implements fin + // TODO: implements repeat + // TODO: implements loop - spec.generate = function($function) { - $function = utils.defaultValue$Nil($function); + spec.asStream = utils.nop; - $function.value(this); + // TODO: implements streamArg - return this; + spec.eventAt = utils.alwaysReturn$nil; + + spec.composeEvents = fn(function($event) { + return $event.copy(); + }, "event"); + + spec.finishEvent = utils.nop; + spec.atLimit = utils.alwaysReturn$false; + spec.isRest = utils.alwaysReturn$false; + spec.threadPlayer = utils.nop; + spec.threadPlayer_ = utils.nop; + spec["?"] = utils.nop; + spec["??"] = utils.nop; + + spec["!?"] = function($obj) { + return $obj.value(this); }; - spec.collectAs = function($function, $class) { - var $res; - var i, imax; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); + spec.isNil = utils.alwaysReturn$false; + spec.notNil = utils.alwaysReturn$true; + spec.isNumber = utils.alwaysReturn$false; + spec.isInteger = utils.alwaysReturn$false; + spec.isFloat = utils.alwaysReturn$false; + spec.isSequenceableCollection = utils.alwaysReturn$false; + spec.isCollection = utils.alwaysReturn$false; + spec.isArray = utils.alwaysReturn$false; + spec.isString = utils.alwaysReturn$false; + spec.containsSeqColl = utils.alwaysReturn$false; + spec.isValidUGenInput = utils.alwaysReturn$false; + spec.isException = utils.alwaysReturn$false; + spec.isFunction = utils.alwaysReturn$false; - if ($class === $nil) { - $class = SCArray; - } + spec.matchItem = fn(function($item) { + return this ["==="] ($item); + }, "item"); - $res = $class.new(this); - for (i = 0, imax = this._; i < imax; ++i) { - $res.add($function.value($SC.Integer(i))); - } + spec.trueAt = utils.alwaysReturn$false; - return $res; - }; + spec.falseAt = fn(function($key) { + return this.trueAt($key).not(); + }, "key"); - spec.collect = function($function) { - return this.collectAs($function, SCArray); + // TODO: implements pointsTo + // TODO: implements mutable + // TODO: implements frozen + // TODO: implements halt + // TODO: implements primitiveFailed + // TODO: implements reportError + // TODO: implements subclassResponsibility + spec._subclassResponsibility = function(methodName) { + throw new Error("RECEIVER " + String(this) + ": " + + "'" + methodName + "' should have been implemented by subclass"); }; - spec.reverseDo = function($function) { - iterator.execute( - iterator.integer$reverseDo(this), - $function - ); - return this; + // TODO: implements doesNotUnderstand + spec._doesNotUnderstand = function(methodName) { + throw new Error("RECEIVER " + this.__str__() + ": " + + "Message '" + methodName + "' not understood."); }; - spec.for = function($endval, $function) { - iterator.execute( - iterator.integer$for(this, $endval), - $function - ); - return this; + // TODO: implements shouldNotImplement + // TODO: implements outOfContextReturn + // TODO: implements immutableError + // TODO: implements deprecated + // TODO: implements mustBeBoolean + // TODO: implements notYetImplemented + // TODO: implements dumpBackTrace + // TODO: implements getBackTrace + // TODO: implements throw + + spec.species = function() { + return this.class(); }; - spec.forBy = function($endval, $stepval, $function) { - iterator.execute( - iterator.integer$forBy(this, $endval, $stepval), - $function - ); - return this; + spec.asCollection = function() { + return $SC.Array([ this ]); }; - spec.to = function($hi, $step) { - $step = utils.defaultValue$Integer($step, 1); - return $SC("Interval").new(this, $hi, $step); + spec.asSymbol = function() { + return this.asString().asSymbol(); }; - spec.asAscii = function() { - // <-- _AsAscii --> - return $SC.Char(String.fromCharCode(this._|0)); + spec.asString = function() { + return $SC.String(String(this)); }; - spec.asUnicode = utils.nop; + // TODO: implements asCompileString + // TODO: implements cs + // TODO: implements printClassNameOn + // TODO: implements printOn + // TODO: implements storeOn + // TODO: implements storeParamsOn + // TODO: implements simplifyStoreArgs + // TODO: implements storeArgs + // TODO: implements storeModifiersOn - spec.asDigit = function() { - var c; + spec.as = fn(function($aSimilarClass) { + return $aSimilarClass.newFrom(this); + }, "aSimilarClass"); - // - c = this._; - if (0 <= c && c <= 9) { - return $SC.Char(String(c)); - } - if (10 <= c && c <= 35) { - return $SC.Char(String.fromCharCode(c + 55)); - } + spec.dereference = utils.nop; - throw new Error("Integer: asDigit must be 0 <= this <= 35"); + spec.reference = function() { + return $SC.Ref(this); }; - spec.asBinaryDigits = function($numDigits) { - var raw, array, numDigits, i; - $numDigits = utils.defaultValue$Integer($numDigits, 8); + spec.asRef = function() { + return $SC.Ref(this); + }; - raw = this._; - numDigits = $numDigits.__int__(); - array = new Array(numDigits); - for (i = 0; i < numDigits; ++i) { - array.unshift($SC.Integer((raw >> i) & 1)); - } + spec.asArray = function() { + return this.asCollection().asArray(); + }; - return $SC.Array(array); + spec.asSequenceableCollection = function() { + return this.asArray(); }; - spec.asDigits = function($base, $numDigits) { - var $num; - var array, numDigits, i; - $base = utils.defaultValue$Integer($base, 10); - $numDigits = utils.defaultValue$Nil($numDigits); + spec.rank = utils.alwaysReturn$int_0; - $num = this; - if ($numDigits === $nil) { - $numDigits = ( - this.log() ["/"] ($base.log() ["+"] ($SC.Float(1e-10))) - ).asInteger().__inc__(); - } + spec.deepCollect = fn(function($depth, $function, $index, $rank) { + return $function.value(this, $index, $rank); + }, "depth; function; index; rank"); - array = []; - numDigits = $numDigits.__int__(); - array = new Array(numDigits); - for (i = 0; i < numDigits; ++i) { - array.unshift($num ["%"] ($base)); - $num = $num.div($base); + spec.deepDo = fn(function($depth, $function, $index, $rank) { + $function.value(this, $index, $rank); + return this; + }, "depth; function; index; rank"); + + spec.slice = utils.nop; + spec.shape = utils.alwaysReturn$nil; + spec.unbubble = utils.nop; + + spec.bubble = fn(function($depth, $levels) { + var levels, a; + + levels = $levels.__int__(); + if (levels <= 1) { + a = [ this ]; + } else { + a = [ + this.bubble($depth, $SC.Integer(levels - 1)) + ]; } - return $SC.Array(array); - }; + return $SC.Array(a); + }, "depth; levels"); - // TODO: implements nextPowerOfTwo - // TODO: implements isPowerOfTwo - // TODO: implements leadingZeroes - // TODO: implements trailingZeroes - // TODO: implements numBits - // TODO: implements log2Ceil - // TODO: implements grayCode - // TODO: implements setBit - // TODO: implements nthPrime - // TODO: implements prevPrime - // TODO: implements nextPrime - // TODO: implements indexOfPrime - // TODO: implements isPrime - // TODO: implements exit - // TODO: implements asStringToBase - // TODO: implements asBinaryString - // TODO: implements asHexString - // TODO: implements asIPString - // TODO: implements archiveAsCompileString + spec.obtain = fn(function($index, $default) { + if ($index.__num__() === 0) { + return this; + } else { + return $default; + } + }, "index; defaults"); - spec.geom = function($start, $grow) { - return SCArray.geom(this, $start, $grow); - }; + spec.instill = fn(function($index, $item, $default) { + if ($index.__num__() === 0) { + return $item; + } else { + return this.asArray().instill($index, $item, $default); + } + }, "index; item; default"); - spec.fib = function($a, $b) { - $a = utils.defaultValue$Float($a, 0.0); - $b = utils.defaultValue$Float($b, 1.0); - return SCArray.fib(this, $a, $b); + spec.addFunc = fn(function($$functions) { + return $SC("FunctionList").new(this ["++"] ($$functions)); + }, "*functions"); + + spec.removeFunc = function($function) { + if (this === $function) { + return $nil; + } + return this; }; - // TODO: implements factors - // TODO: implements pidRunning - // TODO: implements factorial - // TODO: implements isCaps - // TODO: implements isShift - // TODO: implements isCtrl - // TODO: implements isAlt - // TODO: implements isCmd - // TODO: implements isNumPad - // TODO: implements isHelp - // TODO: implements isFun + spec.replaceFunc = fn(function($find, $replace) { + if (this === $find) { + return $replace; + } + return this; + }, "find; replace"); - spec.bitNot = function() { - return $SC.Integer(~this._); - }; - }); + // TODO: implements addFuncTo + // TODO: implements removeFuncFrom -})(sc); + spec.while = fn(function($body) { + var $this = this; -// src/sc/lang/classlib/Math/Float.js -(function(sc) { + $SC.Function(function() { + return $this.value(); + }).while($SC.Function(function() { + return $body.value(); + })); - var $SC = sc.lang.$SC; - var iterator = sc.lang.iterator; - var mathlib = sc.libs.mathlib; + return this; + }, "body"); - sc.lang.klass.refine("Float", function(spec, utils) { - spec.toString = function() { - var raw = this._; + spec.switch = function() { + var args, i, imax; - if (raw === Infinity) { - return "inf"; - } - if (raw === -Infinity) { - return "-inf"; + args = slice.call(arguments); + for (i = 0, imax = args.length >> 1; i < imax; i++) { + if (BOOL(this ["=="] (args[i * 2]))) { + return args[i * 2 + 1].value(); + } } - if (isNaN(raw)) { - return "nan"; + + if (args.length % 2 === 1) { + return args[args.length - 1].value(); } - return String(this._); + return $nil; }; - spec.$new = function() { - throw new Error("Float.new is illegal, should use literal."); + spec.yield = function() { + // TODO: implements yield }; - spec.isFloat = utils.alwaysReturn$true; - spec.asFloat = utils.nop; + // TODO: implements alwaysYield + // TODO: implements yieldAndReset + // TODO: implements idle + // TODO: implements $initClass + // TODO: implements dependants + // TODO: implements changed + // TODO: implements addDependant + // TODO: implements removeDependant + // TODO: implements release + // TODO: implements releaseDependants + // TODO: implements update + // TODO: implements addUniqueMethod + // TODO: implements removeUniqueMethods + // TODO: implements removeUniqueMethod + // TODO: implements inspect + // TODO: implements inspectorClass + // TODO: implements inspector + // TODO: implements crash + // TODO: implements stackDepth + // TODO: implements dumpStack + // TODO: implements dumpDetailedBackTrace + // TODO: implements freeze - [ - [ "+" , $SC.Float, $SC.Float ], - [ "-" , $SC.Float, $SC.Float ], - [ "*" , $SC.Float, $SC.Float ], - [ "/" , $SC.Float, $SC.Float ], - [ "mod" , $SC.Float , $SC.Float ], - [ "div" , $SC.Integer, $SC.Integer ], - [ "pow" , $SC.Float , $SC.Float ], - [ "min" , $SC.Float , $SC.Float ], - [ "max" , $SC.Float , $SC.Float ], - [ "bitAnd" , $SC.Float , $SC.Float ], - [ "bitOr" , $SC.Float , $SC.Float ], - [ "bitXor" , $SC.Float , $SC.Float ], - [ "lcm" , $SC.Float , $SC.Float ], - [ "gcd" , $SC.Float , $SC.Float ], - [ "round" , $SC.Float , $SC.Float ], - [ "roundUp" , $SC.Float , $SC.Float ], - [ "trunc" , $SC.Float , $SC.Float ], - [ "atan2" , $SC.Float , $SC.Float ], - [ "hypot" , $SC.Float , $SC.Float ], - [ "hypotApx", $SC.Float , $SC.Float ], - [ "leftShift" , $SC.Float, $SC.Float ], - [ "rightShift" , $SC.Float, $SC.Float ], - [ "unsignedRightShift", $SC.Float, $SC.Float ], - [ "ring1" , $SC.Float, $SC.Float ], - [ "ring2" , $SC.Float, $SC.Float ], - [ "ring3" , $SC.Float, $SC.Float ], - [ "ring4" , $SC.Float, $SC.Float ], - [ "difsqr" , $SC.Float, $SC.Float ], - [ "sumsqr" , $SC.Float, $SC.Float ], - [ "sqrsum" , $SC.Float, $SC.Float ], - [ "sqrdif" , $SC.Float, $SC.Float ], - [ "absdif" , $SC.Float, $SC.Float ], - [ "thresh" , $SC.Float, $SC.Float ], - [ "amclip" , $SC.Float, $SC.Float ], - [ "scaleneg", $SC.Float, $SC.Float ], - [ "clip2" , $SC.Float, $SC.Float ], - [ "fold2" , $SC.Float, $SC.Float ], - [ "wrap2" , $SC.Float, $SC.Float ], - [ "excess" , $SC.Float, $SC.Float ], - [ "firstArg", $SC.Float, $SC.Float ], - [ "rrand" , $SC.Float, $SC.Float ], - [ "exprand" , $SC.Float, $SC.Float ], - ].forEach(function(items) { - spec[items[0]] = sc.lang.classlib.bop.apply(null, items); - }); + spec["&"] = function($that) { + return this.bitAnd($that); + }; - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec["|"] = function($that) { + return this.bitOr($that); + }; - // <-- _ClipFloat --> - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } + spec["%"] = function($that) { + return this.mod($that); + }; - return $SC.Float( - mathlib.clip(this._, $lo.__num__(), $hi.__num__()) - ); + spec["**"] = function($that) { + return this.pow($that); }; - spec.wrap = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec["<<"] = function($that) { + return this.leftShift($that); + }; - // <-- _WrapInt --> - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } + spec[">>"] = function($that) { + return this.rightShift($that); + }; - return $SC.Float( - mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) - ); + spec["+>>"] = function($that) { + return this.unsignedRightShift($that); }; - spec.fold = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec[" - if ($lo.__tag === 1027) { - return $lo; - } - if ($hi.__tag === 1027) { - return $hi; - } - - return $SC.Float( - mathlib.fold(this._, $lo.__num__(), $hi.__num__()) - ); + spec.asInt = function() { + return this.asInteger(); }; - // TODO: implements coin - // TODO: implements xrand2 - - spec.as32Bits = function() { - // <-- _As32Bits --> - return $SC.Integer( - new Int32Array( - new Float32Array([ this._ ]).buffer - )[0] - ); - }; + spec.blend = fn(function($that, $blendFrac) { + return this ["+"] ($blendFrac ["*"] ($that ["-"] (this))); + }, "that; blendFrac=0.5"); - spec.high32Bits = function() { - // <-- _High32Bits --> - return $SC.Integer( - new Int32Array( - new Float64Array([ this._ ]).buffer - )[1] - ); - }; + spec.blendAt = fn(function($index, $method) { + var $iMin; - spec.low32Bits = function() { - // <-- _Low32Bits --> - return $SC.Integer( - new Int32Array( - new Float64Array([ this._ ]).buffer - )[0] + $iMin = $index.roundUp($int_1).asInteger().__dec__(); + return this.perform($method, $iMin).blend( + this.perform($method, $iMin.__inc__()), + $index.absdif($iMin) ); - }; + }, "index; method=\\clipAt"); - spec.$from32Bits = function($word) { - // <-- _From32Bits --> - return $SC.Float( - new Float32Array( - new Int32Array([ $word.__num__() ]).buffer - )[0] - ); - }; + spec.blendPut = fn(function($index, $val, $method) { + var $iMin, $ratio; - spec.$from64Bits = function($hiWord, $loWord) { - // <-- _From64Bits --> - return $SC.Float( - new Float64Array( - new Int32Array([ $loWord.__num__(), $hiWord.__num__() ]).buffer - )[0] - ); - }; + $iMin = $index.floor().asInteger(); + $ratio = $index.absdif($iMin); + this.perform($method, $iMin, $val ["*"] ($int_1 ["-"] ($ratio))); + this.perform($method, $iMin.__inc__(), $val ["*"] ($ratio)); - spec.do = function($function) { - iterator.execute( - iterator.float$do(this), - $function - ); return this; - }; + }, "index; val; method=\\wrapPut"); - spec.reverseDo = function($function) { - iterator.execute( - iterator.float$reverseDo(this), - $function + spec.fuzzyEqual = fn(function($that, $precision) { + return $SC.Float(0.0).max( + $SC.Float(1.0) ["-"] ( + (this ["-"] ($that).abs()) ["/"] ($precision) + ) ); - return this; - }; + }, "that; precision=1.0"); - // TODO: implements asStringPrec - // TODO: implements archiveAsCompileString - // TODO: implements storeOn - // TODO: implements switch + spec.isUGen = utils.alwaysReturn$false; + spec.numChannels = utils.alwaysReturn$int_1; - spec.bitNot = function() { - var f64 = new Float64Array([ this._ ]); - var i32 = new Int32Array(f64.buffer); - i32[0] = ~i32[0]; - return $SC.Float(f64[0]); + spec.pair = fn(function($that) { + return $SC.Array([ this, $that ]); + }, "that"); + + spec.pairs = fn(function($that) { + var $list; + + $list = $SC.Array(); + this.asArray().do($SC.Function(function($a) { + $that.asArray().do($SC.Function(function($b) { + $list = $list.add($a.asArray() ["++"] ($b)); + })); + })); + + return $list; + }, "that"); + + spec.awake = fn(function($beats) { + return this.next($beats); + }, "beats"); + + spec.beats_ = utils.nop; + spec.clock_ = utils.nop; + + spec.performBinaryOpOnSomething = function($aSelector) { + var aSelector; + + aSelector = $aSelector.__sym__(); + if (aSelector === "==") { + return $false; + } + if (aSelector === "!=") { + return $true; + } + + throw new Error("binary operator '" + aSelector + "' failed."); }; - }); -})(sc); + spec.performBinaryOpOnSimpleNumber = function($aSelector, $thig, $adverb) { + return this.performBinaryOpOnSomething($aSelector, $thig, $adverb); + }; -// src/sc/lang/classlib/Core/Thread.js -(function(sc) { + spec.performBinaryOpOnSignal = spec.performBinaryOpOnSimpleNumber; + spec.performBinaryOpOnComplex = spec.performBinaryOpOnSimpleNumber; + spec.performBinaryOpOnSeqColl = spec.performBinaryOpOnSimpleNumber; + spec.performBinaryOpOnUGen = spec.performBinaryOpOnSimpleNumber; - function SCThread() { - this.__initializeWith__("Stream"); - } + // TODO: implements writeDefFile - sc.lang.klass.define(SCThread, "Thread : Stream", function() { - // TODO: implements state - // TODO: implements parent - // TODO: implements primitiveError - // TODO: implements primitiveIndex - // TODO: implements beats - // TODO: implements seconds - // TODO: implements clock - // TODO: implements nextBeat - // TODO: implements endBeat - // TODO: implements endBeat_ - // TODO: implements endValue - // TODO: implements endValue_ - // TODO: implements exceptionHandler - // TODO: implements exceptionHandler_ - // TODO: implements threadPlayer_ - // TODO: implements executingPath - // TODO: implements oldExecutingPath + spec.isInputUGen = utils.alwaysReturn$false; + spec.isOutputUGen = utils.alwaysReturn$false; + spec.isControlUGen = utils.alwaysReturn$false; + spec.source = utils.nop; + spec.asUGenInput = utils.nop; + spec.asControlInput = utils.nop; - // TODO: implements init - // TODO: implements copy - // TODO: implements clock_ - // TODO: implements seconds_ - // TODO: implements beats_ - // TODO: implements isPlaying - // TODO: implements threadPlayer - // TODO: implements findThreadPlayer - // TODO: implements randSeed_ - // TODO: implements randData_ - // TODO: implements randData - // TODO: implements failedPrimitiveName - // TODO: implements handleError - // TODO: implements next - // TODO: implements value - // TODO: implements valueArray - // TODO: implements $primitiveError - // TODO: implements $primitiveErrorString - // TODO: implements storeOn + spec.asAudioRateInput = function() { + if (this.rate().__sym__() !== "audio") { + return $SC("K2A").ar(this); + } + return this; + }; + + // TODO: implements slotSize + // TODO: implements slotAt + // TODO: implements slotPut + // TODO: implements slotKey + // TODO: implements slotIndex + // TODO: implements slotsDo + // TODO: implements slotValuesDo + // TODO: implements getSlots + // TODO: implements setSlots + // TODO: implements instVarSize + // TODO: implements instVarAt + // TODO: implements instVarPut + // TODO: implements writeArchive + // TODO: implements $readArchive + // TODO: implements asArchive + // TODO: implements initFromArchive // TODO: implements archiveAsCompileString + // TODO: implements archiveAsObject // TODO: implements checkCanArchive - }); - - function SCRoutine() { - this.__initializeWith__("Thread"); - } - - sc.lang.klass.define(SCRoutine, "Routine : Thread", function() { - // TODO: implements $run - // TODO: implements next - // TODO: implements value - // TODO: implements resume - // TODO: implements run - // TODO: implements valueArray - // TODO: implements reset - // TODO: implements stop - // TODO: implements p - // TODO: implements storeArgs - // TODO: implements storeOn - // TODO: implements awake + // TODO: implements writeTextArchive + // TODO: implements $readTextArchive + // TODO: implements asTextArchive + // TODO: implements getContainedObjects + // TODO: implements writeBinaryArchive + // TODO: implements $readBinaryArchive + // TODO: implements asBinaryArchive + // TODO: implements genNext + // TODO: implements genCurrent + // TODO: implements $classRedirect + // TODO: implements help }); })(sc); -// src/sc/lang/classlib/Core/Symbol.js +// src/sc/lang/classlib/Core/AbstractFunction.js (function(sc) { - var $SC = sc.lang.$SC; - - sc.lang.klass.refine("Symbol", function(spec, utils) { - var $nil = utils.$nil; + var $SC = sc.lang.$SC; + var fn = sc.lang.fn; + var utils = sc.lang.klass.utils; + var $nil = utils.$nil; - spec.__sym__ = function() { - return this._; + sc.lang.klass.refine("AbstractFunction", function(spec, utils) { + spec.composeUnaryOp = function($aSelector) { + return $SC("UnaryOpFunction").new($aSelector, this); }; - spec.__str__ = function() { - return this._; + spec.composeBinaryOp = function($aSelector, $something, $adverb) { + return $SC("BinaryOpFunction").new($aSelector, this, $something, $adverb); }; - spec.$new = function() { - throw new Error("Symbol.new is illegal, should use literal."); + spec.reverseComposeBinaryOp = function($aSelector, $something, $adverb) { + return $SC("BinaryOpFunction").new($aSelector, $something, this, $adverb); }; - spec.asSymbol = utils.nop; - - spec.asInteger = function() { - var m = /^[-+]?\d+/.exec(this._); - return $SC.Integer(m ? m[0]|0 : 0); + spec.composeNAryOp = function($aSelector, $anArgList) { + return $SC("NAryOpFunction").new($aSelector, this, $anArgList); }; - spec.asFloat = function() { - var m = /^[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/.exec(this._); - return $SC.Float(m ? +m[0] : 0); + spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber, $adverb) { + return this.reverseComposeBinaryOp($aSelector, $aNumber, $adverb); }; - spec.ascii = function() { - return this.asString().ascii(); + spec.performBinaryOpOnSignal = function($aSelector, $aSignal, $adverb) { + return this.reverseComposeBinaryOp($aSelector, $aSignal, $adverb); }; - // TODO: implements asCompileString + spec.performBinaryOpOnComplex = function($aSelector, $aComplex, $adverb) { + return this.reverseComposeBinaryOp($aSelector, $aComplex, $adverb); + }; - spec.asClass = function() { - if (sc.lang.klass.exists(this._)) { - return sc.lang.klass.get(this._); - } - return $nil; + spec.performBinaryOpOnSeqColl = function($aSelector, $aSeqColl, $adverb) { + return this.reverseComposeBinaryOp($aSelector, $aSeqColl, $adverb); }; - // TODO: implements asSetter - // TODO: implements asGetter - // TODO: implements asSpec - // TODO: implements asWarp - // TODO: implements asTuning - // TODO: implements asScale - // TODO: implements isSetter - // TODO: implements isClassName - // TODO: implements isMetaClassName - // TODO: implements isPrefix - // TODO: implements isPrimitiveName - // TODO: implements isPrimitive - // TODO: implements isMap - // TODO: implements isRest - // TODO: implements envirGet - // TODO: implements envirPut - // TODO: implements blend - // TODO: implements ++ - // TODO: implements asBinOpString - // TODO: implements applyTo - // TODO: implements performBinaryOpOnSomething + spec.neg = function() { + return this.composeUnaryOp($SC.Symbol("neg")); + }; - spec.neg = utils.nop; - spec.bitNot = utils.nop; - spec.abs = utils.nop; - spec.ceil = utils.nop; - spec.floor = utils.nop; - spec.frac = utils.nop; - spec.sign = utils.nop; - spec.sqrt = utils.nop; - spec.exp = utils.nop; - spec.midicps = utils.nop; - spec.cpsmidi = utils.nop; - spec.midiratio = utils.nop; - spec.ratiomidi = utils.nop; - spec.ampdb = utils.nop; - spec.dbamp = utils.nop; - spec.octcps = utils.nop; - spec.cpsoct = utils.nop; - spec.log = utils.nop; - spec.log2 = utils.nop; - spec.log10 = utils.nop; - spec.sin = utils.nop; - spec.cos = utils.nop; - spec.tan = utils.nop; - spec.asin = utils.nop; - spec.acos = utils.nop; - spec.atan = utils.nop; - spec.sinh = utils.nop; - spec.cosh = utils.nop; - spec.tanh = utils.nop; - spec.rand = utils.nop; - spec.rand2 = utils.nop; - spec.linrand = utils.nop; - spec.bilinrand = utils.nop; - spec.sum3rand = utils.nop; - spec.distort = utils.nop; - spec.softclip = utils.nop; - spec.coin = utils.nop; - spec.even = utils.nop; - spec.odd = utils.nop; - spec.rectWindow = utils.nop; - spec.hanWindow = utils.nop; - spec.welWindow = utils.nop; - spec.triWindow = utils.nop; - spec.scurve = utils.nop; - spec.ramp = utils.nop; - spec["+"] = utils.nop; - spec["-"] = utils.nop; - spec["*"] = utils.nop; - spec["/"] = utils.nop; - spec.mod = utils.nop; - spec.min = utils.nop; - spec.max = utils.nop; - spec.bitAnd = utils.nop; - spec.bitOr = utils.nop; - spec.bitXor = utils.nop; - spec.bitHammingDistance = utils.nop; - // TODO: Implements hammingDistance - spec.lcm = utils.nop; - spec.gcd = utils.nop; - spec.round = utils.nop; - spec.roundUp = utils.nop; - spec.trunc = utils.nop; - spec.atan2 = utils.nop; - spec.hypot = utils.nop; - spec.hypotApx = utils.nop; - spec.pow = utils.nop; - spec.leftShift = utils.nop; - spec.rightShift = utils.nop; - spec.unsignedRightShift = utils.nop; - spec.rrand = utils.nop; - spec.exprand = utils.nop; + spec.reciprocal = function() { + return this.composeUnaryOp($SC.Symbol("reciprocal")); + }; - // TODO: Implements < - // TODO: Implements > - // TODO: Implements <= - // TODO: Implements >= + spec.bitNot = function() { + return this.composeUnaryOp($SC.Symbol("bitNot")); + }; - spec.degreeToKey = utils.nop; - spec.degrad = utils.nop; - spec.raddeg = utils.nop; - spec.doNumberOp = utils.nop; - spec.doComplexOp = utils.nop; - spec.doSignalOp = utils.nop; + spec.abs = function() { + return this.composeUnaryOp($SC.Symbol("abs")); + }; - // TODO: Implements doListOp - // TODO: Implements primitiveIndex - // TODO: Implements specialIndex - // TODO: Implements printOn - // TODO: Implements storeOn - // TODO: Implements codegen_UGenCtorArg + spec.asFloat = function() { + return this.composeUnaryOp($SC.Symbol("asFloat")); + }; - spec.archiveAsCompileString = utils.alwaysReturn$true; + spec.asInteger = function() { + return this.composeUnaryOp($SC.Symbol("asInteger")); + }; - // TODO: Implements kr - // TODO: Implements ir - // TODO: Implements tr - // TODO: Implements ar - // TODO: Implements matchOSCAddressPattern - // TODO: Implements help + spec.ceil = function() { + return this.composeUnaryOp($SC.Symbol("ceil")); + }; - spec.asString = function() { - return $SC.String(this._); + spec.floor = function() { + return this.composeUnaryOp($SC.Symbol("floor")); }; - spec.shallowCopy = utils.nop; + spec.frac = function() { + return this.composeUnaryOp($SC.Symbol("frac")); + }; - spec.performBinaryOpOnSimpleNumber = utils.nop; - }); + spec.sign = function() { + return this.composeUnaryOp($SC.Symbol("sign")); + }; -})(sc); + spec.squared = function() { + return this.composeUnaryOp($SC.Symbol("squared")); + }; -// src/sc/lang/classlib/Core/Ref.js -(function(sc) { + spec.cubed = function() { + return this.composeUnaryOp($SC.Symbol("cubed")); + }; - var $SC = sc.lang.$SC; + spec.sqrt = function() { + return this.composeUnaryOp($SC.Symbol("sqrt")); + }; - function SCRef(args) { - this.__initializeWith__("Object"); - this._value = args[0] || $SC.Nil(); - } + spec.exp = function() { + return this.composeUnaryOp($SC.Symbol("exp")); + }; - sc.lang.klass.define(SCRef, "Ref : AbstractFunction", function(spec, utils) { - spec.valueOf = function() { - return this._value.valueOf(); + spec.midicps = function() { + return this.composeUnaryOp($SC.Symbol("midicps")); }; - spec.value = function() { - return this._value; + spec.cpsmidi = function() { + return this.composeUnaryOp($SC.Symbol("cpsmidi")); }; - spec.value_ = function($value) { - this._value = $value; - return this; + spec.midiratio = function() { + return this.composeUnaryOp($SC.Symbol("midiratio")); }; - // $new + spec.ratiomidi = function() { + return this.composeUnaryOp($SC.Symbol("ratiomidi")); + }; - spec.set = function($thing) { - $thing = utils.defaultValue$Nil($thing); - this._value = $thing; - return this; + spec.ampdb = function() { + return this.composeUnaryOp($SC.Symbol("ampdb")); }; - spec.get = function() { - return this._value; + spec.dbamp = function() { + return this.composeUnaryOp($SC.Symbol("dbamp")); }; - spec.dereference = spec.value; + spec.octcps = function() { + return this.composeUnaryOp($SC.Symbol("octcps")); + }; - spec.asRef = utils.nop; + spec.cpsoct = function() { + return this.composeUnaryOp($SC.Symbol("cpsoct")); + }; - spec.valueArray = spec.value; + spec.log = function() { + return this.composeUnaryOp($SC.Symbol("log")); + }; - spec.valueEnvir = spec.value; + spec.log2 = function() { + return this.composeUnaryOp($SC.Symbol("log2")); + }; - spec.valueArrayEnvir = spec.value; + spec.log10 = function() { + return this.composeUnaryOp($SC.Symbol("log10")); + }; - spec.next = spec.value; + spec.sin = function() { + return this.composeUnaryOp($SC.Symbol("sin")); + }; - spec.asUGenInput = utils.nop; + spec.cos = function() { + return this.composeUnaryOp($SC.Symbol("cos")); + }; - // TODO: implements printOn - // TODO: implements storeOn + spec.tan = function() { + return this.composeUnaryOp($SC.Symbol("tan")); + }; - spec.at = function($key) { - return this._value.at($key); + spec.asin = function() { + return this.composeUnaryOp($SC.Symbol("asin")); }; - spec.put = function($key, $val) { - return this._value.put($key, $val); + spec.acos = function() { + return this.composeUnaryOp($SC.Symbol("acos")); }; - // TODO: implements seq - // TODO: implements asControlInput - // TODO: implements asBufWithValues - // TODO: implements multichannelExpandRef - }); + spec.atan = function() { + return this.composeUnaryOp($SC.Symbol("atan")); + }; -})(sc); + spec.sinh = function() { + return this.composeUnaryOp($SC.Symbol("sinh")); + }; -// src/sc/lang/classlib/Core/Nil.js -(function(sc) { + spec.cosh = function() { + return this.composeUnaryOp($SC.Symbol("cosh")); + }; - var slice = [].slice; - var $SC = sc.lang.$SC; + spec.tanh = function() { + return this.composeUnaryOp($SC.Symbol("tanh")); + }; - sc.lang.klass.refine("Nil", function(spec, utils) { - var $nil = utils.$nil; + spec.rand = function() { + return this.composeUnaryOp($SC.Symbol("rand")); + }; - spec.__num__ = function() { - return 0; + spec.rand2 = function() { + return this.composeUnaryOp($SC.Symbol("rand2")); }; - spec.__bool__ = function() { - return false; + spec.linrand = function() { + return this.composeUnaryOp($SC.Symbol("linrand")); }; - spec.__sym__ = function() { - return "nil"; + spec.bilinrand = function() { + return this.composeUnaryOp($SC.Symbol("bilinrand")); }; - spec.toString = function() { - return "nil"; + spec.sum3rand = function() { + return this.composeUnaryOp($SC.Symbol("sum3rand")); }; - spec.$new = function() { - throw new Error("Nil.new is illegal, should use literal."); + spec.distort = function() { + return this.composeUnaryOp($SC.Symbol("distort")); }; - spec.isNil = utils.alwaysReturn$true; - spec.notNil = utils.alwaysReturn$false; + spec.softclip = function() { + return this.composeUnaryOp($SC.Symbol("softclip")); + }; - spec["?"] = function($obj) { - return $obj; + spec.coin = function() { + return this.composeUnaryOp($SC.Symbol("coin")); }; - spec["??"] = function($obj) { - return $obj.value(); + spec.even = function() { + return this.composeUnaryOp($SC.Symbol("even")); }; - spec["!?"] = utils.nop; + spec.odd = function() { + return this.composeUnaryOp($SC.Symbol("odd")); + }; - spec.asBoolean = utils.alwaysReturn$false; - spec.booleanValue = utils.alwaysReturn$false; + spec.rectWindow = function() { + return this.composeUnaryOp($SC.Symbol("rectWindow")); + }; - spec.push = function($function) { - $function = utils.defaultValue$Nil($function); - return $function.value(); + spec.hanWindow = function() { + return this.composeUnaryOp($SC.Symbol("hanWindow")); }; - spec.appendStream = function($stream) { - $stream = utils.defaultValue$Nil($stream); - return $stream; + spec.welWindow = function() { + return this.composeUnaryOp($SC.Symbol("welWindow")); }; - spec.pop = utils.nop; - spec.source = utils.nop; - spec.source_ = utils.nop; + spec.triWindow = function() { + return this.composeUnaryOp($SC.Symbol("triWindow")); + }; - spec.rate = utils.nop; - spec.numChannels = utils.nop; - spec.isPlaying = utils.alwaysReturn$false; + spec.scurve = function() { + return this.composeUnaryOp($SC.Symbol("scurve")); + }; - spec.do = utils.nop; - spec.reverseDo = utils.nop; - spec.pairsDo = utils.nop; - spec.collect = utils.nop; - spec.select = utils.nop; - spec.reject = utils.nop; - spec.detect = utils.nop; - spec.collectAs = utils.nop; - spec.selectAs = utils.nop; - spec.rejectAs = utils.nop; + spec.ramp = function() { + return this.composeUnaryOp($SC.Symbol("ramp")); + }; - spec.dependants = function() { - return $SC("IdentitySet").new(); + spec.isPositive = function() { + return this.composeUnaryOp($SC.Symbol("isPositive")); }; - spec.changed = utils.nop; - spec.addDependant = utils.nop; - spec.removeDependant = utils.nop; - spec.release = utils.nop; - spec.update = utils.nop; + spec.isNegative = function() { + return this.composeUnaryOp($SC.Symbol("isNegative")); + }; - spec.transformEvent = function($event) { - $event = utils.defaultValue$Nil($event); - return $event; + spec.isStrictlyPositive = function() { + return this.composeUnaryOp($SC.Symbol("isStrictlyPositive")); }; - spec.awake = utils.alwaysReturn$nil; + spec.rho = function() { + return this.composeUnaryOp($SC.Symbol("rho")); + }; - spec.play = utils.nop; + spec.theta = function() { + return this.composeUnaryOp($SC.Symbol("theta")); + }; - spec.nextTimeOnGrid = function($clock) { - $clock = utils.defaultValue$Nil($clock); + spec.rotate = function($function) { + return this.composeBinaryOp($SC.Symbol("rotate"), $function); + }; - if ($clock === $nil) { - return $clock; - } + spec.dist = function($function) { + return this.composeBinaryOp($SC.Symbol("dist"), $function); + }; - return $SC.Function(function() { - return $clock.nextTimeOnGrid(); - }); + spec["+"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("+"), $function, $adverb); }; - spec.asQuant = function() { - return $SC("Quant").default(); + spec["-"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("-"), $function, $adverb); }; - spec.swapThisGroup = utils.nop; - spec.performMsg = utils.nop; + spec["*"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("*"), $function, $adverb); + }; - spec.printOn = function($stream) { - $stream = utils.defaultValue$Nil($stream); - $stream.putAll($SC.String("nil")); - return this; + spec["/"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("/"), $function, $adverb); }; - spec.storeOn = function($stream) { - $stream = utils.defaultValue$Nil($stream); - $stream.putAll($SC.String("nil")); - return this; + spec.div = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("div"), $function, $adverb); }; - spec.matchItem = utils.alwaysReturn$true; + spec.mod = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("mod"), $function, $adverb); + }; - spec.add = function($value) { - $value = utils.defaultValue$Nil($value); - return $SC.Array([ $value ]); + spec.pow = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("pow"), $function, $adverb); }; - spec.addAll = function($array) { - $array = utils.defaultValue$Nil($array); - return $array.asArray(); + spec.min = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("min"), $function, $adverb); }; - spec["++"] = function($array) { - $array = utils.defaultValue$Nil($array); - return $array.asArray(); + spec.max = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("max"), $function, $adverb); }; - spec.asCollection = function() { - return $SC.Array(); + spec["<"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("<"), $function, $adverb); }; - spec.remove = utils.nop; + spec["<="] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("<="), $function, $adverb); + }; - spec.set = utils.nop; + spec[">"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol(">"), $function, $adverb); + }; - spec.get = function($prevVal) { - $prevVal = utils.defaultValue$Nil($prevVal); - return $prevVal; + spec[">="] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol(">="), $function, $adverb); }; - spec.addFunc = function() { - var functions = slice.call(arguments); - if (functions.length <= 1) { - return functions[0]; - } - return $SC("FunctionList").new($SC.Array(functions)); + spec.bitAnd = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("bitAnd"), $function, $adverb); }; - spec.removeFunc = utils.nop; + spec.bitOr = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("bitOr"), $function, $adverb); + }; - spec.replaceFunc = utils.nop; - spec.seconds_ = utils.nop; - spec.throw = utils.nop; + spec.bitXor = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("bitXor"), $function, $adverb); + }; - // TODO: implements handleError + spec.bitHammingDistance = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("bitHammingDistance"), $function, $adverb); + }; - spec.archiveAsCompileString = utils.alwaysReturn$true; + spec.lcm = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("lcm"), $function, $adverb); + }; - spec.asSpec = function() { - return $SC("ControlSpec").new(); + spec.gcd = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("gcd"), $function, $adverb); }; - spec.superclassesDo = utils.nop; + spec.round = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("round"), $function, $adverb); + }; - spec.shallowCopy = utils.nop; - }); + spec.roundUp = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("roundUp"), $function, $adverb); + }; -})(sc); + spec.trunc = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("trunc"), $function, $adverb); + }; -// src/sc/lang/classlib/Core/Kernel.js -(function(sc) { + spec.atan2 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("atan2"), $function, $adverb); + }; - sc.lang.klass.refine("Class", { - // TODO: implements superclass - // TODO: implements asClass - // TODO: implements initClass - // TODO: implements $initClassTree - // TODO: implements $allClasses - // TODO: implements findMethod - // TODO: implements findRespondingMethodFor - // TODO: implements findOverriddenMethod - // TODO: implements superclassesDo - // TODO: implements while - // TODO: implements dumpByteCodes - // TODO: implements dumpClassSubtree - // TODO: implements dumpInterface - // TODO: implements asString - // TODO: implements printOn - // TODO: implements storeOn - // TODO: implements archiveAsCompileString - // TODO: implements hasHelpFile - // TODO: implements helpFilePath - // TODO: implements help - // TODO: implements openHelpFile - // TODO: implements shallowCopy - // TODO: implements openCodeFile - // TODO: implements classVars - // TODO: implements inspectorClass - // TODO: implements findReferences - // TODO: implements $findAllReferences - // TODO: implements allSubclasses - // TODO: implements superclasses - }); - -})(sc); - -// src/sc/lang/classlib/Core/Function.js -(function(sc) { - - var slice = [].slice; - var $SC = sc.lang.$SC; - - sc.lang.klass.refine("Function", function(spec, utils) { - var BOOL = utils.BOOL; - var $nil = utils.$nil; - var SCArray = $SC("Array"); - - // TODO: implements def - - spec.$new = function() { - throw new Error("Function.new is illegal, should use literal."); + spec.hypot = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("hypot"), $function, $adverb); }; - spec.isFunction = utils.alwaysReturn$true; - - // TODO: implements isClosed - - spec.archiveAsCompileString = utils.alwaysReturn$true; - spec.archiveAsObject = utils.alwaysReturn$true; - - // TODO: implements checkCanArchive - - spec.shallowCopy = utils.nop; - - spec.choose = function() { - return this.value(); + spec.hypotApx = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("hypotApx"), $function, $adverb); }; - spec.update = function() { - return this._.apply(this, arguments); + spec.leftShift = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("leftShift"), $function, $adverb); }; - spec.value = function() { - return this._.apply(this, arguments); + spec.rightShift = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("rightShift"), $function, $adverb); }; - spec.valueArray = function($args) { - $args = utils.defaultValue$Nil($args); - return this._.apply(this, $args.asArray()._); + spec.unsignedRightShift = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("unsignedRightShift"), $function, $adverb); }; - // TODO: implements valueEnvir - // TODO: implements valueArrayEnvir - // TODO: implements functionPerformList - // TODO: implements valueWithEnvir - // TODO: implements performWithEnvir - // TODO: implements performKeyValuePairs - // TODO: implements numArgs - // TODO: implements numVars - // TODO: implements varArgs - // TODO: implements loop - // TODO: implements block - - spec.asRoutine = function() { - return $SC("Routine").new(this); + spec.ring1 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("ring1"), $function, $adverb); }; - spec.dup = function($n) { - $n = utils.defaultValue$Integer($n, 2); - return SCArray.fill($n, this); + spec.ring2 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("ring2"), $function, $adverb); }; - // TODO: implements sum - // TODO: implements defer - // TODO: implements thunk - // TODO: implements transformEvent - // TODO: implements set - // TODO: implements get - // TODO: implements fork - // TODO: implements forkIfNeeded - // TODO: implements awake - // TODO: implements cmdPeriod - // TODO: implements bench - // TODO: implements protect - // TODO: implements try - // TODO: implements prTry - // TODO: implements handleError - - spec.case = function() { - var args, i, imax; - - args = slice.call(arguments); - args.unshift(this); - - for (i = 0, imax = args.length >> 1; i < imax; ++i) { - if (BOOL(args[i * 2].value())) { - return args[i * 2 + 1].value(); - } - } - - if (args.length % 2 === 1) { - return args[args.length - 1].value(); - } - - return $nil; + spec.ring3 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("ring3"), $function, $adverb); }; - spec.r = function() { - return $SC("Routine").new(this); + spec.ring4 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("ring4"), $function, $adverb); }; - spec.p = function() { - return $SC("Prout").new(this); + spec.difsqr = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("difsqr"), $function, $adverb); }; - // TODO: implements matchItem - // TODO: implements performDegreeToKey - - spec.flop = function() { - var $this = this; - // if(def.argNames.isNil) { ^this }; - return $SC.Function(function() { - var $$args = $SC.Array(slice.call(arguments)); - return $$args.flop().collect($SC.Function(function($_) { - return $this.valueArray($_); - })); - }); + spec.sumsqr = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("sumsqr"), $function, $adverb); }; - // TODO: implements envirFlop - // TODO: implements makeFlopFunc - // TODO: implements inEnvir - - spec.while = function($body) { - $body = utils.defaultValue$Nil($body); - - sc.lang.iterator.execute( - sc.lang.iterator.function$while(this), - $body - ); - - return this; + spec.sqrsum = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("sqrsum"), $function, $adverb); }; - }); - -})(sc); -// src/sc/lang/classlib/Core/Char.js -(function(sc) { + spec.sqrdif = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("sqrdif"), $function, $adverb); + }; - var $SC = sc.lang.$SC; + spec.absdif = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("absdif"), $function, $adverb); + }; - sc.lang.klass.refine("Char", function(spec, utils) { - spec.__str__ = function() { - return this._; + spec.thresh = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("thresh"), $function, $adverb); }; - spec.$nl = function() { - return $SC.Char("\n"); + spec.amclip = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("amclip"), $function, $adverb); }; - spec.$ff = function() { - return $SC.Char("\f"); + spec.scaleneg = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("scaleneg"), $function, $adverb); }; - spec.$tab = function() { - return $SC.Char("\t"); + spec.clip2 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("clip2"), $function, $adverb); }; - spec.$space = function() { - return $SC.Char(" "); + spec.fold2 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("fold2"), $function, $adverb); }; - spec.$comma = function() { - return $SC.Char(","); + spec.wrap2 = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("wrap2"), $function, $adverb); }; - spec.$new = function() { - throw new Error("Char.new is illegal, should use literal."); + spec.excess = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("excess"), $function, $adverb); }; - // TODO: implements hash + spec.firstArg = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("firstArg"), $function, $adverb); + }; - spec.ascii = function() { - return $SC.Integer(this._.charCodeAt(0)); + spec.rrand = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("rrand"), $function, $adverb); }; - spec.digit = function() { - var ascii = this._.charCodeAt(0); - if (0x30 <= ascii && ascii <= 0x39) { - return $SC.Integer(ascii - 0x30); - } - if (0x41 <= ascii && ascii <= 0x5a) { - return $SC.Integer(ascii - 0x37); - } - if (0x61 <= ascii && ascii <= 0x7a) { - return $SC.Integer(ascii - 0x57); - } - throw new Error("digitValue failed"); + spec.exprand = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("exprand"), $function, $adverb); }; - spec.asAscii = utils.nop; + spec["@"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("@"), $function, $adverb); + }; - spec.asUnicode = function() { - return this.ascii(); + spec.real = utils.nop; + spec.imag = function() { + return $SC.Float(0.0); }; - spec.toUpper = function() { - return $SC.Char(this._.toUpperCase()); + spec["||"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("||"), $function, $adverb); }; - spec.toLower = function() { - return $SC.Char(this._.toLowerCase()); + spec["&&"] = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("&&"), $function, $adverb); }; - spec.isAlpha = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x41 <= ascii && ascii <= 0x5a) || - (0x61 <= ascii && ascii <= 0x7a)); + spec.xor = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("xor"), $function, $adverb); }; - spec.isAlphaNum = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x30 <= ascii && ascii <= 0x39) || - (0x41 <= ascii && ascii <= 0x5a) || - (0x61 <= ascii && ascii <= 0x7a)); + spec.nand = function($function, $adverb) { + return this.composeBinaryOp($SC.Symbol("nand"), $function, $adverb); }; - spec.isPrint = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x20 <= ascii && ascii <= 0x7e)); + spec.not = function() { + return this.composeUnaryOp($SC.Symbol("not")); }; - spec.isPunct = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x21 <= ascii && ascii <= 0x2f) || - (0x3a <= ascii && ascii <= 0x40) || - (0x5b <= ascii && ascii <= 0x60) || - (0x7b <= ascii && ascii <= 0x7e)); + spec.ref = function() { + return this.composeUnaryOp($SC.Symbol("asRef")); }; - spec.isControl = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x00 <= ascii && ascii <= 0x1f) || ascii === 0x7f); + spec.clip = function($lo, $hi) { + return this.composeNAryOp($SC.Symbol("clip"), $SC.Array([ $lo, $hi ])); }; - spec.isSpace = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x09 <= ascii && ascii <= 0x0d) || ascii === 0x20); + spec.wrap = function($lo, $hi) { + return this.composeNAryOp($SC.Symbol("wrap"), $SC.Array([ $lo, $hi ])); }; - spec.isVowl = function() { - var ch = this._.charAt(0).toUpperCase(); - return $SC.Boolean("AEIOU".indexOf(ch) !== -1); + spec.fold = function($lo, $hi) { + return this.composeNAryOp($SC.Symbol("fold"), $SC.Array([ $lo, $hi ])); }; - spec.isDecDigit = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x30 <= ascii && ascii <= 0x39)); - }; + spec.blend = fn(function($that, $blendFrac) { + return this.composeNAryOp( + $SC.Symbol("blend"), $SC.Array([ $that, $blendFrac ]) + ); + }, "that; blendFrac=0.5"); - spec.isUpper = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x41 <= ascii && ascii <= 0x5a)); - }; + spec.linlin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("linlin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) + ); + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.isLower = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x61 <= ascii && ascii <= 0x7a)); - }; + spec.linexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("linexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) + ); + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.isFileSafe = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean((0x20 <= ascii && ascii <= 0x7e) && - ascii !== 0x2f && // 0x2f is '/' - ascii !== 0x3a && // 0x3a is ':' - ascii !== 0x22); // 0x22 is '"' + spec.explin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("explin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) + ); + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); + + spec.expexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("expexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) + ); + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); + + spec.lincurve = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + return this.composeNAryOp( + $SC.Symbol("lincurve"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) + ); + }, "inMin=0; inMax=1; outMin=1; outMax=1; curve=-4; clip=\\minmax"); + + spec.curvelin = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + return this.composeNAryOp( + $SC.Symbol("curvelin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) + ); + }, "inMin=0; inMax=1; outMin=1; outMax=1; curve=-4; clip=\\minmax"); + + spec.bilin = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("bilin"), $SC.Array([ + $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip + ]) + ); + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); + + spec.biexp = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + return this.composeNAryOp( + $SC.Symbol("biexp"), $SC.Array([ + $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip + ]) + ); + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); + + spec.moddif = fn(function($function, $mod) { + return this.composeNAryOp( + $SC.Symbol("moddif"), $SC.Array([ $function, $mod ]) + ); + }, "function; mod"); + + spec.degreeToKey = fn(function($scale, $stepsPerOctave) { + return this.composeNAryOp( + $SC.Symbol("degreeToKey"), $SC.Array([ $scale, $stepsPerOctave ]) + ); + }, "scale; stepsPerOctave=12"); + + spec.degrad = function() { + return this.composeUnaryOp($SC.Symbol("degrad")); }; - spec.isPathSeparator = function() { - var ascii = this._.charCodeAt(0); - return $SC.Boolean(ascii === 0x2f); + spec.raddeg = function() { + return this.composeUnaryOp($SC.Symbol("raddeg")); }; - spec["<"] = function($aChar) { - return $SC.Boolean(this.ascii() < $aChar.ascii()); + spec.applyTo = function() { + return this.value.apply(this, arguments); }; - spec["++"] = function($that) { - return $SC.String(this._ + $that.__str__()); + // TODO: implements <> + // TODO: implements sampled + + spec.asUGenInput = function($for) { + return this.value($for); }; - // TODO: implements $bullet - // TODO: implements printOn - // TODO: implements storeOn + spec.asAudioRateInput = function($for) { + var $result; - spec.archiveAsCompileString = function() { - return $SC.True(); + $result = this.value($for); + + if ($result.rate().__sym__() !== "audio") { + return $SC("K2A").ar($result); + } + + return $result; }; - spec.asString = function() { - return $SC.String(this._); + spec.asControlInput = function() { + return this.value(); }; - spec.shallowCopy = utils.nop; + spec.isValidUGenInput = utils.alwaysReturn$true; }); -})(sc); - -// src/sc/lang/classlib/Core/Boolean.js -(function(sc) { + function SCUnaryOpFunction(args) { + this.__initializeWith__("AbstractFunction"); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; + } - var $SC = sc.lang.$SC; + sc.lang.klass.define(SCUnaryOpFunction, "UnaryOpFunction : AbstractFunction", function(spec) { - sc.lang.klass.refine("Boolean", function(spec, utils) { - spec.__bool__ = function() { - return this._; + spec.value = function() { + var $a = this.$a; + return $a.value.apply($a, arguments).perform(this.$selector); }; - spec.toString = function() { - return String(this._); + spec.valueArray = function($args) { + return this.$a.valueArray($args).perform(this.$selector); }; - spec.$new = function() { - throw new Error("Boolean.new is illegal, should use literal."); - }; + // TODO: implements valueEnvir + // TODO: implements valueArrayEnvir - spec.xor = function($bool) { - return $SC.Boolean(this === $bool).not(); + spec.functionPerformList = function($selector, $arglist) { + return this.performList($selector, $arglist); }; - // TODO: implements if - // TODO: implements nop - // TODO: implements && - // TODO: implements || - // TODO: implements and - // TODO: implements or - // TODO: implements nand - // TODO: implements asInteger - // TODO: implements binaryValue - - spec.asBoolean = utils.nop; - spec.booleanValue = utils.nop; - - // TODO: implements keywordWarnings - // TODO: implements trace - // TODO: implements printOn // TODO: implements storeOn + }); - spec.archiveAsCompileString = utils.alwaysReturn$true; - - spec.while = function() { - var msg = "While was called with a fixed (unchanging) Boolean as the condition. "; - msg += "Please supply a Function instead."; - throw new Error(msg); - }; + function SCBinaryOpFunction(args) { + this.__initializeWith__("AbstractFunction"); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; + this.$b = args[2] || /* istanbul ignore next */ $nil; + this.$adverb = args[3] || /* istanbul ignore next */ $nil; + } - spec.shallowCopy = utils.nop; - }); + sc.lang.klass.define(SCBinaryOpFunction, "BinaryOpFunction : AbstractFunction", function(spec) { - sc.lang.klass.refine("True", function(spec, utils) { - spec.$new = function() { - throw new Error("True.new is illegal, should use literal."); + spec.value = function() { + return this.$a.value.apply(this.$a, arguments) + .perform(this.$selector, this.$b.value.apply(this.$b, arguments), this.$adverb); }; - spec.if = function($trueFunc) { - $trueFunc = utils.defaultValue$Nil($trueFunc); - return $trueFunc.value(); + spec.valueArray = function($args) { + return this.$a.valueArray($args) + .perform(this.$selector, this.$b.valueArray($args, arguments), this.$adverb); }; - spec.not = utils.alwaysReturn$false; + // TODO: implements valueEnvir + // TODO: implements valueArrayEnvir - spec["&&"] = function($that) { - return $that.value(); + spec.functionPerformList = function($selector, $arglist) { + return this.performList($selector, $arglist); }; - spec["||"] = utils.nop; + // TODO: implements storeOn + }); - spec.and = function($that) { - $that = utils.defaultValue$Nil($that); - return $that.value(); + function SCNAryOpFunction(args) { + this.__initializeWith__("AbstractFunction"); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; + this.$arglist = args[2] || /* istanbul ignore next */ $nil; + } + + sc.lang.klass.define(SCNAryOpFunction, "NAryOpFunction : AbstractFunction", function(spec) { + + spec.value = function() { + var args = arguments; + return this.$a.value.apply(this.$a, args) + .performList(this.$selector, this.$arglist.collect($SC.Function(function($_) { + return $_.value.apply($_, args); + }))); }; - spec.or = spec["||"]; - spec.nand = function($that) { - $that = utils.defaultValue$Nil($that); - return $that.value().not(); + spec.valueArray = function($args) { + return this.$a.valueArray($args) + .performList(this.$selector, this.$arglist.collect($SC.Function(function($_) { + return $_.valueArray($args); + }))); }; - spec.asInteger = utils.alwaysReturn$int_1; - spec.binaryValue = utils.alwaysReturn$int_1; - }); + // TODO: implements valueEnvir + // TODO: implements valueArrayEnvir - sc.lang.klass.refine("False", function(spec, utils) { - spec.$new = function() { - throw new Error("False.new is illegal, should use literal."); + spec.functionPerformList = function($selector, $arglist) { + return this.performList($selector, $arglist); }; - spec.if = function($trueFunc, $falseFunc) { - return $falseFunc.value(); - }; + // TODO: implements storeOn + }); - spec.not = utils.alwaysReturn$true; + function SCFunctionList(args) { + this.__initializeWith__("AbstractFunction"); + this.$array = args[0] || /* istanbul ignore next */ $nil; + this._flopped = false; + } - spec["&&"] = utils.nop; + sc.lang.klass.define(SCFunctionList, "FunctionList : AbstractFunction", function(spec, utils) { + var $int_0 = utils.$int_0; - spec["||"] = function($that) { - return $that.value(); + spec.array = function() { + return this.$array; }; - spec.and = utils.nop; + spec.array_ = fn(function($value) { + this.$array = $value; + return this; + }, "value"); - spec.or = function($that) { - $that = utils.defaultValue$Nil($that); - return $that.value(); + spec.flopped = function() { + return $SC.Boolean(this._flopped); }; - spec.nand = utils.alwaysReturn$true; - spec.asInteger = utils.alwaysReturn$int_0; - spec.binaryValue = utils.alwaysReturn$int_0; - }); + spec.addFunc = fn(function($$functions) { + if (this._flopped) { + throw new Error("cannot add a function to a flopped FunctionList"); + } -})(sc); + this.$array = this.$array.addAll($$functions); -// src/sc/lang/classlib/Collections/Collection.js -(function(sc) { + return this; + }, "*functions"); - var $SC = sc.lang.$SC; - var fn = sc.lang.fn; + spec.removeFunc = function($function) { + this.$array.remove($function); - sc.lang.klass.refine("Collection", function(spec, utils) { - var BOOL = utils.BOOL; - var $nil = utils.$nil; - var $true = utils.$true; - var $false = utils.$false; - var $int_0 = utils.$int_0; - var $int_1 = utils.$int_1; - var SCArray = $SC("Array"); + if (this.$array.size() < 2) { + return this.$array.at($int_0); + } - spec.$newFrom = function($aCollection) { - var $newCollection; - $aCollection = utils.defaultValue$Nil($aCollection); + return this; + }; - $newCollection = this.new($aCollection.size()); - $aCollection.do($SC.Function(function($item) { - $newCollection.add($item); + spec.replaceFunc = function($find, $replace) { + this.$array = this.$array.replace($find, $replace); + return this; + }; + + spec.value = function() { + var $res, args = arguments; + + $res = this.$array.collect($SC.Function(function($_) { + return $_.value.apply($_, args); })); - return $newCollection; + return this._flopped ? $res.flop() : $res; }; - spec.$with = fn(function($$args) { - var $newColl; + spec.valueArray = function($args) { + var $res; - $newColl = this.new($$args.size()); - $newColl.addAll($$args); + $res = this.$array.collect($SC.Function(function($_) { + return $_.valueArray($args); + })); - return $newColl; - }, "*args"); + return this._flopped ? $res.flop() : $res; + }; - spec.$fill = function($size, $function) { - var $obj; - var size, i; - $size = utils.defaultValue$Nil($size); - $function = utils.defaultValue$Nil($function); + // TODO: implements valueEnvir + // TODO: implements valueArrayEnvir - if (BOOL($size.isSequenceableCollection())) { - return this.fillND($size, $function); + spec.do = function($function) { + this.$array.do($function); + return this; + }; + + spec.flop = function() { + if (!this._flopped) { + this.$array = this.$array.collect($SC.Function(function($_) { + return $_.flop(); + })); } + this._flopped = true; - $obj = this.new($size); + return this; + }; - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $obj.add($function.value($SC.Integer(i))); - } + // TODO: implements envirFlop - return $obj; + spec.storeArgs = function() { + return $SC.Array([ this.$array ]); }; - spec.$fill2D = function($rows, $cols, $function) { - var $this = this, $obj, $obj2, $row, $col; - var rows, cols, i, j; - $rows = utils.defaultValue$Nil($rows); - $cols = utils.defaultValue$Nil($cols); - $function = utils.defaultValue$Nil($function); + }); - $obj = this.new($rows); +})(sc); - rows = $rows.__int__(); - cols = $cols.__int__(); +// src/sc/lang/classlib/Streams/Stream.js +(function(sc) { - for (i = 0; i < rows; ++i) { - $row = $SC.Integer(i); - $obj2 = $this.new($cols); - for (j = 0; j < cols; ++j) { - $col = $SC.Integer(j); - $obj2 = $obj2.add($function.value($row, $col)); - } - $obj = $obj.add($obj2); - } + function SCStream() { + this.__initializeWith__("AbstractFunction"); + } - return $obj; - }; + sc.lang.klass.define(SCStream, "Stream : AbstractFunction", function() { + // TODO: implements parent + // TODO: implements next + // TODO: implements iter + // TODO: implements value + // TODO: implements valueArray + // TODO: implements nextN + // TODO: implements all + // TODO: implements put + // TODO: implements putN + // TODO: implements putAll + // TODO: implements do + // TODO: implements subSample + // TODO: implements loop + // TODO: implements generate + // TODO: implements collect + // TODO: implements reject + // TODO: implements select + // TODO: implements dot + // TODO: implements interlace + // TODO: implements ++ + // TODO: implements appendStream + // TODO: implements collate + // TODO: implements <> + // TODO: implements composeUnaryOp + // TODO: implements composeBinaryOp + // TODO: implements reverseComposeBinaryOp + // TODO: implements composeNAryOp + // TODO: implements embedInStream + // TODO: implements while + // TODO: implements asEventStreamPlayer + // TODO: implements play + // TODO: implements trace + // TODO: implements constrain + // TODO: implements repeat + }); - spec.$fill3D = function($planes, $rows, $cols, $function) { - var $this = this, $obj, $obj2, $obj3, $plane, $row, $col; - var planes, rows, cols, i, j, k; - $planes = utils.defaultValue$Nil($planes); - $rows = utils.defaultValue$Nil($rows); - $cols = utils.defaultValue$Nil($cols); - $function = utils.defaultValue$Nil($function); + function SCPauseStream() { + this.__initializeWith__("Stream"); + } - $obj = this.new($planes); + sc.lang.klass.define(SCPauseStream, "PauseStream : Stream", function() { + // TODO: implements stream + // TODO: implements originalStream + // TODO: implements clock + // TODO: implements nextBeat + // TODO: implements streamHasEnded + // TODO: implements streamHasEnded_ - planes = $planes.__int__(); - rows = $rows .__int__(); - cols = $cols .__int__(); + // TODO: implements isPlaying + // TODO: implements play + // TODO: implements reset + // TODO: implements stop + // TODO: implements prStop + // TODO: implements removedFromScheduler + // TODO: implements streamError + // TODO: implements wasStopped + // TODO: implements canPause + // TODO: implements pause + // TODO: implements resume + // TODO: implements refresh + // TODO: implements start + // TODO: implements stream_ + // TODO: implements next + // TODO: implements awake + // TODO: implements threadPlayer + }); - for (i = 0; i < planes; ++i) { - $plane = $SC.Integer(i); - $obj2 = $this.new($rows); - for (j = 0; j < rows; ++j) { - $row = $SC.Integer(j); - $obj3 = $this.new($cols); - for (k = 0; k < cols; ++k) { - $col = $SC.Integer(k); - $obj3 = $obj3.add($function.value($plane, $row, $col)); - } - $obj2 = $obj2.add($obj3); - } - $obj = $obj.add($obj2); - } + function SCTask() { + this.__initializeWith__("PauseStream"); + } - return $obj; - }; + sc.lang.klass.define(SCTask, "Task : PauseStream", function() { + // TODO: implements storeArgs + }); - var fillND = function($this, $dimensions, $function, $args) { - var $n, $obj, $argIndex; +})(sc); - $n = $dimensions.first(); - $obj = $this.new($n); - $argIndex = $args.size(); - $args = $args ["++"] ($int_0); +// src/sc/lang/classlib/Math/Magnitude.js +(function(sc) { - if ($dimensions.size().__int__() <= 1) { - $n.do($SC.Function(function($i) { - $obj.add($function.valueArray($args.put($argIndex, $i))); - })); - } else { - $dimensions = $dimensions.drop($int_1); - $n.do($SC.Function(function($i) { - $obj = $obj.add(fillND($this, $dimensions, $function, $args.put($argIndex, $i))); - })); - } + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - return $obj; + sc.lang.klass.refine("Magnitude", function(spec) { + spec["=="] = function($aMagnitude) { + return $SC.Boolean(this.valueOf() === $aMagnitude.valueOf()); }; - spec.$fillND = function($dimensions, $function) { - $dimensions = utils.defaultValue$Nil($dimensions); - $function = utils.defaultValue$Nil($function); - return fillND(this, $dimensions, $function, $SC.Array([])); + spec["!="] = function($aMagnitude) { + return $SC.Boolean(this.valueOf() !== $aMagnitude.valueOf()); }; - spec["@"] = function($index) { - return this.at($index); + spec.hash = function() { + return this._subclassResponsibility("hash"); }; - spec["=="] = function($aCollection) { - var $res = null; - - if ($aCollection.class() !== this.class()) { - return $false; - } - if (this.size() !== $aCollection.size()) { - return $false; - } - this.do($SC.Function(function($item) { - if (!BOOL($aCollection.includes($item))) { - $res = $false; - return 65535; - } - })); - - return $res || $true; + spec["<"] = function($aMagnitude) { + return $SC.Boolean(this < $aMagnitude); }; - // TODO: implements hash + spec[">"] = function($aMagnitude) { + return $SC.Boolean(this > $aMagnitude); + }; - spec.species = function() { - return SCArray; + spec["<="] = function($aMagnitude) { + return $SC.Boolean(this <= $aMagnitude); }; - spec.do = function() { - return this._subclassResponsibility("do"); + spec[">="] = function($aMagnitude) { + return $SC.Boolean(this >= $aMagnitude); }; - // TODO: implements iter + spec.exclusivelyBetween = fn(function($lo, $hi) { + return $SC.Boolean($lo < this && this < $hi); + }, "lo; hi"); - spec.size = function() { - var tally = 0; + spec.inclusivelyBetween = fn(function($lo, $hi) { + return $SC.Boolean($lo <= this && this <= $hi); + }, "lo; hi"); - this.do($SC.Function(function() { - tally++; - })); + spec.min = fn(function($aMagnitude) { + return this <= $aMagnitude ? this : $aMagnitude; + }, "aMagnitude"); - return $SC.Integer(tally); - }; + spec.max = fn(function($aMagnitude) { + return this >= $aMagnitude ? this : $aMagnitude; + }, "aMagnitude"); - spec.flatSize = function() { - return this.sum($SC.Function(function($_) { - return $_.flatSize(); - })); - }; + spec.clip = fn(function($lo, $hi) { + return this <= $lo ? $lo : this >= $hi ? $hi : this; + }, "lo; hi"); + }); - spec.isEmpty = function() { - return $SC.Boolean(this.size().__int__() === 0); - }; +})(sc); - spec.notEmpty = function() { - return $SC.Boolean(this.size().__int__() !== 0); - }; +// src/sc/lang/classlib/Math/Number.js +(function(sc) { - spec.asCollection = utils.nop; - spec.isCollection = utils.alwaysReturn$true; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var iterator = sc.lang.iterator; - spec.add = function() { - return this._subclassResponsibility("add"); - }; + sc.lang.klass.refine("Number", function(spec, utils) { + spec.isNumber = utils.alwaysReturn$true; - spec.addAll = function($aCollection) { - var $this = this; + spec["+"] = function() { + return this._subclassResponsibility("+"); + }; - $aCollection = utils.defaultValue$Nil($aCollection); - $aCollection.asCollection().do($SC.Function(function($item) { - return $this.add($item); - })); + spec["-"] = function() { + return this._subclassResponsibility("-"); + }; - return this; + spec["*"] = function() { + return this._subclassResponsibility("*"); }; - spec.remove = function() { - return this._subclassResponsibility("remove"); + spec["/"] = function() { + return this._subclassResponsibility("/"); }; - spec.removeAll = function($list) { - var $this = this; + spec.mod = function() { + return this._subclassResponsibility("mod"); + }; - $list = utils.defaultValue$Nil($list); - $list.do($SC.Function(function($item) { - $this.remove($item); - })); + spec.div = function() { + return this._subclassResponsibility("div"); + }; - return this; + spec.pow = function() { + return this._subclassResponsibility("pow"); }; - spec.removeEvery = function($list) { - this.removeAllSuchThat($SC.Function(function($_) { - return $list.includes($_); + spec.performBinaryOpOnSeqColl = function($aSelector, $aSeqColl, $adverb) { + var $this = this; + + return $aSeqColl.collect($SC.Function(function($item) { + return $item.perform($aSelector, $this, $adverb); })); - return this; }; - spec.removeAllSuchThat = function($function) { - var $this = this, $removedItems, $copy; + // TODO: implements performBinaryOpOnPoint - $removedItems = this.class().new(); - $copy = this.copy(); - $copy.do($SC.Function(function($item) { - if (BOOL($function.value($item))) { - $this.remove($item); - $removedItems = $removedItems.add($item); - } - })); + spec.rho = utils.nop; - return $removedItems; + spec.theta = function() { + return $SC.Float(0.0); }; - spec.atAll = function($keys) { - var $this = this; + spec.real = utils.nop; - return $keys.collect($SC.Function(function($index) { - return $this.at($index); - })); + spec.imag = function() { + return $SC.Float(0.0); }; - spec.putEach = function($keys, $values) { - var keys, values, i, imax; - $keys = utils.defaultValue$Nil($keys); - $values = utils.defaultValue$Nil($values); + // TODO: implements @ + // TODO: implements complex + // TODO: implements polar - $keys = $keys.asArray(); - $values = $values.asArray(); + spec.for = fn(function($endValue, $function) { + iterator.execute( + iterator.number$for(this, $endValue), + $function + ); + return this; + }, "endValue; function"); - keys = $keys._; - values = $values._; - for (i = 0, imax = keys.length; i < imax; ++i) { - this.put(keys[i], values[i % values.length]); - } + spec.forBy = fn(function($endValue, $stepValue, $function) { + iterator.execute( + iterator.number$forBy(this, $endValue, $stepValue), + $function + ); + return this; + }, "endValue; stepValue; function"); + spec.forSeries = fn(function($second, $last, $function) { + iterator.execute( + iterator.number$forSeries(this, $second, $last), + $function + ); return this; - }; + }, "second; last; function"); + }); - spec.includes = function($item1) { - var $res = null; - $item1 = utils.defaultValue$Nil($item1); +})(sc); - this.do($SC.Function(function($item2) { - if ($item1 === $item2) { - $res = $true; - return 65535; - } - })); +// src/sc/lang/classlib/Math/SimpleNumber.js +(function(sc) { - return $res || $false; - }; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var rand = sc.libs.random; - spec.includesEqual = function($item1) { - var $res = null; - $item1 = utils.defaultValue$Nil($item1); + function prOpSimpleNumber(selector, func) { + return function($aNumber, $adverb) { + var tag = $aNumber.__tag; - this.do($SC.Function(function($item2) { - if (BOOL( $item1 ["=="] ($item2) )) { - $res = $true; - return 65535; - } - })); + switch (tag) { + case 770: + case 777: + return $SC.Boolean(func(this._, $aNumber._)); + } - return $res || $false; + if ($aNumber.isSequenceableCollection().valueOf()) { + return $aNumber.performBinaryOpOnSimpleNumber( + $SC.Symbol(selector), this, $adverb + ); + } + + return $SC.False(); }; + } - spec.includesAny = function($aCollection) { - var $this = this, $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); + sc.lang.klass.refine("SimpleNumber", function(spec, utils) { + var $nil = utils.$nil; + var $int_0 = utils.$int_0; + var $int_1 = utils.$int_1; + var SCArray = $SC("Array"); - $aCollection.do($SC.Function(function($item) { - if (BOOL($this.includes($item))) { - $res = $true; - return 65535; - } - })); + spec.__newFrom__ = $SC.Float; - return $res || $false; + spec.__bool__ = function() { + return this._ !== 0; }; - spec.includesAll = function($aCollection) { - var $this = this, $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); - - $aCollection.do($SC.Function(function($item) { - if (!BOOL($this.includes($item))) { - $res = $false; - return 65535; - } - })); - - return $res || $true; + spec.__dec__ = function() { + return this.__newFrom__(this._ - 1); }; - spec.matchItem = function($item) { - return this.includes($item); + spec.__inc__ = function() { + return this.__newFrom__(this._ + 1); }; - spec.collect = function($function) { - return this.collectAs($function, this.species()); + spec.__int__ = function() { + if (!isFinite(this._)) { + return this._; + } + return this._|0; }; - spec.select = function($function) { - return this.selectAs($function, this.species()); + spec.__num__ = function() { + return this._; }; - spec.reject = function($function) { - return this.rejectAs($function, this.species()); + spec.isValidUGenInput = function() { + return $SC.Boolean(!isNaN(this._)); }; - spec.collectAs = function($function, $class) { - var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); + spec.numChannels = utils.alwaysReturn$int_1; - $res = $class.new(this.size()); - this.do($SC.Function(function($elem, $i) { - return $res.add($function.value($elem, $i)); - })); + spec.magnitude = function() { + return this.abs(); + }; - return $res; + spec.angle = function() { + return $SC.Float(this._ >= 0 ? 0 : Math.PI); }; - spec.selectAs = function($function, $class) { - var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); + spec.neg = function() { + return this.__newFrom__(-this._); + }; - $res = $class.new(this.size()); - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $res.add($elem); - } - })); + // bitNot: implemented by subclass - return $res; + spec.abs = function() { + return this.__newFrom__(Math.abs(this._)); }; - spec.rejectAs = function($function, $class) { - var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); - - $res = $class.new(this.size()); - this.do($SC.Function(function($elem, $i) { - if (!BOOL($function.value($elem, $i))) { - $res = $res.add($elem); - } - })); + spec.ceil = function() { + return this.__newFrom__(Math.ceil(this._)); + }; - return $res; + spec.floor = function() { + return this.__newFrom__(Math.floor(this._)); }; - spec.detect = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.frac = function() { + var a = this._; - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $elem; - return 65535; - } - })); + if (a < 0) { + return this.__newFrom__(1 + (a - (a|0))); + } + return this.__newFrom__(a - (a|0)); + }; - return $res || $nil; + spec.sign = function() { + var a = this._; + return this.__newFrom__( + a > 0 ? 1 : a === 0 ? 0 : -1 + ); }; - spec.detectIndex = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.squared = function() { + return this.__newFrom__(this._ * this._); + }; - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $i; - return 65535; - } - })); - return $res || $nil; + spec.cubed = function() { + return this.__newFrom__(this._ * this._ * this._); }; - spec.doMsg = function($selector) { - var args = arguments; - args[0] = utils.defaultValue$Nil($selector); - this.do($SC.Function(function($item) { - $item.perform.apply($item, args); - })); - return this; + spec.sqrt = function() { + return $SC.Float(Math.sqrt(this._)); }; - spec.collectMsg = function($selector) { - var args = arguments; - args[0] = utils.defaultValue$Nil($selector); - return this.collect($SC.Function(function($item) { - return $item.perform.apply($item, args); - })); + spec.exp = function() { + return $SC.Float(Math.exp(this._)); }; - spec.selectMsg = function($selector) { - var args = arguments; - args[0] = utils.defaultValue$Nil($selector); - return this.select($SC.Function(function($item) { - return $item.perform.apply($item, args); - })); + spec.reciprocal = function() { + return $SC.Float(1 / this._); }; - spec.rejectMsg = function($selector) { - var args = arguments; - args[0] = utils.defaultValue$Nil($selector); - return this.reject($SC.Function(function($item) { - return $item.perform.apply($item, args); - })); + spec.midicps = function() { + return $SC.Float( + 440 * Math.pow(2, (this._ - 69) * 1/12) + ); }; - spec.detectMsg = fn(function($selector, $$args) { - $selector = utils.defaultValue$Nil($selector); + spec.cpsmidi = function() { + return $SC.Float( + Math.log(Math.abs(this._) * 1/440) * Math.LOG2E * 12 + 69 + ); + }; - return this.detect($SC.Function(function($item) { - return $item.performList($selector, $$args); - })); - }, "selector,*args"); + spec.midiratio = function() { + return $SC.Float( + Math.pow(2, this._ * 1/12) + ); + }; - spec.detectIndexMsg = fn(function($selector, $$args) { - $selector = utils.defaultValue$Nil($selector); + spec.ratiomidi = function() { + return $SC.Float( + Math.log(Math.abs(this._)) * Math.LOG2E * 12 + ); + }; - return this.detectIndex($SC.Function(function($item) { - return $item.performList($selector, $$args); - })); - }, "selector,*args"); + spec.ampdb = function() { + return $SC.Float( + Math.log(this._) * Math.LOG10E * 20 + ); + }; - spec.lastForWhich = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.dbamp = function() { + return $SC.Float( + Math.pow(10, this._ * 0.05) + ); + }; - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $elem; - } else { - return 65535; - } - })); + spec.octcps = function() { + return $SC.Float( + 440 * Math.pow(2, this._ - 4.75) + ); + }; - return $res || $nil; + spec.cpsoct = function() { + return $SC.Float( + Math.log(Math.abs(this._) * 1/440) * Math.LOG2E + 4.75 + ); }; - spec.lastIndexForWhich = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.log = function() { + return $SC.Float(Math.log(this._)); + }; - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $i; - } else { - return 65535; - } - })); + spec.log2 = function() { + return $SC.Float(Math.log(Math.abs(this._)) * Math.LOG2E); + }; - return $res || $nil; + spec.log10 = function() { + return $SC.Float(Math.log(this._) * Math.LOG10E); }; - spec.inject = function($thisValue, $function) { - var $nextValue; - $thisValue = utils.defaultValue$Nil($thisValue); - $function = utils.defaultValue$Nil($function); + spec.sin = function() { + return $SC.Float(Math.sin(this._)); + }; - $nextValue = $thisValue; - this.do($SC.Function(function($item, $i) { - $nextValue = $function.value($nextValue, $item, $i); - })); + spec.cos = function() { + return $SC.Float(Math.cos(this._)); + }; - return $nextValue; + spec.tan = function() { + return $SC.Float(Math.tan(this._)); }; - spec.injectr = function($thisValue, $function) { - var $this = this, size, $nextValue; - $thisValue = utils.defaultValue$Nil($thisValue); - $function = utils.defaultValue$Nil($function); + spec.asin = function() { + return $SC.Float(Math.asin(this._)); + }; - size = this.size().__int__(); - $nextValue = $thisValue; - this.do($SC.Function(function($item, $i) { - $item = $this.at($SC.Integer(--size)); - $nextValue = $function.value($nextValue, $item, $i); - })); + spec.acos = function() { + return $SC.Float(Math.acos(this._)); + }; - return $nextValue; + spec.atan = function() { + return $SC.Float(Math.atan(this._)); }; - spec.count = function($function) { - var sum = 0; - $function = utils.defaultValue$Nil($function); + function _sinh(a) { + return (Math.pow(Math.E, a) - Math.pow(Math.E, -a)) * 0.5; + } - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - sum++; - } - })); + spec.sinh = function() { + return $SC.Float(_sinh(this._)); + }; - return $SC.Integer(sum); + function _cosh(a) { + return (Math.pow(Math.E, a) + Math.pow(Math.E, -a)) * 0.5; + } + + spec.cosh = function() { + return $SC.Float(_cosh(this._)); }; - spec.occurrencesOf = function($obj) { - var sum = 0; - $obj = utils.defaultValue$Nil($obj); + spec.tanh = function() { + return $SC.Float(_sinh(this._) / _cosh(this._)); + }; - this.do($SC.Function(function($elem) { - if (BOOL($elem ["=="] ($obj))) { - sum++; - } - })); + spec.rand = function() { + return this.__newFrom__( + rand.next() * this._ + ); + }; - return $SC.Integer(sum); + spec.rand2 = function() { + return this.__newFrom__( + (rand.next() * 2 - 1) * this._ + ); }; - spec.any = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.linrand = function() { + return this.__newFrom__( + Math.min(rand.next(), rand.next()) * this._ + ); + }; - this.do($SC.Function(function($elem, $i) { - if (BOOL($function.value($elem, $i))) { - $res = $true; - return 65535; - } - })); + spec.bilinrand = function() { + return this.__newFrom__( + (rand.next() - rand.next()) * this._ + ); + }; - return $res || $false; + spec.sum3rand = function() { + return this.__newFrom__( + (rand.next() + rand.next() + rand.next() - 1.5) * 2/3 * this._ + ); }; - spec.every = function($function) { - var $res = null; - $function = utils.defaultValue$Nil($function); + spec.distort = function() { + return $SC.Float( + this._ / (1 + Math.abs(this._)) + ); + }; - this.do($SC.Function(function($elem, $i) { - if (!BOOL($function.value($elem, $i))) { - $res = $false; - return 65535; - } - })); + spec.softclip = function() { + var a = this._, abs_a = Math.abs(a); + return $SC.Float(abs_a <= 0.5 ? a : (abs_a - 0.25) / a); + }; - return $res || $true; + spec.coin = function() { + return $SC.Boolean(rand.next() < this._); }; - spec.sum = function($function) { - var $sum; - $function = utils.defaultValue$Nil($function); + spec.isPositive = function() { + return $SC.Boolean(this._ >= 0); + }; - $sum = $int_0; - if ($function === $nil) { - this.do($SC.Function(function($elem) { - $sum = $sum ["+"] ($elem); - })); - } else { - this.do($SC.Function(function($elem, $i) { - $sum = $sum ["+"] ($function.value($elem, $i)); - })); - } + spec.isNegative = function() { + return $SC.Boolean(this._ < 0); + }; - return $sum; + spec.isStrictlyPositive = function() { + return $SC.Boolean(this._ > 0); }; - spec.mean = function($function) { - return this.sum($function) ["/"] (this.size()); + spec.isNaN = function() { + return $SC.Boolean(isNaN(this._)); }; - spec.product = function($function) { - var $product; - $function = utils.defaultValue$Nil($function); + spec.asBoolean = function() { + return $SC.Boolean(this._ > 0); + }; - $product = $int_1; - if ($function === $nil) { - this.do($SC.Function(function($elem) { - $product = $product ["*"] ($elem); - })); - } else { - this.do($SC.Function(function($elem, $i) { - $product = $product ["*"] ($function.value($elem, $i)); - })); - } - - return $product; + spec.booleanValue = function() { + return $SC.Boolean(this._ > 0); }; - spec.sumabs = function() { - var $sum; - - $sum = $int_0; - this.do($SC.Function(function($elem) { - if (BOOL($elem.isSequenceableCollection())) { - $elem = $elem.at($int_0); - } - $sum = $sum ["+"] ($elem.abs()); - })); + spec.binaryValue = function() { + return this._ > 0 ? $int_1 : $int_0; + }; - return $sum; + spec.rectWindow = function() { + var a = this._; + if (a < 0 || 1 < a) { + return $SC.Float(0); + } + return $SC.Float(1); }; - spec.maxItem = function($function) { - var $maxValue, $maxElement; - $function = utils.defaultValue$Nil($function); + spec.hanWindow = function() { + var a = this._; + if (a < 0 || 1 < a) { + return $SC.Float(0); + } + return $SC.Float(0.5 - 0.5 * Math.cos(a * 2 * Math.PI)); + }; - $maxValue = $nil; - $maxElement = $nil; - if ($function === $nil) { - this.do($SC.Function(function($elem) { - if ($maxElement === $nil) { - $maxElement = $elem; - } else if ($elem > $maxElement) { - $maxElement = $elem; - } - })); - } else { - this.do($SC.Function(function($elem, $i) { - var $val; - if ($maxValue === $nil) { - $maxValue = $function.value($elem, $i); - $maxElement = $elem; - } else { - $val = $function.value($elem, $i); - if ($val > $maxValue) { - $maxValue = $val; - $maxElement = $elem; - } - } - })); + spec.welWindow = function() { + var a = this._; + if (a < 0 || 1 < a) { + return $SC.Float(0); } + return $SC.Float(Math.sin(a * Math.PI)); + }; - return $maxElement; + spec.triWindow = function() { + var a = this._; + if (a < 0 || 1 < a) { + return $SC.Float(0); + } + if (a < 0.5) { + return $SC.Float(2 * a); + } + return $SC.Float(-2 * a + 2); }; - spec.minItem = function($function) { - var $minValue, $minElement; - $function = utils.defaultValue$Nil($function); + spec.scurve = function() { + var a = this._; + if (a <= 0) { + return $SC.Float(0); + } + if (1 <= a) { + return $SC.Float(1); + } + return $SC.Float(a * a * (3 - 2 * a)); + }; - $minValue = $nil; - $minElement = $nil; - if ($function === $nil) { - this.do($SC.Function(function($elem) { - if ($minElement === $nil) { - $minElement = $elem; - } else if ($elem < $minElement) { - $minElement = $elem; - } - })); - } else { - this.do($SC.Function(function($elem, $i) { - var $val; - if ($minValue === $nil) { - $minValue = $function.value($elem, $i); - $minElement = $elem; - } else { - $val = $function.value($elem, $i); - if ($val < $minValue) { - $minValue = $val; - $minElement = $elem; - } - } - })); + spec.ramp = function() { + var a = this._; + if (a <= 0) { + return $SC.Float(0); } + if (1 <= a) { + return $SC.Float(1); + } + return $SC.Float(a); + }; - return $minElement; + // +: implemented by subclass + // -: implemented by subclass + // *: implemented by subclass + // /: implemented by subclass + // mod: implemented by subclass + // div: implemented by subclass + // pow: implemented by subclass + // min: implemented by subclass + // max: implemented by subclass + // bitAnd: implemented by subclass + // bitOr : implemented by subclass + // bitXor: implemented by subclass + + spec.bitTest = function($bit) { + return $SC.Boolean( + this.bitAnd($int_1.leftShift($bit)).valueOf() !== 0 + ); }; - spec.maxIndex = function($function) { - var $maxValue, $maxIndex; - $function = utils.defaultValue$Nil($function); + // lcm : implemented by subclass + // gcd : implemented by subclass + // round : implemented by subclass + // roundUp : implemented by subclass + // trunc : implemented by subclass + // atan2 : implemented by subclass + // hypot : implemented by subclass + // hypotApx: implemented by subclass + // leftShift : implemented by subclass + // rightShift : implemented by subclass + // unsignedRightShift: implemented by subclass + // ring1 : implemented by subclass + // ring2 : implemented by subclass + // ring3 : implemented by subclass + // ring4 : implemented by subclass + // difsqr: implemented by subclass + // sumsqr: implemented by subclass + // sqrsum: implemented by subclass + // sqrdif: implemented by subclass + // absdif: implemented by subclass + // thresh: implemented by subclass + // amclip: implemented by subclass + // clip2 : implemented by subclass + // fold2 : implemented by subclass + // wrap2 : implemented by subclass + // excess: implemented by subclass + // firstArg: implemented by subclass + // rrand : implemented by subclass + // exprand : implemented by subclass - $maxValue = $nil; - $maxIndex = $nil; - if ($function === $nil) { - this.do($SC.Function(function($elem, $index) { - if ($maxValue === $nil) { - $maxValue = $elem; - $maxIndex = $index; - } else if ($elem > $maxValue) { - $maxValue = $elem; - $maxIndex = $index; - } - })); - } else { - this.do($SC.Function(function($elem, $i) { - var $val; - if ($maxValue === $nil) { - $maxValue = $function.value($elem, $i); - $maxIndex = $i; - } else { - $val = $function.value($elem, $i); - if ($val > $maxValue) { - $maxValue = $val; - $maxIndex = $i; - } - } - })); - } + spec["=="] = function($aNumber) { + return $SC.Boolean(this._ === $aNumber._); + }; - return $maxIndex; + spec["!="] = function($aNumber) { + return $SC.Boolean(this._ !== $aNumber._); }; - spec.minIndex = function($function) { - var $maxValue, $minIndex; - $function = utils.defaultValue$Nil($function); + spec["<"] = prOpSimpleNumber("<", function(a, b) { + return a < b; + }); + spec[">"] = prOpSimpleNumber(">", function(a, b) { + return a > b; + }); + spec["<="] = prOpSimpleNumber("<=", function(a, b) { + return a <= b; + }); + spec[">="] = prOpSimpleNumber(">=", function(a, b) { + return a >= b; + }); - $maxValue = $nil; - $minIndex = $nil; - if ($function === $nil) { - this.do($SC.Function(function($elem, $index) { - if ($maxValue === $nil) { - $maxValue = $elem; - $minIndex = $index; - } else if ($elem < $maxValue) { - $maxValue = $elem; - $minIndex = $index; - } - })); - } else { - this.do($SC.Function(function($elem, $i) { - var $val; - if ($maxValue === $nil) { - $maxValue = $function.value($elem, $i); - $minIndex = $i; - } else { - $val = $function.value($elem, $i); - if ($val < $maxValue) { - $maxValue = $val; - $minIndex = $i; - } - } - })); - } + spec.equalWithPrecision = fn(function($that, $precision) { + return this.absdif($that) ["<"] ($precision); + }, "that; precision=0.0001"); - return $minIndex; + // TODO: implements hash + + spec.asInteger = function() { + return $SC.Integer(this._); }; - spec.maxValue = function($function) { - var $maxValue, $maxElement; - $function = utils.defaultValue$Nil($function); + spec.asFloat = function() { + return $SC.Float(this._); + }; - $maxValue = $nil; - $maxElement = $nil; - this.do($SC.Function(function($elem, $i) { - var $val; - if ($maxValue === $nil) { - $maxValue = $function.value($elem, $i); - $maxElement = $elem; - } else { - $val = $function.value($elem, $i); - if ($val > $maxValue) { - $maxValue = $val; - $maxElement = $elem; - } - } - })); + // TODO: implements asComplex + // TODO: implements asRect - return $maxValue; + spec.degrad = function() { + return $SC.Float(this._ * Math.PI / 180); }; - spec.minValue = function($function) { - var $minValue, $minElement; - $function = utils.defaultValue$Nil($function); + spec.raddeg = function() { + return $SC.Float(this._ * 180 / Math.PI); + }; - $minValue = $nil; - $minElement = $nil; - this.do($SC.Function(function($elem, $i) { - var $val; - if ($minValue === $nil) { - $minValue = $function.value($elem, $i); - $minElement = $elem; - } else { - $val = $function.value($elem, $i); - if ($val < $minValue) { - $minValue = $val; - $minElement = $elem; - } - } - })); + // TODO: implements performBinaryOpOnSimpleNumber + // TODO: implements performBinaryOpOnComplex + // TODO: implements performBinaryOpOnSignal - return $minValue; + spec.nextPowerOfTwo = function() { + return $SC.Float( + Math.pow(2, Math.ceil(Math.log(this._) / Math.log(2))) + ); }; - spec.maxSizeAtDepth = function($rank) { - var rank, maxsize = 0; - $rank = utils.defaultValue$Nil($rank); + spec.nextPowerOf = fn(function($base) { + return $base.pow( + (this.log() ["/"] ($base.log())).ceil() + ); + }, "base"); - rank = $rank.__num__(); - if (rank === 0) { - return this.size(); + spec.nextPowerOfThree = function() { + return $SC.Float( + Math.pow(3, Math.ceil(Math.log(this._) / Math.log(3))) + ); + }; + + spec.previousPowerOf = fn(function($base) { + return $base.pow( + (this.log() ["/"] ($base.log())).ceil().__dec__() + ); + }, "base"); + + spec.quantize = fn(function($quantum, $tolerance, $strength) { + var $round, $diff; + + $round = this.round($quantum); + $diff = $round ["-"] (this); + + if ($diff.abs() < $tolerance) { + return this ["+"] ($strength ["*"] ($diff)); } - this.do($SC.Function(function($sublist) { - var sz; - if (BOOL($sublist.isCollection())) { - sz = $sublist.maxSizeAtDepth($SC.Integer(rank - 1)); - } else { - sz = 1; - } - if (sz > maxsize) { - maxsize = sz; - } - })); + return this; + }, "quantum=1.0; tolerance=0.05; strength=1.0"); - return $SC.Integer(maxsize); - }; + spec.linlin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + var $res = null; - spec.maxDepth = function($max) { - var $res; - $max = utils.defaultValue$Integer($max, 1); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); - $res = $max; - this.do($SC.Function(function($elem) { - if (BOOL($elem.isCollection())) { - $res = $res.max($elem.maxDepth($max.__inc__())); - } - })); + if ($res === null) { + // (this-inMin)/(inMax-inMin) * (outMax-outMin) + outMin; + $res = ((this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)) + ["*"] ($outMax ["-"] ($outMin)) ["+"] ($outMin)); + } return $res; - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.deepCollect = function($depth, $function, $index, $rank) { - $depth = utils.defaultValue$Integer($depth, 1); - $function = utils.defaultValue$Nil($function); - $index = utils.defaultValue$Integer($index, 0); - $rank = utils.defaultValue$Integer($rank, 0); + spec.linexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + var $res = null; - if ($depth === $nil) { - $rank = $rank.__inc__(); - return this.collect($SC.Function(function($item, $i) { - return $item.deepCollect($depth, $function, $i, $rank); - })); - } - if ($depth.__num__() <= 0) { - return $function.value(this, $index, $rank); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + + if ($res === null) { + // Math.pow(outMax/outMin, (this-inMin)/(inMax-inMin)) * outMin; + $res = $outMax ["/"] ($outMin).pow( + (this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)) + ) ["*"] ($outMin); } - $depth = $depth.__dec__(); - $rank = $rank.__inc__(); - return this.collect($SC.Function(function($item, $i) { - return $item.deepCollect($depth, $function, $i, $rank); - })); - }; + return $res; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.deepDo = function($depth, $function, $index, $rank) { - $depth = utils.defaultValue$Integer($depth, 1); - $function = utils.defaultValue$Nil($function); - $index = utils.defaultValue$Integer($index, 0); - $rank = utils.defaultValue$Integer($rank, 0); + spec.explin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + var $res = null; - if ($depth === $nil) { - $rank = $rank.__inc__(); - return this.do($SC.Function(function($item, $i) { - $item.deepDo($depth, $function, $i, $rank); - })); - } - if ($depth.__num__() <= 0) { - $function.value(this, $index, $rank); - return this; + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + + if ($res === null) { + // (((Math.log(this/inMin)) / (Math.log(inMax/inMin))) * (outMax-outMin)) + outMin; + $res = ((this ["/"] ($inMin).log() ["/"] ($inMax ["/"] ($inMin).log()) + ["*"] ($outMax ["-"] ($outMin))) ["+"] ($outMin)); } - $depth = $depth.__dec__(); - $rank = $rank.__inc__(); - return this.do($SC.Function(function($item, $i) { - $item.deepDo($depth, $function, $i, $rank); - })); - }; + return $res; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.invert = function($axis) { - var $index; - $axis = utils.defaultValue$Nil($axis); + spec.expexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { + var $res = null; - if (BOOL(this.isEmpty())) { - return this.species().new(); - } - if ($axis !== $nil) { - $index = $axis ["*"] ($SC.Integer(2)); - } else { - $index = this.minItem() ["+"] (this.maxItem()); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + + if ($res === null) { + // Math.pow(outMax/outMin, Math.log(this/inMin) / Math.log(inMax/inMin)) * outMin; + $res = $outMax ["/"] ($outMin).pow( + this ["/"] ($inMin).log() ["/"] ($inMax ["/"] ($inMin).log()) + ) ["*"] ($outMin); } - return $index ["-"] (this); - }; + return $res; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.sect = function($that) { - var $result; - $that = utils.defaultValue$Nil($that); + spec.lincurve = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + var $res = null, $grow, $a, $b, $scaled; - $result = this.species().new(); - this.do($SC.Function(function($item) { - if (BOOL($that.includes($item))) { - $result = $result.add($item); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + + if ($res === null) { + if (Math.abs($curve.valueOf()) < 0.001) { + $res = this.linlin($inMin, $inMax, $outMin, $outMax); + } else { + $grow = $curve.exp(); + $a = $outMax ["-"] ($outMin) ["/"] ($SC.Float(1.0) ["-"] ($grow)); + $b = $outMin ["+"] ($a); + $scaled = (this ["-"] ($inMin)) ["/"] ($inMax ["-"] ($inMin)); + + $res = $b ["-"] ($a ["*"] ($grow.pow($scaled))); } - })); + } - return $result; - }; + return $res; + }, "inMin=0; inMax=1; outMin=0; outMax=1; curve=-4; clip=\\minmax"); - spec.union = function($that) { - var $result; - $that = utils.defaultValue$Nil($that); + spec.curvelin = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + var $res = null, $grow, $a, $b; - $result = this.copy(); - $that.do($SC.Function(function($item) { - if (!BOOL($result.includes($item))) { - $result = $result.add($item); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); + + if ($res === null) { + if (Math.abs($curve.valueOf()) < 0.001) { + $res = this.linlin($inMin, $inMax, $outMin, $outMax); + } else { + $grow = $curve.exp(); + $a = $inMax ["-"] ($inMin) ["/"] ($SC.Float(1.0) ["-"] ($grow)); + $b = $inMin ["+"] ($a); + + $res = ((($b ["-"] (this)) ["/"] ($a)).log() + ["*"] ($outMax ["-"] ($outMin)) ["/"] ($curve) ["+"] ($outMin)); } - })); + } - return $result; - }; + return $res; + }, "inMin=0; inMax=1; outMin=0; outMax=1; curve=-4; clip=\\minmax"); - spec.difference = function($that) { - return this.copy().removeAll($that); - }; + spec.bilin = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + var $res = null; - spec.symmetricDifference = function($that) { - var $this = this, $result; - $that = utils.defaultValue$Nil($that); + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); - $result = this.species().new(); - $this.do($SC.Function(function($item) { - if (!BOOL($that.includes($item))) { - $result = $result.add($item); - } - })); - $that.do($SC.Function(function($item) { - if (!BOOL($this.includes($item))) { - $result = $result.add($item); + if ($res === null) { + if (this >= $inCenter) { + $res = this.linlin($inCenter, $inMax, $outCenter, $outMax, $SC.Symbol("none")); + } else { + $res = this.linlin($inMin, $inCenter, $outMin, $outCenter, $SC.Symbol("none")); } - })); + } - return $result; - }; + return $res; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.isSubsetOf = function($that) { - $that = utils.defaultValue$Nil($that); - return $that.includesAll(this); - }; + spec.biexp = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + var $res = null; - spec.asArray = function() { - return SCArray.new(this.size()).addAll(this); - }; + $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); - spec.asBag = function() { - return $SC("Bag").new(this.size()).addAll(this); - }; + if ($res === null) { + if (this >= $inCenter) { + $res = this.explin($inCenter, $inMax, $outCenter, $outMax, $SC.Symbol("none")); + } else { + $res = this.explin($inMin, $inCenter, $outMin, $outCenter, $SC.Symbol("none")); + } + } - spec.asList = function() { - return $SC("List").new(this.size()).addAll(this); - }; + return $res; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.asSet = function() { - return $SC("Set").new(this.size()).addAll(this); - }; + spec.moddif = fn(function($aNumber, $mod) { + var $diff, $modhalf; - spec.asSortedList = function($function) { - return $SC("SortedList").new(this.size(), $function).addAll(this); - }; + $diff = this.absdif($aNumber) ["%"] ($mod); + $modhalf = $mod ["*"] ($SC.Float(0.5)); - // TODO: implements powerset - // TODO: implements flopDict - // TODO: implements histo - // TODO: implements printAll - // TODO: implements printcsAll - // TODO: implements dumpAll - // TODO: implements printOn - // TODO: implements storeOn - // TODO: implements storeItemsOn - // TODO: implements printItemsOn - // TODO: implements writeDef - // TODO: implements writeInputSpec - // TODO: implements case - // TODO: implements makeEnvirValPairs - }); + return $modhalf ["-"] ($diff.absdif($modhalf)); + }, "aNumber=0.0; mod=1.0"); -})(sc); + spec.lcurve = fn(function($a, $m, $n, $tau) { + var $rTau, $x; -// src/sc/lang/classlib/Collections/SequenceableCollection.js -(function(sc) { + $x = this.neg(); - var slice = [].slice; - var $SC = sc.lang.$SC; + if ($tau.__num__() === 1.0) { + // a * (m * exp(x) + 1) / (n * exp(x) + 1) + return $a ["*"] ( + $m ["*"] ($x.exp()).__inc__() + ) ["/"] ( + $n ["*"] ($x.exp()).__inc__() + ); + } else { + $rTau = $tau.reciprocal(); + return $a ["*"] ( + $m ["*"] ($x.exp()) ["*"] ($rTau).__inc__() + ) ["/"] ( + $n ["*"] ($x.exp()) ["*"] ($rTau).__inc__() + ); + } + }, "a=1.0; m=0.0; n=1.0; tau=1.0"); - sc.lang.klass.refine("SequenceableCollection", function(spec, utils) { - var BOOL = utils.BOOL; - var $nil = utils.$nil; - var $true = utils.$true; - var $false = utils.$false; - var $int_0 = utils.$int_0; - var $int_1 = utils.$int_1; + spec.gauss = fn(function($standardDeviation) { + // ^((((-2*log(1.0.rand)).sqrt * sin(2pi.rand)) * standardDeviation) + this) + return ($SC.Float(-2.0) ["*"] ($SC.Float(1.0).rand().log()).sqrt() ["*"] ( + $SC.Float(2 * Math.PI).rand().sin() + ) ["*"] ($standardDeviation)) ["+"] (this); + }, "standardDeviation"); - spec["|@|"] = function($index) { - return this.clipAt($index); - }; + spec.gaussCurve = fn(function($a, $b, $c) { + // ^a * (exp(squared(this - b) / (-2.0 * squared(c)))) + return $a ["*"] (( + (this ["-"] ($b).squared()) ["/"] ($SC.Float(-2.0) ["*"] ($c.squared())) + ).exp()); + }, "a=1.0; b=0.0; c=1.0"); - spec["@@"] = function($index) { - return this.wrapAt($index); - }; + // TODO: implements asPoint + // TODO: implements asWarp - spec["@|@"] = function($index) { - return this.foldAt($index); + spec.wait = function() { + return this.yield(); }; - spec.$series = function($size, $start, $step) { - var $obj, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Integer($start, 0); - $step = utils.defaultValue$Integer($step, 1); + // TODO: implements waitUntil + // TODO: implements sleep + // TODO: implements printOn + // TODO: implements storeOn - $obj = this.new($size); - for (i = 0, imax = $size.__int__(); i < imax; ++i) { - $obj.add($start ["+"] ($step ["*"] ($SC.Integer(i)))); - } + spec.rate = function() { + return $SC.Symbol("scalar"); + }; - return $obj; + spec.asAudioRateInput = function() { + if (this._ === 0) { + return $SC("Silent").ar(); + } + return $SC("DC").ar(this); }; - spec.$geom = function($size, $start, $grow) { - var $obj, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Nil($start); - $grow = utils.defaultValue$Nil($grow); + spec.madd = fn(function($mul, $add) { + return (this ["*"] ($mul)) ["+"] ($add); + }, "mul; add"); - $obj = this.new($size); - for (i = 0, imax = $size.__int__(); i < imax; ++i) { - $obj.add($start); - $start = $start ["*"] ($grow); - } + spec.lag = utils.nop; + spec.lag2 = utils.nop; + spec.lag3 = utils.nop; + spec.lagud = utils.nop; + spec.lag2ud = utils.nop; + spec.lag3ud = utils.nop; + spec.varlag = utils.nop; + spec.slew = utils.nop; - return $obj; - }; + // TODO: implements writeInputSpec - spec.$fib = function($size, $a, $b) { - var $obj, $temp, i, imax; - $size = utils.defaultValue$Nil($size); - $a = utils.defaultValue$Float($a, 0.0); - $b = utils.defaultValue$Float($b, 1.0); + spec.series = fn(function($second, $last) { + var $step; + var last, step, size; - $obj = this.new($size); - for (i = 0, imax = $size.__int__(); i < imax; ++i) { - $obj.add($b); - $temp = $b; - $b = $a ["+"] ($b); - $a = $temp; + if ($second === $nil) { + if (this.valueOf() < $last.valueOf()) { + $second = this.__inc__(); + } else { + $second = this.__dec__(); + } } + $step = $second ["-"] (this); - return $obj; - }; + last = $last.__num__(); + step = $step.__num__(); + size = (Math.floor((last - this._) / step + 0.001)|0) + 1; - // TODO: implements $rand - // TODO: implements $rand2 - // TODO: implements $linrand + return SCArray.series($SC.Integer(size), this, $step); + }, "second; last"); - spec.$interpolation = function($size, $start, $end) { - var $obj, $step, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Float($start, 0.0); - $end = utils.defaultValue$Float($end , 1.0); + // TODO: implements seriesIter + // TODO: implements degreeToKey + // TODO: implements keyToDegree + // TODO: implements nearestInList + // TODO: implements nearestInScale + // TODO: implements partition + // TODO: implements nextTimeOnGrid + // TODO: implements playAndDelta + // TODO: implements asQuant + // TODO: implements asTimeString + // TODO: implements asFraction + // TODO: implements asBufWithValues + // TODO: implements schedBundleArrayOnClock - $obj = this.new($size); - if ($size.__int__() === 1) { - return $obj.add($start); - } + spec.shallowCopy = utils.nop; + }); - $step = ($end ["-"] ($start)) ["/"] ($size.__dec__()); - for (i = 0, imax = $size.__int__(); i < imax; ++i) { - $obj.add($start ["+"] ($SC.Integer(i) ["*"] ($step))); + function clip_for_map($this, $inMin, $inMax, $outMin, $outMax, $clip) { + + switch ($clip.__sym__()) { + case "minmax": + if ($this <= $inMin) { + return $outMin; + } + if ($this >= $inMax) { + return $outMax; + } + break; + case "min": + if ($this <= $inMin) { + return $outMin; + } + break; + case "max": + if ($this >= $inMax) { + return $outMax; } + break; + } - return $obj; - }; + return null; + } - spec["++"] = function($aSequenceableCollection) { - var $newlist; - $aSequenceableCollection = utils.defaultValue$Nil($aSequenceableCollection); +})(sc); - $newlist = this.species().new(this.size() ["+"] ($aSequenceableCollection.size())); - $newlist = $newlist.addAll(this).addAll($aSequenceableCollection); +// src/sc/lang/classlib/Math/bop.js +(function(sc) { - return $newlist; - }; + var $SC = sc.lang.$SC; + var mathlib = sc.libs.mathlib; - // TODO: implements +++ + sc.lang.classlib.bop = function(selector, type1, type2) { + var func = mathlib[selector]; - spec.asSequenceableCollection = utils.nop; + return function($aNumber, $adverb) { + var tag = $aNumber.__tag; - spec.choose = function() { - return this.at(this.size().rand()); - }; + switch (tag) { + case 770: + return type1(func(this._, $aNumber._)); + case 777: + return type2(func(this._, $aNumber._)); + } - spec.wchoose = function($weights) { - $weights = utils.defaultValue$Nil($weights); - return this.at($weights.windex()); + return $aNumber.performBinaryOpOnSimpleNumber( + $SC.Symbol(selector), this, $adverb + ); }; + }; - spec["=="] = function($aCollection) { - var $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); +})(sc); - if ($aCollection.class() !== this.class()) { - return $false; - } - if (this.size() !== $aCollection.size()) { - return $false; - } - this.do($SC.Function(function($item, $i) { - if (BOOL($item ["!="] ($aCollection.at($i)))) { - $res = $false; - return 65535; - } - })); +// src/sc/lang/classlib/Math/Integer.js +(function(sc) { - return $res || $true; - }; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var iterator = sc.lang.iterator; + var mathlib = sc.libs.mathlib; - // TODO: implements hash + sc.lang.klass.refine("Integer", function(spec, utils) { + var $nil = utils.$nil; + var $int_1 = utils.$int_1; + var SCArray = $SC("Array"); - spec.copyRange = function($start, $end) { - var $newColl, i, end; - $start = utils.defaultValue$Nil($start); - $end = utils.defaultValue$Nil($end); + spec.__newFrom__ = $SC.Integer; - i = $start.__int__(); - end = $end.__int__(); - $newColl = this.species().new($SC.Integer(end - i)); - while (i <= end) { - $newColl.add(this.at($SC.Integer(i++))); - } + spec.__int__ = function() { + return this._; + }; - return $newColl; + spec.toString = function() { + return String("" + this._); }; - spec.keep = function($n) { - var n, size; - $n = utils.defaultValue$Nil($n); + spec.$new = function() { + throw new Error("Integer.new is illegal, should use literal."); + }; - n = $n.__int__(); - if (n >= 0) { - return this.copyRange($int_0, $SC.Integer(n - 1)); + spec.isInteger = utils.alwaysReturn$true; + + // TODO: implements hash + + [ + [ "+", $SC.Integer, $SC.Float ], + [ "-", $SC.Integer, $SC.Float ], + [ "*", $SC.Integer, $SC.Float ], + [ "/", $SC.Float , $SC.Float ], + [ "mod" , $SC.Integer, $SC.Float ], + [ "div" , $SC.Integer, $SC.Integer ], + [ "pow" , $SC.Float , $SC.Float ], + [ "min" , $SC.Integer, $SC.Float ], + [ "max" , $SC.Integer, $SC.Float ], + [ "bitAnd" , $SC.Integer, $SC.Float ], + [ "bitOr" , $SC.Integer, $SC.Float ], + [ "bitXor" , $SC.Integer, $SC.Float ], + [ "lcm" , $SC.Integer, $SC.Float ], + [ "gcd" , $SC.Integer, $SC.Float ], + [ "round" , $SC.Integer, $SC.Float ], + [ "roundUp" , $SC.Integer, $SC.Float ], + [ "trunc" , $SC.Integer, $SC.Float ], + [ "atan2" , $SC.Float , $SC.Float ], + [ "hypot" , $SC.Float , $SC.Float ], + [ "hypotApx", $SC.Float , $SC.Float ], + [ "leftShift" , $SC.Integer, $SC.Float ], + [ "rightShift" , $SC.Integer, $SC.Float ], + [ "unsignedRightShift", $SC.Integer, $SC.Float ], + [ "ring1" , $SC.Integer, $SC.Float ], + [ "ring2" , $SC.Integer, $SC.Float ], + [ "ring3" , $SC.Integer, $SC.Float ], + [ "ring4" , $SC.Integer, $SC.Float ], + [ "difsqr" , $SC.Integer, $SC.Float ], + [ "sumsqr" , $SC.Integer, $SC.Float ], + [ "sqrsum" , $SC.Integer, $SC.Float ], + [ "sqrdif" , $SC.Integer, $SC.Float ], + [ "absdif" , $SC.Integer, $SC.Float ], + [ "thresh" , $SC.Integer, $SC.Integer ], + [ "amclip" , $SC.Integer, $SC.Float ], + [ "scaleneg", $SC.Integer, $SC.Float ], + [ "clip2" , $SC.Integer, $SC.Float ], + [ "fold2" , $SC.Integer, $SC.Float ], + [ "excess" , $SC.Integer, $SC.Float ], + [ "firstArg", $SC.Integer, $SC.Integer ], + [ "rrand" , $SC.Integer, $SC.Float ], + [ "exprand" , $SC.Float , $SC.Float ], + ].forEach(function(items) { + spec[items[0]] = sc.lang.classlib.bop.apply(null, items); + }); + + spec.wrap2 = function($aNumber, $adverb) { + var tag = $aNumber.__tag; + + switch (tag) { + case 770: + return $SC.Integer(mathlib.iwrap(this._, -$aNumber._, $aNumber._)); + case 777: + return $SC.Float(mathlib.wrap2(this._, $aNumber._)); } - size = this.size().__int__(); - return this.copyRange($SC.Integer(size + n), $SC.Integer(size - 1)); + return $aNumber.performBinaryOpOnSimpleNumber( + $SC.Symbol("wrap2"), this, $adverb + ); }; - spec.drop = function($n) { - var n, size; - $n = utils.defaultValue$Nil($n); + spec.rrand = function($aNumber, $adverb) { + var tag = $aNumber.__tag; - n = $n.__int__(); - size = this.size().__int__(); - if (n >= 0) { - return this.copyRange($n, $SC.Integer(size - 1)); + switch (tag) { + case 770: + return $SC.Integer(Math.round(mathlib.rrand(this._, $aNumber._))); + case 777: + return $SC.Float(mathlib.rrand(this._, $aNumber._)); } - return this.copyRange($int_0, $SC.Integer(size + n - 1)); + return $aNumber.performBinaryOpOnSimpleNumber( + $SC.Symbol("rrand"), this, $adverb + ); }; - spec.copyToEnd = function($start) { - return this.copyRange($start, $SC.Integer(this.size().__int__() - 1)); - }; + spec.clip = fn(function($lo, $hi) { + // <-- _ClipInt --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; + } + if ($lo.__tag === 770 && $hi.__tag === 770) { + return $SC.Integer( + mathlib.clip(this._, $lo.__int__(), $hi.__int__()) + ); + } - spec.copyFromStart = function($end) { - return this.copyRange($int_0, $end); - }; + return $SC.Float( + mathlib.clip(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - spec.indexOf = function($item) { - var $ret = null; - $item = utils.defaultValue$Nil($item); + spec.wrap = fn(function($lo, $hi) { + // <-- _WrapInt --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; + } + if ($lo.__tag === 770 && $hi.__tag === 770) { + return $SC.Integer( + mathlib.iwrap(this._, $lo.__int__(), $hi.__int__()) + ); + } - this.do($SC.Function(function($elem, $i) { - if ($item === $elem) { - $ret = $i; - return 65535; - } - })); + return $SC.Float( + mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - return $ret || $nil; - }; + spec.fold = fn(function($lo, $hi) { + // <-- _FoldInt --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; + } + if ($lo.__tag === 770 && $hi.__tag === 770) { + return $SC.Integer( + mathlib.ifold(this._, $lo.__int__(), $hi.__int__()) + ); + } - spec.indicesOfEqual = function($item) { - var indices = []; - $item = utils.defaultValue$Nil($item); + return $SC.Float( + mathlib.fold(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - this.do($SC.Function(function($elem, $i) { - if ($item === $elem) { - indices.push($i); - } - })); + spec.even = function() { + return $SC.Boolean(!(this._ & 1)); + }; - return indices.length ? $SC.Array(indices) : $nil; + spec.odd = function() { + return $SC.Boolean(!!(this._ & 1)); }; - spec.find = function($sublist, $offset) { - var $subSize_1, $first, $index; - var size, offset, i, imax; - $sublist = utils.defaultValue$Nil($sublist); - $offset = utils.defaultValue$Integer($offset, 0); + spec.xrand = fn(function($exclude) { + return ($exclude ["+"] (this.__dec__().rand()) ["+"] ($int_1)) ["%"] (this); + }, "exclude=0"); - $subSize_1 = $sublist.size().__dec__(); - $first = $sublist.first(); + spec.xrand2 = fn(function($exclude) { + var raw, res; - size = this.size().__int__(); - offset = $offset.__int__(); - for (i = 0, imax = size - offset; i < imax; ++i) { - $index = $SC.Integer(i + offset); - if (BOOL(this.at($index) ["=="] ($first))) { - if (BOOL(this.copyRange($index, $index ["+"] ($subSize_1)) ["=="] ($sublist))) { - return $index; - } - } + raw = this._; + res = (mathlib.rand((2 * raw))|0) - raw; + + if (res === $exclude._) { + return this; } - return $nil; - }; + return $SC.Integer(res); + }, "exclude=0"); - spec.findAll = function($arr, $offset) { - var $this = this, $indices, $i; - $arr = utils.defaultValue$Nil($arr); - $offset = utils.defaultValue$Integer($offset, 0); + spec.degreeToKey = fn(function($scale, $stepsPerOctave) { + return $scale.performDegreeToKey(this, $stepsPerOctave); + }, "scale; stepsPerOctave=12"); - $indices = $nil; - $i = $int_0; + spec.do = function($function) { + iterator.execute( + iterator.integer$do(this), + $function + ); + return this; + }; - while (($i = $this.find($arr, $offset)) !== $nil) { - $indices = $indices.add($i); - $offset = $i.__inc__(); - } + spec.generate = function($function) { - return $indices; - }; + $function.value(this); - spec.indexOfGreaterThan = function($val) { - $val = utils.defaultValue$Nil($val); - return this.detectIndex($SC.Function(function($item) { - return $SC.Boolean($item > $val); - })); + return this; }; - spec.indexIn = function($val) { - var $i, $j; - $val = utils.defaultValue$Nil($val); + spec.collectAs = fn(function($function, $class) { + var $res; + var i, imax; - $j = this.indexOfGreaterThan($val); - if ($j === $nil) { - return this.size().__dec__(); + if ($class === $nil) { + $class = SCArray; } - if ($j === $int_0) { - return $j; + + $res = $class.new(this); + for (i = 0, imax = this._; i < imax; ++i) { + $res.add($function.value($SC.Integer(i))); } - $i = $j.__dec__(); + return $res; + }, "function; class"); - if ($val ["-"] (this.at($i)) < this.at($j) ["-"] ($val)) { - return $i; - } + spec.collect = function($function) { + return this.collectAs($function, SCArray); + }; - return $j; + spec.reverseDo = function($function) { + iterator.execute( + iterator.integer$reverseDo(this), + $function + ); + return this; }; - spec.indexInBetween = function($val) { - var $a, $b, $div, $i; - $val = utils.defaultValue$Nil($val); + spec.for = fn(function($endval, $function) { + iterator.execute( + iterator.integer$for(this, $endval), + $function + ); + return this; + }, "endval; function"); - if (BOOL(this.isEmpty())) { - return $nil; - } - $i = this.indexOfGreaterThan($val); + spec.forBy = fn(function($endval, $stepval, $function) { + iterator.execute( + iterator.integer$forBy(this, $endval, $stepval), + $function + ); + return this; + }, "endval; stepval; function"); - if ($i === $nil) { - return this.size().__dec__(); - } - if ($i === $int_0) { - return $i; - } + spec.to = fn(function($hi, $step) { + return $SC("Interval").new(this, $hi, $step); + }, "hi; step=1"); - $a = this.at($i.__dec__()); - $b = this.at($i); - $div = $b ["-"] ($a); + spec.asAscii = function() { + // <-- _AsAscii --> + return $SC.Char(String.fromCharCode(this._|0)); + }; - // if (BOOL($div ["=="] ($int_0))) { - // return $i; - // } - - return (($val ["-"] ($a)) ["/"] ($div)) ["+"] ($i.__dec__()); - }; + spec.asUnicode = utils.nop; - spec.isSeries = function($step) { - var $res = null; - $step = utils.defaultValue$Nil($step); + spec.asDigit = function() { + var c; - if (this.size() <= 1) { - return $true; + // + c = this._; + if (0 <= c && c <= 9) { + return $SC.Char(String(c)); + } + if (10 <= c && c <= 35) { + return $SC.Char(String.fromCharCode(c + 55)); } - this.doAdjacentPairs($SC.Function(function($a, $b) { - var $diff = $b ["-"] ($a); - if ($step === $nil) { - $step = $diff; - } else if (BOOL($step ["!="] ($diff))) { - $res = $false; - return 65535; - } - })); - - return $res || $true; - }; - - spec.resamp0 = function($newSize) { - var $this = this, $factor; - $newSize = utils.defaultValue$Nil($newSize); - - $factor = ( - this.size().__dec__() - ) ["/"] ( - ($newSize.__dec__()).max($int_1) - ); - return this.species().fill($newSize, $SC.Function(function($i) { - return $this.at($i ["*"] ($factor).round($SC.Float(1.0)).asInteger()); - })); + throw new Error("Integer: asDigit must be 0 <= this <= 35"); }; - spec.resamp1 = function($newSize) { - var $this = this, $factor; - $newSize = utils.defaultValue$Nil($newSize); + spec.asBinaryDigits = fn(function($numDigits) { + var raw, array, numDigits, i; - $factor = ( - this.size().__dec__() - ) ["/"] ( - ($newSize.__dec__()).max($int_1) - ); + raw = this._; + numDigits = $numDigits.__int__(); + array = new Array(numDigits); + for (i = 0; i < numDigits; ++i) { + array.unshift($SC.Integer((raw >> i) & 1)); + } - return this.species().fill($newSize, $SC.Function(function($i) { - return $this.blendAt($i ["*"] ($factor)); - })); - }; + return $SC.Array(array); + }, "numDigits=8"); - spec.remove = function($item) { - var $index; - $item = utils.defaultValue$Nil($item); + spec.asDigits = fn(function($base, $numDigits) { + var $num; + var array, numDigits, i; - $index = this.indexOf($item); - if ($index !== $nil) { - return this.removeAt($index); + $num = this; + if ($numDigits === $nil) { + $numDigits = ( + this.log() ["/"] ($base.log() ["+"] ($SC.Float(1e-10))) + ).asInteger().__inc__(); } - return $nil; - }; + array = []; + numDigits = $numDigits.__int__(); + array = new Array(numDigits); + for (i = 0; i < numDigits; ++i) { + array.unshift($num ["%"] ($base)); + $num = $num.div($base); + } - spec.removing = function($item) { - var $coll; - $item = utils.defaultValue$Nil($item); + return $SC.Array(array); + }, "base=10; numDigits"); - $coll = this.copy(); - $coll.remove($item); + // TODO: implements nextPowerOfTwo + // TODO: implements isPowerOfTwo + // TODO: implements leadingZeroes + // TODO: implements trailingZeroes + // TODO: implements numBits + // TODO: implements log2Ceil + // TODO: implements grayCode + // TODO: implements setBit + // TODO: implements nthPrime + // TODO: implements prevPrime + // TODO: implements nextPrime + // TODO: implements indexOfPrime + // TODO: implements isPrime + // TODO: implements exit + // TODO: implements asStringToBase + // TODO: implements asBinaryString + // TODO: implements asHexString + // TODO: implements asIPString + // TODO: implements archiveAsCompileString - return $coll; - }; + spec.geom = fn(function($start, $grow) { + return SCArray.geom(this, $start, $grow); + }, "start; grow"); - spec.take = function($item) { - var $index; - $item = utils.defaultValue$Nil($item); + spec.fib = fn(function($a, $b) { + return SCArray.fib(this, $a, $b); + }, "a=0.0; b=1.0"); - $index = this.indexOf($item); - if ($index !== $nil) { - return this.takeAt($index); - } + // TODO: implements factors + // TODO: implements pidRunning + // TODO: implements factorial + // TODO: implements isCaps + // TODO: implements isShift + // TODO: implements isCtrl + // TODO: implements isAlt + // TODO: implements isCmd + // TODO: implements isNumPad + // TODO: implements isHelp + // TODO: implements isFun - return $nil; + spec.bitNot = function() { + return $SC.Integer(~this._); }; + }); - spec.lastIndex = function() { - var size = this.size().__int__(); +})(sc); - if (size > 0) { - return $SC.Integer(size - 1); - } +// src/sc/lang/classlib/Math/Float.js +(function(sc) { - return $nil; - }; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var iterator = sc.lang.iterator; + var mathlib = sc.libs.mathlib; - spec.middleIndex = function() { - var size = this.size().__int__(); + sc.lang.klass.refine("Float", function(spec, utils) { + spec.toString = function() { + var raw = this._; - if (size > 0) { - return $SC.Integer((size - 1) >> 1); + if (raw === Infinity) { + return "inf"; } - - return $nil; - }; - - spec.first = function() { - var size = this.size().__int__(); - - if (size > 0) { - return this.at($int_0); + if (raw === -Infinity) { + return "-inf"; } - - return $nil; - }; - - spec.last = function() { - var size = this.size().__int__(); - - if (size > 0) { - return this.at($SC.Integer(size - 1)); + if (isNaN(raw)) { + return "nan"; } - return $nil; + return String(this._); }; - spec.middle = function() { - var size = this.size().__int__(); - - if (size > 0) { - return this.at($SC.Integer((size - 1) >> 1)); - } - - return $nil; + spec.$new = function() { + throw new Error("Float.new is illegal, should use literal."); }; - spec.top = function() { - return this.last(); - }; + spec.isFloat = utils.alwaysReturn$true; + spec.asFloat = utils.nop; - spec.putFirst = function($obj) { - var size = this.size().__int__(); + [ + [ "+" , $SC.Float, $SC.Float ], + [ "-" , $SC.Float, $SC.Float ], + [ "*" , $SC.Float, $SC.Float ], + [ "/" , $SC.Float, $SC.Float ], + [ "mod" , $SC.Float , $SC.Float ], + [ "div" , $SC.Integer, $SC.Integer ], + [ "pow" , $SC.Float , $SC.Float ], + [ "min" , $SC.Float , $SC.Float ], + [ "max" , $SC.Float , $SC.Float ], + [ "bitAnd" , $SC.Float , $SC.Float ], + [ "bitOr" , $SC.Float , $SC.Float ], + [ "bitXor" , $SC.Float , $SC.Float ], + [ "lcm" , $SC.Float , $SC.Float ], + [ "gcd" , $SC.Float , $SC.Float ], + [ "round" , $SC.Float , $SC.Float ], + [ "roundUp" , $SC.Float , $SC.Float ], + [ "trunc" , $SC.Float , $SC.Float ], + [ "atan2" , $SC.Float , $SC.Float ], + [ "hypot" , $SC.Float , $SC.Float ], + [ "hypotApx", $SC.Float , $SC.Float ], + [ "leftShift" , $SC.Float, $SC.Float ], + [ "rightShift" , $SC.Float, $SC.Float ], + [ "unsignedRightShift", $SC.Float, $SC.Float ], + [ "ring1" , $SC.Float, $SC.Float ], + [ "ring2" , $SC.Float, $SC.Float ], + [ "ring3" , $SC.Float, $SC.Float ], + [ "ring4" , $SC.Float, $SC.Float ], + [ "difsqr" , $SC.Float, $SC.Float ], + [ "sumsqr" , $SC.Float, $SC.Float ], + [ "sqrsum" , $SC.Float, $SC.Float ], + [ "sqrdif" , $SC.Float, $SC.Float ], + [ "absdif" , $SC.Float, $SC.Float ], + [ "thresh" , $SC.Float, $SC.Float ], + [ "amclip" , $SC.Float, $SC.Float ], + [ "scaleneg", $SC.Float, $SC.Float ], + [ "clip2" , $SC.Float, $SC.Float ], + [ "fold2" , $SC.Float, $SC.Float ], + [ "wrap2" , $SC.Float, $SC.Float ], + [ "excess" , $SC.Float, $SC.Float ], + [ "firstArg", $SC.Float, $SC.Float ], + [ "rrand" , $SC.Float, $SC.Float ], + [ "exprand" , $SC.Float, $SC.Float ], + ].forEach(function(items) { + spec[items[0]] = sc.lang.classlib.bop.apply(null, items); + }); - if (size > 0) { - return this.put($int_0, $obj); + spec.clip = fn(function($lo, $hi) { + // <-- _ClipFloat --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; } - return this; - }; - - spec.putLast = function($obj) { - var size = this.size().__int__(); + return $SC.Float( + mathlib.clip(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - if (size > 0) { - return this.put($SC.Integer(size - 1), $obj); + spec.wrap = fn(function($lo, $hi) { + // <-- _WrapInt --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; } - return this; - }; - - spec.obtain = function($index, $default) { - var $res; - $index = utils.defaultValue$Nil($index); - $default = utils.defaultValue$Nil($default); + return $SC.Float( + mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - $res = this.at($index); - if ($res === $nil) { - $res = $default; + spec.fold = fn(function($lo, $hi) { + // <-- _FoldFloat --> + if ($lo.__tag === 1027) { + return $lo; + } + if ($hi.__tag === 1027) { + return $hi; } - return $res; - }; + return $SC.Float( + mathlib.fold(this._, $lo.__num__(), $hi.__num__()) + ); + }, "lo; hi"); - spec.instill = function($index, $item, $default) { - var $res; - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); - $default = utils.defaultValue$Nil($default); + // TODO: implements coin + // TODO: implements xrand2 - if ($index.__num__() >= this.size()) { - $res = this.extend($index.__inc__(), $default); - } else { - $res = this.copy(); - } + spec.as32Bits = function() { + // <-- _As32Bits --> + return $SC.Integer( + new Int32Array( + new Float32Array([ this._ ]).buffer + )[0] + ); + }; - return $res.put($index, $item); + spec.high32Bits = function() { + // <-- _High32Bits --> + return $SC.Integer( + new Int32Array( + new Float64Array([ this._ ]).buffer + )[1] + ); }; - spec.pairsDo = function($function) { - var $this = this, $int2 = $SC.Integer(2); - $function = utils.defaultValue$Nil($function); + spec.low32Bits = function() { + // <-- _Low32Bits --> + return $SC.Integer( + new Int32Array( + new Float64Array([ this._ ]).buffer + )[0] + ); + }; - $int_0.forBy(this.size() ["-"] ($int2), $int2, $SC.Function(function($i) { - return $function.value($this.at($i), $this.at($i.__inc__()), $i); - })); + spec.$from32Bits = fn(function($word) { + // <-- _From32Bits --> + return $SC.Float( + new Float32Array( + new Int32Array([ $word.__num__() ]).buffer + )[0] + ); + }, "word"); + + spec.$from64Bits = fn(function($hiWord, $loWord) { + // <-- _From64Bits --> + return $SC.Float( + new Float64Array( + new Int32Array([ $loWord.__num__(), $hiWord.__num__() ]).buffer + )[0] + ); + }, "hiWord; loWord"); + spec.do = function($function) { + iterator.execute( + iterator.float$do(this), + $function + ); return this; }; - spec.keysValuesDo = function($function) { - return this.pairsDo($function); + spec.reverseDo = function($function) { + iterator.execute( + iterator.float$reverseDo(this), + $function + ); + return this; }; - spec.doAdjacentPairs = function($function) { - var $i; - var size, i, imax; - $function = utils.defaultValue$Nil($function); - - size = this.size().__int__(); - for (i = 0, imax = size - 1; i < imax; ++i) { - $i = $SC.Integer(i); - $function.value(this.at($i), this.at($i.__inc__()), $i); - } + // TODO: implements asStringPrec + // TODO: implements archiveAsCompileString + // TODO: implements storeOn + // TODO: implements switch - return this; + spec.bitNot = function() { + var f64 = new Float64Array([ this._ ]); + var i32 = new Int32Array(f64.buffer); + i32[0] = ~i32[0]; + return $SC.Float(f64[0]); }; + }); - spec.separate = function($function) { - var $this = this, $list, $sublist; - $function = utils.defaultValue$Boolean($function, true); +})(sc); - $list = $SC.Array(); - $sublist = this.species().new(); - this.doAdjacentPairs($SC.Function(function($a, $b, $i) { - $sublist = $sublist.add($a); - if (BOOL($function.value($a, $b, $i))) { - $list = $list.add($sublist); - $sublist = $this.species().new(); - } - })); - if (BOOL(this.notEmpty())) { - $sublist = $sublist.add(this.last()); - } - $list = $list.add($sublist); +// src/sc/lang/classlib/Core/Thread.js +(function(sc) { - return $list; - }; + function SCThread() { + this.__initializeWith__("Stream"); + } - spec.delimit = function($function) { - var $this = this, $list, $sublist; - $function = utils.defaultValue$Nil($function); + sc.lang.klass.define(SCThread, "Thread : Stream", function() { + // TODO: implements state + // TODO: implements parent + // TODO: implements primitiveError + // TODO: implements primitiveIndex + // TODO: implements beats + // TODO: implements seconds + // TODO: implements clock + // TODO: implements nextBeat + // TODO: implements endBeat + // TODO: implements endBeat_ + // TODO: implements endValue + // TODO: implements endValue_ + // TODO: implements exceptionHandler + // TODO: implements exceptionHandler_ + // TODO: implements threadPlayer_ + // TODO: implements executingPath + // TODO: implements oldExecutingPath - $list = $SC.Array(); - $sublist = this.species().new(); - this.do($SC.Function(function($item, $i) { - if (BOOL($function.value($item, $i))) { - $list = $list.add($sublist); - $sublist = $this.species().new(); - } else { - $sublist = $sublist.add($item); - } - })); - $list = $list.add($sublist); + // TODO: implements init + // TODO: implements copy + // TODO: implements clock_ + // TODO: implements seconds_ + // TODO: implements beats_ + // TODO: implements isPlaying + // TODO: implements threadPlayer + // TODO: implements findThreadPlayer + // TODO: implements randSeed_ + // TODO: implements randData_ + // TODO: implements randData + // TODO: implements failedPrimitiveName + // TODO: implements handleError + // TODO: implements next + // TODO: implements value + // TODO: implements valueArray + // TODO: implements $primitiveError + // TODO: implements $primitiveErrorString + // TODO: implements storeOn + // TODO: implements archiveAsCompileString + // TODO: implements checkCanArchive + }); - return $list; - }; + function SCRoutine() { + this.__initializeWith__("Thread"); + } - spec.clump = function($groupSize) { - var $this = this, $list, $sublist; - $groupSize = utils.defaultValue$Nil($groupSize); + sc.lang.klass.define(SCRoutine, "Routine : Thread", function() { + // TODO: implements $run + // TODO: implements next + // TODO: implements value + // TODO: implements resume + // TODO: implements run + // TODO: implements valueArray + // TODO: implements reset + // TODO: implements stop + // TODO: implements p + // TODO: implements storeArgs + // TODO: implements storeOn + // TODO: implements awake + }); - $list = $SC.Array(); - $sublist = this.species().new($groupSize); - this.do($SC.Function(function($item) { - $sublist.add($item); - if ($sublist.size() >= $groupSize) { - $list.add($sublist); - $sublist = $this.species().new($groupSize); - } - })); - if ($sublist.size() > 0) { - $list = $list.add($sublist); - } +})(sc); - return $list; - }; +// src/sc/lang/classlib/Core/Symbol.js +(function(sc) { - spec.clumps = function($groupSizeList) { - var $this = this, $list, $subSize, $sublist, i = 0; - $groupSizeList = utils.defaultValue$Nil($groupSizeList); + var $SC = sc.lang.$SC; - $list = $SC.Array(); - $subSize = $groupSizeList.at($int_0); - $sublist = this.species().new($subSize); - this.do($SC.Function(function($item) { - $sublist = $sublist.add($item); - if ($sublist.size() >= $subSize) { - $list = $list.add($sublist); - $subSize = $groupSizeList.wrapAt($SC.Integer(++i)); - $sublist = $this.species().new($subSize); - } - })); - if ($sublist.size() > 0) { - $list = $list.add($sublist); - } + sc.lang.klass.refine("Symbol", function(spec, utils) { + var $nil = utils.$nil; - return $list; + spec.__sym__ = function() { + return this._; }; - spec.curdle = function($probability) { - $probability = utils.defaultValue$Nil($probability); - return this.separate($SC.Function(function() { - return $probability.coin(); - })); + spec.__str__ = function() { + return this._; }; - spec.flatten = function($numLevels) { - $numLevels = utils.defaultValue$Integer($numLevels, 1); - return this._flatten($numLevels.__num__()); + spec.$new = function() { + throw new Error("Symbol.new is illegal, should use literal."); }; - spec._flatten = function(numLevels) { - var $list; + spec.asSymbol = utils.nop; - if (numLevels <= 0) { - return this; - } - numLevels = numLevels - 1; + spec.asInteger = function() { + var m = /^[-+]?\d+/.exec(this._); + return $SC.Integer(m ? m[0]|0 : 0); + }; - $list = this.species().new(); - this.do($SC.Function(function($item) { - if ($item._flatten) { - $list = $list.addAll($item._flatten(numLevels)); - } else { - $list = $list.add($item); - } - })); - - return $list; + spec.asFloat = function() { + var m = /^[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/.exec(this._); + return $SC.Float(m ? +m[0] : 0); }; - spec.flat = function() { - return this._flat(this.species().new(this.flatSize())); + spec.ascii = function() { + return this.asString().ascii(); }; - spec._flat = function($list) { - this.do($SC.Function(function($item) { - if ($item._flat) { - $list = $item._flat($list); - } else { - $list = $list.add($item); - } - })); - return $list; - }; + // TODO: implements asCompileString - spec.flatIf = function($func) { - $func = utils.defaultValue$Nil($func); - return this._flatIf($func); + spec.asClass = function() { + if (sc.lang.klass.exists(this._)) { + return sc.lang.klass.get(this._); + } + return $nil; }; - spec._flatIf = function($func) { - var $list; + // TODO: implements asSetter + // TODO: implements asGetter + // TODO: implements asSpec + // TODO: implements asWarp + // TODO: implements asTuning + // TODO: implements asScale + // TODO: implements isSetter + // TODO: implements isClassName + // TODO: implements isMetaClassName + // TODO: implements isPrefix + // TODO: implements isPrimitiveName + // TODO: implements isPrimitive + // TODO: implements isMap + // TODO: implements isRest + // TODO: implements envirGet + // TODO: implements envirPut + // TODO: implements blend + // TODO: implements ++ + // TODO: implements asBinOpString + // TODO: implements applyTo + // TODO: implements performBinaryOpOnSomething - $list = this.species().new(this.size()); - this.do($SC.Function(function($item, $i) { - if ($item._flatIf && BOOL($func.value($item, $i))) { - $list = $list.addAll($item._flatIf($func)); - } else { - $list = $list.add($item); - } - })); + spec.neg = utils.nop; + spec.bitNot = utils.nop; + spec.abs = utils.nop; + spec.ceil = utils.nop; + spec.floor = utils.nop; + spec.frac = utils.nop; + spec.sign = utils.nop; + spec.sqrt = utils.nop; + spec.exp = utils.nop; + spec.midicps = utils.nop; + spec.cpsmidi = utils.nop; + spec.midiratio = utils.nop; + spec.ratiomidi = utils.nop; + spec.ampdb = utils.nop; + spec.dbamp = utils.nop; + spec.octcps = utils.nop; + spec.cpsoct = utils.nop; + spec.log = utils.nop; + spec.log2 = utils.nop; + spec.log10 = utils.nop; + spec.sin = utils.nop; + spec.cos = utils.nop; + spec.tan = utils.nop; + spec.asin = utils.nop; + spec.acos = utils.nop; + spec.atan = utils.nop; + spec.sinh = utils.nop; + spec.cosh = utils.nop; + spec.tanh = utils.nop; + spec.rand = utils.nop; + spec.rand2 = utils.nop; + spec.linrand = utils.nop; + spec.bilinrand = utils.nop; + spec.sum3rand = utils.nop; + spec.distort = utils.nop; + spec.softclip = utils.nop; + spec.coin = utils.nop; + spec.even = utils.nop; + spec.odd = utils.nop; + spec.rectWindow = utils.nop; + spec.hanWindow = utils.nop; + spec.welWindow = utils.nop; + spec.triWindow = utils.nop; + spec.scurve = utils.nop; + spec.ramp = utils.nop; + spec["+"] = utils.nop; + spec["-"] = utils.nop; + spec["*"] = utils.nop; + spec["/"] = utils.nop; + spec.mod = utils.nop; + spec.min = utils.nop; + spec.max = utils.nop; + spec.bitAnd = utils.nop; + spec.bitOr = utils.nop; + spec.bitXor = utils.nop; + spec.bitHammingDistance = utils.nop; + // TODO: Implements hammingDistance + spec.lcm = utils.nop; + spec.gcd = utils.nop; + spec.round = utils.nop; + spec.roundUp = utils.nop; + spec.trunc = utils.nop; + spec.atan2 = utils.nop; + spec.hypot = utils.nop; + spec.hypotApx = utils.nop; + spec.pow = utils.nop; + spec.leftShift = utils.nop; + spec.rightShift = utils.nop; + spec.unsignedRightShift = utils.nop; + spec.rrand = utils.nop; + spec.exprand = utils.nop; - return $list; - }; + // TODO: Implements < + // TODO: Implements > + // TODO: Implements <= + // TODO: Implements >= - spec.flop = function() { - var $this = this, $list, $size, $maxsize; + spec.degreeToKey = utils.nop; + spec.degrad = utils.nop; + spec.raddeg = utils.nop; + spec.doNumberOp = utils.nop; + spec.doComplexOp = utils.nop; + spec.doSignalOp = utils.nop; - $size = this.size(); - $maxsize = $int_0; - this.do($SC.Function(function($sublist) { - var $sz; - if (BOOL($sublist.isSequenceableCollection())) { - $sz = $sublist.size(); - } else { - $sz = $int_1; - } - if ($sz > $maxsize) { - $maxsize = $sz; - } - })); + // TODO: Implements doListOp + // TODO: Implements primitiveIndex + // TODO: Implements specialIndex + // TODO: Implements printOn + // TODO: Implements storeOn + // TODO: Implements codegen_UGenCtorArg - $list = this.species().fill($maxsize, $SC.Function(function() { - return $this.species().new($size); - })); + spec.archiveAsCompileString = utils.alwaysReturn$true; - this.do($SC.Function(function($isublist) { - if (BOOL($isublist.isSequenceableCollection())) { - $list.do($SC.Function(function($jsublist, $j) { - $jsublist.add($isublist.wrapAt($j)); - })); - } else { - $list.do($SC.Function(function($jsublist) { - $jsublist.add($isublist); - })); - } - })); + // TODO: Implements kr + // TODO: Implements ir + // TODO: Implements tr + // TODO: Implements ar + // TODO: Implements matchOSCAddressPattern + // TODO: Implements help - return $list; + spec.asString = function() { + return $SC.String(this._); }; - spec.flopWith = function($func) { - var $this = this, $maxsize; - $func = utils.defaultValue$Nil($func); + spec.shallowCopy = utils.nop; - $maxsize = this.maxValue($SC.Function(function($sublist) { - if (BOOL($sublist.isSequenceableCollection())) { - return $sublist.size(); - } - return $int_1; - })); + spec.performBinaryOpOnSimpleNumber = utils.nop; + }); - return this.species().fill($maxsize, $SC.Function(function($i) { - return $func.valueArray($this.collect($SC.Function(function($sublist) { - if (BOOL($sublist.isSequenceableCollection())) { - return $sublist.wrapAt($i); - } else { - return $sublist; - } - }))); - })); - }; +})(sc); - // TODO: implements flopTogether - // TODO: implements flopDeep - // TODO: implements wrapAtDepth - // TODO: implements unlace - // TODO: implements integrate - // TODO: implements differentiate - // TODO: implements convertDigits - // TODO: implements hammingDistance - // TODO: implements degreeToKey - // TODO: implements keyToDegree - // TODO: implements nearestInScale - // TODO: implements nearestInList - // TODO: implements transposeKey - // TODO: implements mode - // TODO: implements performDegreeToKey - // TODO: implements performNearestInList - // TODO: implements performNearestInScale - // TODO: implements convertRhythm - // TODO: implements sumRhythmDivisions - // TODO: implements convertOneRhythm +// src/sc/lang/classlib/Core/Ref.js +(function(sc) { - spec.isSequenceableCollection = utils.alwaysReturn$true; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - spec.containsSeqColl = function() { - return this.any($SC.Function(function($_) { - return $_.isSequenceableCollection(); - })); - }; + function SCRef(args) { + this.__initializeWith__("Object"); + this._value = args[0] || $SC.Nil(); + } - spec.neg = function() { - return this.performUnaryOp($SC.Symbol("neg")); + sc.lang.klass.define(SCRef, "Ref : AbstractFunction", function(spec, utils) { + spec.valueOf = function() { + return this._value.valueOf(); }; - spec.bitNot = function() { - return this.performUnaryOp($SC.Symbol("bitNot")); + spec.value = function() { + return this._value; }; - spec.abs = function() { - return this.performUnaryOp($SC.Symbol("abs")); - }; + spec.value_ = fn(function($value) { + this._value = $value; + return this; + }, "value"); - spec.ceil = function() { - return this.performUnaryOp($SC.Symbol("ceil")); - }; + // $new - spec.floor = function() { - return this.performUnaryOp($SC.Symbol("floor")); - }; + spec.set = fn(function($thing) { + this._value = $thing; + return this; + }, "thing"); - spec.frac = function() { - return this.performUnaryOp($SC.Symbol("frac")); + spec.get = function() { + return this._value; }; - spec.sign = function() { - return this.performUnaryOp($SC.Symbol("sign")); - }; + spec.dereference = spec.value; - spec.squared = function() { - return this.performUnaryOp($SC.Symbol("squared")); - }; + spec.asRef = utils.nop; - spec.cubed = function() { - return this.performUnaryOp($SC.Symbol("cubed")); - }; + spec.valueArray = spec.value; - spec.sqrt = function() { - return this.performUnaryOp($SC.Symbol("sqrt")); - }; + spec.valueEnvir = spec.value; - spec.exp = function() { - return this.performUnaryOp($SC.Symbol("exp")); - }; + spec.valueArrayEnvir = spec.value; - spec.reciprocal = function() { - return this.performUnaryOp($SC.Symbol("reciprocal")); - }; + spec.next = spec.value; - spec.midicps = function() { - return this.performUnaryOp($SC.Symbol("midicps")); - }; + spec.asUGenInput = utils.nop; - spec.cpsmidi = function() { - return this.performUnaryOp($SC.Symbol("cpsmidi")); - }; + // TODO: implements printOn + // TODO: implements storeOn - spec.midiratio = function() { - return this.performUnaryOp($SC.Symbol("midiratio")); + spec.at = function($key) { + return this._value.at($key); }; - spec.ratiomidi = function() { - return this.performUnaryOp($SC.Symbol("ratiomidi")); + spec.put = function($key, $val) { + return this._value.put($key, $val); }; - spec.ampdb = function() { - return this.performUnaryOp($SC.Symbol("ampdb")); - }; + // TODO: implements seq + // TODO: implements asControlInput + // TODO: implements asBufWithValues + // TODO: implements multichannelExpandRef + }); - spec.dbamp = function() { - return this.performUnaryOp($SC.Symbol("dbamp")); - }; +})(sc); - spec.octcps = function() { - return this.performUnaryOp($SC.Symbol("octcps")); - }; +// src/sc/lang/classlib/Core/Nil.js +(function(sc) { - spec.cpsoct = function() { - return this.performUnaryOp($SC.Symbol("cpsoct")); - }; + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - spec.log = function() { - return this.performUnaryOp($SC.Symbol("log")); - }; + sc.lang.klass.refine("Nil", function(spec, utils) { + var $nil = utils.$nil; - spec.log2 = function() { - return this.performUnaryOp($SC.Symbol("log2")); + spec.__num__ = function() { + return 0; }; - spec.log10 = function() { - return this.performUnaryOp($SC.Symbol("log10")); + spec.__bool__ = function() { + return false; }; - spec.sin = function() { - return this.performUnaryOp($SC.Symbol("sin")); + spec.__sym__ = function() { + return "nil"; }; - spec.cos = function() { - return this.performUnaryOp($SC.Symbol("cos")); + spec.toString = function() { + return "nil"; }; - spec.tan = function() { - return this.performUnaryOp($SC.Symbol("tan")); + spec.$new = function() { + throw new Error("Nil.new is illegal, should use literal."); }; - spec.asin = function() { - return this.performUnaryOp($SC.Symbol("asin")); - }; + spec.isNil = utils.alwaysReturn$true; + spec.notNil = utils.alwaysReturn$false; - spec.acos = function() { - return this.performUnaryOp($SC.Symbol("acos")); + spec["?"] = function($obj) { + return $obj; }; - spec.atan = function() { - return this.performUnaryOp($SC.Symbol("atan")); + spec["??"] = function($obj) { + return $obj.value(); }; - spec.sinh = function() { - return this.performUnaryOp($SC.Symbol("sinh")); - }; + spec["!?"] = utils.nop; - spec.cosh = function() { - return this.performUnaryOp($SC.Symbol("cosh")); - }; + spec.asBoolean = utils.alwaysReturn$false; + spec.booleanValue = utils.alwaysReturn$false; - spec.tanh = function() { - return this.performUnaryOp($SC.Symbol("tanh")); - }; + spec.push = fn(function($function) { + return $function.value(); + }, "function"); - spec.rand = function() { - return this.performUnaryOp($SC.Symbol("rand")); - }; + spec.appendStream = fn(function($stream) { + return $stream; + }, "stream"); - spec.rand2 = function() { - return this.performUnaryOp($SC.Symbol("rand2")); - }; + spec.pop = utils.nop; + spec.source = utils.nop; + spec.source_ = utils.nop; - spec.linrand = function() { - return this.performUnaryOp($SC.Symbol("linrand")); - }; + spec.rate = utils.nop; + spec.numChannels = utils.nop; + spec.isPlaying = utils.alwaysReturn$false; - spec.bilinrand = function() { - return this.performUnaryOp($SC.Symbol("bilinrand")); - }; + spec.do = utils.nop; + spec.reverseDo = utils.nop; + spec.pairsDo = utils.nop; + spec.collect = utils.nop; + spec.select = utils.nop; + spec.reject = utils.nop; + spec.detect = utils.nop; + spec.collectAs = utils.nop; + spec.selectAs = utils.nop; + spec.rejectAs = utils.nop; - spec.sum3rand = function() { - return this.performUnaryOp($SC.Symbol("sum3rand")); + spec.dependants = function() { + return $SC("IdentitySet").new(); }; - spec.distort = function() { - return this.performUnaryOp($SC.Symbol("distort")); - }; + spec.changed = utils.nop; + spec.addDependant = utils.nop; + spec.removeDependant = utils.nop; + spec.release = utils.nop; + spec.update = utils.nop; - spec.softclip = function() { - return this.performUnaryOp($SC.Symbol("softclip")); - }; + spec.transformEvent = fn(function($event) { + return $event; + }, "event"); - spec.coin = function() { - return this.performUnaryOp($SC.Symbol("coin")); - }; + spec.awake = utils.alwaysReturn$nil; - spec.even = function() { - return this.performUnaryOp($SC.Symbol("even")); - }; + spec.play = utils.nop; - spec.odd = function() { - return this.performUnaryOp($SC.Symbol("odd")); - }; + spec.nextTimeOnGrid = fn(function($clock) { + if ($clock === $nil) { + return $clock; + } + return $SC.Function(function() { + return $clock.nextTimeOnGrid(); + }); + }, "clock"); - spec.isPositive = function() { - return this.performUnaryOp($SC.Symbol("isPositive")); + spec.asQuant = function() { + return $SC("Quant").default(); }; - spec.isNegative = function() { - return this.performUnaryOp($SC.Symbol("isNegative")); - }; + spec.swapThisGroup = utils.nop; + spec.performMsg = utils.nop; - spec.isStrictlyPositive = function() { - return this.performUnaryOp($SC.Symbol("isStrictlyPositive")); - }; + spec.printOn = fn(function($stream) { + $stream.putAll($SC.String("nil")); + return this; + }, "stream"); - spec.rectWindow = function() { - return this.performUnaryOp($SC.Symbol("rectWindow")); - }; + spec.storeOn = fn(function($stream) { + $stream.putAll($SC.String("nil")); + return this; + }, "stream"); - spec.hanWindow = function() { - return this.performUnaryOp($SC.Symbol("hanWindow")); - }; + spec.matchItem = utils.alwaysReturn$true; - spec.welWindow = function() { - return this.performUnaryOp($SC.Symbol("welWindow")); - }; + spec.add = fn(function($value) { + return $SC.Array([ $value ]); + }, "value"); - spec.triWindow = function() { - return this.performUnaryOp($SC.Symbol("triWindow")); - }; + spec.addAll = fn(function($array) { + return $array.asArray(); + }, "array"); - spec.scurve = function() { - return this.performUnaryOp($SC.Symbol("scurve")); + spec["++"] = function($array) { + return $array.asArray(); }; - spec.ramp = function() { - return this.performUnaryOp($SC.Symbol("ramp")); + spec.asCollection = function() { + return $SC.Array(); }; - spec.asFloat = function() { - return this.performUnaryOp($SC.Symbol("asFloat")); - }; + spec.remove = utils.nop; - spec.asInteger = function() { - return this.performUnaryOp($SC.Symbol("asInteger")); - }; + spec.set = utils.nop; - spec.nthPrime = function() { - return this.performUnaryOp($SC.Symbol("nthPrime")); - }; + spec.get = fn(function($prevVal) { + return $prevVal; + }, "prevVal"); - spec.prevPrime = function() { - return this.performUnaryOp($SC.Symbol("prevPrime")); + spec.addFunc = function() { + var functions = slice.call(arguments); + if (functions.length <= 1) { + return functions[0]; + } + return $SC("FunctionList").new($SC.Array(functions)); }; - spec.nextPrime = function() { - return this.performUnaryOp($SC.Symbol("nextPrime")); - }; + spec.removeFunc = utils.nop; - spec.indexOfPrime = function() { - return this.performUnaryOp($SC.Symbol("indexOfPrime")); - }; + spec.replaceFunc = utils.nop; + spec.seconds_ = utils.nop; + spec.throw = utils.nop; - spec.real = function() { - return this.performUnaryOp($SC.Symbol("real")); - }; + // TODO: implements handleError - spec.imag = function() { - return this.performUnaryOp($SC.Symbol("imag")); - }; + spec.archiveAsCompileString = utils.alwaysReturn$true; - spec.magnitude = function() { - return this.performUnaryOp($SC.Symbol("magnitude")); + spec.asSpec = function() { + return $SC("ControlSpec").new(); }; - spec.magnitudeApx = function() { - return this.performUnaryOp($SC.Symbol("magnitudeApx")); - }; + spec.superclassesDo = utils.nop; - spec.phase = function() { - return this.performUnaryOp($SC.Symbol("phase")); - }; + spec.shallowCopy = utils.nop; + }); - spec.angle = function() { - return this.performUnaryOp($SC.Symbol("angle")); - }; +})(sc); - spec.rho = function() { - return this.performUnaryOp($SC.Symbol("rho")); - }; +// src/sc/lang/classlib/Core/Kernel.js +(function(sc) { - spec.theta = function() { - return this.performUnaryOp($SC.Symbol("theta")); - }; + sc.lang.klass.refine("Class", { + // TODO: implements superclass + // TODO: implements asClass + // TODO: implements initClass + // TODO: implements $initClassTree + // TODO: implements $allClasses + // TODO: implements findMethod + // TODO: implements findRespondingMethodFor + // TODO: implements findOverriddenMethod + // TODO: implements superclassesDo + // TODO: implements while + // TODO: implements dumpByteCodes + // TODO: implements dumpClassSubtree + // TODO: implements dumpInterface + // TODO: implements asString + // TODO: implements printOn + // TODO: implements storeOn + // TODO: implements archiveAsCompileString + // TODO: implements hasHelpFile + // TODO: implements helpFilePath + // TODO: implements help + // TODO: implements openHelpFile + // TODO: implements shallowCopy + // TODO: implements openCodeFile + // TODO: implements classVars + // TODO: implements inspectorClass + // TODO: implements findReferences + // TODO: implements $findAllReferences + // TODO: implements allSubclasses + // TODO: implements superclasses + }); - spec.degrad = function() { - return this.performUnaryOp($SC.Symbol("degrad")); +})(sc); - }; - spec.raddeg = function() { - return this.performUnaryOp($SC.Symbol("raddeg")); - }; +// src/sc/lang/classlib/Core/Function.js +(function(sc) { - spec["+"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("+"), $aNumber, $adverb); - }; + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - spec["-"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("-"), $aNumber, $adverb); - }; + sc.lang.klass.refine("Function", function(spec, utils) { + var BOOL = utils.BOOL; + var $nil = utils.$nil; + var SCArray = $SC("Array"); - spec["*"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("*"), $aNumber, $adverb); - }; + // TODO: implements def - spec["/"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("/"), $aNumber, $adverb); + spec.$new = function() { + throw new Error("Function.new is illegal, should use literal."); }; - spec.div = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("div"), $aNumber, $adverb); - }; + spec.isFunction = utils.alwaysReturn$true; - spec.mod = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("mod"), $aNumber, $adverb); - }; + // TODO: implements isClosed - spec.pow = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("pow"), $aNumber, $adverb); - }; + spec.archiveAsCompileString = utils.alwaysReturn$true; + spec.archiveAsObject = utils.alwaysReturn$true; - spec.min = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("min"), $aNumber, $adverb); - }; + // TODO: implements checkCanArchive - spec.max = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("max"), $aNumber, $adverb); - }; + spec.shallowCopy = utils.nop; - spec["<"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("<"), $aNumber, $adverb); + spec.choose = function() { + return this.value(); }; - spec["<="] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("<="), $aNumber, $adverb); + spec.update = function() { + return this._.apply(this, arguments); }; - spec[">"] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol(">"), $aNumber, $adverb); + spec.value = function() { + return this._.apply(this, arguments); }; - spec[">="] = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol(">="), $aNumber, $adverb); + spec.valueArray = function($args) { + return this._.apply(this, $args.asArray()._); }; - spec.bitAnd = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("bitAnd"), $aNumber, $adverb); - }; + // TODO: implements valueEnvir + // TODO: implements valueArrayEnvir + // TODO: implements functionPerformList + // TODO: implements valueWithEnvir + // TODO: implements performWithEnvir + // TODO: implements performKeyValuePairs + // TODO: implements numArgs + // TODO: implements numVars + // TODO: implements varArgs + // TODO: implements loop + // TODO: implements block - spec.bitOr = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("bitOr"), $aNumber, $adverb); + spec.asRoutine = function() { + return $SC("Routine").new(this); }; - spec.bitXor = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("bitXor"), $aNumber, $adverb); - }; + spec.dup = fn(function($n) { + return SCArray.fill($n, this); + }, "n=2"); - spec.bitHammingDistance = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("bitHammingDistance"), $aNumber, $adverb); - }; + // TODO: implements sum + // TODO: implements defer + // TODO: implements thunk + // TODO: implements transformEvent + // TODO: implements set + // TODO: implements get + // TODO: implements fork + // TODO: implements forkIfNeeded + // TODO: implements awake + // TODO: implements cmdPeriod + // TODO: implements bench + // TODO: implements protect + // TODO: implements try + // TODO: implements prTry + // TODO: implements handleError - spec.lcm = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("lcm"), $aNumber, $adverb); - }; + spec.case = function() { + var args, i, imax; - spec.gcd = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("gcd"), $aNumber, $adverb); - }; + args = slice.call(arguments); + args.unshift(this); - spec.round = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("round"), $aNumber, $adverb); - }; + for (i = 0, imax = args.length >> 1; i < imax; ++i) { + if (BOOL(args[i * 2].value())) { + return args[i * 2 + 1].value(); + } + } - spec.roundUp = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("roundUp"), $aNumber, $adverb); - }; + if (args.length % 2 === 1) { + return args[args.length - 1].value(); + } - spec.trunc = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("trunc"), $aNumber, $adverb); + return $nil; }; - spec.atan2 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("atan2"), $aNumber, $adverb); + spec.r = function() { + return $SC("Routine").new(this); }; - spec.hypot = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("hypot"), $aNumber, $adverb); + spec.p = function() { + return $SC("Prout").new(this); }; - spec.hypotApx = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("hypotApx"), $aNumber, $adverb); - }; + // TODO: implements matchItem + // TODO: implements performDegreeToKey - spec.leftShift = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("leftShift"), $aNumber, $adverb); + spec.flop = function() { + var $this = this; + // if(def.argNames.isNil) { ^this }; + return $SC.Function(function() { + var $$args = $SC.Array(slice.call(arguments)); + return $$args.flop().collect($SC.Function(function($_) { + return $this.valueArray($_); + })); + }); }; - spec.rightShift = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("rightShift"), $aNumber, $adverb); - }; + // TODO: implements envirFlop + // TODO: implements makeFlopFunc + // TODO: implements inEnvir - spec.unsignedRightShift = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("unsignedRightShift"), $aNumber, $adverb); - }; + spec.while = fn(function($body) { + sc.lang.iterator.execute( + sc.lang.iterator.function$while(this), + $body + ); + return this; + }, "body"); + }); - spec.ring1 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("ring1"), $aNumber, $adverb); - }; +})(sc); - spec.ring2 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("ring2"), $aNumber, $adverb); - }; +// src/sc/lang/classlib/Core/Char.js +(function(sc) { - spec.ring3 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("ring3"), $aNumber, $adverb); + var $SC = sc.lang.$SC; + + sc.lang.klass.refine("Char", function(spec, utils) { + spec.__str__ = function() { + return this._; }; - spec.ring4 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("ring4"), $aNumber, $adverb); + spec.$nl = function() { + return $SC.Char("\n"); }; - spec.difsqr = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("difsqr"), $aNumber, $adverb); + spec.$ff = function() { + return $SC.Char("\f"); }; - spec.sumsqr = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("sumsqr"), $aNumber, $adverb); + spec.$tab = function() { + return $SC.Char("\t"); }; - spec.sqrsum = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("sqrsum"), $aNumber, $adverb); + spec.$space = function() { + return $SC.Char(" "); }; - spec.sqrdif = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("sqrdif"), $aNumber, $adverb); + spec.$comma = function() { + return $SC.Char(","); }; - spec.absdif = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("absdif"), $aNumber, $adverb); + spec.$new = function() { + throw new Error("Char.new is illegal, should use literal."); }; - spec.thresh = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("thresh"), $aNumber, $adverb); + // TODO: implements hash + + spec.ascii = function() { + return $SC.Integer(this._.charCodeAt(0)); }; - spec.amclip = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("amclip"), $aNumber, $adverb); + spec.digit = function() { + var ascii = this._.charCodeAt(0); + if (0x30 <= ascii && ascii <= 0x39) { + return $SC.Integer(ascii - 0x30); + } + if (0x41 <= ascii && ascii <= 0x5a) { + return $SC.Integer(ascii - 0x37); + } + if (0x61 <= ascii && ascii <= 0x7a) { + return $SC.Integer(ascii - 0x57); + } + throw new Error("digitValue failed"); }; - spec.scaleneg = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("scaleneg"), $aNumber, $adverb); + spec.asAscii = utils.nop; + + spec.asUnicode = function() { + return this.ascii(); }; - spec.clip2 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("clip2"), $aNumber, $adverb); + spec.toUpper = function() { + return $SC.Char(this._.toUpperCase()); }; - spec.fold2 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("fold2"), $aNumber, $adverb); + spec.toLower = function() { + return $SC.Char(this._.toLowerCase()); }; - spec.wrap2 = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("wrap2"), $aNumber, $adverb); + spec.isAlpha = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x41 <= ascii && ascii <= 0x5a) || + (0x61 <= ascii && ascii <= 0x7a)); }; - spec.excess = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("excess"), $aNumber, $adverb); + spec.isAlphaNum = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x30 <= ascii && ascii <= 0x39) || + (0x41 <= ascii && ascii <= 0x5a) || + (0x61 <= ascii && ascii <= 0x7a)); }; - spec.firstArg = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("firstArg"), $aNumber, $adverb); + spec.isPrint = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x20 <= ascii && ascii <= 0x7e)); }; - spec.rrand = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("rrand"), $aNumber, $adverb); + spec.isPunct = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x21 <= ascii && ascii <= 0x2f) || + (0x3a <= ascii && ascii <= 0x40) || + (0x5b <= ascii && ascii <= 0x60) || + (0x7b <= ascii && ascii <= 0x7e)); }; - spec.exprand = function($aNumber, $adverb) { - return this.performBinaryOp($SC.Symbol("exprand"), $aNumber, $adverb); + spec.isControl = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x00 <= ascii && ascii <= 0x1f) || ascii === 0x7f); }; - spec.performUnaryOp = function($aSelector) { - return this.collect($SC.Function(function($item) { - return $item.perform($aSelector); - })); + spec.isSpace = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x09 <= ascii && ascii <= 0x0d) || ascii === 0x20); }; - spec.performBinaryOp = function($aSelector, $theOperand, $adverb) { - $theOperand = utils.defaultValue$Nil($theOperand); - return $theOperand.performBinaryOpOnSeqColl($aSelector, this, $adverb); + spec.isVowl = function() { + var ch = this._.charAt(0).toUpperCase(); + return $SC.Boolean("AEIOU".indexOf(ch) !== -1); }; - spec.performBinaryOpOnSeqColl = function($aSelector, $theOperand, $adverb) { - var adverb; - $aSelector = utils.defaultValue$Nil($aSelector); - $theOperand = utils.defaultValue$Nil($theOperand); - $adverb = utils.defaultValue$Nil($adverb); + spec.isDecDigit = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x30 <= ascii && ascii <= 0x39)); + }; - if ($adverb === $nil) { - return _performBinaryOpOnSeqColl_adverb_nil( - this, $aSelector, $theOperand - ); - } - if (BOOL($adverb.isInteger())) { - return _performBinaryOpOnSeqColl_adverb_int( - this, $aSelector, $theOperand, $adverb.valueOf() - ); - } + spec.isUpper = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x41 <= ascii && ascii <= 0x5a)); + }; - adverb = $adverb.__sym__(); - if (adverb === "t") { - return _performBinaryOpOnSeqColl_adverb_t( - this, $aSelector, $theOperand - ); - } - if (adverb === "x") { - return _performBinaryOpOnSeqColl_adverb_x( - this, $aSelector, $theOperand - ); - } - if (adverb === "s") { - return _performBinaryOpOnSeqColl_adverb_s( - this, $aSelector, $theOperand - ); - } - if (adverb === "f") { - return _performBinaryOpOnSeqColl_adverb_f( - this, $aSelector, $theOperand - ); - } + spec.isLower = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x61 <= ascii && ascii <= 0x7a)); + }; - throw new Error( - "unrecognized adverb: '" + adverb + "' for operator '" + String($aSelector) + "'" - ); + spec.isFileSafe = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean((0x20 <= ascii && ascii <= 0x7e) && + ascii !== 0x2f && // 0x2f is '/' + ascii !== 0x3a && // 0x3a is ':' + ascii !== 0x22); // 0x22 is '"' }; - function _performBinaryOpOnSeqColl_adverb_nil($this, $aSelector, $theOperand) { - var $size, $newList, $i; - var size, i; + spec.isPathSeparator = function() { + var ascii = this._.charCodeAt(0); + return $SC.Boolean(ascii === 0x2f); + }; - $size = $this.size().max($theOperand.size()); - $newList = $this.species().new($size); + spec["<"] = function($aChar) { + return $SC.Boolean(this.ascii() < $aChar.ascii()); + }; - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $i = $SC.Integer(i); - $newList.add( - $theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i)) - ); - } + spec["++"] = function($that) { + return $SC.String(this._ + $that.__str__()); + }; - return $newList; - } + // TODO: implements $bullet + // TODO: implements printOn + // TODO: implements storeOn - function _performBinaryOpOnSeqColl_adverb_int($this, $aSelector, $theOperand, adverb) { - var $size, $newList, $i; - var size, i; + spec.archiveAsCompileString = function() { + return $SC.True(); + }; - if (adverb === 0) { - $size = $this.size().max($theOperand.size()); - $newList = $this.species().new($size); + spec.asString = function() { + return $SC.String(this._); + }; - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $i = $SC.Integer(i); - $newList.add($theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i))); - } + spec.shallowCopy = utils.nop; + }); - } else if (adverb > 0) { +})(sc); - $newList = $theOperand.collect($SC.Function(function($item) { - return $item.perform($aSelector, $this, $SC.Integer(adverb - 1)); - })); +// src/sc/lang/classlib/Core/Boolean.js +(function(sc) { - } else { + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - $newList = $this.collect($SC.Function(function($item) { - return $theOperand.perform($aSelector, $item, $SC.Integer(adverb + 1)); - })); + sc.lang.klass.refine("Boolean", function(spec, utils) { + spec.__bool__ = function() { + return this._; + }; - } + spec.toString = function() { + return String(this._); + }; - return $newList; - } + spec.$new = function() { + throw new Error("Boolean.new is illegal, should use literal."); + }; - function _performBinaryOpOnSeqColl_adverb_t($this, $aSelector, $theOperand) { - var $size, $newList, $i; - var size, i; + spec.xor = function($bool) { + return $SC.Boolean(this === $bool).not(); + }; - $size = $theOperand.size(); - $newList = $this.species().new($size); + // TODO: implements if + // TODO: implements nop + // TODO: implements && + // TODO: implements || + // TODO: implements and + // TODO: implements or + // TODO: implements nand + // TODO: implements asInteger + // TODO: implements binaryValue - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $i = $SC.Integer(i); - $newList.add($theOperand.at($i).perform($aSelector, $this)); - } + spec.asBoolean = utils.nop; + spec.booleanValue = utils.nop; - return $newList; - } + // TODO: implements keywordWarnings + // TODO: implements trace + // TODO: implements printOn + // TODO: implements storeOn - function _performBinaryOpOnSeqColl_adverb_x($this, $aSelector, $theOperand) { - var $size, $newList; + spec.archiveAsCompileString = utils.alwaysReturn$true; - $size = $theOperand.size() ["*"] ($this.size()); - $newList = $this.species().new($size); - $theOperand.do($SC.Function(function($a) { - $this.do($SC.Function(function($b) { - $newList.add($a.perform($aSelector, $b)); - })); - })); + spec.while = function() { + var msg = "While was called with a fixed (unchanging) Boolean as the condition. "; + msg += "Please supply a Function instead."; + throw new Error(msg); + }; - return $newList; - } + spec.shallowCopy = utils.nop; + }); - function _performBinaryOpOnSeqColl_adverb_s($this, $aSelector, $theOperand) { - var $size, $newList, $i; - var size, i; + sc.lang.klass.refine("True", function(spec, utils) { + spec.$new = function() { + throw new Error("True.new is illegal, should use literal."); + }; - $size = $this.size().min($theOperand.size()); - $newList = $this.species().new($size); + spec.if = fn(function($trueFunc) { + return $trueFunc.value(); + }, "trueFunc"); - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $i = $SC.Integer(i); - $newList.add($theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i))); - } + spec.not = utils.alwaysReturn$false; - return $newList; - } + spec["&&"] = function($that) { + return $that.value(); + }; - function _performBinaryOpOnSeqColl_adverb_f($this, $aSelector, $theOperand) { - var $size, $newList, $i; - var size, i; + spec["||"] = utils.nop; - $size = $this.size().max($theOperand.size()); - $newList = $this.species().new($size); + spec.and = fn(function($that) { + return $that.value(); + }, "that"); - size = $size.__int__(); - for (i = 0; i < size; ++i) { - $i = $SC.Integer(i); - $newList.add($theOperand.foldAt($i).perform($aSelector, $this.foldAt($i))); - } + spec.or = spec["||"]; - return $newList; - } + spec.nand = fn(function($that) { + return $that.value().not(); + }, "that"); - spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber, $adverb) { - $aNumber = utils.defaultValue$Nil($aNumber); - return this.collect($SC.Function(function($item) { - return $aNumber.perform($aSelector, $item, $adverb); - })); - }; + spec.asInteger = utils.alwaysReturn$int_1; + spec.binaryValue = utils.alwaysReturn$int_1; + }); - spec.performBinaryOpOnComplex = function($aSelector, $aComplex, $adverb) { - $aComplex = utils.defaultValue$Nil($aComplex); - return this.collect($SC.Function(function($item) { - return $aComplex.perform($aSelector, $item, $adverb); - })); + sc.lang.klass.refine("False", function(spec, utils) { + spec.$new = function() { + throw new Error("False.new is illegal, should use literal."); }; - spec.asFraction = function($denominator, $fasterBetter) { - return this.collect($SC.Function(function($item) { - return $item.asFraction($denominator, $fasterBetter); - })); - }; + spec.if = fn(function($trueFunc, $falseFunc) { + return $falseFunc.value(); + }, "trueFunc; falseFunc"); - // TODO: implements asPoint - // TODO: implements asRect + spec.not = utils.alwaysReturn$true; - spec.ascii = function() { - return this.collect($SC.Function(function($item) { - return $item.ascii(); - })); - }; + spec["&&"] = utils.nop; - spec.rate = function() { - if (this.size().__int__() === 1) { - return this.first().rate(); - } - return this.collect($SC.Function(function($item) { - return $item.rate(); - })).minItem(); + spec["||"] = function($that) { + return $that.value(); }; - spec.multiChannelPerform = function() { - var method; + spec.and = utils.nop; - if (this.size() > 0) { - method = utils.getMethod("Object", "multiChannelPerform"); - return method.apply(this, arguments); - } + spec.or = fn(function($that) { + return $that.value(); + }, "that"); - return this.class().new(); - }; + spec.nand = utils.alwaysReturn$true; + spec.asInteger = utils.alwaysReturn$int_0; + spec.binaryValue = utils.alwaysReturn$int_0; + }); - spec.multichannelExpandRef = utils.nop; +})(sc); - spec.clip = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("clip") ].concat(slice.call(arguments)) - ); - }; +// src/sc/lang/classlib/Collections/Collection.js +(function(sc) { - spec.wrap = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("wrap") ].concat(slice.call(arguments)) - ); - }; + var $SC = sc.lang.$SC; + var fn = sc.lang.fn; - spec.fold = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("fold") ].concat(slice.call(arguments)) - ); - }; + sc.lang.klass.refine("Collection", function(spec, utils) { + var BOOL = utils.BOOL; + var $nil = utils.$nil; + var $true = utils.$true; + var $false = utils.$false; + var $int_0 = utils.$int_0; + var $int_1 = utils.$int_1; + var SCArray = $SC("Array"); - spec.linlin = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("linlin") ].concat(slice.call(arguments)) - ); - }; + spec.$newFrom = fn(function($aCollection) { + var $newCollection; - spec.linexp = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("linexp") ].concat(slice.call(arguments)) - ); - }; + $newCollection = this.new($aCollection.size()); + $aCollection.do($SC.Function(function($item) { + $newCollection.add($item); + })); - spec.explin = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("explin") ].concat(slice.call(arguments)) - ); - }; + return $newCollection; + }, "aCollection"); - spec.expexp = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("expexp") ].concat(slice.call(arguments)) - ); - }; + spec.$with = fn(function($$args) { + var $newColl; - spec.lincurve = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lincurve") ].concat(slice.call(arguments)) - ); - }; + $newColl = this.new($$args.size()); + $newColl.addAll($$args); - spec.curvelin = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("curvelin") ].concat(slice.call(arguments)) - ); - }; + return $newColl; + }, "*args"); - spec.bilin = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("bilin") ].concat(slice.call(arguments)) - ); - }; + spec.$fill = fn(function($size, $function) { + var $obj; + var size, i; - spec.biexp = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("biexp") ].concat(slice.call(arguments)) - ); - }; + if (BOOL($size.isSequenceableCollection())) { + return this.fillND($size, $function); + } - spec.moddif = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("moddif") ].concat(slice.call(arguments)) - ); - }; + $obj = this.new($size); - spec.range = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("range") ].concat(slice.call(arguments)) - ); - }; + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $obj.add($function.value($SC.Integer(i))); + } - spec.exprange = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("exprange") ].concat(slice.call(arguments)) - ); - }; + return $obj; + }, "size; function"); - spec.curverange = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("curverange") ].concat(slice.call(arguments)) - ); - }; + spec.$fill2D = fn(function($rows, $cols, $function) { + var $this = this, $obj, $obj2, $row, $col; + var rows, cols, i, j; - spec.unipolar = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("unipolar") ].concat(slice.call(arguments)) - ); - }; + $obj = this.new($rows); - spec.bipolar = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("bipolar") ].concat(slice.call(arguments)) - ); - }; + rows = $rows.__int__(); + cols = $cols.__int__(); - spec.lag = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lag") ].concat(slice.call(arguments)) - ); - }; + for (i = 0; i < rows; ++i) { + $row = $SC.Integer(i); + $obj2 = $this.new($cols); + for (j = 0; j < cols; ++j) { + $col = $SC.Integer(j); + $obj2 = $obj2.add($function.value($row, $col)); + } + $obj = $obj.add($obj2); + } - spec.lag2 = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lag2") ].concat(slice.call(arguments)) - ); - }; + return $obj; + }, "rows; cols; function"); - spec.lag3 = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lag3") ].concat(slice.call(arguments)) - ); - }; + spec.$fill3D = fn(function($planes, $rows, $cols, $function) { + var $this = this, $obj, $obj2, $obj3, $plane, $row, $col; + var planes, rows, cols, i, j, k; - spec.lagud = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lagud") ].concat(slice.call(arguments)) - ); - }; + $obj = this.new($planes); - spec.lag2ud = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lag2ud") ].concat(slice.call(arguments)) - ); - }; + planes = $planes.__int__(); + rows = $rows .__int__(); + cols = $cols .__int__(); - spec.lag3ud = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("lag3ud") ].concat(slice.call(arguments)) - ); - }; + for (i = 0; i < planes; ++i) { + $plane = $SC.Integer(i); + $obj2 = $this.new($rows); + for (j = 0; j < rows; ++j) { + $row = $SC.Integer(j); + $obj3 = $this.new($cols); + for (k = 0; k < cols; ++k) { + $col = $SC.Integer(k); + $obj3 = $obj3.add($function.value($plane, $row, $col)); + } + $obj2 = $obj2.add($obj3); + } + $obj = $obj.add($obj2); + } - spec.varlag = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("varlag") ].concat(slice.call(arguments)) - ); - }; + return $obj; + }, "planes; rows; cols; function"); - spec.slew = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("slew") ].concat(slice.call(arguments)) - ); - }; + var fillND = function($this, $dimensions, $function, $args) { + var $n, $obj, $argIndex; - spec.blend = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("blend") ].concat(slice.call(arguments)) - ); - }; + $n = $dimensions.first(); + $obj = $this.new($n); + $argIndex = $args.size(); + $args = $args ["++"] ($int_0); - spec.checkBadValues = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("checkBadValues") ].concat(slice.call(arguments)) - ); - }; + if ($dimensions.size().__int__() <= 1) { + $n.do($SC.Function(function($i) { + $obj.add($function.valueArray($args.put($argIndex, $i))); + })); + } else { + $dimensions = $dimensions.drop($int_1); + $n.do($SC.Function(function($i) { + $obj = $obj.add(fillND($this, $dimensions, $function, $args.put($argIndex, $i))); + })); + } - spec.prune = function() { - return this.multiChannelPerform.apply( - this, [ $SC.Symbol("prune") ].concat(slice.call(arguments)) - ); + return $obj; }; - // TODO: implements minNyquist - // TODO: implements sort - // TODO: implements sortBy - // TODO: implements sortMap - // TODO: implements sortedMedian - // TODO: implements median - // TODO: implements quickSort - // TODO: implements order + spec.$fillND = fn(function($dimensions, $function) { + return fillND(this, $dimensions, $function, $SC.Array([])); + }, "dimensions; function"); - spec.swap = function($i, $j) { - var $temp; - $i = utils.defaultValue$Nil($i); - $j = utils.defaultValue$Nil($j); + spec["@"] = function($index) { + return this.at($index); + }; - $temp = this.at($i); - this.put($i, this.at($j)); - this.put($j, $temp); + spec["=="] = function($aCollection) { + var $res = null; - return this; + if ($aCollection.class() !== this.class()) { + return $false; + } + if (this.size() !== $aCollection.size()) { + return $false; + } + this.do($SC.Function(function($item) { + if (!BOOL($aCollection.includes($item))) { + $res = $false; + return 65535; + } + })); + + return $res || $true; }; - // TODO: implements quickSortRange - // TODO: implements mergeSort - // TODO: implements mergeSortTemp - // TODO: implements mergeTemp - // TODO: implements insertionSort - // TODO: implements insertionSortRange - // TODO: implements hoareMedian - // TODO: implements hoareFind - // TODO: implements hoarePartition - // TODO: implements $streamContensts - // TODO: implements $streamContenstsLimit + // TODO: implements hash - spec.wrapAt = function($index) { - $index = utils.defaultValue$Nil($index); - $index = $index ["%"] (this.size()); - return this.at($index); + spec.species = function() { + return SCArray; }; - spec.wrapPut = function($index, $value) { - $index = utils.defaultValue$Nil($index); - $value = utils.defaultValue$Nil($value); - $index = $index ["%"] (this.size()); - return this.put($index, $value); + spec.do = function() { + return this._subclassResponsibility("do"); }; - // TODO: implements reduce - // TODO: implements join - // TODO: implements nextTimeOnGrid - // TODO: implements asQuant - // TODO: implements schedBundleArrayOnClock - }); - -})(sc); + // TODO: implements iter -// src/sc/lang/classlib/Collections/ArrayedCollection.js -(function(sc) { + spec.size = function() { + var tally = 0; - var slice = [].slice; - var $SC = sc.lang.$SC; - var iterator = sc.lang.iterator; - var fn = sc.lang.fn; - var rand = sc.libs.random; - var mathlib = sc.libs.mathlib; + this.do($SC.Function(function() { + tally++; + })); - sc.lang.klass.refine("ArrayedCollection", function(spec, utils) { - var BOOL = utils.BOOL; - var $nil = utils.$nil; - var $int_0 = utils.$int_0; - var $int_1 = utils.$int_1; + return $SC.Integer(tally); + }; - spec.valueOf = function() { - return this._.map(function(elem) { - return elem.valueOf(); - }); + spec.flatSize = function() { + return this.sum($SC.Function(function($_) { + return $_.flatSize(); + })); }; - spec.__elem__ = function(item) { - return item; + spec.isEmpty = function() { + return $SC.Boolean(this.size().__int__() === 0); }; - spec._ThrowIfImmutable = function() { - if (this._immutable) { - throw new Error("Attempted write to immutable object."); - } + spec.notEmpty = function() { + return $SC.Boolean(this.size().__int__() !== 0); }; - // TODO: implements $newClear - // TODO: implements indexedSize + spec.asCollection = utils.nop; + spec.isCollection = utils.alwaysReturn$true; - spec.size = function() { - return $SC.Integer(this._.length); + spec.add = function() { + return this._subclassResponsibility("add"); }; - // TODO: implements maxSize + spec.addAll = fn(function($aCollection) { + var $this = this; - spec.swap = function($a, $b) { - var raw = this._; - var a, b, len, tmp; - $a = utils.defaultValue$Nil($a); - $b = utils.defaultValue$Nil($b); + $aCollection.asCollection().do($SC.Function(function($item) { + return $this.add($item); + })); - this._ThrowIfImmutable(); + return this; + }, "aCollection"); - a = $a.__int__(); - b = $b.__int__(); - len = raw.length; + spec.remove = function() { + return this._subclassResponsibility("remove"); + }; - if (a < 0 || len <= a || b < 0 || len <= b) { - throw new Error("out of index"); - } + spec.removeAll = fn(function($list) { + var $this = this; - tmp = raw[b]; - raw[b] = raw[a]; - raw[a] = tmp; + $list.do($SC.Function(function($item) { + $this.remove($item); + })); return this; - }; + }, "list"); - spec.at = function($index) { - var i; - $index = utils.defaultValue$Nil($index); + spec.removeEvery = fn(function($list) { + this.removeAllSuchThat($SC.Function(function($_) { + return $list.includes($_); + })); + return this; + }, "list"); - if (Array.isArray($index._)) { - return $SC.Array($index._.map(function($index) { - i = $index.__int__(); - if (i < 0 || this._.length <= i) { - return $nil; - } - return this._[i]; - }, this)); - } + spec.removeAllSuchThat = function($function) { + var $this = this, $removedItems, $copy; - i = $index.__int__(); + $removedItems = this.class().new(); + $copy = this.copy(); + $copy.do($SC.Function(function($item) { + if (BOOL($function.value($item))) { + $this.remove($item); + $removedItems = $removedItems.add($item); + } + })); - return this._[i] || $nil; + return $removedItems; }; - spec.clipAt = function($index) { - var i; - $index = utils.defaultValue$Nil($index); + spec.atAll = fn(function($keys) { + var $this = this; - if (Array.isArray($index._)) { - return $SC.Array($index._.map(function($index) { - i = mathlib.clip_idx($index.__int__(), this._.length); - return this._[i]; - }, this)); - } + return $keys.collect($SC.Function(function($index) { + return $this.at($index); + })); + }, "keys"); - i = mathlib.clip_idx($index.__int__(), this._.length); + spec.putEach = fn(function($keys, $values) { + var keys, values, i, imax; - return this._[i]; - }; - - spec.wrapAt = function($index) { - var i; - $index = utils.defaultValue$Nil($index); + $keys = $keys.asArray(); + $values = $values.asArray(); - if (Array.isArray($index._)) { - return $SC.Array($index._.map(function($index) { - var i = mathlib.wrap_idx($index.__int__(), this._.length); - return this._[i]; - }, this)); + keys = $keys._; + values = $values._; + for (i = 0, imax = keys.length; i < imax; ++i) { + this.put(keys[i], values[i % values.length]); } - i = mathlib.wrap_idx($index.__int__(), this._.length); - - return this._[i]; - }; - - spec.foldAt = function($index) { - var i; - $index = utils.defaultValue$Nil($index); - - if (Array.isArray($index._)) { - return $SC.Array($index._.map(function($index) { - var i = mathlib.fold_idx($index.__int__(), this._.length); - return this._[i]; - }, this)); - } + return this; + }, "keys; values"); - i = mathlib.fold_idx($index.__int__(), this._.length); + spec.includes = fn(function($item1) { + var $res = null; - return this._[i]; - }; + this.do($SC.Function(function($item2) { + if ($item1 === $item2) { + $res = $true; + return 65535; + } + })); - spec.put = function($index, $item) { - var i; - $index = utils.defaultValue$Nil($index); + return $res || $false; + }, "item1"); - this._ThrowIfImmutable(); + spec.includesEqual = fn(function($item1) { + var $res = null; - 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.do($SC.Function(function($item2) { + if (BOOL( $item1 ["=="] ($item2) )) { + $res = $true; + return 65535; } - this._[i] = this.__elem__($item); - } + })); - return this; - }; + return $res || $false; + }, "item1"); - spec.clipPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + spec.includesAny = fn(function($aCollection) { + var $this = this, $res = null; - this._ThrowIfImmutable(); + $aCollection.do($SC.Function(function($item) { + if (BOOL($this.includes($item))) { + $res = $true; + return 65535; + } + })); - if (Array.isArray($index._)) { - $index._.forEach(function($index) { - this._[mathlib.clip_idx($index.__int__(), this._.length)] = this.__elem__($item); - }, this); - } else { - this._[mathlib.clip_idx($index.__int__(), this._.length)] = this.__elem__($item); - } + return $res || $false; + }, "aCollection"); - return this; - }; + spec.includesAll = fn(function($aCollection) { + var $this = this, $res = null; - spec.wrapPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + $aCollection.do($SC.Function(function($item) { + if (!BOOL($this.includes($item))) { + $res = $false; + return 65535; + } + })); - this._ThrowIfImmutable(); + return $res || $true; + }, "aCollection"); - if (Array.isArray($index._)) { - $index._.forEach(function($index) { - this._[mathlib.wrap_idx($index.__int__(), this._.length)] = this.__elem__($item); - }, this); - } else { - this._[mathlib.wrap_idx($index.__int__(), this._.length)] = this.__elem__($item); - } + spec.matchItem = fn(function($item) { + return this.includes($item); + }, "item"); - return this; + spec.collect = function($function) { + return this.collectAs($function, this.species()); }; - spec.foldPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); - - this._ThrowIfImmutable(); - - if (Array.isArray($index._)) { - $index._.forEach(function($index) { - this._[mathlib.fold_idx($index.__int__(), this._.length)] = this.__elem__($item); - }, this); - } else { - this._[mathlib.fold_idx($index.__int__(), this._.length)] = this.__elem__($item); - } - - return this; + spec.select = function($function) { + return this.selectAs($function, this.species()); }; - spec.removeAt = function($index) { - var raw = this._; - var index; - $index = utils.defaultValue$Nil($index); - - this._ThrowIfImmutable(); - - index = $index.__int__(); - if (index < 0 || raw.length <= index) { - throw new Error("out of index"); - } - - return raw.splice(index, 1)[0]; + spec.reject = function($function) { + return this.rejectAs($function, this.species()); }; - spec.takeAt = function($index) { - var raw = this._; - var index, ret, instead; - $index = utils.defaultValue$Nil($index); - - this._ThrowIfImmutable(); + spec.collectAs = fn(function($function, $class) { + var $res; - index = $index.__int__(); - if (index < 0 || raw.length <= index) { - throw new Error("out of index"); - } + $res = $class.new(this.size()); + this.do($SC.Function(function($elem, $i) { + return $res.add($function.value($elem, $i)); + })); - ret = raw[index]; - instead = raw.pop(); - if (index !== raw.length) { - raw[index] = instead; - } + return $res; + }, "function; class"); - return ret; - }; + spec.selectAs = fn(function($function, $class) { + var $res; - spec.indexOf = function($item) { - var index; - $item = utils.defaultValue$Nil($item); + $res = $class.new(this.size()); + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $res.add($elem); + } + })); - index = this._.indexOf($item); - return index === -1 ? $nil : $SC.Integer(index); - }; + return $res; + }, "function; class"); - spec.indexOfGreaterThan = function($val) { - var raw = this._; - var val, i, imax = raw.length; - $val = utils.defaultValue$Nil($val); + spec.rejectAs = fn(function($function, $class) { + var $res; - val = $val.__num__(); - for (i = 0; i < imax; ++i) { - if (raw[i].__num__() > val) { - return $SC.Integer(i); + $res = $class.new(this.size()); + this.do($SC.Function(function($elem, $i) { + if (!BOOL($function.value($elem, $i))) { + $res = $res.add($elem); } - } + })); - return $nil; - }; + return $res; + }, "function; class"); - spec.takeThese = function($func) { - var raw = this._; - var i = 0, $i; - $func = utils.defaultValue$Nil($func); + spec.detect = function($function) { + var $res = null; - $i = $SC.Integer(i); - while (i < raw.length) { - if (BOOL($func.value(raw[i], $i))) { - this.takeAt($i); - } else { - $i = $SC.Integer(++i); + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $elem; + return 65535; } - } + })); - return this; + return $res || $nil; }; - spec.replace = function($find, $replace) { - var $index, $out, $array; - $find = utils.defaultValue$Nil($find); - $replace = utils.defaultValue$Nil($replace); - - this._ThrowIfImmutable(); + spec.detectIndex = function($function) { + var $res = null; - $out = $SC.Array(); - $array = this; - $find = $find.asArray(); - $replace = $replace.asArray(); - $SC.Function(function() { - return ($index = $array.find($find)).notNil(); - }).while($SC.Function(function() { - $out = $out ["++"] ($array.keep($index)) ["++"] ($replace); - $array = $array.drop($index ["+"] ($find.size())); + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $i; + return 65535; + } })); - - return $out ["++"] ($array); + return $res || $nil; }; - spec.slotSize = function() { - return this.size(); + spec.doMsg = function() { + var args = arguments; + this.do($SC.Function(function($item) { + $item.perform.apply($item, args); + })); + return this; }; - spec.slotAt = function($index) { - return this.at($index); + spec.collectMsg = function() { + var args = arguments; + return this.collect($SC.Function(function($item) { + return $item.perform.apply($item, args); + })); }; - spec.slotPut = function($index, $value) { - return this.put($index, $value); + spec.selectMsg = function() { + var args = arguments; + return this.select($SC.Function(function($item) { + return $item.perform.apply($item, args); + })); }; - spec.slotKey = function($index) { - return $index; + spec.rejectMsg = function() { + var args = arguments; + return this.reject($SC.Function(function($item) { + return $item.perform.apply($item, args); + })); }; - spec.slotIndex = utils.alwaysReturn$nil; + spec.detectMsg = fn(function($selector, $$args) { + return this.detect($SC.Function(function($item) { + return $item.performList($selector, $$args); + })); + }, "selector; *args"); - spec.getSlots = function() { - return this.copy(); - }; + spec.detectIndexMsg = fn(function($selector, $$args) { + return this.detectIndex($SC.Function(function($item) { + return $item.performList($selector, $$args); + })); + }, "selector; *args"); - spec.setSlots = function($array) { - $array = utils.defaultValue$Nil($array); - return this.overWrite($array); - }; + spec.lastForWhich = function($function) { + var $res = null; + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $elem; + } else { + return 65535; + } + })); - spec.atModify = function($index, $function) { - this.put($index, $function.value(this.at($index), $index)); - return this; + return $res || $nil; }; - spec.atInc = function($index, $inc) { - $inc = utils.defaultValue$Integer($inc, 1); - this.put($index, this.at($index) ["+"] ($inc)); - return this; - }; + spec.lastIndexForWhich = function($function) { + var $res = null; + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $i; + } else { + return 65535; + } + })); - spec.atDec = function($index, $dec) { - $dec = utils.defaultValue$Integer($dec, 1); - this.put($index, this.at($index) ["-"] ($dec)); - return this; + return $res || $nil; }; - spec.isArray = utils.alwaysReturn$true; - spec.asArray = utils.nop; + spec.inject = fn(function($thisValue, $function) { + var $nextValue; - spec.copyRange = function($start, $end) { - var start, end, instance, raw; - $start = utils.defaultValue$Nil($start); - $end = utils.defaultValue$Nil($end); + $nextValue = $thisValue; + this.do($SC.Function(function($item, $i) { + $nextValue = $function.value($nextValue, $item, $i); + })); - 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); + return $nextValue; + }, "thisValue; function"); - instance = new this.__Spec(); - instance._ = raw; - return instance; - }; + spec.injectr = fn(function($thisValue, $function) { + var $this = this, size, $nextValue; - spec.copySeries = function($first, $second, $last) { - var i, first, second, last, step, instance, raw; - $first = utils.defaultValue$Nil($first); - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); + size = this.size().__int__(); + $nextValue = $thisValue; + this.do($SC.Function(function($item, $i) { + $item = $this.at($SC.Integer(--size)); + $nextValue = $function.value($nextValue, $item, $i); + })); - 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; + return $nextValue; + }, "thisValue; function"); - 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]); + spec.count = function($function) { + var sum = 0; + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + sum++; } - } + })); - instance = new this.__Spec(); - instance._ = raw; - return instance; + return $SC.Integer(sum); }; - spec.putSeries = function($first, $second, $last, $value) { - var i, first, second, last, step; - $first = utils.defaultValue$Nil($first); - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); - $value = utils.defaultValue$Nil($value); + spec.occurrencesOf = fn(function($obj) { + var sum = 0; - this._ThrowIfImmutable(); + this.do($SC.Function(function($elem) { + if (BOOL($elem ["=="] ($obj))) { + sum++; + } + })); - 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; + return $SC.Integer(sum); + }, "obj"); - $value = this.__elem__($value); + spec.any = function($function) { + var $res = null; - 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; + this.do($SC.Function(function($elem, $i) { + if (BOOL($function.value($elem, $i))) { + $res = $true; + return 65535; } - } + })); - return this; + return $res || $false; }; - spec.add = function($item) { - $item = utils.defaultValue$Nil($item); + spec.every = function($function) { + var $res = null; - this._ThrowIfImmutable(); - this._.push(this.__elem__($item)); + this.do($SC.Function(function($elem, $i) { + if (!BOOL($function.value($elem, $i))) { + $res = $false; + return 65535; + } + })); - return this; + return $res || $true; }; - spec.addAll = function($aCollection) { - var $this = this; - $aCollection = utils.defaultValue$Nil($aCollection); - - this._ThrowIfImmutable(); + spec.sum = fn(function($function) { + var $sum; - if ($aCollection.isSequenceableCollection().valueOf()) { - $aCollection.do($SC.Function(function($item) { - $this._.push($this.__elem__($item)); + $sum = $int_0; + if ($function === $nil) { + this.do($SC.Function(function($elem) { + $sum = $sum ["+"] ($elem); })); } else { - this.add($aCollection); + this.do($SC.Function(function($elem, $i) { + $sum = $sum ["+"] ($function.value($elem, $i)); + })); } - return this; - }; - - spec.putEach = function($keys, $values) { - var keys, values, i, imax; - $keys = utils.defaultValue$Nil($keys); - $values = utils.defaultValue$Nil($values); + return $sum; + }, "function"); - this._ThrowIfImmutable(); + spec.mean = function($function) { + return this.sum($function) ["/"] (this.size()); + }; - $keys = $keys.asArray(); - $values = $values.asArray(); + spec.product = fn(function($function) { + var $product; - keys = $keys._; - values = $values._; - for (i = 0, imax = keys.length; i < imax; ++i) { - this.put(keys[i], this.__elem__(values[i % values.length])); + $product = $int_1; + if ($function === $nil) { + this.do($SC.Function(function($elem) { + $product = $product ["*"] ($elem); + })); + } else { + this.do($SC.Function(function($elem, $i) { + $product = $product ["*"] ($function.value($elem, $i)); + })); } - return this; - }; - - spec.extend = function($size, $item) { - var instance, raw, size, i; + return $product; + }, "function"); - $size = utils.defaultValue$Nil($size); - $item = utils.defaultValue$Nil($item); + spec.sumabs = function() { + var $sum; - 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)); + $sum = $int_0; + this.do($SC.Function(function($elem) { + if (BOOL($elem.isSequenceableCollection())) { + $elem = $elem.at($int_0); } - } - - instance = new this.__Spec(); - instance._ = raw; - return instance; + $sum = $sum ["+"] ($elem.abs()); + })); + return $sum; }; - spec.insert = function($index, $item) { - var index; - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + spec.maxItem = fn(function($function) { + var $maxValue, $maxElement; - this._ThrowIfImmutable(); + $maxValue = $nil; + $maxElement = $nil; + if ($function === $nil) { + this.do($SC.Function(function($elem) { + if ($maxElement === $nil) { + $maxElement = $elem; + } else if ($elem > $maxElement) { + $maxElement = $elem; + } + })); + } else { + this.do($SC.Function(function($elem, $i) { + var $val; + if ($maxValue === $nil) { + $maxValue = $function.value($elem, $i); + $maxElement = $elem; + } else { + $val = $function.value($elem, $i); + if ($val > $maxValue) { + $maxValue = $val; + $maxElement = $elem; + } + } + })); + } - index = Math.max(0, $index.__int__()); - this._.splice(index, 0, this.__elem__($item)); + return $maxElement; + }, "function"); - return this; - }; + spec.minItem = fn(function($function) { + var $minValue, $minElement; - spec.move = function($fromIndex, $toIndex) { - return this.insert($toIndex, this.removeAt($fromIndex)); - }; - - spec.addFirst = function($item) { - var instance, raw; - $item = utils.defaultValue$Nil($item); - - raw = this._.slice(); - raw.unshift(this.__elem__($item)); - - instance = new this.__Spec(); - instance._ = raw; - return instance; - }; - - spec.addIfNotNil = function($item) { - $item = utils.defaultValue$Nil($item); - - if ($item === $nil) { - return this; + $minValue = $nil; + $minElement = $nil; + if ($function === $nil) { + this.do($SC.Function(function($elem) { + if ($minElement === $nil) { + $minElement = $elem; + } else if ($elem < $minElement) { + $minElement = $elem; + } + })); + } else { + this.do($SC.Function(function($elem, $i) { + var $val; + if ($minValue === $nil) { + $minValue = $function.value($elem, $i); + $minElement = $elem; + } else { + $val = $function.value($elem, $i); + if ($val < $minValue) { + $minValue = $val; + $minElement = $elem; + } + } + })); } - return this.addFirst(this.__elem__($item)); - }; + return $minElement; + }, "function"); - spec.pop = function() { - if (this._.length === 0) { - return $nil; + spec.maxIndex = fn(function($function) { + var $maxValue, $maxIndex; + + $maxValue = $nil; + $maxIndex = $nil; + if ($function === $nil) { + this.do($SC.Function(function($elem, $index) { + if ($maxValue === $nil) { + $maxValue = $elem; + $maxIndex = $index; + } else if ($elem > $maxValue) { + $maxValue = $elem; + $maxIndex = $index; + } + })); + } else { + this.do($SC.Function(function($elem, $i) { + var $val; + if ($maxValue === $nil) { + $maxValue = $function.value($elem, $i); + $maxIndex = $i; + } else { + $val = $function.value($elem, $i); + if ($val > $maxValue) { + $maxValue = $val; + $maxIndex = $i; + } + } + })); } - this._ThrowIfImmutable(); - return this._.pop(); - }; - spec["++"] = function($anArray) { - var instance, raw; + return $maxIndex; + }, "function"); - raw = this._.slice(); + spec.minIndex = fn(function($function) { + var $maxValue, $minIndex; - instance = new this.__Spec(); - instance._ = raw; - if ($anArray !== $nil) { - instance.addAll($anArray); + $maxValue = $nil; + $minIndex = $nil; + if ($function === $nil) { + this.do($SC.Function(function($elem, $index) { + if ($maxValue === $nil) { + $maxValue = $elem; + $minIndex = $index; + } else if ($elem < $maxValue) { + $maxValue = $elem; + $minIndex = $index; + } + })); + } else { + this.do($SC.Function(function($elem, $i) { + var $val; + if ($maxValue === $nil) { + $maxValue = $function.value($elem, $i); + $minIndex = $i; + } else { + $val = $function.value($elem, $i); + if ($val < $maxValue) { + $maxValue = $val; + $minIndex = $i; + } + } + })); } - return instance; - }; - // TODO: implements overWrite - // TODO: implements grow - // TODO: implements growClear + return $minIndex; + }, "function"); - spec.seriesFill = function($start, $step) { - var i, imax; - $start = utils.defaultValue$Nil($start); - $step = utils.defaultValue$Nil($step); + spec.maxValue = fn(function($function) { + var $maxValue, $maxElement; - for (i = 0, imax = this._.length; i < imax; ++i) { - this.put($SC.Integer(i), $start); - $start = $start ["+"] ($step); - } + $maxValue = $nil; + $maxElement = $nil; + this.do($SC.Function(function($elem, $i) { + var $val; + if ($maxValue === $nil) { + $maxValue = $function.value($elem, $i); + $maxElement = $elem; + } else { + $val = $function.value($elem, $i); + if ($val > $maxValue) { + $maxValue = $val; + $maxElement = $elem; + } + } + })); - return this; - }; + return $maxValue; + }, "function"); - spec.fill = function($value) { - var raw, i, imax; - $value = utils.defaultValue$Nil($value); + spec.minValue = fn(function($function) { + var $minValue, $minElement; - this._ThrowIfImmutable(); + $minValue = $nil; + $minElement = $nil; + this.do($SC.Function(function($elem, $i) { + var $val; + if ($minValue === $nil) { + $minValue = $function.value($elem, $i); + $minElement = $elem; + } else { + $val = $function.value($elem, $i); + if ($val < $minValue) { + $minValue = $val; + $minElement = $elem; + } + } + })); - $value = this.__elem__($value); + return $minValue; + }, "function"); - raw = this._; - for (i = 0, imax = raw.length; i < imax; ++i) { - raw[i] = $value; - } + spec.maxSizeAtDepth = fn(function($rank) { + var rank, maxsize = 0; - return this; - }; + rank = $rank.__num__(); + if (rank === 0) { + return this.size(); + } - spec.do = function($function) { - iterator.execute( - iterator.array$do(this), - $function - ); - return this; - }; + this.do($SC.Function(function($sublist) { + var sz; + if (BOOL($sublist.isCollection())) { + sz = $sublist.maxSizeAtDepth($SC.Integer(rank - 1)); + } else { + sz = 1; + } + if (sz > maxsize) { + maxsize = sz; + } + })); - spec.reverseDo = function($function) { - iterator.execute( - iterator.array$reverseDo(this), - $function - ); - return this; - }; + return $SC.Integer(maxsize); + }, "rank"); - spec.reverse = function() { - var $res = this.copy(); + spec.maxDepth = fn(function($max) { + var $res; - $res._.reverse(); + $res = $max; + this.do($SC.Function(function($elem) { + if (BOOL($elem.isCollection())) { + $res = $res.max($elem.maxDepth($max.__inc__())); + } + })); return $res; - }; - - spec.windex = function() { - var raw = this._; - var x, r, i, imax; + }, "max=1"); - // <-- _ArrayWindex --> - x = 0; - r = rand.next(); - for (i = 0, imax = raw.length; i < imax; ++i) { - x += raw[i].__num__(); - if (x >= r) { - return $SC.Integer(i); - } + spec.deepCollect = fn(function($depth, $function, $index, $rank) { + if ($depth === $nil) { + $rank = $rank.__inc__(); + return this.collect($SC.Function(function($item, $i) { + return $item.deepCollect($depth, $function, $i, $rank); + })); + } + if ($depth.__num__() <= 0) { + return $function.value(this, $index, $rank); } + $depth = $depth.__dec__(); + $rank = $rank.__inc__(); - return $int_0; - }; + return this.collect($SC.Function(function($item, $i) { + return $item.deepCollect($depth, $function, $i, $rank); + })); + }, "depth=1; function; index=0; rank=0"); - spec.normalizeSum = function() { - return this ["*"] (this.sum().reciprocal()); - }; + spec.deepDo = fn(function($depth, $function, $index, $rank) { + if ($depth === $nil) { + $rank = $rank.__inc__(); + return this.do($SC.Function(function($item, $i) { + $item.deepDo($depth, $function, $i, $rank); + })); + } + if ($depth.__num__() <= 0) { + $function.value(this, $index, $rank); + return this; + } + $depth = $depth.__dec__(); + $rank = $rank.__inc__(); - spec.normalize = function($min, $max) { - var $minItem, $maxItem; - $min = utils.defaultValue$Float($min, 0.0); - $max = utils.defaultValue$Float($max, 1.0); + return this.do($SC.Function(function($item, $i) { + $item.deepDo($depth, $function, $i, $rank); + })); + }, "depth=1; function; index=0; rank=0"); - $minItem = this.minItem(); - $maxItem = this.maxItem(); - return this.collect($SC.Function(function($el) { - return $el.linlin($minItem, $maxItem, $min, $max); - })); - }; - - // TODO: implements asciiPlot - // TODO: implements perfectShuffle - // TODO: implements performInPlace - - spec.clipExtend = function($length) { - var last = this._[this._.length - 1] || $nil; - return this.extend($length, last); - }; + spec.invert = fn(function($axis) { + var $index; - spec.rank = function() { - return $int_1 ["+"] (this.first().rank()); - }; + if (BOOL(this.isEmpty())) { + return this.species().new(); + } + if ($axis !== $nil) { + $index = $axis ["*"] ($SC.Integer(2)); + } else { + $index = this.minItem() ["+"] (this.maxItem()); + } - spec.shape = function() { - return $SC.Array([ this.size() ]) ["++"] (this.at(0).shape()); - }; + return $index ["-"] (this); + }, "axis"); - spec.reshape = function() { + spec.sect = fn(function($that) { var $result; - var shape, size, i, imax; - - shape = slice.call(arguments); - size = 1; - for (i = 0, imax = shape.length; i < imax; ++i) { - size *= shape[i].__int__(); - } - - $result = this.flat().wrapExtend($SC.Integer(size)); - for (i = imax - 1; i >= 1; --i) { - $result = $result.clump(shape[i]); - } + $result = this.species().new(); + this.do($SC.Function(function($item) { + if (BOOL($that.includes($item))) { + $result = $result.add($item); + } + })); return $result; - }; + }, "that"); - spec.reshapeLike = function($another, $indexing) { - var $index, $flat; - $another = utils.defaultValue$Nil($another); - $indexing = utils.defaultValue$Symbol($indexing, "wrapAt"); - - $index = $int_0; - $flat = this.flat(); + spec.union = fn(function($that) { + var $result; - return $another.deepCollect($SC.Integer(0x7FFFFFFF), $SC.Function(function() { - var $item = $flat.perform($indexing, $index); - $index = $index.__inc__(); - return $item; + $result = this.copy(); + $that.do($SC.Function(function($item) { + if (!BOOL($result.includes($item))) { + $result = $result.add($item); + } })); - }; - // TODO: implements deepCollect - // TODO: implements deepDo + return $result; + }, "that"); - spec.unbubble = function($depth, $levels) { - $depth = utils.defaultValue$Integer($depth , 0); - $levels = utils.defaultValue$Integer($levels, 1); + spec.difference = fn(function($that) { + return this.copy().removeAll($that); + }, "that"); - if ($depth.__num__() <= 0) { - if (this.size().__int__() > 1) { - return this; - } - if ($levels.__int__() <= 1) { - return this.at(0); - } - return this.at(0).unbubble($depth, $levels.__dec__()); - } + spec.symmetricDifference = fn(function($that) { + var $this = this, $result; - return this.collect($SC.Function(function($item) { - return $item.unbubble($depth.__dec__()); + $result = this.species().new(); + $this.do($SC.Function(function($item) { + if (!BOOL($that.includes($item))) { + $result = $result.add($item); + } })); - }; - - spec.bubble = function($depth, $levels) { - $depth = utils.defaultValue$Integer($depth , 0); - $levels = utils.defaultValue$Integer($levels, 1); - - if ($depth.__int__() <= 0) { - if ($levels.__int__() <= 1) { - return $SC.Array([ this ]); + $that.do($SC.Function(function($item) { + if (!BOOL($this.includes($item))) { + $result = $result.add($item); } - return $SC.Array([ this.bubble($depth, $levels.__dec__()) ]); - } - - return this.collect($SC.Function(function($item) { - return $item.bubble($depth.__dec__(), $levels); })); - }; - - spec.slice = fn(function($$cuts) { - var $firstCut, $list; - var cuts_size, cuts; - - cuts_size = $$cuts.size().__int__(); - if (cuts_size === 0) { - return this.copy(); - } - - $firstCut = $$cuts.at(0); - if ($firstCut === $nil) { - $list = this.copy(); - } else { - $list = this.at($firstCut.asArray()); - } - if (cuts_size === 1) { - return $list.unbubble(); - } - - cuts = $$cuts._.slice(1); - return $list.collect($SC.Function(function($item) { - return $item.slice.apply($item, cuts); - })).unbubble(); - }, "*cuts"); - - spec.$iota = function() { - var $a; - var args, product, i, imax, a; - - args = arguments; + return $result; + }, "that"); - product = 1; - for (i = 0, imax = args.length; i < imax; ++i) { - product *= args[i].__int__(); - } + spec.isSubsetOf = fn(function($that) { + return $that.includesAll(this); + }, "that"); - a = new Array(product); - for (i = 0; i < product; ++i) { - a[i] = $SC.Integer(i); - } + spec.asArray = function() { + return SCArray.new(this.size()).addAll(this); + }; - $a = $SC.Array(a); - return $a.reshape.apply($a, args); + spec.asBag = function() { + return $SC("Bag").new(this.size()).addAll(this); }; - // TODO: implements asRandomTable - // TODO: implements tableRand - // TODO: implements msgSize - // TODO: implements bundleSize - // TODO: implements clumpBundles + spec.asList = function() { + return $SC("List").new(this.size()).addAll(this); + }; - spec.includes = function($item) { - return $SC.Boolean(this._.indexOf($item) !== -1); + spec.asSet = function() { + return $SC("Set").new(this.size()).addAll(this); }; - }); - sc.lang.klass.refine("RawArray", function(spec, utils) { - spec.archiveAsCompileString = utils.alwaysReturn$true; - spec.archiveAsObject = utils.alwaysReturn$true; - spec.rate = function() { - return $SC.Symbol("scalar"); + spec.asSortedList = function($function) { + return $SC("SortedList").new(this.size(), $function).addAll(this); }; - // TODO: implements readFromStream // TODO: implements powerset + // TODO: implements flopDict + // TODO: implements histo + // TODO: implements printAll + // TODO: implements printcsAll + // TODO: implements dumpAll + // TODO: implements printOn + // TODO: implements storeOn + // TODO: implements storeItemsOn + // TODO: implements printItemsOn + // TODO: implements writeDef + // TODO: implements writeInputSpec + // TODO: implements case + // TODO: implements makeEnvirValPairs }); })(sc); -// src/sc/lang/classlib/Collections/String.js +// src/sc/lang/classlib/Collections/SequenceableCollection.js (function(sc) { - var $SC = sc.lang.$SC; + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - sc.lang.klass.refine("String", function(spec, utils) { + sc.lang.klass.refine("SequenceableCollection", function(spec, utils) { + var BOOL = utils.BOOL; var $nil = utils.$nil; + var $true = utils.$true; var $false = utils.$false; + var $int_0 = utils.$int_0; + var $int_1 = utils.$int_1; - spec.__str__ = function() { - return this.valueOf(); - }; - - spec.__elem__ = function($item) { - if ($item.__tag !== 1028) { - throw new TypeError("Wrong type."); - } - return $item; + spec["|@|"] = function($index) { + return this.clipAt($index); }; - spec.valueOf = function() { - return this._.map(function(elem) { - return elem.__str__(); - }).join(""); + spec["@@"] = function($index) { + return this.wrapAt($index); }; - spec.toString = function() { - return this.valueOf(); + spec["@|@"] = function($index) { + return this.foldAt($index); }; - // TODO: implements unixCmdActions - // TODO: implements unixCmdActions_ + spec.$series = fn(function($size, $start, $step) { + var $obj, i, imax; - spec.$new = function() { - throw new Error("String.new is illegal, should use literal."); - }; + $obj = this.new($size); + for (i = 0, imax = $size.__int__(); i < imax; ++i) { + $obj.add($start ["+"] ($step ["*"] ($SC.Integer(i)))); + } - // TODO: implements $initClass - // TODO: implements $doUnixCmdAction - // TODO: implements unixCmd - // TODO: implements unixCmdGetStdOut + return $obj; + }, "size; start=0; step=1"); - spec.asSymbol = function() { - return $SC.Symbol(this.__str__()); - }; + spec.$geom = fn(function($size, $start, $grow) { + var $obj, i, imax; - spec.asInteger = function() { - var m = /^[-+]?\d+/.exec(this.__str__()); - return $SC.Integer(m ? m[0]|0 : 0); - }; + $obj = this.new($size); + for (i = 0, imax = $size.__int__(); i < imax; ++i) { + $obj.add($start); + $start = $start ["*"] ($grow); + } - spec.asFloat = function() { - var m = /^[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/.exec(this.__str__()); - return $SC.Float(m ? +m[0] : 0); - }; + return $obj; + }, "size; start; grow"); - spec.ascii = function() { - var raw = this.__str__(); - var a, i, imax; + spec.$fib = fn(function($size, $a, $b) { + var $obj, $temp, i, imax; - a = new Array(raw.length); - for (i = 0, imax = a.length; i < imax; ++i) { - a[i] = $SC.Integer(raw.charCodeAt(i)); + $obj = this.new($size); + for (i = 0, imax = $size.__int__(); i < imax; ++i) { + $obj.add($b); + $temp = $b; + $b = $a ["+"] ($b); + $a = $temp; } - return $SC.Array(a); - }; + return $obj; + }, "size; a=0.0; b=1.0"); - // TODO: implements stripRTF - // TODO: implements stripHTML - // TODO: implements $scDir + // TODO: implements $rand + // TODO: implements $rand2 + // TODO: implements $linrand - spec.compare = function($aString, $ignoreCase) { - var araw, braw, length, i, a, b, cmp, fn; - $aString = utils.defaultValue$Nil($aString); - $ignoreCase = utils.defaultValue$Boolean($ignoreCase, false); + spec.$interpolation = fn(function($size, $start, $end) { + var $obj, $step, i, imax; - if ($aString.__tag !== 1034) { - return $nil; + $obj = this.new($size); + if ($size.__int__() === 1) { + return $obj.add($start); } - araw = this._; - braw = $aString._; - length = Math.min(araw.length, braw.length); - - if ($ignoreCase.__bool__()) { - fn = function(ch) { - return ch.toLowerCase(); - }; - } else { - fn = function(ch) { - return ch; - }; - } - for (i = 0; i < length; i++) { - a = fn(araw[i]._).charCodeAt(0); - b = fn(braw[i]._).charCodeAt(0); - cmp = a - b; - if (cmp !== 0) { - return $SC.Integer(cmp < 0 ? -1 : +1); - } + $step = ($end ["-"] ($start)) ["/"] ($size.__dec__()); + for (i = 0, imax = $size.__int__(); i < imax; ++i) { + $obj.add($start ["+"] ($SC.Integer(i) ["*"] ($step))); } - if (araw.length < braw.length) { - cmp = -1; - } else if (araw.length > braw.length) { - cmp = 1; - } + return $obj; + }, "size; start=0.0; end=1.0"); - return $SC.Integer(cmp); - }; + spec["++"] = function($aSequenceableCollection) { + var $newlist; - spec["<"] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() < 0 - ); - }; + $newlist = this.species().new(this.size() ["+"] ($aSequenceableCollection.size())); + $newlist = $newlist.addAll(this).addAll($aSequenceableCollection); - spec[">"] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() > 0 - ); + return $newlist; }; - spec["<="] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() <= 0 - ); - }; + // TODO: implements +++ - spec[">="] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() >= 0 - ); - }; + spec.asSequenceableCollection = utils.nop; - spec["=="] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() === 0 - ); + spec.choose = function() { + return this.at(this.size().rand()); }; - spec["!="] = function($aString) { - return $SC.Boolean( - this.compare($aString, $false).valueOf() !== 0 - ); + spec.wchoose = fn(function($weights) { + return this.at($weights.windex()); + }, "weights"); + + spec["=="] = function($aCollection) { + var $res = null; + + if ($aCollection.class() !== this.class()) { + return $false; + } + if (this.size() !== $aCollection.size()) { + return $false; + } + this.do($SC.Function(function($item, $i) { + if (BOOL($item ["!="] ($aCollection.at($i)))) { + $res = $false; + return 65535; + } + })); + + return $res || $true; }; // TODO: implements hash - spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber) { - $aNumber = utils.defaultValue$Nil($aNumber); - return $aNumber.asString().perform($aSelector, this); - }; + spec.copyRange = fn(function($start, $end) { + var $newColl, i, end; - spec.performBinaryOpOnComplex = function($aSelector, $aComplex) { - $aComplex = utils.defaultValue$Nil($aComplex); - return $aComplex.asString().perform($aSelector, this); - }; + i = $start.__int__(); + end = $end.__int__(); + $newColl = this.species().new($SC.Integer(end - i)); + while (i <= end) { + $newColl.add(this.at($SC.Integer(i++))); + } - spec.multiChannelPerform = function() { - throw new Error("String:multiChannelPerform. Cannot expand strings."); - }; + return $newColl; + }, "start; end"); - spec.isString = utils.alwaysReturn$true; + spec.keep = fn(function($n) { + var n, size; - spec.asString = utils.nop; + n = $n.__int__(); + if (n >= 0) { + return this.copyRange($int_0, $SC.Integer(n - 1)); + } + size = this.size().__int__(); - spec.asCompileString = function() { - return $SC.String("\"" + this.__str__() + "\""); - }; + return this.copyRange($SC.Integer(size + n), $SC.Integer(size - 1)); + }, "n"); - spec.species = function() { - return $SC("String"); - }; + spec.drop = fn(function($n) { + var n, size; - // TODO: implements postln - // TODO: implements post - // TODO: implements postcln - // TODO: implements postc - // TODO: implements postf - // TODO: implements format - // TODO: implements matchRegexp - // TODO: implements fformat - // TODO: implements die - // TODO: implements error - // TODO: implements warn - // TODO: implements inform + n = $n.__int__(); + size = this.size().__int__(); + if (n >= 0) { + return this.copyRange($n, $SC.Integer(size - 1)); + } - spec["++"] = function($anObject) { - return $SC.String( - this.toString() + $anObject.asString().toString() - ); - }; + return this.copyRange($int_0, $SC.Integer(size + n - 1)); + }, "n"); - spec["+"] = function($anObject) { - return $SC.String( - this.toString() + " " + $anObject.asString().toString() - ); - }; + spec.copyToEnd = fn(function($start) { + return this.copyRange($start, $SC.Integer(this.size().__int__() - 1)); + }, "start"); - // TODO: implements catArgs - // TODO: implements scatArgs - // TODO: implements ccatArgs - // TODO: implements catList - // TODO: implements scatList - // TODO: implements ccatList - // TODO: implements split - // TODO: implements containsStringAt - // TODO: implements icontainsStringAt - // TODO: implements contains - // TODO: implements containsi - // TODO: implements findRegexp - // TODO: implements findAllRegexp - // TODO: implements find - // TODO: implements findBackwards - // TODO: implements endsWith - // TODO: implements beginsWith - // TODO: implements findAll - // TODO: implements replace - // TODO: implements escapeChar - // TODO: implements shellQuote - // TODO: implements quote - // TODO: implements tr - // TODO: implements insert - // TODO: implements wrapExtend - // TODO: implements zeroPad - // TODO: implements padLeft - // TODO: implements padRight - // TODO: implements underlined - // TODO: implements scramble - // TODO: implements rotate - // TODO: implements compile - // TODO: implements interpret - // TODO: implements interpretPrint - // TODO: implements $readNew - // TODO: implements printOn - // TODO: implements storeOn - // TODO: implements inspectorClass - // TODO: implements standardizePath - // TODO: implements realPath - // TODO: implements withTrailingSlash - // TODO: implements withoutTrailingSlash - // TODO: implements absolutePath - // TODO: implements pathMatch - // TODO: implements load - // TODO: implements loadPaths - // TODO: implements loadRelative - // TODO: implements resolveRelative - // TODO: implements include - // TODO: implements exclude - // TODO: implements basename - // TODO: implements dirname - // TODO: implements splittext - // TODO: implements +/+ - // TODO: implements asRelativePath - // TODO: implements asAbsolutePath - // TODO: implements systemCmd - // TODO: implements gethostbyname - // TODO: implements getenv - // TODO: implements setenv - // TODO: implements unsetenv - // TODO: implements codegen_UGenCtorArg - // TODO: implements ugenCodeString - // TODO: implements asSecs - // TODO: implements speak - // TODO: implements toLower - // TODO: implements toUpper - // TODO: implements mkdir - // TODO: implements parseYAML - // TODO: implements parseYAMLFile - }); + spec.copyFromStart = fn(function($end) { + return this.copyRange($int_0, $end); + }, "end"); -})(sc); + spec.indexOf = fn(function($item) { + var $ret = null; -// src/sc/lang/classlib/Collections/Set.js -(function(sc) { + this.do($SC.Function(function($elem, $i) { + if ($item === $elem) { + $ret = $i; + return 65535; + } + })); - function SCSet() { - this.__initializeWith__("Collection"); - } + return $ret || $nil; + }, "item"); - sc.lang.klass.define(SCSet, "Set : Collection", function() { - // TODO: implements species - // TODO: implements copy - // TODO: implements do - // TODO: implements clear - // TODO: implements makeEmpty - // TODO: implements includes - // TODO: implements findMatch - // TODO: implements add - // TODO: implements remove - // TODO: implements choose - // TODO: implements pop - // TODO: implements powerset - // TODO: implements unify - // TODO: implements sect - // TODO: implements union - // TODO: implements difference - // TODO: implements symmetricDifference - // TODO: implements isSubsetOf - // TODO: implements initSet - // TODO: implements putCheck - // TODO: implements fullCheck - // TODO: implements grow - // TODO: implements noCheckAdd - // TODO: implements scanFor - // TODO: implements fixCollisionsFrom - // TODO: implements keyAt - // TODO: implements asSet - }); - -})(sc); - -// src/sc/lang/classlib/Collections/Dictionary.js -(function(sc) { - - function SCDictionary() { - this.__initializeWith__("Set"); - this._ = {}; - } - - sc.lang.klass.define(SCDictionary, "Dictionary : Set", function() { - // TODO: implements $newFrom - // TODO: implements at - // TODO: implements atFail - // TODO: implements matchAt - // TODO: implements trueAt - // TODO: implements add - // TODO: implements put - // TODO: implements putAll - // TODO: implements putPairs - // TODO: implements getPairs - // TODO: implements associationAt - // TODO: implements associationAtFail - // TODO: implements keys - // TODO: implements values - // TODO: implements includes - // TODO: implements includesKey - // TODO: implements removeAt - // TODO: implements removeAtFail - // TODO: implements remove - // TODO: implements removeFail - // TODO: implements keysValuesDo - // TODO: implements keysValuesChange - // TODO: implements do - // TODO: implements keysDo - // TODO: implements associationsDo - // TODO: implements pairsDo - // TODO: implements collect - // TODO: implements select - // TODO: implements reject - // TODO: implements invert - // TODO: implements merge - // TODO: implements blend - // TODO: implements findKeyForValue - // TODO: implements sortedKeysValuesDo - // TODO: implements choose - // TODO: implements order - // TODO: implements powerset - // TODO: implements transformEvent - // TODO: implements embedInStream - // TODO: implements asSortedArray - // TODO: implements asKeyValuePairs - // TODO: implements keysValuesArrayDo - // TODO: implements grow - // TODO: implements fixCollisionsFrom - // TODO: implements scanFor - // TODO: implements storeItemsOn - // TODO: implements printItemsOn - }); - - function SCIdentityDictionary() { - this.__initializeWith__("Dictionary"); - } - - sc.lang.klass.define(SCIdentityDictionary, "IdentityDictionary : Dictionary", function() { - // TODO: implements at - // TODO: implements put - // TODO: implements putGet - // TODO: implements includesKey - // TODO: implements findKeyForValue - // TODO: implements scanFor - // TODO: implements freezeAsParent - // TODO: implements insertParent - // TODO: implements storeItemsOn - // TODO: implements doesNotUnderstand - // TODO: implements nextTimeOnGrid - // TODO: implements asQuant - // TODO: implements timingOffset - }); - -})(sc); + spec.indicesOfEqual = fn(function($item) { + var indices = []; -// src/sc/lang/classlib/Collections/Environment.js -(function(sc) { + this.do($SC.Function(function($elem, $i) { + if ($item === $elem) { + indices.push($i); + } + })); - function SCEnvironment() { - this.__initializeWith__("IdentityDictionary"); - } + return indices.length ? $SC.Array(indices) : $nil; + }, "item"); - sc.lang.klass.define(SCEnvironment, "Environment : IdentityDictionary", function() { - // TODO: implements $make - // TODO: implements $use - // TODO: implements make - // TODO: implements use - // TODO: implements eventAt - // TODO: implements composeEvents - // TODO: implements $pop - // TODO: implements $push - // TODO: implements pop - // TODO: implements push - // TODO: implements linkDoc - // TODO: implements unlinkDoc - }); + spec.find = fn(function($sublist, $offset) { + var $subSize_1, $first, $index; + var size, offset, i, imax; -})(sc); + $subSize_1 = $sublist.size().__dec__(); + $first = $sublist.first(); -// src/sc/lang/classlib/Collections/Event.js -(function(sc) { + size = this.size().__int__(); + offset = $offset.__int__(); + for (i = 0, imax = size - offset; i < imax; ++i) { + $index = $SC.Integer(i + offset); + if (BOOL(this.at($index) ["=="] ($first))) { + if (BOOL(this.copyRange($index, $index ["+"] ($subSize_1)) ["=="] ($sublist))) { + return $index; + } + } + } - function SCEvent() { - this.__initializeWith__("Environment"); - } + return $nil; + }, "sublist; offset=0"); - sc.lang.klass.define(SCEvent, "Event : Environment", function() { - // TODO: implements $default - // TODO: implements $silent - // TODO: implements $addEventType - // TODO: implements next - // TODO: implements delta - // TODO: implements play - // TODO: implements isRest - // TODO: implements isPlaying_ - // TODO: implements isRunning_ - // TODO: implements playAndDelta - // TODO: implements synchWithQuant - // TODO: implements asControlInput - // TODO: implements asUGenInput - // TODO: implements printOn - // TODO: implements storeOn - // TODO: implements $initClass - // TODO: implements $makeDefaultSynthDef - // TODO: implements $makeParentEvents - }); + spec.findAll = fn(function($arr, $offset) { + var $this = this, $indices, $i; -})(sc); + $indices = $nil; + $i = $int_0; -// src/sc/lang/classlib/Collections/Array.js -(function(sc) { + while (($i = $this.find($arr, $offset)) !== $nil) { + $indices = $indices.add($i); + $offset = $i.__inc__(); + } - var slice = [].slice; - var $SC = sc.lang.$SC; - var rand = sc.libs.random; - var mathlib = sc.libs.mathlib; + return $indices; + }, "arr; offset=0"); - sc.lang.klass.refine("Array", function(spec, utils) { - var BOOL = utils.BOOL; - var SCArray = $SC("Array"); + spec.indexOfGreaterThan = fn(function($val) { + return this.detectIndex($SC.Function(function($item) { + return $SC.Boolean($item > $val); + })); + }, "val"); - spec.$with = function() { - return $SC.Array(slice.call(arguments)); - }; + spec.indexIn = fn(function($val) { + var $i, $j; - spec.reverse = function() { - // <-- _ArrayReverse --> - return $SC.Array(this._.slice().reverse()); - }; + $j = this.indexOfGreaterThan($val); + if ($j === $nil) { + return this.size().__dec__(); + } + if ($j === $int_0) { + return $j; + } - spec.scramble = function() { - var a, tmp, i, j, m; + $i = $j.__dec__(); - // <-- _ArrayScramble --> - a = this._.slice(); - m = a.length; - if (m > 1) { - for (i = 0; m > 0; ++i, --m) { - j = i + (rand.next() * m)|0; - tmp = a[i]; - a[i] = a[j]; - a[j] = tmp; - } + if ($val ["-"] (this.at($i)) < this.at($j) ["-"] ($val)) { + return $i; } - return $SC.Array(a); - }; + return $j; + }, "val"); - spec.mirror = function() { - var raw = this._; - var size, i, j, imax, a; + spec.indexInBetween = fn(function($val) { + var $a, $b, $div, $i; - // <-- _ArrayMirror --> - size = raw.length * 2 - 1; - if (size < 2) { - return $SC.Array(raw.slice(0)); + if (BOOL(this.isEmpty())) { + return $nil; } + $i = this.indexOfGreaterThan($val); - a = new Array(size); - for (i = 0, imax = raw.length; i < imax; ++i) { - a[i] = raw[i]; + if ($i === $nil) { + return this.size().__dec__(); } - for (j = imax - 2, imax = size; i < imax; ++i, --j) { - a[i] = raw[j]; + if ($i === $int_0) { + return $i; } - return $SC.Array(a); - }; + $a = this.at($i.__dec__()); + $b = this.at($i); + $div = $b ["-"] ($a); - spec.mirror1 = function() { - var raw = this._; - var size, i, j, imax, a; + // if (BOOL($div ["=="] ($int_0))) { + // return $i; + // } - // <-- _ArrayMirror1 --> - size = raw.length * 2 - 2; - if (size < 2) { - return $SC.Array(raw.slice(0)); + return (($val ["-"] ($a)) ["/"] ($div)) ["+"] ($i.__dec__()); + }, "val"); + + spec.isSeries = fn(function($step) { + var $res = null; + + if (this.size() <= 1) { + return $true; } + this.doAdjacentPairs($SC.Function(function($a, $b) { + var $diff = $b ["-"] ($a); + if ($step === $nil) { + $step = $diff; + } else if (BOOL($step ["!="] ($diff))) { + $res = $false; + return 65535; + } + })); - a = new Array(size); - for (i = 0, imax = raw.length; i < imax; ++i) { - a[i] = raw[i]; + return $res || $true; + }, "step"); + + spec.resamp0 = fn(function($newSize) { + var $this = this, $factor; + + $factor = ( + this.size().__dec__() + ) ["/"] ( + ($newSize.__dec__()).max($int_1) + ); + + return this.species().fill($newSize, $SC.Function(function($i) { + return $this.at($i ["*"] ($factor).round($SC.Float(1.0)).asInteger()); + })); + }, "newSize"); + + spec.resamp1 = fn(function($newSize) { + var $this = this, $factor; + + $factor = ( + this.size().__dec__() + ) ["/"] ( + ($newSize.__dec__()).max($int_1) + ); + + return this.species().fill($newSize, $SC.Function(function($i) { + return $this.blendAt($i ["*"] ($factor)); + })); + }, "newSize"); + + spec.remove = fn(function($item) { + var $index; + + $index = this.indexOf($item); + if ($index !== $nil) { + return this.removeAt($index); } - for (j = imax - 2, imax = size; i < imax; ++i, --j) { - a[i] = raw[j]; + + return $nil; + }, "item"); + + spec.removing = fn(function($item) { + var $coll; + + $coll = this.copy(); + $coll.remove($item); + + return $coll; + }, "item"); + + spec.take = fn(function($item) { + var $index; + + $index = this.indexOf($item); + if ($index !== $nil) { + return this.takeAt($index); } - return $SC.Array(a); + return $nil; + }, "item"); + + spec.lastIndex = function() { + var size = this.size().__int__(); + + if (size > 0) { + return $SC.Integer(size - 1); + } + + return $nil; }; - spec.mirror2 = function() { - var raw = this._; - var size, i, j, imax, a; + spec.middleIndex = function() { + var size = this.size().__int__(); - // <-- _ArrayMirror2 --> - size = raw.length * 2; - if (size < 2) { - return $SC.Array(raw.slice(0)); + if (size > 0) { + return $SC.Integer((size - 1) >> 1); } - a = new Array(size); - for (i = 0, imax = raw.length; i < imax; ++i) { - a[i] = raw[i]; + return $nil; + }; + + spec.first = function() { + var size = this.size().__int__(); + + if (size > 0) { + return this.at($int_0); } - for (j = imax - 1, imax = size; i < imax; ++i, --j) { - a[i] = raw[j]; + + return $nil; + }; + + spec.last = function() { + var size = this.size().__int__(); + + if (size > 0) { + return this.at($SC.Integer(size - 1)); } - return $SC.Array(a); + return $nil; }; - spec.stutter = function($n) { - var raw = this._; - var n, a, i, j, imax, k; - $n = utils.defaultValue$Integer($n, 2); + spec.middle = function() { + var size = this.size().__int__(); - // <-- _ArrayStutter --> - n = Math.max(0, $n.__int__()); - a = new Array(raw.length * n); - for (i = 0, j = 0, imax = raw.length; i < imax; ++i) { - for (k = 0; k < n; ++k, ++j) { - a[j] = raw[i]; - } + if (size > 0) { + return this.at($SC.Integer((size - 1) >> 1)); } - return $SC.Array(a); + return $nil; }; - spec.rotate = function($n) { - var raw = this._; - var n, a, size, i, j; - $n = utils.defaultValue$Integer($n, 1); + spec.top = function() { + return this.last(); + }; - // <-- _ArrayRotate --> - n = $n.__int__(); - a = new Array(raw.length); - size = a.length; - n %= size; - if (n < 0) { - n += size; + spec.putFirst = fn(function($obj) { + var size = this.size().__int__(); + + if (size > 0) { + return this.put($int_0, $obj); } - for (i = 0, j = n; i < size; ++i) { - a[j] = raw[i]; - if (++j >= size) { - j = 0; - } + + return this; + }, "obj"); + + spec.putLast = fn(function($obj) { + var size = this.size().__int__(); + + if (size > 0) { + return this.put($SC.Integer(size - 1), $obj); } - return $SC.Array(a); + return this; + }, "obj"); + + spec.obtain = fn(function($index, $default) { + var $res; + + $res = this.at($index); + if ($res === $nil) { + $res = $default; + } + + return $res; + }, "index; default"); + + spec.instill = fn(function($index, $item, $default) { + var $res; + + if ($index.__num__() >= this.size()) { + $res = this.extend($index.__inc__(), $default); + } else { + $res = this.copy(); + } + + return $res.put($index, $item); + }, "index; item; default"); + + spec.pairsDo = function($function) { + var $this = this, $int2 = $SC.Integer(2); + + $int_0.forBy(this.size() ["-"] ($int2), $int2, $SC.Function(function($i) { + return $function.value($this.at($i), $this.at($i.__inc__()), $i); + })); + + return this; }; - spec.pyramid = function($patternType) { - var patternType; - var obj1, obj2, i, j, k, n, numslots, x; - $patternType = utils.defaultValue$Integer($patternType, 1); + spec.keysValuesDo = function($function) { + return this.pairsDo($function); + }; - obj1 = this._; - obj2 = []; + spec.doAdjacentPairs = function($function) { + var $i; + var size, i, imax; - patternType = Math.max(1, Math.min($patternType.__int__(), 10)); - x = numslots = obj1.length; + size = this.size().__int__(); + for (i = 0, imax = size - 1; i < imax; ++i) { + $i = $SC.Integer(i); + $function.value(this.at($i), this.at($i.__inc__()), $i); + } - switch (patternType) { - case 1: - n = (x * x + x) >> 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = 0; j <= i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 2: - n = (x * x + x) >> 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } + return this; + }; + + spec.separate = fn(function($function) { + var $this = this, $list, $sublist; + + $list = $SC.Array(); + $sublist = this.species().new(); + this.doAdjacentPairs($SC.Function(function($a, $b, $i) { + $sublist = $sublist.add($a); + if (BOOL($function.value($a, $b, $i))) { + $list = $list.add($sublist); + $sublist = $this.species().new(); } - break; - case 3: - n = (x * x + x) >> 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = 0; j <= numslots - 1 - i; ++j, ++k) { - obj2[k] = obj1[j]; - } + })); + if (BOOL(this.notEmpty())) { + $sublist = $sublist.add(this.last()); + } + $list = $list.add($sublist); + + return $list; + }, "function=true"); + + spec.delimit = function($function) { + var $this = this, $list, $sublist; + + $list = $SC.Array(); + $sublist = this.species().new(); + this.do($SC.Function(function($item, $i) { + if (BOOL($function.value($item, $i))) { + $list = $list.add($sublist); + $sublist = $this.species().new(); + } else { + $sublist = $sublist.add($item); } - break; - case 4: - n = (x * x + x) >> 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 5: - n = x * x; - for (i = k = 0; i < numslots; ++i) { - for (j = 0; j <= i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 0; i < numslots - 1; ++i) { - for (j = 0; j <= numslots - 2 - i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 6: - n = x * x; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 0; i < numslots - 1; ++i) { - for (j = i + 1; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 7: - n = x * x + x - 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = 0; j <= numslots - 1 - i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 1; i < numslots; ++i) { - for (j = 0; j <= i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 8: - n = x * x + x - 1; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 1; i < numslots; ++i) { - for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 9: - n = x * x; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = 0; j <= i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 0; i < numslots - 1; ++i) { - for (j = i + 1; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - case 10: - n = x * x; - for (i = 0, k = 0; i < numslots; ++i) { - for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - for (i = 0; i < numslots - 1; ++i) { - for (j = 0; j <= numslots - 2 - i; ++j, ++k) { - obj2[k] = obj1[j]; - } - } - break; - } + })); + $list = $list.add($sublist); - return $SC.Array(obj2); + return $list; }; - spec.pyramidg = function($patternType) { - var raw = this._; - var patternType; - var list = [], lastIndex, i; - $patternType = utils.defaultValue$Integer($patternType, 1); - - patternType = Math.max(1, Math.min($patternType.__int__(), 10)); - lastIndex = raw.length - 1; + spec.clump = fn(function($groupSize) { + var $this = this, $list, $sublist; - switch (patternType) { - case 1: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - break; - case 2: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); - } - break; - case 3: - for (i = lastIndex; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - break; - case 4: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex + 1))); - } - break; - case 5: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - for (i = lastIndex - 1; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - break; - case 6: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); - } - for (i = lastIndex - 1; i >= 0; --i) { - list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); - } - break; - case 7: - for (i = lastIndex; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - for (i = 1; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - break; - case 8: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex + 1))); - } - for (i = lastIndex - 1; i >= 0; --i) { - list.push($SC.Array(raw.slice(i, lastIndex + 1))); - } - break; - case 9: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i + 1))); - } - for (i = 1; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex + 1))); - } - break; - case 10: - for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); - } - for (i = lastIndex - 1; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i + 1))); + $list = $SC.Array(); + $sublist = this.species().new($groupSize); + this.do($SC.Function(function($item) { + $sublist.add($item); + if ($sublist.size() >= $groupSize) { + $list.add($sublist); + $sublist = $this.species().new($groupSize); } - break; + })); + if ($sublist.size() > 0) { + $list = $list.add($sublist); } - return $SC.Array(list); - }; + return $list; + }, "groupSize"); - spec.sputter = function($probability, $maxlen) { - var list, prob, maxlen, i, length; - $probability = utils.defaultValue$Float($probability, 0.25); - $maxlen = utils.defaultValue$Float($maxlen, 100); + spec.clumps = fn(function($groupSizeList) { + var $this = this, $list, $subSize, $sublist, i = 0; - list = []; - prob = 1.0 - $probability.__num__(); - maxlen = $maxlen.__int__(); - i = 0; - length = this._.length; - while (i < length && list.length < maxlen) { - list.push(this._[i]); - if (rand.next() < prob) { - i += 1; + $list = $SC.Array(); + $subSize = $groupSizeList.at($int_0); + $sublist = this.species().new($subSize); + this.do($SC.Function(function($item) { + $sublist = $sublist.add($item); + if ($sublist.size() >= $subSize) { + $list = $list.add($sublist); + $subSize = $groupSizeList.wrapAt($SC.Integer(++i)); + $sublist = $this.species().new($subSize); } + })); + if ($sublist.size() > 0) { + $list = $list.add($sublist); } - return $SC.Array(list); - }; + return $list; + }, "groupSizeList"); - spec.lace = function($length) { - var raw = this._; - var length, wrap = raw.length; - var a, i, $item; - $length = utils.defaultValue$Integer($length, wrap); + spec.curdle = fn(function($probability) { + return this.separate($SC.Function(function() { + return $probability.coin(); + })); + }, "probability"); - length = $length.__int__(); - a = new Array(length); + spec.flatten = fn(function($numLevels) { + return this._flatten($numLevels.__num__()); + }, "numLevels=1"); - for (i = 0; i < length; ++i) { - $item = raw[i % wrap]; - if (Array.isArray($item._)) { - a[i] = $item._[ ((i / wrap)|0) % $item._.length ]; + spec._flatten = fn(function(numLevels) { + var $list; + + if (numLevels <= 0) { + return this; + } + numLevels = numLevels - 1; + + $list = this.species().new(); + this.do($SC.Function(function($item) { + if ($item._flatten) { + $list = $list.addAll($item._flatten(numLevels)); } else { - a[i] = $item; + $list = $list.add($item); } - } + })); - return $SC.Array(a); + return $list; + }, "numLevels"); + + spec.flat = function() { + return this._flat(this.species().new(this.flatSize())); }; - spec.permute = function($nthPermutation) { - var raw = this._; - var obj1, obj2, size, $item; - var nthPermutation, i, imax, j; - $nthPermutation = utils.defaultValue$Integer($nthPermutation, 0); + spec._flat = fn(function($list) { + this.do($SC.Function(function($item) { + if ($item._flat) { + $list = $item._flat($list); + } else { + $list = $list.add($item); + } + })); + return $list; + }, "list"); - obj1 = raw; - obj2 = raw.slice(); - size = raw.length; - nthPermutation = $nthPermutation.__int__(); + spec.flatIf = fn(function($func) { + return this._flatIf($func); + }, "func"); - for (i = 0, imax = size - 1; i < imax; ++i) { - j = i + nthPermutation % (size - i); - nthPermutation = (nthPermutation / (size - i))|0; + spec._flatIf = function($func) { + var $list; - $item = obj2[i]; - obj2[i] = obj2[j]; - obj2[j] = $item; - } + $list = this.species().new(this.size()); + this.do($SC.Function(function($item, $i) { + if ($item._flatIf && BOOL($func.value($item, $i))) { + $list = $list.addAll($item._flatIf($func)); + } else { + $list = $list.add($item); + } + })); - return $SC.Array(obj2); + return $list; }; - spec.allTuples = function($maxTuples) { - var maxSize; - var obj1, obj2, obj3, obj4, newSize, tupSize; - var i, j, k; - $maxTuples = utils.defaultValue$Integer($maxTuples, 16384); - - maxSize = $maxTuples.__int__(); + spec.flop = function() { + var $this = this, $list, $size, $maxsize; - obj1 = this._; - newSize = 1; - tupSize = obj1.length; - for (i = 0; i < tupSize; ++i) { - if (Array.isArray(obj1[i]._)) { - newSize *= obj1[i]._.length; + $size = this.size(); + $maxsize = $int_0; + this.do($SC.Function(function($sublist) { + var $sz; + if (BOOL($sublist.isSequenceableCollection())) { + $sz = $sublist.size(); + } else { + $sz = $int_1; } - } - newSize = Math.min(newSize, maxSize); + if ($sz > $maxsize) { + $maxsize = $sz; + } + })); - obj2 = new Array(newSize); + $list = this.species().fill($maxsize, $SC.Function(function() { + return $this.species().new($size); + })); - for (i = 0; i < newSize; ++i) { - k = i; - obj3 = new Array(tupSize); - for (j = tupSize - 1; j >= 0; --j) { - if (Array.isArray(obj1[j]._)) { - obj4 = obj1[j]._; - obj3[j] = obj4[k % obj4.length]; - k = (k / obj4.length)|0; - } else { - obj3[j] = obj1[j]; - } + this.do($SC.Function(function($isublist) { + if (BOOL($isublist.isSequenceableCollection())) { + $list.do($SC.Function(function($jsublist, $j) { + $jsublist.add($isublist.wrapAt($j)); + })); + } else { + $list.do($SC.Function(function($jsublist) { + $jsublist.add($isublist); + })); } - obj2[i] = $SC.Array(obj3); - } + })); - return $SC.Array(obj2); + return $list; }; - spec.wrapExtend = function($size) { - var raw = this._; - var size, a, i; - $size = utils.defaultValue$Nil($size); + spec.flopWith = fn(function($func) { + var $this = this, $maxsize; - size = Math.max(0, $size.__int__()); - if (raw.length < size) { - a = new Array(size); - for (i = 0; i < size; ++i) { - a[i] = raw[i % raw.length]; + $maxsize = this.maxValue($SC.Function(function($sublist) { + if (BOOL($sublist.isSequenceableCollection())) { + return $sublist.size(); } - } else { - a = raw.slice(0, size); - } - - return $SC.Array(a); - }; + return $int_1; + })); - spec.foldExtend = function($size) { - var raw = this._; - var size, a, i; - $size = utils.defaultValue$Nil($size); + return this.species().fill($maxsize, $SC.Function(function($i) { + return $func.valueArray($this.collect($SC.Function(function($sublist) { + if (BOOL($sublist.isSequenceableCollection())) { + return $sublist.wrapAt($i); + } else { + return $sublist; + } + }))); + })); + }, "func"); - size = Math.max(0, $size.__int__()); + // TODO: implements flopTogether + // TODO: implements flopDeep + // TODO: implements wrapAtDepth + // TODO: implements unlace + // TODO: implements integrate + // TODO: implements differentiate + // TODO: implements convertDigits + // TODO: implements hammingDistance + // TODO: implements degreeToKey + // TODO: implements keyToDegree + // TODO: implements nearestInScale + // TODO: implements nearestInList + // TODO: implements transposeKey + // TODO: implements mode + // TODO: implements performDegreeToKey + // TODO: implements performNearestInList + // TODO: implements performNearestInScale + // TODO: implements convertRhythm + // TODO: implements sumRhythmDivisions + // TODO: implements convertOneRhythm - if (raw.length < size) { - a = new Array(size); - for (i = 0; i < size; ++i) { - a[i] = raw[mathlib.fold_idx(i, raw.length)]; - } - } else { - a = raw.slice(0, size); - } + spec.isSequenceableCollection = utils.alwaysReturn$true; - return $SC.Array(a); + spec.containsSeqColl = function() { + return this.any($SC.Function(function($_) { + return $_.isSequenceableCollection(); + })); }; - spec.clipExtend = function($size) { - var raw = this._; - var size, a, i, imax, b; - $size = utils.defaultValue$Nil($size); + spec.neg = function() { + return this.performUnaryOp($SC.Symbol("neg")); + }; - size = Math.max(0, $size.__int__()); + spec.bitNot = function() { + return this.performUnaryOp($SC.Symbol("bitNot")); + }; - if (raw.length < size) { - a = new Array(size); - for (i = 0, imax = raw.length; i < imax; ++i) { - a[i] = raw[i]; - } - for (b = a[i - 1]; i < size; ++i) { - a[i] = b; - } - } else { - a = raw.slice(0, size); - } + spec.abs = function() { + return this.performUnaryOp($SC.Symbol("abs")); + }; - return $SC.Array(a); + spec.ceil = function() { + return this.performUnaryOp($SC.Symbol("ceil")); }; - spec.slide = function($windowLength, $stepSize) { - var raw = this._; - var windowLength, stepSize; - var obj1, obj2, m, n, numwin, numslots; - var i, j, h, k; - $windowLength = utils.defaultValue$Integer($windowLength, 3); - $stepSize = utils.defaultValue$Integer($stepSize , 1); + spec.floor = function() { + return this.performUnaryOp($SC.Symbol("floor")); + }; - windowLength = $windowLength.__int__(); - stepSize = $stepSize.__int__(); - obj1 = raw; - obj2 = []; - m = windowLength; - n = stepSize; - numwin = ((raw.length + n - m) / n)|0; - numslots = numwin * m; + spec.frac = function() { + return this.performUnaryOp($SC.Symbol("frac")); + }; - for (i = h = k = 0; i < numwin; ++i,h += n) { - for (j = h; j < m + h; ++j) { - obj2[k++] = obj1[j]; - } - } + spec.sign = function() { + return this.performUnaryOp($SC.Symbol("sign")); + }; - return $SC.Array(obj2); + spec.squared = function() { + return this.performUnaryOp($SC.Symbol("squared")); }; - spec.containsSeqColl = function() { - var raw = this._; - var i, imax; + spec.cubed = function() { + return this.performUnaryOp($SC.Symbol("cubed")); + }; - for (i = 0, imax = raw.length; i < imax; ++i) { - if (BOOL(raw[i].isSequenceableCollection())) { - return $SC.True(); - } - } + spec.sqrt = function() { + return this.performUnaryOp($SC.Symbol("sqrt")); + }; - return $SC.False(); + spec.exp = function() { + return this.performUnaryOp($SC.Symbol("exp")); }; - spec.unlace = function($clumpSize, $numChan, $clip) { - var raw = this._; - var clumpSize, numChan; - var a, b, size, i, j, k; - $clumpSize = utils.defaultValue$Integer($clumpSize, 2); - $numChan = utils.defaultValue$Integer($numChan , 1); - $clip = utils.defaultValue$Boolean($clip, false); + spec.reciprocal = function() { + return this.performUnaryOp($SC.Symbol("reciprocal")); + }; - clumpSize = $clumpSize.__int__(); - numChan = $numChan .__int__(); - size = (raw.length / clumpSize)|0; - size = size - (size % numChan); - if (size) { - a = new Array(clumpSize); - for (i = 0; i < clumpSize; ++i) { - b = new Array(size); - for (j = 0; j < size; j += numChan) { - for (k = 0; k < numChan; ++k) { - b[j + k] = raw[i * numChan + k + j * clumpSize]; - } - } - a[i] = $SC.Array(b); - } - } else { - a = []; - } + spec.midicps = function() { + return this.performUnaryOp($SC.Symbol("midicps")); + }; - return $SC.Array(a); + spec.cpsmidi = function() { + return this.performUnaryOp($SC.Symbol("cpsmidi")); }; - // TODO: implements interlace - // TODO: implements deinterlace + spec.midiratio = function() { + return this.performUnaryOp($SC.Symbol("midiratio")); + }; - spec.flop = function() { - return this.multiChannelExpand(); + spec.ratiomidi = function() { + return this.performUnaryOp($SC.Symbol("ratiomidi")); }; - spec.multiChannelExpand = function() { - var raw = this._; - var maxSize, size, obj1, obj2, obj3; - var i, j; + spec.ampdb = function() { + return this.performUnaryOp($SC.Symbol("ampdb")); + }; - obj1 = raw; - maxSize = obj1.reduce(function(len, $elem) { - return Math.max(len, Array.isArray($elem._) ? $elem._.length : 1); - }, 0); + spec.dbamp = function() { + return this.performUnaryOp($SC.Symbol("dbamp")); + }; - obj2 = new Array(maxSize); - size = obj1.length; + spec.octcps = function() { + return this.performUnaryOp($SC.Symbol("octcps")); + }; - if (size === 0) { - obj2[0] = $SC.Array([]); - } else { - for (i = 0; i < maxSize; ++i) { - obj3 = new Array(size); - for (j = 0; j < size; ++j) { - if (Array.isArray(obj1[j]._)) { - obj3[j] = obj1[j]._[i % obj1[j]._.length]; - } else { - obj3[j] = obj1[j]; - } - } - obj2[i] = $SC.Array(obj3); - } - } + spec.cpsoct = function() { + return this.performUnaryOp($SC.Symbol("cpsoct")); + }; - return $SC.Array(obj2); + spec.log = function() { + return this.performUnaryOp($SC.Symbol("log")); }; - // TODO: implements envirPairs + spec.log2 = function() { + return this.performUnaryOp($SC.Symbol("log2")); + }; - spec.shift = function($n, $filler) { - var $fill, $remain; - $n = utils.defaultValue$Nil($n); - $filler = utils.defaultValue$Float($filler, 0.0); + spec.log10 = function() { + return this.performUnaryOp($SC.Symbol("log10")); + }; - $fill = SCArray.fill($n.abs(), $filler); - $remain = this.drop($n.neg()); + spec.sin = function() { + return this.performUnaryOp($SC.Symbol("sin")); + }; - if ($n < 0) { - return $remain ["++"] ($fill); - } + spec.cos = function() { + return this.performUnaryOp($SC.Symbol("cos")); + }; - return $fill ["++"] ($remain); + spec.tan = function() { + return this.performUnaryOp($SC.Symbol("tan")); }; - spec.powerset = function() { - var raw = this._; - var arrSize, powersize; - var result, elemArr, mod, i, j; + spec.asin = function() { + return this.performUnaryOp($SC.Symbol("asin")); + }; - arrSize = this.size().__int__(); - powersize = Math.pow(2, arrSize); + spec.acos = function() { + return this.performUnaryOp($SC.Symbol("acos")); + }; - result = []; - for (i = 0; i < powersize; ++i) { - elemArr = []; - for (j = 0; j < arrSize; ++j) { - mod = Math.pow(2, j); - if (((i / mod)|0) % 2) { - elemArr.push(raw[j]); - } - } - result[i] = $SC.Array(elemArr); - } + spec.atan = function() { + return this.performUnaryOp($SC.Symbol("atan")); + }; - return $SC.Array(result); + spec.sinh = function() { + return this.performUnaryOp($SC.Symbol("sinh")); }; - // TODO: implements source + spec.cosh = function() { + return this.performUnaryOp($SC.Symbol("cosh")); + }; - spec.asUGenInput = function($for) { - return this.collect($SC.Function(function($_) { - return $_.asUGenInput($for); - })); + spec.tanh = function() { + return this.performUnaryOp($SC.Symbol("tanh")); }; - spec.asAudioRateInput = function($for) { - return this.collect($SC.Function(function($_) { - return $_.asAudioRateInput($for); - })); + spec.rand = function() { + return this.performUnaryOp($SC.Symbol("rand")); }; - spec.asControlInput = function() { - return this.collect($SC.Function(function($_) { - return $_.asControlInput(); - })); + spec.rand2 = function() { + return this.performUnaryOp($SC.Symbol("rand2")); }; - spec.isValidUGenInput = utils.alwaysReturn$true; + spec.linrand = function() { + return this.performUnaryOp($SC.Symbol("linrand")); + }; - spec.numChannels = function() { - return this.size(); + spec.bilinrand = function() { + return this.performUnaryOp($SC.Symbol("bilinrand")); }; - // TODO: implements poll - // TODO: implements dpoll - // TODO: implements evnAt - // TODO: implements atIdentityHash - // TODO: implements atIdentityHashInPairs - // TODO: implements asSpec - // TODO: implements fork + spec.sum3rand = function() { + return this.performUnaryOp($SC.Symbol("sum3rand")); + }; - spec.madd = function($mul, $add) { - $mul = utils.defaultValue$Float($mul, 1.0); - $add = utils.defaultValue$Float($add, 0.0); - return $SC("MulAdd").new(this, $mul, $add); + spec.distort = function() { + return this.performUnaryOp($SC.Symbol("distort")); }; - // TODO: implements asRawOSC - // TODO: implements printOn - // TODO: implements storeOn - }); + spec.softclip = function() { + return this.performUnaryOp($SC.Symbol("softclip")); + }; -})(sc); + spec.coin = function() { + return this.performUnaryOp($SC.Symbol("coin")); + }; -// src/sc/lang/compiler.js -(function(sc) { + spec.even = function() { + return this.performUnaryOp($SC.Symbol("even")); + }; - var compiler = {}; + spec.odd = function() { + return this.performUnaryOp($SC.Symbol("odd")); + }; - compiler.Token = { - CharLiteral: "Char", - EOF: "", - FalseLiteral: "False", - FloatLiteral: "Float", - Identifier: "Identifier", - IntegerLiteral: "Integer", - Keyword: "Keyword", - Label: "Label", - NilLiteral: "Nil", - Punctuator: "Punctuator", - StringLiteral: "String", - SymbolLiteral: "Symbol", - TrueLiteral: "True" - }; + spec.isPositive = function() { + return this.performUnaryOp($SC.Symbol("isPositive")); + }; - compiler.Syntax = { - AssignmentExpression: "AssignmentExpression", - BinaryExpression: "BinaryExpression", - BlockExpression: "BlockExpression", - CallExpression: "CallExpression", - FunctionExpression: "FunctionExpression", - GlobalExpression: "GlobalExpression", - Identifier: "Identifier", - ListExpression: "ListExpression", - Label: "Label", - Literal: "Literal", - ObjectExpression: "ObjectExpression", - Program: "Program", - ThisExpression: "ThisExpression", - UnaryExpression: "UnaryExpression", - VariableDeclaration: "VariableDeclaration", - VariableDeclarator: "VariableDeclarator" - }; + spec.isNegative = function() { + return this.performUnaryOp($SC.Symbol("isNegative")); + }; - var Message = compiler.Message = { - ArgumentAlreadyDeclared: "argument '%0' already declared", - InvalidLHSInAssignment: "invalid left-hand side in assignment", - NotImplemented: "not implemented %0", - UnexpectedEOS: "unexpected end of input", - UnexpectedIdentifier: "unexpected identifier", - UnexpectedChar: "unexpected char", - UnexpectedLabel: "unexpected label", - UnexpectedNumber: "unexpected number", - UnexpectedString: "unexpected string", - UnexpectedSymbol: "unexpected symbol", - UnexpectedToken: "unexpected token %0", - VariableAlreadyDeclared: "variable '%0' already declared", - VariableNotDefined: "variable '%0' not defined" - }; + spec.isStrictlyPositive = function() { + return this.performUnaryOp($SC.Symbol("isStrictlyPositive")); + }; - compiler.Keywords = { - var: "keyword", - arg: "keyword", - const: "keyword", - this: "function", - thisThread: "function", - thisProcess: "function", - thisFunction: "function", - thisFunctionDef: "function", - }; + spec.rectWindow = function() { + return this.performUnaryOp($SC.Symbol("rectWindow")); + }; - var Scope = (function() { - function Scope(methods) { - var f = function(parent) { - this.parent = parent; - this.stack = []; - }; + spec.hanWindow = function() { + return this.performUnaryOp($SC.Symbol("hanWindow")); + }; - function F() {} - F.prototype = Scope; - f.prototype = new F(); + spec.welWindow = function() { + return this.performUnaryOp($SC.Symbol("welWindow")); + }; - Object.keys(methods).forEach(function(key) { - f.prototype[key] = methods[key]; - }); + spec.triWindow = function() { + return this.performUnaryOp($SC.Symbol("triWindow")); + }; - return f; - } + spec.scurve = function() { + return this.performUnaryOp($SC.Symbol("scurve")); + }; - Scope.add = function(type, id, scope) { - var peek = this.stack[this.stack.length - 1]; - var vars, args, declared, stmt, indent; + spec.ramp = function() { + return this.performUnaryOp($SC.Symbol("ramp")); + }; - if (scope) { - vars = scope.vars; - args = scope.args; - declared = scope.declared; - stmt = scope.stmt; - indent = scope.indent; - } else { - vars = peek.vars; - args = peek.args; - declared = peek.declared; - stmt = peek.stmt; - indent = peek.indent; - } + spec.asFloat = function() { + return this.performUnaryOp($SC.Symbol("asFloat")); + }; - if (args[id]) { - this.parent.throwError({}, Message.ArgumentAlreadyDeclared, id); - } + spec.asInteger = function() { + return this.performUnaryOp($SC.Symbol("asInteger")); + }; - if (vars[id] && id.charAt(0) !== "_") { - this.parent.throwError({}, Message.VariableAlreadyDeclared, id); - } + spec.nthPrime = function() { + return this.performUnaryOp($SC.Symbol("nthPrime")); + }; - switch (type) { - case "var": - if (!vars[id]) { - this.add_delegate(stmt, id, indent, peek, scope); - vars[id] = true; - delete declared[id]; - } - break; - case "arg": - args[id] = true; - delete declared[id]; - break; - } + spec.prevPrime = function() { + return this.performUnaryOp($SC.Symbol("prevPrime")); }; - Scope.add_delegate = function() { + spec.nextPrime = function() { + return this.performUnaryOp($SC.Symbol("nextPrime")); }; - Scope.end = function() { - this.stack.pop(); + spec.indexOfPrime = function() { + return this.performUnaryOp($SC.Symbol("indexOfPrime")); }; - Scope.getDeclaredVariable = function() { - var peek = this.stack[this.stack.length - 1]; - var declared = {}; + spec.real = function() { + return this.performUnaryOp($SC.Symbol("real")); + }; - if (peek) { - Array.prototype.concat.apply([], [ - peek.declared, peek.args, peek.vars - ].map(Object.keys)).forEach(function(key) { - declared[key] = true; - }); - } + spec.imag = function() { + return this.performUnaryOp($SC.Symbol("imag")); + }; - return declared; + spec.magnitude = function() { + return this.performUnaryOp($SC.Symbol("magnitude")); }; - Scope.find = function(id) { - var peek = this.stack[this.stack.length - 1]; - return peek.vars[id] || peek.args[id] || peek.declared[id]; + spec.magnitudeApx = function() { + return this.performUnaryOp($SC.Symbol("magnitudeApx")); }; - Scope.peek = function() { - return this.stack[this.stack.length - 1]; + spec.phase = function() { + return this.performUnaryOp($SC.Symbol("phase")); }; - return Scope; - })(); + spec.angle = function() { + return this.performUnaryOp($SC.Symbol("angle")); + }; - compiler.Scope = Scope; + spec.rho = function() { + return this.performUnaryOp($SC.Symbol("rho")); + }; - sc.lang.compiler = compiler; + spec.theta = function() { + return this.performUnaryOp($SC.Symbol("theta")); + }; - var SCScript = sc.SCScript; + spec.degrad = function() { + return this.performUnaryOp($SC.Symbol("degrad")); - SCScript.tokenize = function(source, opts) { - opts = opts || /* istanbul ignore next */ {}; - opts.tokens = true; - return sc.lang.parser.parse(source, opts).tokens || /* istanbul ignore next */ []; - }; + }; + spec.raddeg = function() { + return this.performUnaryOp($SC.Symbol("raddeg")); + }; - SCScript.parse = function(source, opts) { - return sc.lang.parser.parse(source, opts); - }; + spec["+"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("+"), $aNumber, $adverb); + }; - SCScript.compile = function(source, opts) { - var ast = SCScript.parse(source, opts); - return sc.lang.codegen.compile(ast, opts); - }; + spec["-"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("-"), $aNumber, $adverb); + }; -})(sc); + spec["*"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("*"), $aNumber, $adverb); + }; -// src/sc/lang/parser.js -(function(sc) { + spec["/"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("/"), $aNumber, $adverb); + }; - var parser = {}; + spec.div = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("div"), $aNumber, $adverb); + }; - var Token = sc.lang.compiler.Token; - var Syntax = sc.lang.compiler.Syntax; - var Message = sc.lang.compiler.Message; - var Keywords = sc.lang.compiler.Keywords; + spec.mod = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("mod"), $aNumber, $adverb); + }; - var binaryPrecedenceDefaults = { - "?" : 1, - "??" : 1, - "!?" : 1, - "->" : 2, - "||" : 3, - "&&" : 4, - "|" : 5, - "&" : 6, - "==" : 7, - "!=" : 7, - "===": 7, - "!==": 7, - "<" : 8, - ">" : 8, - "<=" : 8, - ">=" : 8, - "<<" : 9, - ">>" : 9, - "+>>": 9, - "+" : 10, - "-" : 10, - "*" : 11, - "/" : 11, - "%" : 11, - "!" : 12, - }; + spec.pow = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("pow"), $aNumber, $adverb); + }; - function char2num(ch) { - var n = ch.charCodeAt(0); + spec.min = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("min"), $aNumber, $adverb); + }; - if (48 <= n && n <= 57) { - return n - 48; - } - if (65 <= n && n <= 90) { - return n - 55; - } - return n - 87; // if (97 <= n && n <= 122) - } + spec.max = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("max"), $aNumber, $adverb); + }; - function isNumber(ch) { - return "0" <= ch && ch <= "9"; - } + spec["<"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("<"), $aNumber, $adverb); + }; - var Scope = sc.lang.compiler.Scope({ - begin: function() { - var declared = this.getDeclaredVariable(); + spec["<="] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("<="), $aNumber, $adverb); + }; - this.stack.push({ - vars: {}, - args: {}, - declared: declared - }); - } - }); + spec[">"] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol(">"), $aNumber, $adverb); + }; - function LocationMarker(parser) { - this.parser = parser; - this.marker = [ - parser.index, - parser.lineNumber, - parser.index - parser.lineStart - ]; - } + spec[">="] = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol(">="), $aNumber, $adverb); + }; - LocationMarker.prototype.apply = function(node) { - var parser = this.parser; - var marker = this.marker; + spec.bitAnd = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("bitAnd"), $aNumber, $adverb); + }; - /* istanbul ignore else */ - if (this.parser.opts.range) { - node.range = [ marker[0], parser.index ]; - } - /* istanbul ignore else */ - if (this.parser.opts.loc) { - node.loc = { - start: { - line: marker[1], - column: marker[2] - }, - end: { - line: parser.lineNumber, - column: parser.index - parser.lineStart - } - }; - } - }; + spec.bitOr = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("bitOr"), $aNumber, $adverb); + }; - function SCParser(source, opts) { - /* istanbul ignore next */ - if (typeof source !== "string") { - if (typeof source === "undefined") { - source = ""; - } - source = String(source); - } - source = source.replace(/\r\n?/g, "\n"); - this.source = source; - this.opts = opts; - this.length = source.length; - this.index = 0; - this.lineNumber = this.length ? 1 : 0; - this.lineStart = 0; - this.reverted = null; - this.scope = new Scope(this); - this.marker = []; - this.tokens = opts.tokens ? [] : null; - this.errors = opts.tolerant ? [] : null; - this.state = { - closedFunction: false, - disallowGenerator: false, - innerElements: false, - immutableList: false, - underscore: [] + spec.bitXor = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("bitXor"), $aNumber, $adverb); }; - } - SCParser.prototype.parse = function() { - return this.parseProgram(); - }; - - SCParser.prototype.skipComment = function() { - var source = this.source; - var length = this.length; - var index = this.index; - var ch; + spec.bitHammingDistance = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("bitHammingDistance"), $aNumber, $adverb); + }; - LOOP: while (index < length) { - ch = source.charAt(index); + spec.lcm = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("lcm"), $aNumber, $adverb); + }; - if (ch === " " || ch === "\t") { - index += 1; - continue; - } + spec.gcd = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("gcd"), $aNumber, $adverb); + }; - if (ch === "\n") { - index += 1; - this.lineNumber += 1; - this.lineStart = index; - continue; - } + spec.round = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("round"), $aNumber, $adverb); + }; - if (ch === "/") { - ch = source.charAt(index + 1); - if (ch === "/") { - index = this.skipLineComment(index + 2); - continue; - } - if (ch === "*") { - index = this.skipBlockComment(index + 2); - continue; - } - } + spec.roundUp = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("roundUp"), $aNumber, $adverb); + }; - break; - } + spec.trunc = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("trunc"), $aNumber, $adverb); + }; - this.index = index; - }; + spec.atan2 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("atan2"), $aNumber, $adverb); + }; - SCParser.prototype.skipLineComment = function(index) { - var source = this.source; - var length = this.length; - var ch; + spec.hypot = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("hypot"), $aNumber, $adverb); + }; - while (index < length) { - ch = source.charAt(index); - index += 1; - if (ch === "\n") { - this.lineNumber += 1; - this.lineStart = index; - break; - } - } + spec.hypotApx = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("hypotApx"), $aNumber, $adverb); + }; - return index; - }; + spec.leftShift = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("leftShift"), $aNumber, $adverb); + }; - SCParser.prototype.skipBlockComment = function(index) { - var source = this.source; - var length = this.length; - var ch, depth; + spec.rightShift = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("rightShift"), $aNumber, $adverb); + }; - depth = 1; - while (index < length) { - ch = source.charAt(index); + spec.unsignedRightShift = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("unsignedRightShift"), $aNumber, $adverb); + }; - if (ch === "\n") { - this.lineNumber += 1; - this.lineStart = index; - } else { - ch = ch + source.charAt(index + 1); - if (ch === "/*") { - depth += 1; - index += 1; - } else if (ch === "*/") { - depth -= 1; - index += 1; - if (depth === 0) { - return index + 1; - } - } - } + spec.ring1 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("ring1"), $aNumber, $adverb); + }; - index += 1; - } - this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + spec.ring2 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("ring2"), $aNumber, $adverb); + }; - return index; - }; + spec.ring3 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("ring3"), $aNumber, $adverb); + }; - SCParser.prototype.collectToken = function() { - var loc, token, source, t; + spec.ring4 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("ring4"), $aNumber, $adverb); + }; - this.skipComment(); + spec.difsqr = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("difsqr"), $aNumber, $adverb); + }; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - } + spec.sumsqr = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("sumsqr"), $aNumber, $adverb); }; - token = this.advance(); + spec.sqrsum = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("sqrsum"), $aNumber, $adverb); + }; - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart + spec.sqrdif = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("sqrdif"), $aNumber, $adverb); }; - if (token.type !== Token.EOF) { - source = this.source; - t = { - type: token.type, - value: source.slice(token.range[0], token.range[1]) - }; - if (this.opts.range) { - t.range = [ token.range[0], token.range[1] ]; - } - if (this.opts.loc) { - t.loc = loc; - } - this.tokens.push(t); - } + spec.absdif = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("absdif"), $aNumber, $adverb); + }; - return token; - }; + spec.thresh = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("thresh"), $aNumber, $adverb); + }; - SCParser.prototype.advance = function() { - var ch, token; + spec.amclip = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("amclip"), $aNumber, $adverb); + }; - this.skipComment(); + spec.scaleneg = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("scaleneg"), $aNumber, $adverb); + }; - if (this.length <= this.index) { - return this.EOFToken(); - } + spec.clip2 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("clip2"), $aNumber, $adverb); + }; - ch = this.source.charAt(this.index); + spec.fold2 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("fold2"), $aNumber, $adverb); + }; - // Symbol literal starts with back slash - if (ch === "\\") { - return this.scanSymbolLiteral(); - } + spec.wrap2 = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("wrap2"), $aNumber, $adverb); + }; - // Char literal starts with dollar - if (ch === "$") { - return this.scanCharLiteral(); - } + spec.excess = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("excess"), $aNumber, $adverb); + }; - // String literal starts with single quote or double quote - if (ch === "'" || ch === "\"") { - return this.scanStringLiteral(); - } + spec.firstArg = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("firstArg"), $aNumber, $adverb); + }; - // for partial application - if (ch === "_") { - return this.scanUnderscore(); - } + spec.rrand = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("rrand"), $aNumber, $adverb); + }; - if (ch === "-") { - token = this.scanNegativeNumericLiteral(); - if (token) { - return token; - } - } + spec.exprand = function($aNumber, $adverb) { + return this.performBinaryOp($SC.Symbol("exprand"), $aNumber, $adverb); + }; - // Identifier starts with alphabet - if (("A" <= ch && ch <= "Z") || ("a" <= ch && ch <= "z")) { - return this.scanIdentifier(); - } + spec.performUnaryOp = function($aSelector) { + return this.collect($SC.Function(function($item) { + return $item.perform($aSelector); + })); + }; - // Number literal starts with number - if (isNumber(ch)) { - return this.scanNumericLiteral(); - } + spec.performBinaryOp = function($aSelector, $theOperand, $adverb) { + return $theOperand.performBinaryOpOnSeqColl($aSelector, this, $adverb); + }; - return this.scanPunctuator(); - }; + spec.performBinaryOpOnSeqColl = function($aSelector, $theOperand, $adverb) { + var adverb; - SCParser.prototype.expect = function(value) { - var token = this.lex(); - if (token.type !== Token.Punctuator || token.value !== value) { - this.throwUnexpected(token, value); - } - }; + if ($adverb === $nil || !$adverb) { + return _performBinaryOpOnSeqColl_adverb_nil( + this, $aSelector, $theOperand + ); + } + if (BOOL($adverb.isInteger())) { + return _performBinaryOpOnSeqColl_adverb_int( + this, $aSelector, $theOperand, $adverb.valueOf() + ); + } - SCParser.prototype.peek = function() { - var index, lineNumber, lineStart; + adverb = $adverb.__sym__(); + if (adverb === "t") { + return _performBinaryOpOnSeqColl_adverb_t( + this, $aSelector, $theOperand + ); + } + if (adverb === "x") { + return _performBinaryOpOnSeqColl_adverb_x( + this, $aSelector, $theOperand + ); + } + if (adverb === "s") { + return _performBinaryOpOnSeqColl_adverb_s( + this, $aSelector, $theOperand + ); + } + if (adverb === "f") { + return _performBinaryOpOnSeqColl_adverb_f( + this, $aSelector, $theOperand + ); + } - index = this.index; - lineNumber = this.lineNumber; - lineStart = this.lineStart; + throw new Error( + "unrecognized adverb: '" + adverb + "' for operator '" + String($aSelector) + "'" + ); + }; - if (this.opts.tokens) { - this.lookahead = this.collectToken(); - } else { - this.lookahead = this.advance(); - } + function _performBinaryOpOnSeqColl_adverb_nil($this, $aSelector, $theOperand) { + var $size, $newList, $i; + var size, i; - this.index = index; - this.lineNumber = lineNumber; - this.lineStart = lineStart; - }; + $size = $this.size().max($theOperand.size()); + $newList = $this.species().new($size); - SCParser.prototype.lex = function(saved) { - var that = this; - var token = this.lookahead; + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $i = $SC.Integer(i); + $newList.add( + $theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i)) + ); + } - if (saved) { - saved = [ this.lookahead, this.index, this.lineNumber, this.lineStart ]; + return $newList; } - this.index = token.range[1]; - this.lineNumber = token.lineNumber; - this.lineStart = token.lineStart; - - if (this.opts.tokens) { - this.lookahead = this.collectToken(); - } else { - this.lookahead = this.advance(); - } + function _performBinaryOpOnSeqColl_adverb_int($this, $aSelector, $theOperand, adverb) { + var $size, $newList, $i; + var size, i; - this.index = token.range[1]; - this.lineNumber = token.lineNumber; - this.lineStart = token.lineStart; + if (adverb === 0) { + $size = $this.size().max($theOperand.size()); + $newList = $this.species().new($size); - if (saved) { - token.restore = function() { - that.lookahead = saved[0]; - that.index = saved[1]; - that.lineNumber = saved[2]; - that.lineStart = saved[3]; - if (that.tokens) { - that.tokens.pop(); + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $i = $SC.Integer(i); + $newList.add($theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i))); } - }; - } - - return token; - }; - SCParser.prototype.EOFToken = function() { - return { - type: Token.EOF, - value: "", - lineNumber: this.lineNumber, - lineStart: this.lineStart, - range: [ this.index, this.index ] - }; - }; + } else if (adverb > 0) { - SCParser.prototype.scanCharLiteral = function() { - var start, value; + $newList = $theOperand.collect($SC.Function(function($item) { + return $item.perform($aSelector, $this, $SC.Integer(adverb - 1)); + })); - start = this.index; - value = this.source.charAt(this.index + 1); + } else { - this.index += 2; + $newList = $this.collect($SC.Function(function($item) { + return $theOperand.perform($aSelector, $item, $SC.Integer(adverb + 1)); + })); - return { - type : Token.CharLiteral, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] - }; - }; + } - SCParser.prototype.scanIdentifier = function() { - var source = this.source.slice(this.index); - var start = this.index; - var value, type; + return $newList; + } - value = /^[a-zA-Z][a-zA-Z0-9_]*/.exec(source)[0]; + function _performBinaryOpOnSeqColl_adverb_t($this, $aSelector, $theOperand) { + var $size, $newList, $i; + var size, i; - this.index += value.length; + $size = $theOperand.size(); + $newList = $this.species().new($size); - if (this.source.charAt(this.index) === ":") { - this.index += 1; - return { - type: Token.Label, - value: value, - lineNumber: this.lineNumber, - lineStart: this.lineStart, - range: [ start, this.index ] - }; - } else if (this.isKeyword(value)) { - type = Token.Keyword; - } else { - switch (value) { - case "inf": - type = Token.FloatLiteral; - value = "Infinity"; - break; - case "pi": - type = Token.FloatLiteral; - value = "Math.PI"; - break; - case "nil": - type = Token.NilLiteral; - value = "null"; - break; - case "true": - type = Token.TrueLiteral; - break; - case "false": - type = Token.FalseLiteral; - break; - default: - type = Token.Identifier; - break; + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $i = $SC.Integer(i); + $newList.add($theOperand.at($i).perform($aSelector, $this)); } + + return $newList; } - return { - type: type, - value: value, - lineNumber: this.lineNumber, - lineStart: this.lineStart, - range: [ start, this.index ] - }; - }; + function _performBinaryOpOnSeqColl_adverb_x($this, $aSelector, $theOperand) { + var $size, $newList; - SCParser.prototype.scanNumericLiteral = function(neg) { - return this.scanNAryNumberLiteral(neg) || this.scanDecimalNumberLiteral(neg); - }; + $size = $theOperand.size() ["*"] ($this.size()); + $newList = $this.species().new($size); + $theOperand.do($SC.Function(function($a) { + $this.do($SC.Function(function($b) { + $newList.add($a.perform($aSelector, $b)); + })); + })); - SCParser.prototype.scanNegativeNumericLiteral = function() { - var token, ch1, ch2, ch3; - var start, value = null; + return $newList; + } - start = this.index; - ch1 = this.source.charAt(this.index + 1); + function _performBinaryOpOnSeqColl_adverb_s($this, $aSelector, $theOperand) { + var $size, $newList, $i; + var size, i; - if (isNumber(ch1)) { - this.index += 1; - token = this.scanNumericLiteral(true); - token.range[0] = start; - return token; - } + $size = $this.size().min($theOperand.size()); + $newList = $this.species().new($size); - ch2 = this.source.charAt(this.index + 2); - ch3 = this.source.charAt(this.index + 3); + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $i = $SC.Integer(i); + $newList.add($theOperand.wrapAt($i).perform($aSelector, $this.wrapAt($i))); + } - if (ch1 + ch2 === "pi") { - this.index += 3; - value = -Math.PI; - } else if (ch1 + ch2 + ch3 === "inf") { - this.index += 4; - value = -Infinity; + return $newList; } - if (value !== null) { - return { - type : Token.FloatLiteral, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] - }; - } + function _performBinaryOpOnSeqColl_adverb_f($this, $aSelector, $theOperand) { + var $size, $newList, $i; + var size, i; - return null; - }; + $size = $this.size().max($theOperand.size()); + $newList = $this.species().new($size); - SCParser.prototype.scanNAryNumberLiteral = function(neg) { - var re, start, items; - var base, integer, frac, pi; - var value, type; - - re = /^(\d+)r((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+)(?:\.((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+))?/; - start = this.index; - items = re.exec(this.source.slice(this.index)); + size = $size.__int__(); + for (i = 0; i < size; ++i) { + $i = $SC.Integer(i); + $newList.add($theOperand.foldAt($i).perform($aSelector, $this.foldAt($i))); + } - if (!items) { - return; + return $newList; } - base = items[1].replace(/^0+(?=\d)/g, "")|0; - integer = items[2].replace(/(^0+(?=\d)|_)/g, ""); - frac = items[3] && items[3].replace(/_/g, ""); + spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber, $adverb) { + return this.collect($SC.Function(function($item) { + return $aNumber.perform($aSelector, $item, $adverb); + })); + }; - if (!frac && base < 26 && integer.substr(-2) === "pi") { - integer = integer.substr(0, integer.length - 2); - pi = true; - } + spec.performBinaryOpOnComplex = function($aSelector, $aComplex, $adverb) { + return this.collect($SC.Function(function($item) { + return $aComplex.perform($aSelector, $item, $adverb); + })); + }; - type = Token.IntegerLiteral; - value = this.calcNBasedInteger(integer, base); + spec.asFraction = function($denominator, $fasterBetter) { + return this.collect($SC.Function(function($item) { + return $item.asFraction($denominator, $fasterBetter); + })); + }; - if (frac) { - type = Token.FloatLiteral; - value += this.calcNBasedFrac(frac, base); - } + // TODO: implements asPoint + // TODO: implements asRect - if (neg) { - value *= -1; - } + spec.ascii = function() { + return this.collect($SC.Function(function($item) { + return $item.ascii(); + })); + }; - if (pi) { - type = Token.FloatLiteral; - value = value + " * Math.PI"; - } + spec.rate = function() { + if (this.size().__int__() === 1) { + return this.first().rate(); + } + return this.collect($SC.Function(function($item) { + return $item.rate(); + })).minItem(); + }; - if (type === Token.FloatLiteral && value === (value|0)) { - value = value + ".0"; - } else { - value = String(value); - } + spec.multiChannelPerform = function() { + var method; - this.index += items[0].length; + if (this.size() > 0) { + method = utils.getMethod("Object", "multiChannelPerform"); + return method.apply(this, arguments); + } - return { - type : type, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] + return this.class().new(); }; - }; - - SCParser.prototype.char2num = function(ch, base) { - var x = char2num(ch, base); - if (x >= base) { - this.throwError({}, Message.UnexpectedToken, ch); - } - return x; - }; - SCParser.prototype.calcNBasedInteger = function(integer, base) { - var value, i, imax; + spec.multichannelExpandRef = utils.nop; - for (i = value = 0, imax = integer.length; i < imax; ++i) { - value *= base; - value += this.char2num(integer[i], base); - } + spec.clip = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("clip") ].concat(slice.call(arguments)) + ); + }; - return value; - }; + spec.wrap = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("wrap") ].concat(slice.call(arguments)) + ); + }; - SCParser.prototype.calcNBasedFrac = function(frac, base) { - var value, i, imax; + spec.fold = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("fold") ].concat(slice.call(arguments)) + ); + }; - for (i = value = 0, imax = frac.length; i < imax; ++i) { - value += this.char2num(frac[i], base) * Math.pow(base, -(i + 1)); - } + spec.linlin = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("linlin") ].concat(slice.call(arguments)) + ); + }; - return value; - }; + spec.linexp = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("linexp") ].concat(slice.call(arguments)) + ); + }; - SCParser.prototype.scanDecimalNumberLiteral = function(neg) { - var re, start, items, integer, frac, pi; - var value, type; + spec.explin = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("explin") ].concat(slice.call(arguments)) + ); + }; - re = /^((?:\d(?:_(?=\d))?)+((?:\.(?:\d(?:_(?=\d))?)+)?(?:e[-+]?(?:\d(?:_(?=\d))?)+)?))(pi)?/; - start = this.index; - items = re.exec(this.source.slice(this.index)); + spec.expexp = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("expexp") ].concat(slice.call(arguments)) + ); + }; - integer = items[1]; - frac = items[2]; - pi = items[3]; + spec.lincurve = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lincurve") ].concat(slice.call(arguments)) + ); + }; - type = (frac || pi) ? Token.FloatLiteral : Token.IntegerLiteral; - value = +integer.replace(/(^0+(?=\d)|_)/g, ""); + spec.curvelin = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("curvelin") ].concat(slice.call(arguments)) + ); + }; - if (neg) { - value *= -1; - } + spec.bilin = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("bilin") ].concat(slice.call(arguments)) + ); + }; - if (pi) { - value = value + " * Math.PI"; - } + spec.biexp = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("biexp") ].concat(slice.call(arguments)) + ); + }; - if (type === Token.FloatLiteral && value === (value|0)) { - value = value + ".0"; - } else { - value = String(value); - } + spec.moddif = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("moddif") ].concat(slice.call(arguments)) + ); + }; - this.index += items[0].length; + spec.range = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("range") ].concat(slice.call(arguments)) + ); + }; - return { - type : type, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] + spec.exprange = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("exprange") ].concat(slice.call(arguments)) + ); }; - }; - SCParser.prototype.scanPunctuator = function() { - var re, start, items; + spec.curverange = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("curverange") ].concat(slice.call(arguments)) + ); + }; - re = /^(\.{1,3}|[(){}[\]:;,~#`]|[-+*\/%<=>!?&|@]+)/; - start = this.index; - items = re.exec(this.source.slice(this.index)); + spec.unipolar = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("unipolar") ].concat(slice.call(arguments)) + ); + }; - if (items) { - this.index += items[0].length; - return { - type : Token.Punctuator, - value: items[0], - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] - }; - } + spec.bipolar = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("bipolar") ].concat(slice.call(arguments)) + ); + }; - this.throwError({}, Message.UnexpectedToken, this.source.charAt(this.index)); + spec.lag = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lag") ].concat(slice.call(arguments)) + ); + }; - this.index = this.length; + spec.lag2 = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lag2") ].concat(slice.call(arguments)) + ); + }; - return this.EOFToken(); - }; + spec.lag3 = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lag3") ].concat(slice.call(arguments)) + ); + }; - SCParser.prototype.scanStringLiteral = function() { - var source, start; - var length, index; - var quote, ch, value, type; - - source = this.source; - length = this.length; - index = start = this.index; - quote = source.charAt(start); - type = (quote === '"') ? Token.StringLiteral : Token.SymbolLiteral; - - index += 1; - while (index < length) { - ch = source.charAt(index); - index += 1; - if (ch === quote) { - value = source.substr(start + 1, index - start - 2); - value = value.replace(/\n/g, "\\n"); - this.index = index; - return { - type : type, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] - }; - } else if (ch === "\n") { - this.lineNumber += 1; - this.lineStart = index; - } else if (ch === "\\") { - index += 1; - } - } + spec.lagud = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lagud") ].concat(slice.call(arguments)) + ); + }; - this.index = index; - this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + spec.lag2ud = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lag2ud") ].concat(slice.call(arguments)) + ); + }; - return this.EOFToken(); - }; + spec.lag3ud = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("lag3ud") ].concat(slice.call(arguments)) + ); + }; - SCParser.prototype.scanSymbolLiteral = function() { - var re, start, items; - var value; + spec.varlag = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("varlag") ].concat(slice.call(arguments)) + ); + }; - re = /^\\([a-z_]\w*)?/i; - start = this.index; - items = re.exec(this.source.slice(this.index)); + spec.slew = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("slew") ].concat(slice.call(arguments)) + ); + }; - value = items[1]; + spec.blend = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("blend") ].concat(slice.call(arguments)) + ); + }; - this.index += items[0].length; + spec.checkBadValues = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("checkBadValues") ].concat(slice.call(arguments)) + ); + }; - return { - type : Token.SymbolLiteral, - value: value, - lineNumber: this.lineNumber, - lineStart : this.lineStart, - range: [ start, this.index ] + spec.prune = function() { + return this.multiChannelPerform.apply( + this, [ $SC.Symbol("prune") ].concat(slice.call(arguments)) + ); }; - }; - SCParser.prototype.scanUnderscore = function() { - var start = this.index; + // TODO: implements minNyquist + // TODO: implements sort + // TODO: implements sortBy + // TODO: implements sortMap + // TODO: implements sortedMedian + // TODO: implements median + // TODO: implements quickSort + // TODO: implements order - this.index += 1; + spec.swap = fn(function($i, $j) { + var $temp; - return { - type: Token.Identifier, - value: "_", - lineNumber: this.lineNumber, - lineStart: this.lineStart, - range: [ start, this.index ] - }; - }; + $temp = this.at($i); + this.put($i, this.at($j)); + this.put($j, $temp); - SCParser.prototype.createAssignmentExpression = function(operator, left, right, remain) { - var node = { - type: Syntax.AssignmentExpression, - operator: operator, - left: left, - right: right - }; - if (remain) { - node.remain = remain; - } - return node; - }; + return this; + }, "i; j"); - SCParser.prototype.createBinaryExpression = function(operator, left, right) { - var node = { - type: Syntax.BinaryExpression, - operator: operator.value, - left: left, - right: right - }; - if (operator.adverb) { - node.adverb = operator.adverb; - } - return node; - }; + // TODO: implements quickSortRange + // TODO: implements mergeSort + // TODO: implements mergeSortTemp + // TODO: implements mergeTemp + // TODO: implements insertionSort + // TODO: implements insertionSortRange + // TODO: implements hoareMedian + // TODO: implements hoareFind + // TODO: implements hoarePartition + // TODO: implements $streamContensts + // TODO: implements $streamContenstsLimit - SCParser.prototype.createBlockExpression = function(body) { - return { - type: Syntax.BlockExpression, - body: body - }; - }; + spec.wrapAt = fn(function($index) { + $index = $index ["%"] (this.size()); + return this.at($index); + }, "index"); - SCParser.prototype.createCallExpression = function(callee, method, args, stamp) { - var node; + spec.wrapPut = fn(function($index, $value) { + $index = $index ["%"] (this.size()); + return this.put($index, $value); + }, "index; value"); - node = { - type: Syntax.CallExpression, - callee: callee, - method: method, - args : args, - }; + // TODO: implements reduce + // TODO: implements join + // TODO: implements nextTimeOnGrid + // TODO: implements asQuant + // TODO: implements schedBundleArrayOnClock + }); - if (stamp) { - node.stamp = stamp; - } +})(sc); - return node; - }; +// src/sc/lang/classlib/Collections/ArrayedCollection.js +(function(sc) { - SCParser.prototype.createGlobalExpression = function(id) { - return { - type: Syntax.GlobalExpression, - id: id - }; - }; + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var iterator = sc.lang.iterator; + var rand = sc.libs.random; + var mathlib = sc.libs.mathlib; - SCParser.prototype.createFunctionExpression = function(args, body, closed, partial, blocklist) { - var node; + sc.lang.klass.refine("ArrayedCollection", function(spec, utils) { + var BOOL = utils.BOOL; + var $nil = utils.$nil; + var $int_0 = utils.$int_0; + var $int_1 = utils.$int_1; - node = { - type: Syntax.FunctionExpression, - body: body + spec.valueOf = function() { + return this._.map(function(elem) { + return elem.valueOf(); + }); }; - if (args) { - node.args = args; - } - if (closed) { - node.closed = true; - } - if (partial) { - node.partial = true; - } - if (blocklist) { - node.blocklist = true; - } - return node; - }; - SCParser.prototype.createIdentifier = function(name) { - return { - type: Syntax.Identifier, - name: name + spec.__elem__ = function(item) { + return item; }; - }; - SCParser.prototype.createLabel = function(name) { - return { - type: Syntax.Label, - name: name + spec._ThrowIfImmutable = function() { + if (this._immutable) { + throw new Error("Attempted write to immutable object."); + } }; - }; - SCParser.prototype.createListExpression = function(elements, immutable) { - var node = { - type: Syntax.ListExpression, - elements: elements - }; - if (immutable) { - node.immutable = !!immutable; - } - return node; - }; + // TODO: implements $newClear + // TODO: implements indexedSize - SCParser.prototype.createLiteral = function(token) { - return { - type: Syntax.Literal, - value: token.value, - valueType: token.type + spec.size = function() { + return $SC.Integer(this._.length); }; - }; - SCParser.prototype.createLocationMarker = function() { - if (this.opts.loc || this.opts.range) { - this.skipComment(); - return new LocationMarker(this); - } - }; + // TODO: implements maxSize - SCParser.prototype.createObjectExpression = function(elements) { - return { - type: Syntax.ObjectExpression, - elements: elements - }; - }; + spec.swap = fn(function($a, $b) { + var raw = this._; + var a, b, len, tmp; - SCParser.prototype.createProgram = function(body) { - return { - type: Syntax.Program, - body: body - }; - }; + this._ThrowIfImmutable(); - SCParser.prototype.createThisExpression = function(name) { - return { - type: Syntax.ThisExpression, - name: name - }; - }; + a = $a.__int__(); + b = $b.__int__(); + len = raw.length; - SCParser.prototype.createUnaryExpression = function(operator, arg) { - return { - type: Syntax.UnaryExpression, - operator: operator, - arg: arg - }; - }; + if (a < 0 || len <= a || b < 0 || len <= b) { + throw new Error("out of index"); + } - SCParser.prototype.createVariableDeclaration = function(declarations, kind) { - return { - type: Syntax.VariableDeclaration, - declarations: declarations, - kind: kind - }; - }; + tmp = raw[b]; + raw[b] = raw[a]; + raw[a] = tmp; - SCParser.prototype.createVariableDeclarator = function(id, init) { - var node = { - type: Syntax.VariableDeclarator, - id: id - }; - if (init) { - node.init = init; - } - return node; - }; + return this; + }, "a; b"); - SCParser.prototype.isClassName = function(node) { - var name, ch; + spec.at = fn(function($index) { + var i; - if (node.type === Syntax.Identifier) { - name = node.value || node.name; - ch = name.charAt(0); - return "A" <= ch && ch <= "Z"; - } + if (Array.isArray($index._)) { + return $SC.Array($index._.map(function($index) { + i = $index.__int__(); + if (i < 0 || this._.length <= i) { + return $nil; + } + return this._[i]; + }, this)); + } - return false; - }; + i = $index.__int__(); - SCParser.prototype.isKeyword = function(value) { - return !!Keywords[value] || false; - }; + return this._[i] || $nil; + }, "index"); - SCParser.prototype.isLeftHandSide = function(expr) { - switch (expr.type) { - case Syntax.Identifier: - case Syntax.GlobalExpression: - return true; - } - return false; - }; + spec.clipAt = fn(function($index) { + var i; - SCParser.prototype._match = function(value, type) { - var token = this.lookahead; - return token.type === type && token.value === value; - }; + if (Array.isArray($index._)) { + return $SC.Array($index._.map(function($index) { + i = mathlib.clip_idx($index.__int__(), this._.length); + return this._[i]; + }, this)); + } - SCParser.prototype.match = function(value) { - return this._match(value, Token.Punctuator); - }; + i = mathlib.clip_idx($index.__int__(), this._.length); - SCParser.prototype.matchKeyword = function(value) { - return this._match(value, Token.Keyword); - }; + return this._[i]; + }, "index"); - SCParser.prototype.matchAny = function(list) { - var value, i, imax; + spec.wrapAt = fn(function($index) { + var i; - if (this.lookahead.type === Token.Punctuator) { - value = this.lookahead.value; - for (i = 0, imax = list.length; i < imax; ++i) { - if (list[i] === value) { - return value; - } + if (Array.isArray($index._)) { + return $SC.Array($index._.map(function($index) { + var i = mathlib.wrap_idx($index.__int__(), this._.length); + return this._[i]; + }, this)); } - } - return null; - }; + i = mathlib.wrap_idx($index.__int__(), this._.length); - SCParser.prototype.withScope = function(fn) { - var result; + return this._[i]; + }, "index"); - this.scope.begin(); - result = fn.call(this); - this.scope.end(); + spec.foldAt = fn(function($index) { + var i; - return result; - }; + if (Array.isArray($index._)) { + return $SC.Array($index._.map(function($index) { + var i = mathlib.fold_idx($index.__int__(), this._.length); + return this._[i]; + }, this)); + } - // 1. Program - SCParser.prototype.parseProgram = function() { - var node; + i = mathlib.fold_idx($index.__int__(), this._.length); - this.skipComment(); - this.markStart(); - this.peek(); + return this._[i]; + }, "index"); - node = this.withScope(function() { - var body; + spec.put = fn(function($index, $item) { + var i; - body = this.parseFunctionBody(""); - if (body.length === 1 && body[0].type === Syntax.BlockExpression) { - body = body[0].body; + this._ThrowIfImmutable(); + + 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.createProgram(body); - }); + return this; + }, "index; item"); - return this.markEnd(node); - }; + spec.clipPut = fn(function($index, $item) { + this._ThrowIfImmutable(); - // 2. Function - // 2.1 Function Expression - SCParser.prototype.parseFunctionExpression = function(closed, blocklist) { - var node; + if (Array.isArray($index._)) { + $index._.forEach(function($index) { + this._[mathlib.clip_idx($index.__int__(), this._.length)] = this.__elem__($item); + }, this); + } else { + this._[mathlib.clip_idx($index.__int__(), this._.length)] = this.__elem__($item); + } - node = this.withScope(function() { - var args, body; + return this; + }, "index; item"); - if (this.match("|")) { - args = this.parseFunctionArgument("|"); - } else if (this.matchKeyword("arg")) { - args = this.parseFunctionArgument(";"); + spec.wrapPut = fn(function($index, $item) { + this._ThrowIfImmutable(); + + if (Array.isArray($index._)) { + $index._.forEach(function($index) { + this._[mathlib.wrap_idx($index.__int__(), this._.length)] = this.__elem__($item); + }, this); + } else { + this._[mathlib.wrap_idx($index.__int__(), this._.length)] = this.__elem__($item); } - body = this.parseFunctionBody("}"); - return this.createFunctionExpression(args, body, closed, false, blocklist); - }); + return this; + }, "index; item"); - return node; - }; + spec.foldPut = fn(function($index, $item) { + this._ThrowIfImmutable(); - // 2.2 Function Argument - SCParser.prototype.parseFunctionArgument = function(expect) { - var args = { list: [] }, lookahead; + if (Array.isArray($index._)) { + $index._.forEach(function($index) { + this._[mathlib.fold_idx($index.__int__(), this._.length)] = this.__elem__($item); + }, this); + } else { + this._[mathlib.fold_idx($index.__int__(), this._.length)] = this.__elem__($item); + } - this.lex(); + return this; + }, "index; item"); - if (!this.match("...")) { - do { - args.list.push(this.parseFunctionArgumentElement()); - if (!this.match(",")) { - break; - } - this.lex(); - } while (this.lookahead.type !== Token.EOF); - } + spec.removeAt = fn(function($index) { + var raw = this._; + var index; - if (this.match("...")) { - this.lex(); - lookahead = this.lookahead; - args.remain = this.parseVariableIdentifier(); - this.scope.add("arg", args.remain.name); - } + this._ThrowIfImmutable(); - this.expect(expect); + index = $index.__int__(); + if (index < 0 || raw.length <= index) { + throw new Error("out of index"); + } - return args; - }; + return raw.splice(index, 1)[0]; + }, "index"); - SCParser.prototype._parseArgVarElement = function(type, method) { - var init = null, id; + spec.takeAt = fn(function($index) { + var raw = this._; + var index, ret, instead; - this.skipComment(); - this.markStart(); - id = this.parseVariableIdentifier(); - this.scope.add(type, id.name); + this._ThrowIfImmutable(); - if (this.match("=")) { - this.lex(); - init = this[method](); - } + index = $index.__int__(); + if (index < 0 || raw.length <= index) { + throw new Error("out of index"); + } - return this.markEnd(this.createVariableDeclarator(id, init)); - }; + ret = raw[index]; + instead = raw.pop(); + if (index !== raw.length) { + raw[index] = instead; + } - SCParser.prototype.parseFunctionArgumentElement = function() { - // literal or immurable array of literals - return this._parseArgVarElement("arg", "parseUnaryExpression"); - }; + return ret; + }, "index"); - // 2.3 Function Body - SCParser.prototype.parseFunctionBody = function(match) { - var elements = []; + spec.indexOf = fn(function($item) { + var index; - while (this.matchKeyword("var")) { - elements.push(this.parseVariableDeclaration()); - } + index = this._.indexOf($item); + return index === -1 ? $nil : $SC.Integer(index); + }, "item"); - while (this.lookahead.type !== Token.EOF && !this.match(match)) { - elements.push(this.parseExpression()); - if (this.lookahead.type !== Token.EOF && !this.match(match)) { - this.expect(";"); - } else { - break; + spec.indexOfGreaterThan = fn(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 $SC.Integer(i); + } } - } - return elements; - }; + return $nil; + }, "val"); - // 3. Variable Declarations - SCParser.prototype.parseVariableDeclaration = function() { - var declaration; + spec.takeThese = fn(function($func) { + var raw = this._; + var i = 0, $i; - this.skipComment(); - this.markStart(); + $i = $SC.Integer(i); + while (i < raw.length) { + if (BOOL($func.value(raw[i], $i))) { + this.takeAt($i); + } else { + $i = $SC.Integer(++i); + } + } - this.lex(); // var + return this; + }, "func"); - declaration = this.markEnd( - this.createVariableDeclaration( - this.parseVariableDeclarationList(), "var" - ) - ); + spec.replace = fn(function($find, $replace) { + var $index, $out, $array; - this.expect(";"); + this._ThrowIfImmutable(); - return declaration; - }; + $out = $SC.Array(); + $array = this; + $find = $find.asArray(); + $replace = $replace.asArray(); + $SC.Function(function() { + return ($index = $array.find($find)).notNil(); + }).while($SC.Function(function() { + $out = $out ["++"] ($array.keep($index)) ["++"] ($replace); + $array = $array.drop($index ["+"] ($find.size())); + })); - SCParser.prototype.parseVariableDeclarationList = function() { - var list = []; + return $out ["++"] ($array); + }, "find; replace"); - do { - list.push(this.parseVariableDeclarationElement()); - if (!this.match(",")) { - break; - } - this.lex(); - } while (this.lookahead.type !== Token.EOF); + spec.slotSize = function() { + return this.size(); + }; - return list; - }; + spec.slotAt = function($index) { + return this.at($index); + }; - SCParser.prototype.parseVariableDeclarationElement = function() { - return this._parseArgVarElement("var", "parseAssignmentExpression"); - }; + spec.slotPut = function($index, $value) { + return this.put($index, $value); + }; - // 4. Expression - SCParser.prototype.parseExpression = function(node) { - return this.parseAssignmentExpression(node); - }; + spec.slotKey = function($index) { + return $index; + }; - // 4.1 Expressions - SCParser.prototype.parseExpressions = function(node) { - var nodes = []; + spec.slotIndex = utils.alwaysReturn$nil; - if (node) { - nodes.push(node); - this.lex(); - } + spec.getSlots = function() { + return this.copy(); + }; - while (this.lookahead.type !== Token.EOF && !this.matchAny([ ",", ")", "]", ".." ])) { - this.skipComment(); - this.markStart(); - node = this.parseAssignmentExpression(); - this.markEnd(node); - nodes.push(node); - if (this.match(";")) { - this.lex(); - } - } + spec.setSlots = function($array) { + return this.overWrite($array); + }; - if (nodes.length === 0) { - this.throwUnexpected(this.lookahead); - } + spec.atModify = fn(function($index, $function) { + this.put($index, $function.value(this.at($index), $index)); + return this; + }, "index; function"); - return nodes.length === 1 ? nodes[0] : nodes; - }; + spec.atInc = fn(function($index, $inc) { + this.put($index, this.at($index) ["+"] ($inc)); + return this; + }, "index; inc=1"); - // 4.2 Assignment Expression - SCParser.prototype.parseAssignmentExpression = function(node) { - var token; + spec.atDec = fn(function($index, $dec) { + this.put($index, this.at($index) ["-"] ($dec)); + return this; + }, "index; dec=1"); - if (node) { - return this.parsePartialExpression(node); - } + spec.isArray = utils.alwaysReturn$true; + spec.asArray = utils.nop; - this.skipComment(); - this.markStart(); + spec.copyRange = fn(function($start, $end) { + var start, end, instance, raw; - if (this.match("#")) { - token = this.lex(true); - if (this.matchAny([ "[", "{" ])) { - token.restore(); + if ($start === $nil) { + start = 0; } else { - node = this.parseDestructuringAssignmentExpression(); + start = $start.__int__(); } - } - - if (!node) { - node = this.parseSimpleAssignmentExpression(); - } + if ($end === $nil) { + end = this._.length; + } else { + end = $end.__int__(); + } + raw = this._.slice(start, end + 1); - return this.markEnd(node); - }; + instance = new this.__Spec(); + instance._ = raw; + return instance; + }, "start; end"); - SCParser.prototype.parseDestructuringAssignmentExpression = function() { - var node, left, right, token; + spec.copySeries = fn(function($first, $second, $last) { + var i, first, second, last, step, instance, raw; - left = this.parseDestructuringAssignmentLeft(); - token = this.lookahead; - this.expect("="); + 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; - right = this.parseAssignmentExpression(); - node = this.createAssignmentExpression( - token.value, left.list, right, left.remain - ); + 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]); + } + } - return node; - }; + instance = new this.__Spec(); + instance._ = raw; + return instance; + }, "first; second; last"); - SCParser.prototype.parseSimpleAssignmentExpression = function() { - var node, left, right, token; + spec.putSeries = fn(function($first, $second, $last, $value) { + var i, first, second, last, step; - node = left = this.parsePartialExpression(); + this._ThrowIfImmutable(); - if (this.match("=")) { - if (node.type === Syntax.CallExpression) { - token = this.lex(); - right = this.parseAssignmentExpression(); - left.method.name = this.getAssignMethod(left.method.name); - left.args.list = node.args.list.concat(right); - /* istanbul ignore else */ - if (this.opts.range) { - left.range[1] = this.index; - } - /* istanbul ignore else */ - if (this.opts.loc) { - left.loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - } - node = left; + if ($first === $nil) { + first = 0; } else { - // TODO: fix - if (!this.isLeftHandSide(left)) { - this.throwError({}, Message.InvalidLHSInAssignment); - } - - token = this.lex(); - right = this.parseAssignmentExpression(); - node = this.createAssignmentExpression( - token.value, left, right - ); + first = $first.__int__(); } - } - - return node; - }; - - SCParser.prototype.getAssignMethod = function(methodName) { - switch (methodName) { - case "at": - return "put"; - case "copySeries": - return "putSeries"; - } - return methodName + "_"; - }; + 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; - SCParser.prototype.parseDestructuringAssignmentLeft = function() { - var params = { list: [] }, element; + $value = this.__elem__($value); - do { - element = this.parseLeftHandSideExpression(); - if (!this.isLeftHandSide(element)) { - this.throwError({}, Message.InvalidLHSInAssignment); - } - params.list.push(element); - if (this.match(",")) { - this.lex(); - } else if (this.match("...")) { - this.lex(); - params.remain = this.parseLeftHandSideExpression(); - if (!this.isLeftHandSide(params.remain)) { - this.throwError({}, Message.InvalidLHSInAssignment); + 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; } - break; } - } while (this.lookahead.type !== Token.EOF && !this.match("=")); - return params; - }; - - // 4.3 Partial Expression - SCParser.prototype.parsePartialExpression = function(node) { - var underscore, x, y; + return this; + }, "first; second; last; value"); - if (this.state.innerElements) { - node = this.parseBinaryExpression(node); - } else { - underscore = this.state.underscore; - this.state.underscore = []; + spec.add = fn(function($item) { + this._ThrowIfImmutable(); + this._.push(this.__elem__($item)); - node = this.parseBinaryExpression(node); + return this; + }, "item"); - if (this.state.underscore.length) { - node = this.withScope(function() { - var args, i, imax; + spec.addAll = fn(function($aCollection) { + var $this = this; - args = new Array(this.state.underscore.length); - for (i = 0, imax = args.length; i < imax; ++i) { - x = this.state.underscore[i]; - y = this.createVariableDeclarator(x); - /* istanbul ignore else */ - if (x.range) { - y.range = x.range; - } - /* istanbul ignore else */ - if (x.loc) { - y.loc = x.loc; - } - args[i] = y; - this.scope.add("arg", this.state.underscore[i].name); - } + this._ThrowIfImmutable(); - return this.createFunctionExpression( - { list: args }, [ node ], false, true, false - ); - }); + if ($aCollection.isSequenceableCollection().valueOf()) { + $aCollection.do($SC.Function(function($item) { + $this._.push($this.__elem__($item)); + })); + } else { + this.add($aCollection); } - this.state.underscore = underscore; - } - - return node; - }; + return this; + }, "aCollection"); - // 4.4 Conditional Expression - // 4.5 Binary Expression - SCParser.prototype.parseBinaryExpression = function(node) { - var marker, left, token, prec; + spec.putEach = fn(function($keys, $values) { + var keys, values, i, imax; - this.skipComment(); + this._ThrowIfImmutable(); - marker = this.createLocationMarker(); - left = this.parseUnaryExpression(node); - token = this.lookahead; + $keys = $keys.asArray(); + $values = $values.asArray(); - prec = this.binaryPrecedence(token); - if (prec === 0) { - if (node) { - return this.parseUnaryExpression(node); + keys = $keys._; + values = $values._; + for (i = 0, imax = keys.length; i < imax; ++i) { + this.put(keys[i], this.__elem__(values[i % values.length])); } - return left; - } - this.lex(); - token.prec = prec; - token.adverb = this.parseAdverb(); + return this; + }, "keys; values"); - return this.sortByBinaryPrecedence(left, token, marker); - }; + spec.extend = fn(function($size, $item) { + var instance, raw, size, i; - SCParser.prototype.sortByBinaryPrecedence = function(left, operator, marker) { - var expr; - var prec, token; - var markers, i; - var right, stack; + 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)); + } + } - markers = [ marker, this.createLocationMarker() ]; - right = this.parseUnaryExpression(); + instance = new this.__Spec(); + instance._ = raw; + return instance; + }, "size; item"); - stack = [ left, operator, right ]; + spec.insert = fn(function($index, $item) { + var index; - while ((prec = this.binaryPrecedence(this.lookahead)) > 0) { - // Reduce: make a binary expression from the three topmost entries. - while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { - right = stack.pop(); - operator = stack.pop(); - left = stack.pop(); - expr = this.createBinaryExpression(operator, left, right); - markers.pop(); + this._ThrowIfImmutable(); - marker = markers.pop(); - /* istanbul ignore else */ - if (marker) { - marker.apply(expr); - } - stack.push(expr); - markers.push(marker); - } + index = Math.max(0, $index.__int__()); + this._.splice(index, 0, this.__elem__($item)); - // Shift. - token = this.lex(); - token.prec = prec; - token.adverb = this.parseAdverb(); + return this; + }, "index; item"); - stack.push(token); - markers.push(this.createLocationMarker()); - expr = this.parseUnaryExpression(); - stack.push(expr); - } + spec.move = function($fromIndex, $toIndex) { + return this.insert($toIndex, this.removeAt($fromIndex)); + }; - // Final reduce to clean-up the stack. - i = stack.length - 1; - expr = stack[i]; - markers.pop(); - while (i > 1) { - expr = this.createBinaryExpression(stack[i - 1], stack[i - 2], expr); - i -= 2; - marker = markers.pop(); - /* istanbul ignore else */ - if (marker) { - marker.apply(expr); - } - } + spec.addFirst = fn(function($item) { + var instance, raw; - return expr; - }; + raw = this._.slice(); + raw.unshift(this.__elem__($item)); - SCParser.prototype.binaryPrecedence = function(token) { - var table, prec = 0; + instance = new this.__Spec(); + instance._ = raw; + return instance; + }, "item"); - if (this.opts.binaryPrecedence) { - if (typeof this.opts.binaryPrecedence === "object") { - table = this.opts.binaryPrecedence; - } else { - table = binaryPrecedenceDefaults; + spec.addIfNotNil = fn(function($item) { + if ($item === $nil) { + return this; } - } else { - table = {}; - } - switch (token.type) { - case Token.Punctuator: - if (token.value !== "=") { - if (table.hasOwnProperty(token.value)) { - prec = table[token.value]; - } else if (/^[-+*\/%<=>!?&|@]+$/.test(token.value)) { - prec = 255; - } + + return this.addFirst(this.__elem__($item)); + }, "item"); + + spec.pop = function() { + if (this._.length === 0) { + return $nil; } - break; - case Token.Label: - prec = 255; - break; - } + this._ThrowIfImmutable(); + return this._.pop(); + }; - return prec; - }; + spec["++"] = function($anArray) { + var instance, raw; - SCParser.prototype.parseAdverb = function() { - var adverb, lookahead; + raw = this._.slice(); - if (this.match(".")) { - this.lex(); + instance = new this.__Spec(); + instance._ = raw; + if ($anArray !== $nil) { + instance.addAll($anArray); + } + return instance; + }; - lookahead = this.lookahead; - adverb = this.parsePrimaryExpression(); + // TODO: implements overWrite + // TODO: implements grow + // TODO: implements growClear - if (adverb.type === Syntax.Literal) { - return adverb; - } + spec.seriesFill = fn(function($start, $step) { + var i, imax; - if (adverb.type === Syntax.Identifier) { - adverb.type = Syntax.Literal; - adverb.value = adverb.name; - adverb.valueType = Token.SymbolLiteral; - delete adverb.name; - return adverb; + for (i = 0, imax = this._.length; i < imax; ++i) { + this.put($SC.Integer(i), $start); + $start = $start ["+"] ($step); } - this.throwUnexpected(lookahead); - } + return this; + }, "start; step"); - return null; - }; + spec.fill = fn(function($value) { + var raw, i, imax; - // 4.6 Unary Expressions - SCParser.prototype.parseUnaryExpression = function(node) { - var token, expr; + this._ThrowIfImmutable(); - this.markStart(); + $value = this.__elem__($value); - if (this.match("`")) { - token = this.lex(); - expr = this.parseUnaryExpression(); - expr = this.createUnaryExpression(token.value, expr); - } else { - expr = this.parseLeftHandSideExpression(node); - } + raw = this._; + for (i = 0, imax = raw.length; i < imax; ++i) { + raw[i] = $value; + } - return this.markEnd(expr); - }; + return this; + }, "value"); - // 4.7 LeftHandSide Expressions - SCParser.prototype.parseLeftHandSideExpression = function(node) { - var marker, expr, prev, lookahead; - var blocklist, stamp; + spec.do = function($function) { + iterator.execute( + iterator.array$do(this), + $function + ); + return this; + }; - this.skipComment(); + spec.reverseDo = function($function) { + iterator.execute( + iterator.array$reverseDo(this), + $function + ); + return this; + }; - marker = this.createLocationMarker(); - expr = this.parsePrimaryExpression(node); + spec.reverse = function() { + var $res = this.copy(); - blocklist = false; + $res._.reverse(); - while ((stamp = this.matchAny([ "(", "{", "#", "[", "." ])) !== null) { - lookahead = this.lookahead; - if ((prev === "{" && (stamp !== "#" && stamp !== "{")) || (prev === "(" && stamp === "(")) { - this.throwUnexpected(lookahead); - } - switch (stamp) { - case "(": - expr = this.parseLeftHandSideParenthesis(expr); - break; - case "#": - expr = this.parseLeftHandSideClosedBrace(expr); - break; - case "{": - expr = this.parseLeftHandSideBrace(expr); - break; - case "[": - expr = this.parseLeftHandSideBracket(expr); - break; - case ".": - expr = this.parseLeftHandSideDot(expr); - break; - } + return $res; + }; - /* istanbul ignore else */ - if (marker) { - marker.apply(expr); + spec.windex = function() { + var raw = this._; + var x, r, i, imax; + + // <-- _ArrayWindex --> + x = 0; + r = rand.next(); + for (i = 0, imax = raw.length; i < imax; ++i) { + x += raw[i].__num__(); + if (x >= r) { + return $SC.Integer(i); + } } - prev = stamp; - } - return expr; - }; + return $int_0; + }; - SCParser.prototype.parseLeftHandSideParenthesis = function(expr) { - if (this.isClassName(expr)) { - return this.parseLeftHandSideClassNew(expr); - } + spec.normalizeSum = function() { + return this ["*"] (this.sum().reciprocal()); + }; - return this.parseLeftHandSideMethodCall(expr); - }; + spec.normalize = fn(function($min, $max) { + var $minItem, $maxItem; - SCParser.prototype.parseLeftHandSideClassNew = function(expr) { - var method, args; + $minItem = this.minItem(); + $maxItem = this.maxItem(); + return this.collect($SC.Function(function($el) { + return $el.linlin($minItem, $maxItem, $min, $max); + })); + }, "min=0.0; max=1.0"); - method = this.markTouch(this.createIdentifier("new")); - args = this.parseCallArgument(); + // TODO: implements asciiPlot + // TODO: implements perfectShuffle + // TODO: implements performInPlace - return this.createCallExpression(expr, method, args, "("); - }; + spec.clipExtend = fn(function($length) { + var last = this._[this._.length - 1] || $nil; + return this.extend($length, last); + }, "length"); - SCParser.prototype.parseLeftHandSideMethodCall = function(expr) { - var method, args, lookahead; + spec.rank = function() { + return $int_1 ["+"] (this.first().rank()); + }; - if (expr.type !== Syntax.Identifier) { - this.throwUnexpected(this.lookahead); - } + spec.shape = function() { + return $SC.Array([ this.size() ]) ["++"] (this.at($int_0).shape()); + }; - lookahead = this.lookahead; - args = this.parseCallArgument(); + spec.reshape = function() { + var $result; + var shape, size, i, imax; - method = expr; - expr = args.list.shift(); + shape = slice.call(arguments); - if (!expr) { - if (args.expand) { - expr = args.expand; - delete args.expand; - } else { - this.throwUnexpected(lookahead); + size = 1; + for (i = 0, imax = shape.length; i < imax; ++i) { + size *= shape[i].__int__(); } - } - // max(0, 1) -> 0.max(1) - return this.createCallExpression(expr, method, args, "("); - }; + $result = this.flat().wrapExtend($SC.Integer(size)); + for (i = imax - 1; i >= 1; --i) { + $result = $result.clump(shape[i]); + } - SCParser.prototype.parseLeftHandSideClosedBrace = function(expr) { - this.lex(); - if (!this.match("{")) { - this.throwUnexpected(this.lookahead); - } + return $result; + }; - this.state.closedFunction = true; - expr = this.parseLeftHandSideBrace(expr); - this.state.closedFunction = false; + spec.reshapeLike = fn(function($another, $indexing) { + var $index, $flat; - return expr; - }; + $index = $int_0; + $flat = this.flat(); - SCParser.prototype.parseLeftHandSideBrace = function(expr) { - var method, lookahead, disallowGenerator, node; + return $another.deepCollect($SC.Integer(0x7FFFFFFF), $SC.Function(function() { + var $item = $flat.perform($indexing, $index); + $index = $index.__inc__(); + return $item; + })); + }, "another; indexing=\\wrapAt"); - if (expr.type === Syntax.CallExpression && expr.stamp && expr.stamp !== "(") { - this.throwUnexpected(this.lookahead); - } - if (expr.type === Syntax.Identifier) { - if (this.isClassName(expr)) { - method = this.markTouch(this.createIdentifier("new")); - expr = this.createCallExpression(expr, method, { list: [] }, "{"); - } else { - expr = this.createCallExpression(null, expr, { list: [] }); + // TODO: implements deepCollect + // TODO: implements deepDo + + spec.unbubble = fn(function($depth, $levels) { + if ($depth.__num__() <= 0) { + if (this.size().__int__() > 1) { + return this; + } + if ($levels.__int__() <= 1) { + return this.at($int_0); + } + return this.at($int_0).unbubble($depth, $levels.__dec__()); } - } - lookahead = this.lookahead; - disallowGenerator = this.state.disallowGenerator; - this.state.disallowGenerator = true; - node = this.parseBraces(true); - this.state.disallowGenerator = disallowGenerator; - // TODO: refactoring - if (expr.callee === null) { - expr.callee = node; - node = expr; - } else { - expr.args.list.push(node); - } + return this.collect($SC.Function(function($item) { + return $item.unbubble($depth.__dec__()); + })); + }, "depth=0; levels=1"); - return expr; - }; + spec.bubble = fn(function($depth, $levels) { + if ($depth.__int__() <= 0) { + if ($levels.__int__() <= 1) { + return $SC.Array([ this ]); + } + return $SC.Array([ this.bubble($depth, $levels.__dec__()) ]); + } - SCParser.prototype.parseLeftHandSideBracket = function(expr) { - if (expr.type === Syntax.CallExpression && expr.stamp === "(") { - this.throwUnexpected(this.lookahead); - } + return this.collect($SC.Function(function($item) { + return $item.bubble($depth.__dec__(), $levels); + })); + }, "depth=0; levels=1"); - if (this.isClassName(expr)) { - expr = this.parseLeftHandSideNewFrom(expr); - } else { - expr = this.parseLeftHandSideListAt(expr); - } - - return expr; - }; + spec.slice = fn(function($$cuts) { + var $firstCut, $list; + var cuts_size, cuts; - SCParser.prototype.parseLeftHandSideNewFrom = function(expr) { - var node, method; + cuts_size = $$cuts.size().__int__(); + if (cuts_size === 0) { + return this.copy(); + } - method = this.markTouch(this.createIdentifier("newFrom")); + $firstCut = $$cuts.at($int_0); + if ($firstCut === $nil) { + $list = this.copy(); + } else { + $list = this.at($firstCut.asArray()); + } - this.skipComment(); - this.markStart(); + if (cuts_size === 1) { + return $list.unbubble(); + } - node = this.markEnd(this.parseListInitialiser()); + cuts = $$cuts._.slice(1); + return $list.collect($SC.Function(function($item) { + return $item.slice.apply($item, cuts); + })).unbubble(); + }, "*cuts"); - return this.createCallExpression(expr, method, { list: [ node ] }, "["); - }; + spec.$iota = function() { + var $a; + var args, product, i, imax, a; - SCParser.prototype.parseLeftHandSideListAt = function(expr) { - var indexes, method; + args = arguments; - method = this.markTouch(this.createIdentifier("at")); + product = 1; + for (i = 0, imax = args.length; i < imax; ++i) { + product *= args[i].__int__(); + } - indexes = this.parseListIndexer(); - if (indexes) { - if (indexes.length === 3) { - method.name = "copySeries"; + a = new Array(product); + for (i = 0; i < product; ++i) { + a[i] = $SC.Integer(i); } - } else { - this.throwUnexpected(this.lookahead); - } - return this.createCallExpression(expr, method, { list: indexes }, "["); - }; + $a = $SC.Array(a); + return $a.reshape.apply($a, args); + }; - SCParser.prototype.parseLeftHandSideDot = function(expr) { - var method, args; + // TODO: implements asRandomTable + // TODO: implements tableRand + // TODO: implements msgSize + // TODO: implements bundleSize + // TODO: implements clumpBundles - this.lex(); + spec.includes = function($item) { + return $SC.Boolean(this._.indexOf($item) !== -1); + }; + }); - if (this.match("(")) { - // expr.() - return this.parseLeftHandSideDotValue(expr); - } else if (this.match("[")) { - // expr.[0] - return this.parseLeftHandSideDotBracket(expr); - } + sc.lang.klass.refine("RawArray", function(spec, utils) { + spec.archiveAsCompileString = utils.alwaysReturn$true; + spec.archiveAsObject = utils.alwaysReturn$true; + spec.rate = function() { + return $SC.Symbol("scalar"); + }; - method = this.parseProperty(); - if (this.match("(")) { - // expr.method(args) - args = this.parseCallArgument(); - return this.createCallExpression(expr, method, args); - } + // TODO: implements readFromStream + // TODO: implements powerset + }); - // expr.method - return this.createCallExpression(expr, method, { list: [] }); - }; +})(sc); - SCParser.prototype.parseLeftHandSideDotValue = function(expr) { - var method, args; +// src/sc/lang/classlib/Collections/String.js +(function(sc) { - method = this.markTouch(this.createIdentifier("value")); - args = this.parseCallArgument(); + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; - return this.createCallExpression(expr, method, args, "."); - }; + sc.lang.klass.refine("String", function(spec, utils) { + var $nil = utils.$nil; + var $false = utils.$false; - SCParser.prototype.parseLeftHandSideDotBracket = function(expr) { - var save, method; + spec.__str__ = function() { + return this.valueOf(); + }; - save = expr; - method = this.markTouch(this.createIdentifier("value")); - expr = this.markTouch(this.createCallExpression(expr, method, { list: [] }, ".")); + spec.__elem__ = function($item) { + if ($item.__tag !== 1028) { + throw new TypeError("Wrong type."); + } + return $item; + }; - /* istanbul ignore else */ - if (this.opts.range) { - expr.range[0] = save.range[0]; - } + spec.valueOf = function() { + return this._.map(function(elem) { + return elem.__str__(); + }).join(""); + }; - /* istanbul ignore else */ - if (this.opts.loc) { - expr.loc.start = save.loc.start; - } + spec.toString = function() { + return this.valueOf(); + }; - return this.parseLeftHandSideListAt(expr); - }; + // TODO: implements unixCmdActions + // TODO: implements unixCmdActions_ - SCParser.prototype.parseCallArgument = function() { - var args, node, hasKeyword, lookahead; + spec.$new = function() { + throw new Error("String.new is illegal, should use literal."); + }; - args = { list: [] }; - hasKeyword = false; + // TODO: implements $initClass + // TODO: implements $doUnixCmdAction + // TODO: implements unixCmd + // TODO: implements unixCmdGetStdOut - this.expect("("); + spec.asSymbol = function() { + return $SC.Symbol(this.__str__()); + }; - while (this.lookahead.type !== Token.EOF && !this.match(")")) { - lookahead = this.lookahead; - if (!hasKeyword) { - if (this.match("*")) { - this.lex(); - args.expand = this.parseExpressions(); - hasKeyword = true; - } else if (lookahead.type === Token.Label) { - this.parseCallArgumentKeyword(args); - hasKeyword = true; - } else { - node = this.parseExpressions(); - args.list.push(node); - } - } else { - if (lookahead.type !== Token.Label) { - this.throwUnexpected(lookahead); - } - this.parseCallArgumentKeyword(args); - } - if (this.match(")")) { - break; - } - this.expect(","); - } + spec.asInteger = function() { + var m = /^[-+]?\d+/.exec(this.__str__()); + return $SC.Integer(m ? m[0]|0 : 0); + }; - this.expect(")"); + spec.asFloat = function() { + var m = /^[-+]?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?/.exec(this.__str__()); + return $SC.Float(m ? +m[0] : 0); + }; - return args; - }; + spec.ascii = function() { + var raw = this.__str__(); + var a, i, imax; - SCParser.prototype.parseCallArgumentKeyword = function(args) { - var key, value; + a = new Array(raw.length); + for (i = 0, imax = a.length; i < imax; ++i) { + a[i] = $SC.Integer(raw.charCodeAt(i)); + } - key = this.lex().value; - value = this.parseExpressions(); - if (!args.keywords) { - args.keywords = {}; - } - args.keywords[key] = value; - }; + return $SC.Array(a); + }; - SCParser.prototype.parseListIndexer = function() { - var node = null; + // TODO: implements stripRTF + // TODO: implements stripHTML + // TODO: implements $scDir - this.expect("["); + spec.compare = fn(function($aString, $ignoreCase) { + var araw, braw, length, i, a, b, cmp, func; - if (!this.match("]")) { - if (this.match("..")) { - // [..last] / [..] - node = this.parseListIndexerWithoutFirst(); + if ($aString.__tag !== 1034) { + return $nil; + } + + araw = this._; + braw = $aString._; + length = Math.min(araw.length, braw.length); + + if ($ignoreCase.__bool__()) { + func = function(ch) { + return ch.toLowerCase(); + }; } else { - // [first] / [first..last] / [first, second..last] - node = this.parseListIndexerWithFirst(); + func = function(ch) { + return ch; + }; + } + for (i = 0; i < length; i++) { + a = func(araw[i]._).charCodeAt(0); + b = func(braw[i]._).charCodeAt(0); + cmp = a - b; + if (cmp !== 0) { + return $SC.Integer(cmp < 0 ? -1 : +1); + } } - } - this.expect("]"); + if (araw.length < braw.length) { + cmp = -1; + } else if (araw.length > braw.length) { + cmp = 1; + } - if (node === null) { - this.throwUnexpected({ value: "]" }); - } + return $SC.Integer(cmp); + }, "aString; ignoreCase=false"); - return node; - }; + spec["<"] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() < 0 + ); + }; - SCParser.prototype.parseListIndexerWithoutFirst = function() { - var last; + spec[">"] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() > 0 + ); + }; - this.lex(); + spec["<="] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() <= 0 + ); + }; - if (!this.match("]")) { - last = this.parseExpressions(); + spec[">="] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() >= 0 + ); + }; - // [..last] - return [ null, null, last ]; - } + spec["=="] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() === 0 + ); + }; - // [..] - return [ null, null, null ]; - }; + spec["!="] = function($aString) { + return $SC.Boolean( + this.compare($aString, $false).valueOf() !== 0 + ); + }; - SCParser.prototype.parseListIndexerWithFirst = function() { - var first = null; + // TODO: implements hash - if (!this.match(",")) { - first = this.parseExpressions(); - } else { - this.throwUnexpected(this.lookahead); - } + spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber) { + return $aNumber.asString().perform($aSelector, this); + }; - if (this.match("..")) { - return this.parseListIndexerWithoutSecond(first); - } else if (this.match(",")) { - return this.parseListIndexerWithSecond(first); - } + spec.performBinaryOpOnComplex = function($aSelector, $aComplex) { + return $aComplex.asString().perform($aSelector, this); + }; - // [first] - return [ first ]; - }; + spec.multiChannelPerform = function() { + throw new Error("String:multiChannelPerform. Cannot expand strings."); + }; - SCParser.prototype.parseListIndexerWithoutSecond = function(first) { - var last = null; + spec.isString = utils.alwaysReturn$true; - this.lex(); + spec.asString = utils.nop; - if (!this.match("]")) { - last = this.parseExpressions(); - } + spec.asCompileString = function() { + return $SC.String("\"" + this.__str__() + "\""); + }; - // [first..last] - return [ first, null, last ]; - }; + spec.species = function() { + return $SC("String"); + }; - SCParser.prototype.parseListIndexerWithSecond = function(first) { - var second, last = null; + // TODO: implements postln + // TODO: implements post + // TODO: implements postcln + // TODO: implements postc + // TODO: implements postf + // TODO: implements format + // TODO: implements matchRegexp + // TODO: implements fformat + // TODO: implements die + // TODO: implements error + // TODO: implements warn + // TODO: implements inform - this.lex(); + spec["++"] = function($anObject) { + return $SC.String( + this.toString() + $anObject.asString().toString() + ); + }; - second = this.parseExpressions(); - if (this.match("..")) { - this.lex(); - if (!this.match("]")) { - last = this.parseExpressions(); - } - } else { - this.throwUnexpected(this.lookahead); - } + spec["+"] = function($anObject) { + return $SC.String( + this.toString() + " " + $anObject.asString().toString() + ); + }; - // [first, second..last] - return [ first, second, last ]; - }; + // TODO: implements catArgs + // TODO: implements scatArgs + // TODO: implements ccatArgs + // TODO: implements catList + // TODO: implements scatList + // TODO: implements ccatList + // TODO: implements split + // TODO: implements containsStringAt + // TODO: implements icontainsStringAt + // TODO: implements contains + // TODO: implements containsi + // TODO: implements findRegexp + // TODO: implements findAllRegexp + // TODO: implements find + // TODO: implements findBackwards + // TODO: implements endsWith + // TODO: implements beginsWith + // TODO: implements findAll + // TODO: implements replace + // TODO: implements escapeChar + // TODO: implements shellQuote + // TODO: implements quote + // TODO: implements tr + // TODO: implements insert + // TODO: implements wrapExtend + // TODO: implements zeroPad + // TODO: implements padLeft + // TODO: implements padRight + // TODO: implements underlined + // TODO: implements scramble + // TODO: implements rotate + // TODO: implements compile + // TODO: implements interpret + // TODO: implements interpretPrint + // TODO: implements $readNew + // TODO: implements printOn + // TODO: implements storeOn + // TODO: implements inspectorClass + // TODO: implements standardizePath + // TODO: implements realPath + // TODO: implements withTrailingSlash + // TODO: implements withoutTrailingSlash + // TODO: implements absolutePath + // TODO: implements pathMatch + // TODO: implements load + // TODO: implements loadPaths + // TODO: implements loadRelative + // TODO: implements resolveRelative + // TODO: implements include + // TODO: implements exclude + // TODO: implements basename + // TODO: implements dirname + // TODO: implements splittext + // TODO: implements +/+ + // TODO: implements asRelativePath + // TODO: implements asAbsolutePath + // TODO: implements systemCmd + // TODO: implements gethostbyname + // TODO: implements getenv + // TODO: implements setenv + // TODO: implements unsetenv + // TODO: implements codegen_UGenCtorArg + // TODO: implements ugenCodeString + // TODO: implements asSecs + // TODO: implements speak + // TODO: implements toLower + // TODO: implements toUpper + // TODO: implements mkdir + // TODO: implements parseYAML + // TODO: implements parseYAMLFile + }); - SCParser.prototype.parseProperty = function() { - var token; +})(sc); - this.skipComment(); - this.markStart(); - token = this.lex(); +// src/sc/lang/classlib/Collections/Set.js +(function(sc) { - if (token.type !== Token.Identifier || this.isClassName(token)) { - this.throwUnexpected(token); - } + function SCSet() { + this.__initializeWith__("Collection"); + } - return this.markEnd(this.createIdentifier(token.value)); - }; + sc.lang.klass.define(SCSet, "Set : Collection", function() { + // TODO: implements species + // TODO: implements copy + // TODO: implements do + // TODO: implements clear + // TODO: implements makeEmpty + // TODO: implements includes + // TODO: implements findMatch + // TODO: implements add + // TODO: implements remove + // TODO: implements choose + // TODO: implements pop + // TODO: implements powerset + // TODO: implements unify + // TODO: implements sect + // TODO: implements union + // TODO: implements difference + // TODO: implements symmetricDifference + // TODO: implements isSubsetOf + // TODO: implements initSet + // TODO: implements putCheck + // TODO: implements fullCheck + // TODO: implements grow + // TODO: implements noCheckAdd + // TODO: implements scanFor + // TODO: implements fixCollisionsFrom + // TODO: implements keyAt + // TODO: implements asSet + }); - // 4.8 Primary Expressions - SCParser.prototype.parsePrimaryExpression = function(node) { - var expr; +})(sc); - if (node) { - return node; - } +// src/sc/lang/classlib/Collections/Dictionary.js +(function(sc) { - this.skipComment(); - this.markStart(); + function SCDictionary() { + this.__initializeWith__("Set"); + this._ = {}; + } - if (this.match("~")) { - this.lex(); - expr = this.createGlobalExpression(this.parseIdentifier()); - } else { - - switch (this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type) { - case "(": - expr = this.parseParentheses(); - break; - case "{": - expr = this.parseBraces(); - break; - case "[": - expr = this.parseListInitialiser(); - break; - case "#": - expr = this.parsePrimaryHashedExpression(); - break; - case Token.Keyword: - expr = this.parsePrimaryKeywordExpression(); - break; - case Token.Identifier: - expr = this.parsePrimaryIdentifier(); - break; - case Token.CharLiteral: - case Token.FloatLiteral: - case Token.FalseLiteral: - case Token.IntegerLiteral: - case Token.NilLiteral: - case Token.SymbolLiteral: - case Token.TrueLiteral: - expr = this.createLiteral(this.lex()); - break; - case Token.StringLiteral: - expr = this.parsePrimaryStringExpression(); - break; - } - } + sc.lang.klass.define(SCDictionary, "Dictionary : Set", function() { + // TODO: implements $newFrom + // TODO: implements at + // TODO: implements atFail + // TODO: implements matchAt + // TODO: implements trueAt + // TODO: implements add + // TODO: implements put + // TODO: implements putAll + // TODO: implements putPairs + // TODO: implements getPairs + // TODO: implements associationAt + // TODO: implements associationAtFail + // TODO: implements keys + // TODO: implements values + // TODO: implements includes + // TODO: implements includesKey + // TODO: implements removeAt + // TODO: implements removeAtFail + // TODO: implements remove + // TODO: implements removeFail + // TODO: implements keysValuesDo + // TODO: implements keysValuesChange + // TODO: implements do + // TODO: implements keysDo + // TODO: implements associationsDo + // TODO: implements pairsDo + // TODO: implements collect + // TODO: implements select + // TODO: implements reject + // TODO: implements invert + // TODO: implements merge + // TODO: implements blend + // TODO: implements findKeyForValue + // TODO: implements sortedKeysValuesDo + // TODO: implements choose + // TODO: implements order + // TODO: implements powerset + // TODO: implements transformEvent + // TODO: implements embedInStream + // TODO: implements asSortedArray + // TODO: implements asKeyValuePairs + // TODO: implements keysValuesArrayDo + // TODO: implements grow + // TODO: implements fixCollisionsFrom + // TODO: implements scanFor + // TODO: implements storeItemsOn + // TODO: implements printItemsOn + }); - if (!expr) { - expr = {}; - this.throwUnexpected(this.lex()); - } + function SCIdentityDictionary() { + this.__initializeWith__("Dictionary"); + } - return this.markEnd(expr); - }; + sc.lang.klass.define(SCIdentityDictionary, "IdentityDictionary : Dictionary", function() { + // TODO: implements at + // TODO: implements put + // TODO: implements putGet + // TODO: implements includesKey + // TODO: implements findKeyForValue + // TODO: implements scanFor + // TODO: implements freezeAsParent + // TODO: implements insertParent + // TODO: implements storeItemsOn + // TODO: implements doesNotUnderstand + // TODO: implements nextTimeOnGrid + // TODO: implements asQuant + // TODO: implements timingOffset + }); - SCParser.prototype.parsePrimaryHashedExpression = function() { - var expr, lookahead; +})(sc); - lookahead = this.lookahead; +// src/sc/lang/classlib/Collections/Environment.js +(function(sc) { - this.lex(); + function SCEnvironment() { + this.__initializeWith__("IdentityDictionary"); + } - switch (this.matchAny([ "[", "{" ])) { - case "[": - expr = this.parsePrimaryImmutableListExpression(lookahead); - break; - case "{": - expr = this.parsePrimaryClosedFunctionExpression(); - break; - default: - expr = {}; - this.throwUnexpected(this.lookahead); - break; - } + sc.lang.klass.define(SCEnvironment, "Environment : IdentityDictionary", function() { + // TODO: implements $make + // TODO: implements $use + // TODO: implements make + // TODO: implements use + // TODO: implements eventAt + // TODO: implements composeEvents + // TODO: implements $pop + // TODO: implements $push + // TODO: implements pop + // TODO: implements push + // TODO: implements linkDoc + // TODO: implements unlinkDoc + }); - return expr; - }; +})(sc); - SCParser.prototype.parsePrimaryImmutableListExpression = function(lookahead) { - var expr; +// src/sc/lang/classlib/Collections/Event.js +(function(sc) { - if (this.state.immutableList) { - this.throwUnexpected(lookahead); - } + function SCEvent() { + this.__initializeWith__("Environment"); + } - this.state.immutableList = true; - expr = this.parseListInitialiser(); - this.state.immutableList = false; + sc.lang.klass.define(SCEvent, "Event : Environment", function() { + // TODO: implements $default + // TODO: implements $silent + // TODO: implements $addEventType + // TODO: implements next + // TODO: implements delta + // TODO: implements play + // TODO: implements isRest + // TODO: implements isPlaying_ + // TODO: implements isRunning_ + // TODO: implements playAndDelta + // TODO: implements synchWithQuant + // TODO: implements asControlInput + // TODO: implements asUGenInput + // TODO: implements printOn + // TODO: implements storeOn + // TODO: implements $initClass + // TODO: implements $makeDefaultSynthDef + // TODO: implements $makeParentEvents + }); - return expr; - }; +})(sc); - SCParser.prototype.parsePrimaryClosedFunctionExpression = function() { - var expr, disallowGenerator, closedFunction; +// src/sc/lang/classlib/Collections/Array.js +(function(sc) { - disallowGenerator = this.state.disallowGenerator; - closedFunction = this.state.closedFunction; + var slice = [].slice; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var rand = sc.libs.random; + var mathlib = sc.libs.mathlib; - this.state.disallowGenerator = true; - this.state.closedFunction = true; - expr = this.parseBraces(); - this.state.closedFunction = closedFunction; - this.state.disallowGenerator = disallowGenerator; + sc.lang.klass.refine("Array", function(spec, utils) { + var BOOL = utils.BOOL; + var $nil = utils.$nil; + var SCArray = $SC("Array"); - return expr; - }; + spec.$with = function() { + return $SC.Array(slice.call(arguments)); + }; - SCParser.prototype.parsePrimaryKeywordExpression = function() { - if (Keywords[this.lookahead.value] === "keyword") { - this.throwUnexpected(this.lookahead); - } + spec.reverse = function() { + // <-- _ArrayReverse --> + return $SC.Array(this._.slice().reverse()); + }; - return this.createThisExpression(this.lex().value); - }; + spec.scramble = function() { + var a, tmp, i, j, m; - SCParser.prototype.parsePrimaryIdentifier = function() { - var expr, lookahead; + // <-- _ArrayScramble --> + a = this._.slice(); + m = a.length; + if (m > 1) { + for (i = 0; m > 0; ++i, --m) { + j = i + (rand.next() * m)|0; + tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; + } + } - lookahead = this.lookahead; + return $SC.Array(a); + }; - expr = this.parseIdentifier(); + spec.mirror = function() { + var raw = this._; + var size, i, j, imax, a; - if (expr.name === "_") { - expr.name = "$_" + this.state.underscore.length.toString(); - this.state.underscore.push(expr); - } + // <-- _ArrayMirror --> + size = raw.length * 2 - 1; + if (size < 2) { + return $SC.Array(raw.slice(0)); + } - return expr; - }; + a = new Array(size); + for (i = 0, imax = raw.length; i < imax; ++i) { + a[i] = raw[i]; + } + for (j = imax - 2, imax = size; i < imax; ++i, --j) { + a[i] = raw[j]; + } - SCParser.prototype.isInterpolatedString = function(value) { - var re = /(^|[^\x5c])#\{/; - return re.test(value); - }; + return $SC.Array(a); + }; - SCParser.prototype.parsePrimaryStringExpression = function() { - var token; + spec.mirror1 = function() { + var raw = this._; + var size, i, j, imax, a; - token = this.lex(); - - if (this.isInterpolatedString(token.value)) { - return this.parseInterpolatedString(token.value); - } - - return this.createLiteral(token); - }; - - SCParser.prototype.parseInterpolatedString = function(value) { - var len, items; - var index1, index2, code, parser; - - len = value.length; - items = []; - - index1 = 0; - - do { - index2 = findString$InterpolatedString(value, index1); - if (index2 >= len) { - break; - } - code = value.substr(index1, index2 - index1); - if (code) { - items.push('"' + code + '"'); + // <-- _ArrayMirror1 --> + size = raw.length * 2 - 2; + if (size < 2) { + return $SC.Array(raw.slice(0)); } - index1 = index2 + 2; - index2 = findExpression$InterpolatedString(value, index1, items); - - code = value.substr(index1, index2 - index1); - if (code) { - items.push("(" + code + ").asString"); + a = new Array(size); + for (i = 0, imax = raw.length; i < imax; ++i) { + a[i] = raw[i]; + } + for (j = imax - 2, imax = size; i < imax; ++i, --j) { + a[i] = raw[j]; } - index1 = index2 + 1; - } while (index1 < len); + return $SC.Array(a); + }; - if (index1 < len) { - items.push('"' + value.substr(index1) + '"'); - } + spec.mirror2 = function() { + var raw = this._; + var size, i, j, imax, a; - code = items.join("++"); - parser = new SCParser(code, {}); - parser.peek(); + // <-- _ArrayMirror2 --> + size = raw.length * 2; + if (size < 2) { + return $SC.Array(raw.slice(0)); + } - return parser.parseExpression(); - }; + a = new Array(size); + for (i = 0, imax = raw.length; i < imax; ++i) { + a[i] = raw[i]; + } + for (j = imax - 1, imax = size; i < imax; ++i, --j) { + a[i] = raw[j]; + } - var findString$InterpolatedString = function(value, index) { - var len, ch; + return $SC.Array(a); + }; - len = value.length; + spec.stutter = fn(function($n) { + var raw = this._; + var n, a, i, j, imax, k; - while (index < len) { - ch = value.charAt(index); - if (ch === "#") { - if (value.charAt(index + 1) === "{") { - break; + // <-- _ArrayStutter --> + n = Math.max(0, $n.__int__()); + a = new Array(raw.length * n); + for (i = 0, j = 0, imax = raw.length; i < imax; ++i) { + for (k = 0; k < n; ++k, ++j) { + a[j] = raw[i]; } - } else if (ch === "\\") { - index += 1; } - index += 1; - } - return index; - }; - - var findExpression$InterpolatedString = function(value, index) { - var len, depth, ch; + return $SC.Array(a); + }, "n=2"); - len = value.length; + spec.rotate = fn(function($n) { + var raw = this._; + var n, a, size, i, j; - depth = 0; - while (index < len) { - ch = value.charAt(index); - if (ch === "}") { - if (depth === 0) { - break; + // <-- _ArrayRotate --> + n = $n.__int__(); + a = new Array(raw.length); + size = a.length; + n %= size; + if (n < 0) { + n += size; + } + for (i = 0, j = n; i < size; ++i) { + a[j] = raw[i]; + if (++j >= size) { + j = 0; } - depth -= 1; - } else if (ch === "{") { - depth += 1; } - index += 1; - } - - return index; - }; - // ( ... ) - SCParser.prototype.parseParentheses = function() { - var marker, expr, generator, items; - - this.skipComment(); + return $SC.Array(a); + }, "n=1"); - marker = this.createLocationMarker(); - this.expect("("); + spec.pyramid = fn(function($patternType) { + var patternType; + var obj1, obj2, i, j, k, n, numslots, x; - if (this.match(":")) { - this.lex(); - generator = true; - } + obj1 = this._; + obj2 = []; - if (this.lookahead.type === Token.Label) { - expr = this.parseObjectInitialiser(); - } else if (this.matchKeyword("var")) { - expr = this.withScope(function() { - var body; - body = this.parseFunctionBody(")"); - return this.createBlockExpression(body); - }); - } else if (this.match("..")) { - expr = this.parseSeriesInitialiser(null, generator); - } else if (this.match(")")) { - expr = this.createObjectExpression([]); - } else { - items = this.parseParenthesesGuess(generator, marker); - expr = items[0]; - marker = items[1]; - } + patternType = Math.max(1, Math.min($patternType.__int__(), 10)); + x = numslots = obj1.length; - this.expect(")"); + switch (patternType) { + case 1: + n = (x * x + x) >> 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = 0; j <= i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 2: + n = (x * x + x) >> 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 3: + n = (x * x + x) >> 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = 0; j <= numslots - 1 - i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 4: + n = (x * x + x) >> 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 5: + n = x * x; + for (i = k = 0; i < numslots; ++i) { + for (j = 0; j <= i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 0; i < numslots - 1; ++i) { + for (j = 0; j <= numslots - 2 - i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 6: + n = x * x; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 0; i < numslots - 1; ++i) { + for (j = i + 1; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 7: + n = x * x + x - 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = 0; j <= numslots - 1 - i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 1; i < numslots; ++i) { + for (j = 0; j <= i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 8: + n = x * x + x - 1; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 1; i < numslots; ++i) { + for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 9: + n = x * x; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = 0; j <= i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 0; i < numslots - 1; ++i) { + for (j = i + 1; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + case 10: + n = x * x; + for (i = 0, k = 0; i < numslots; ++i) { + for (j = numslots - 1 - i; j <= numslots - 1; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + for (i = 0; i < numslots - 1; ++i) { + for (j = 0; j <= numslots - 2 - i; ++j, ++k) { + obj2[k] = obj1[j]; + } + } + break; + } - /* istanbul ignore else */ - if (marker) { - marker.apply(expr); - } + return $SC.Array(obj2); + }, "n=1"); - return expr; - }; + spec.pyramidg = fn(function($patternType) { + var raw = this._; + var patternType; + var list = [], lastIndex, i; - SCParser.prototype.parseParenthesesGuess = function(generator, marker) { - var node, expr; + patternType = Math.max(1, Math.min($patternType.__int__(), 10)); + lastIndex = raw.length - 1; - node = this.parseExpression(); - if (this.matchAny([ ",", ".." ])) { - expr = this.parseSeriesInitialiser(node, generator); - } else if (this.match(":")) { - expr = this.parseObjectInitialiser(node); - } else if (this.match(";")) { - expr = this.parseExpressions(node); - if (this.matchAny([ ",", ".." ])) { - expr = this.parseSeriesInitialiser(expr, generator); + switch (patternType) { + case 1: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + break; + case 2: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); + } + break; + case 3: + for (i = lastIndex; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + break; + case 4: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(i, lastIndex + 1))); + } + break; + case 5: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + break; + case 6: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); + } + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); + } + break; + case 7: + for (i = lastIndex; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + for (i = 1; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + break; + case 8: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(i, lastIndex + 1))); + } + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(i, lastIndex + 1))); + } + break; + case 9: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + for (i = 1; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(i, lastIndex + 1))); + } + break; + case 10: + for (i = 0; i <= lastIndex; ++i) { + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); + } + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); + } + break; } - marker = null; - } else { - expr = this.parseExpression(node); - marker = null; - } - - return [ expr, marker ]; - }; - - SCParser.prototype.parseObjectInitialiser = function(node) { - var elements = [], innerElements; - - innerElements = this.state.innerElements; - this.state.innerElements = true; - if (node) { - this.expect(":"); - } else { - node = this.parseLabelAsSymbol(); - } - elements.push(node, this.parseExpression()); + return $SC.Array(list); + }, "n=1"); - if (this.match(",")) { - this.lex(); - } + spec.sputter = fn(function($probability, $maxlen) { + var list, prob, maxlen, i, length; - while (this.lookahead.type !== Token.EOF && !this.match(")")) { - if (this.lookahead.type === Token.Label) { - node = this.parseLabelAsSymbol(); - } else { - node = this.parseExpression(); - this.expect(":"); - } - elements.push(node, this.parseExpression()); - if (!this.match(")")) { - this.expect(","); + list = []; + prob = 1.0 - $probability.__num__(); + maxlen = $maxlen.__int__(); + i = 0; + length = this._.length; + while (i < length && list.length < maxlen) { + list.push(this._[i]); + if (rand.next() < prob) { + i += 1; + } } - } - - this.state.innerElements = innerElements; - return this.createObjectExpression(elements); - }; + return $SC.Array(list); + }, "probability=0.25; maxlen=100"); - SCParser.prototype.parseSeriesInitialiser = function(node, generator) { - var method, innerElements; - var items = []; + spec.lace = fn(function($length) { + var raw = this._; + var length, wrap = raw.length; + var a, i, $item; - innerElements = this.state.innerElements; - this.state.innerElements = true; + if ($length === $nil) { + $length = $SC.Integer(wrap); + } - method = this.markTouch(this.createIdentifier( - generator ? "seriesIter" : "series" - )); + length = $length.__int__(); + a = new Array(length); - if (node === null) { - // (..), (..last) - items = this.parseSeriesInitialiserWithoutFirst(generator); - } else { - items = this.parseSeriesInitialiserWithFirst(node, generator); - } + for (i = 0; i < length; ++i) { + $item = raw[i % wrap]; + if (Array.isArray($item._)) { + a[i] = $item._[ ((i / wrap)|0) % $item._.length ]; + } else { + a[i] = $item; + } + } - this.state.innerElements = innerElements; + return $SC.Array(a); + }, "length"); - return this.createCallExpression(items.shift(), method, { list: items }); - }; + spec.permute = fn(function($nthPermutation) { + var raw = this._; + var obj1, obj2, size, $item; + var nthPermutation, i, imax, j; - SCParser.prototype.parseSeriesInitialiserWithoutFirst = function(generator) { - var first, last = null; + obj1 = raw; + obj2 = raw.slice(); + size = raw.length; + nthPermutation = $nthPermutation.__int__(); - // (..last) - first = this.markTouch({ - type: Syntax.Literal, - value: "0", - valueType: Token.IntegerLiteral - }); + for (i = 0, imax = size - 1; i < imax; ++i) { + j = i + nthPermutation % (size - i); + nthPermutation = (nthPermutation / (size - i))|0; - this.expect(".."); - if (this.match(")")) { - if (!generator) { - this.throwUnexpected(this.lookahead); + $item = obj2[i]; + obj2[i] = obj2[j]; + obj2[j] = $item; } - } else { - last = this.parseExpressions(); - } - return [ first, null, last ]; - }; + return $SC.Array(obj2); + }, "nthPermutation=0"); - SCParser.prototype.parseSeriesInitialiserWithFirst = function(node, generator) { - var first, second = null, last = null; + spec.allTuples = fn(function($maxTuples) { + var maxSize; + var obj1, obj2, obj3, obj4, newSize, tupSize; + var i, j, k; - first = node; - if (this.match(",")) { - // (first, second .. last) - this.lex(); - second = this.parseExpressions(); - if (Array.isArray(second) && second.length === 0) { - this.throwUnexpected(this.lookahead); - } - this.expect(".."); - if (!this.match(")")) { - last = this.parseExpressions(); - } else if (!generator) { - this.throwUnexpected(this.lookahead); - } - } else { - // (first..last) - this.lex(); - if (!this.match(")")) { - last = this.parseExpressions(); - } else if (!generator) { - this.throwUnexpected(this.lookahead); - } - } + maxSize = $maxTuples.__int__(); - return [ first, second, last ]; - }; + obj1 = this._; + newSize = 1; + tupSize = obj1.length; + for (i = 0; i < tupSize; ++i) { + if (Array.isArray(obj1[i]._)) { + newSize *= obj1[i]._.length; + } + } + newSize = Math.min(newSize, maxSize); - SCParser.prototype.parseListInitialiser = function() { - var elements, innerElements; + obj2 = new Array(newSize); - elements = []; + for (i = 0; i < newSize; ++i) { + k = i; + obj3 = new Array(tupSize); + for (j = tupSize - 1; j >= 0; --j) { + if (Array.isArray(obj1[j]._)) { + obj4 = obj1[j]._; + obj3[j] = obj4[k % obj4.length]; + k = (k / obj4.length)|0; + } else { + obj3[j] = obj1[j]; + } + } + obj2[i] = $SC.Array(obj3); + } - innerElements = this.state.innerElements; - this.state.innerElements = true; + return $SC.Array(obj2); + }, "maxTuples=16384"); - this.expect("["); + spec.wrapExtend = fn(function($size) { + var raw = this._; + var size, a, i; - while (this.lookahead.type !== Token.EOF && !this.match("]")) { - if (this.lookahead.type === Token.Label) { - elements.push(this.parseLabelAsSymbol(), this.parseExpression()); - } else { - elements.push(this.parseExpression()); - if (this.match(":")) { - this.lex(); - elements.push(this.parseExpression()); + size = Math.max(0, $size.__int__()); + if (raw.length < size) { + a = new Array(size); + for (i = 0; i < size; ++i) { + a[i] = raw[i % raw.length]; } + } else { + a = raw.slice(0, size); } - if (!this.match("]")) { - this.expect(","); - } - } - this.expect("]"); + return $SC.Array(a); + }, "size"); - this.state.innerElements = innerElements; + spec.foldExtend = fn(function($size) { + var raw = this._; + var size, a, i; - return this.createListExpression(elements, this.state.immutableList); - }; + size = Math.max(0, $size.__int__()); - // { ... } - SCParser.prototype.parseBraces = function(blocklist) { - var expr; + if (raw.length < size) { + a = new Array(size); + for (i = 0; i < size; ++i) { + a[i] = raw[mathlib.fold_idx(i, raw.length)]; + } + } else { + a = raw.slice(0, size); + } - this.skipComment(); - this.markStart(); + return $SC.Array(a); + }, "size"); - this.expect("{"); + spec.clipExtend = fn(function($size) { + var raw = this._; + var size, a, i, imax, b; - if (this.match(":")) { - if (!this.state.disallowGenerator) { - this.lex(); - expr = this.parseGeneratorInitialiser(); + size = Math.max(0, $size.__int__()); + + if (raw.length < size) { + a = new Array(size); + for (i = 0, imax = raw.length; i < imax; ++i) { + a[i] = raw[i]; + } + for (b = a[i - 1]; i < size; ++i) { + a[i] = b; + } } else { - expr = {}; - this.throwUnexpected(this.lookahead); + a = raw.slice(0, size); } - } else { - expr = this.parseFunctionExpression(this.state.closedFunction, blocklist); - } - - this.expect("}"); - return this.markEnd(expr); - }; + return $SC.Array(a); + }, "size"); - SCParser.prototype.parseGeneratorInitialiser = function() { - this.throwError({}, Message.NotImplemented, "generator literal"); + spec.slide = fn(function($windowLength, $stepSize) { + var raw = this._; + var windowLength, stepSize; + var obj1, obj2, m, n, numwin, numslots; + var i, j, h, k; - this.parseExpression(); - this.expect(","); + windowLength = $windowLength.__int__(); + stepSize = $stepSize.__int__(); + obj1 = raw; + obj2 = []; + m = windowLength; + n = stepSize; + numwin = ((raw.length + n - m) / n)|0; + numslots = numwin * m; - while (this.lookahead.type !== Token.EOF && !this.match("}")) { - this.parseExpression(); - if (!this.match("}")) { - this.expect(","); + for (i = h = k = 0; i < numwin; ++i,h += n) { + for (j = h; j < m + h; ++j) { + obj2[k++] = obj1[j]; + } } - } - return this.createLiteral({ value: "null", valueType: Token.NilLiteral }); - }; + return $SC.Array(obj2); + }, "windowLength=3; stepSize=1"); - SCParser.prototype.parseLabel = function() { - this.skipComment(); - this.markStart(); - return this.markEnd(this.createLabel(this.lex().value)); - }; + spec.containsSeqColl = function() { + var raw = this._; + var i, imax; - SCParser.prototype.parseLabelAsSymbol = function() { - var label, node; + for (i = 0, imax = raw.length; i < imax; ++i) { + if (BOOL(raw[i].isSequenceableCollection())) { + return $SC.True(); + } + } - label = this.parseLabel(); - node = { - type: Syntax.Literal, - value: label.name, - valueType: Token.SymbolLiteral + return $SC.False(); }; - /* istanbul ignore else */ - if (label.range) { - node.range = label.range; - } - /* istanbul ignore else */ - if (label.loc) { - node.loc = label.loc; - } + spec.unlace = fn(function($clumpSize, $numChan) { + var raw = this._; + var clumpSize, numChan; + var a, b, size, i, j, k; - return node; - }; + clumpSize = $clumpSize.__int__(); + numChan = $numChan .__int__(); + size = (raw.length / clumpSize)|0; + size = size - (size % numChan); + if (size) { + a = new Array(clumpSize); + for (i = 0; i < clumpSize; ++i) { + b = new Array(size); + for (j = 0; j < size; j += numChan) { + for (k = 0; k < numChan; ++k) { + b[j + k] = raw[i * numChan + k + j * clumpSize]; + } + } + a[i] = $SC.Array(b); + } + } else { + a = []; + } + + return $SC.Array(a); + }, "clumpSize=2; numChan=1"); + + // TODO: implements interlace + // TODO: implements deinterlace + + spec.flop = function() { + return this.multiChannelExpand(); + }; - SCParser.prototype.parseIdentifier = function() { - var expr; + spec.multiChannelExpand = function() { + var raw = this._; + var maxSize, size, obj1, obj2, obj3; + var i, j; - this.skipComment(); - this.markStart(); + obj1 = raw; + maxSize = obj1.reduce(function(len, $elem) { + return Math.max(len, Array.isArray($elem._) ? $elem._.length : 1); + }, 0); - if (this.lookahead.type !== Syntax.Identifier) { - this.throwUnexpected(this.lookahead); - } + obj2 = new Array(maxSize); + size = obj1.length; - expr = this.lex(); + if (size === 0) { + obj2[0] = $SC.Array([]); + } else { + for (i = 0; i < maxSize; ++i) { + obj3 = new Array(size); + for (j = 0; j < size; ++j) { + if (Array.isArray(obj1[j]._)) { + obj3[j] = obj1[j]._[i % obj1[j]._.length]; + } else { + obj3[j] = obj1[j]; + } + } + obj2[i] = $SC.Array(obj3); + } + } - return this.markEnd(this.createIdentifier(expr.value)); - }; + return $SC.Array(obj2); + }; - SCParser.prototype.parseVariableIdentifier = function() { - var token, value, ch; + // TODO: implements envirPairs - this.skipComment(); - this.markStart(); + spec.shift = fn(function($n, $filler) { + var $fill, $remain; - token = this.lex(); - value = token.value; + $fill = SCArray.fill($n.abs(), $filler); + $remain = this.drop($n.neg()); - if (token.type !== Token.Identifier) { - this.throwUnexpected(token); - } else { - ch = value.charAt(0); - if (("A" <= ch && ch <= "Z") || ch === "_") { - this.throwUnexpected(token); + if ($n < 0) { + return $remain ["++"] ($fill); } - } - return this.markEnd(this.createIdentifier(value)); - }; + return $fill ["++"] ($remain); + }, "n; fillter=0.0"); - SCParser.prototype.markStart = function() { - /* istanbul ignore else */ - if (this.opts.loc) { - this.marker.push( - this.index - this.lineStart, - this.lineNumber - ); - } - /* istanbul ignore else */ - if (this.opts.range) { - this.marker.push( - this.index - ); - } - }; + spec.powerset = function() { + var raw = this._; + var arrSize, powersize; + var result, elemArr, mod, i, j; - SCParser.prototype.markEnd = function(node) { - if (Array.isArray(node) || node.range || node.loc) { - /* istanbul ignore else */ - if (this.opts.range) { - this.marker.pop(); - } - /* istanbul ignore else */ - if (this.opts.loc) { - this.marker.pop(); - this.marker.pop(); - } - } else { - /* istanbul ignore else */ - if (this.opts.range) { - node.range = [ this.marker.pop(), this.index ]; - } - /* istanbul ignore else */ - if (this.opts.loc) { - node.loc = { - start: { - line: this.marker.pop(), - column: this.marker.pop() - }, - end: { - line: this.lineNumber, - column: this.index - this.lineStart - } - }; - } - } - return node; - }; + arrSize = this.size().__int__(); + powersize = Math.pow(2, arrSize); - SCParser.prototype.markTouch = function(node) { - /* istanbul ignore else */ - if (this.opts.range) { - node.range = [ this.index, this.index ]; - } - /* istanbul ignore else */ - if (this.opts.loc) { - node.loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - }, - end: { - line: this.lineNumber, - column: this.index - this.lineStart + result = []; + for (i = 0; i < powersize; ++i) { + elemArr = []; + for (j = 0; j < arrSize; ++j) { + mod = Math.pow(2, j); + if (((i / mod)|0) % 2) { + elemArr.push(raw[j]); + } } - }; - } - return node; - }; - - SCParser.prototype.throwError = function(token, messageFormat) { - var args, message; - var error, index, lineNumber, column; - var prev; - - args = Array.prototype.slice.call(arguments, 2); - message = messageFormat.replace(/%(\d)/g, function(whole, index) { - return args[index]; - }); + result[i] = $SC.Array(elemArr); + } - if (typeof token.lineNumber === "number") { - index = token.range[0]; - lineNumber = token.lineNumber; - column = token.range[0] - token.lineStart + 1; - } else { - index = this.index; - lineNumber = this.lineNumber; - column = this.index - this.lineStart + 1; - } + return $SC.Array(result); + }; - error = new Error("Line " + lineNumber + ": " + message); - error.index = index; - error.lineNumber = lineNumber; - error.column = column; - error.description = message; + // TODO: implements source - if (this.errors) { - prev = this.errors[this.errors.length - 1]; - if (!(prev && error.index <= prev.index)) { - this.errors.push(error); - } - } else { - throw error; - } - }; + spec.asUGenInput = function($for) { + return this.collect($SC.Function(function($_) { + return $_.asUGenInput($for); + })); + }; - SCParser.prototype.throwUnexpected = function(token) { - switch (token.type) { - case Token.EOF: - this.throwError(token, Message.UnexpectedEOS); - break; - case Token.FloatLiteral: - case Token.IntegerLiteral: - this.throwError(token, Message.UnexpectedNumber); - break; - case Token.CharLiteral: - this.throwError(token, Message.UnexpectedChar); - break; - case Token.StringLiteral: - this.throwError(token, Message.UnexpectedString); - break; - case Token.SymbolLiteral: - this.throwError(token, Message.UnexpectedSymbol); - break; - case Token.Identifier: - this.throwError(token, Message.UnexpectedIdentifier); - break; - default: - this.throwError(token, Message.UnexpectedToken, token.value); - break; - } - }; + spec.asAudioRateInput = function($for) { + return this.collect($SC.Function(function($_) { + return $_.asAudioRateInput($for); + })); + }; - parser.parse = function(source, opts) { - var instance, ast; + spec.asControlInput = function() { + return this.collect($SC.Function(function($_) { + return $_.asControlInput(); + })); + }; - opts = opts || /* istanbul ignore next */ {}; + spec.isValidUGenInput = utils.alwaysReturn$true; - instance = new SCParser(source, opts); - ast = instance.parse(); + spec.numChannels = function() { + return this.size(); + }; - if (!!opts.tokens && typeof instance.tokens !== "undefined") { - ast.tokens = instance.tokens; - } - if (!!opts.tolerant && typeof instance.errors !== "undefined") { - ast.errors = instance.errors; - } + // TODO: implements poll + // TODO: implements dpoll + // TODO: implements evnAt + // TODO: implements atIdentityHash + // TODO: implements atIdentityHashInPairs + // TODO: implements asSpec + // TODO: implements fork - return ast; - }; + spec.madd = fn(function($mul, $add) { + return $SC("MulAdd").new(this, $mul, $add); + }, "mul=1.0; add=0.0"); - sc.lang.parser = parser; + // TODO: implements asRawOSC + // TODO: implements printOn + // TODO: implements storeOn + }); })(sc); @@ -13386,6 +13052,21 @@ var sc = { VERSION: "0.0.17" }; ]; }; + var format_argument = function(node) { + switch (node.valueType) { + case Token.NilLiteral : return "nil"; + case Token.TrueLiteral : return "true"; + case Token.FalseLiteral : return "false"; + case Token.CharLiteral : return "$" + node.value; + case Token.SymbolLiteral: return "\\" + node.value; + } + switch (node.value) { + case "Infinity" : return "inf"; + case "-Infinity": return "-inf"; + } + return node.value; + }; + CodeGen.prototype._FunctionMetadata = function(info) { var keys, vals; var args, result; @@ -13401,7 +13082,13 @@ var sc = { VERSION: "0.0.17" }; var result = [ keys[i] ]; if (vals[i]) { - result.push("=", vals[i].value); // TODO #[] + if (vals[i].type === Syntax.ListExpression) { + result.push("=[ ", this.stitchWith(vals[i].elements, ", ", function(item) { + return format_argument(item); + }), " ]"); + } else { + result.push("=", format_argument(vals[i])); + } } return result; diff --git a/package.json b/package.json index 3c0d5ba..18e0fdd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scscript", - "version": "0.0.17", + "version": "0.0.18", "author": "Nao Yonamine ", "homepage": "http://mohayonao.github.io/SCScript/", "bugs": "https://github.com/mohayonao/SCScript/issues", diff --git a/src/sc/lang/classlib/Collections/Array.js b/src/sc/lang/classlib/Collections/Array.js index ab29f22..410c321 100644 --- a/src/sc/lang/classlib/Collections/Array.js +++ b/src/sc/lang/classlib/Collections/Array.js @@ -4,12 +4,14 @@ require("./ArrayedCollection"); var slice = [].slice; - var $SC = sc.lang.$SC; - var rand = sc.libs.random; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var rand = sc.libs.random; var mathlib = sc.libs.mathlib; sc.lang.klass.refine("Array", function(spec, utils) { var BOOL = utils.BOOL; + var $nil = utils.$nil; var SCArray = $SC("Array"); spec.$with = function() { @@ -102,10 +104,9 @@ return $SC.Array(a); }; - spec.stutter = function($n) { + spec.stutter = fn(function($n) { var raw = this._; var n, a, i, j, imax, k; - $n = utils.defaultValue$Integer($n, 2); // <-- _ArrayStutter --> n = Math.max(0, $n.__int__()); @@ -117,12 +118,11 @@ } return $SC.Array(a); - }; + }, "n=2"); - spec.rotate = function($n) { + spec.rotate = fn(function($n) { var raw = this._; var n, a, size, i, j; - $n = utils.defaultValue$Integer($n, 1); // <-- _ArrayRotate --> n = $n.__int__(); @@ -140,12 +140,11 @@ } return $SC.Array(a); - }; + }, "n=1"); - spec.pyramid = function($patternType) { + spec.pyramid = fn(function($patternType) { var patternType; var obj1, obj2, i, j, k, n, numslots, x; - $patternType = utils.defaultValue$Integer($patternType, 1); obj1 = this._; obj2 = []; @@ -267,13 +266,12 @@ } return $SC.Array(obj2); - }; + }, "n=1"); - spec.pyramidg = function($patternType) { + spec.pyramidg = fn(function($patternType) { var raw = this._; var patternType; var list = [], lastIndex, i; - $patternType = utils.defaultValue$Integer($patternType, 1); patternType = Math.max(1, Math.min($patternType.__int__(), 10)); lastIndex = raw.length - 1; @@ -350,12 +348,10 @@ } return $SC.Array(list); - }; + }, "n=1"); - spec.sputter = function($probability, $maxlen) { + spec.sputter = fn(function($probability, $maxlen) { var list, prob, maxlen, i, length; - $probability = utils.defaultValue$Float($probability, 0.25); - $maxlen = utils.defaultValue$Float($maxlen, 100); list = []; prob = 1.0 - $probability.__num__(); @@ -370,13 +366,16 @@ } return $SC.Array(list); - }; + }, "probability=0.25; maxlen=100"); - spec.lace = function($length) { + spec.lace = fn(function($length) { var raw = this._; var length, wrap = raw.length; var a, i, $item; - $length = utils.defaultValue$Integer($length, wrap); + + if ($length === $nil) { + $length = $SC.Integer(wrap); + } length = $length.__int__(); a = new Array(length); @@ -391,13 +390,12 @@ } return $SC.Array(a); - }; + }, "length"); - spec.permute = function($nthPermutation) { + spec.permute = fn(function($nthPermutation) { var raw = this._; var obj1, obj2, size, $item; var nthPermutation, i, imax, j; - $nthPermutation = utils.defaultValue$Integer($nthPermutation, 0); obj1 = raw; obj2 = raw.slice(); @@ -414,13 +412,12 @@ } return $SC.Array(obj2); - }; + }, "nthPermutation=0"); - spec.allTuples = function($maxTuples) { + spec.allTuples = fn(function($maxTuples) { var maxSize; var obj1, obj2, obj3, obj4, newSize, tupSize; var i, j, k; - $maxTuples = utils.defaultValue$Integer($maxTuples, 16384); maxSize = $maxTuples.__int__(); @@ -452,12 +449,11 @@ } return $SC.Array(obj2); - }; + }, "maxTuples=16384"); - spec.wrapExtend = function($size) { + spec.wrapExtend = fn(function($size) { var raw = this._; var size, a, i; - $size = utils.defaultValue$Nil($size); size = Math.max(0, $size.__int__()); if (raw.length < size) { @@ -470,12 +466,11 @@ } return $SC.Array(a); - }; + }, "size"); - spec.foldExtend = function($size) { + spec.foldExtend = fn(function($size) { var raw = this._; var size, a, i; - $size = utils.defaultValue$Nil($size); size = Math.max(0, $size.__int__()); @@ -489,12 +484,11 @@ } return $SC.Array(a); - }; + }, "size"); - spec.clipExtend = function($size) { + spec.clipExtend = fn(function($size) { var raw = this._; var size, a, i, imax, b; - $size = utils.defaultValue$Nil($size); size = Math.max(0, $size.__int__()); @@ -511,15 +505,13 @@ } return $SC.Array(a); - }; + }, "size"); - spec.slide = function($windowLength, $stepSize) { + spec.slide = fn(function($windowLength, $stepSize) { var raw = this._; var windowLength, stepSize; var obj1, obj2, m, n, numwin, numslots; var i, j, h, k; - $windowLength = utils.defaultValue$Integer($windowLength, 3); - $stepSize = utils.defaultValue$Integer($stepSize , 1); windowLength = $windowLength.__int__(); stepSize = $stepSize.__int__(); @@ -537,7 +529,7 @@ } return $SC.Array(obj2); - }; + }, "windowLength=3; stepSize=1"); spec.containsSeqColl = function() { var raw = this._; @@ -552,13 +544,10 @@ return $SC.False(); }; - spec.unlace = function($clumpSize, $numChan, $clip) { + spec.unlace = fn(function($clumpSize, $numChan) { var raw = this._; var clumpSize, numChan; var a, b, size, i, j, k; - $clumpSize = utils.defaultValue$Integer($clumpSize, 2); - $numChan = utils.defaultValue$Integer($numChan , 1); - $clip = utils.defaultValue$Boolean($clip, false); clumpSize = $clumpSize.__int__(); numChan = $numChan .__int__(); @@ -580,7 +569,7 @@ } return $SC.Array(a); - }; + }, "clumpSize=2; numChan=1"); // TODO: implements interlace // TODO: implements deinterlace @@ -623,10 +612,8 @@ // TODO: implements envirPairs - spec.shift = function($n, $filler) { + spec.shift = fn(function($n, $filler) { var $fill, $remain; - $n = utils.defaultValue$Nil($n); - $filler = utils.defaultValue$Float($filler, 0.0); $fill = SCArray.fill($n.abs(), $filler); $remain = this.drop($n.neg()); @@ -636,7 +623,7 @@ } return $fill ["++"] ($remain); - }; + }, "n; fillter=0.0"); spec.powerset = function() { var raw = this._; @@ -695,11 +682,9 @@ // TODO: implements asSpec // TODO: implements fork - spec.madd = function($mul, $add) { - $mul = utils.defaultValue$Float($mul, 1.0); - $add = utils.defaultValue$Float($add, 0.0); + spec.madd = fn(function($mul, $add) { return $SC("MulAdd").new(this, $mul, $add); - }; + }, "mul=1.0; add=0.0"); // TODO: implements asRawOSC // TODO: implements printOn diff --git a/src/sc/lang/classlib/Collections/ArrayedCollection.js b/src/sc/lang/classlib/Collections/ArrayedCollection.js index d6e2fff..7dfd48b 100644 --- a/src/sc/lang/classlib/Collections/ArrayedCollection.js +++ b/src/sc/lang/classlib/Collections/ArrayedCollection.js @@ -4,11 +4,11 @@ require("./SequenceableCollection"); var slice = [].slice; + var fn = sc.lang.fn; var $SC = sc.lang.$SC; var iterator = sc.lang.iterator; - var fn = sc.lang.fn; - var rand = sc.libs.random; - var mathlib = sc.libs.mathlib; + var rand = sc.libs.random; + var mathlib = sc.libs.mathlib; sc.lang.klass.refine("ArrayedCollection", function(spec, utils) { var BOOL = utils.BOOL; @@ -41,11 +41,9 @@ // TODO: implements maxSize - spec.swap = function($a, $b) { + spec.swap = fn(function($a, $b) { var raw = this._; var a, b, len, tmp; - $a = utils.defaultValue$Nil($a); - $b = utils.defaultValue$Nil($b); this._ThrowIfImmutable(); @@ -62,11 +60,10 @@ raw[a] = tmp; return this; - }; + }, "a; b"); - spec.at = function($index) { + spec.at = fn(function($index) { var i; - $index = utils.defaultValue$Nil($index); if (Array.isArray($index._)) { return $SC.Array($index._.map(function($index) { @@ -81,11 +78,10 @@ i = $index.__int__(); return this._[i] || $nil; - }; + }, "index"); - spec.clipAt = function($index) { + spec.clipAt = fn(function($index) { var i; - $index = utils.defaultValue$Nil($index); if (Array.isArray($index._)) { return $SC.Array($index._.map(function($index) { @@ -97,11 +93,10 @@ i = mathlib.clip_idx($index.__int__(), this._.length); return this._[i]; - }; + }, "index"); - spec.wrapAt = function($index) { + spec.wrapAt = fn(function($index) { var i; - $index = utils.defaultValue$Nil($index); if (Array.isArray($index._)) { return $SC.Array($index._.map(function($index) { @@ -113,11 +108,10 @@ i = mathlib.wrap_idx($index.__int__(), this._.length); return this._[i]; - }; + }, "index"); - spec.foldAt = function($index) { + spec.foldAt = fn(function($index) { var i; - $index = utils.defaultValue$Nil($index); if (Array.isArray($index._)) { return $SC.Array($index._.map(function($index) { @@ -129,11 +123,10 @@ i = mathlib.fold_idx($index.__int__(), this._.length); return this._[i]; - }; + }, "index"); - spec.put = function($index, $item) { + spec.put = fn(function($index, $item) { var i; - $index = utils.defaultValue$Nil($index); this._ThrowIfImmutable(); @@ -154,12 +147,9 @@ } return this; - }; - - spec.clipPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + }, "index; item"); + spec.clipPut = fn(function($index, $item) { this._ThrowIfImmutable(); if (Array.isArray($index._)) { @@ -171,12 +161,9 @@ } return this; - }; - - spec.wrapPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + }, "index; item"); + spec.wrapPut = fn(function($index, $item) { this._ThrowIfImmutable(); if (Array.isArray($index._)) { @@ -188,12 +175,9 @@ } return this; - }; - - spec.foldPut = function($index, $item) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + }, "index; item"); + spec.foldPut = fn(function($index, $item) { this._ThrowIfImmutable(); if (Array.isArray($index._)) { @@ -205,12 +189,11 @@ } return this; - }; + }, "index; item"); - spec.removeAt = function($index) { + spec.removeAt = fn(function($index) { var raw = this._; var index; - $index = utils.defaultValue$Nil($index); this._ThrowIfImmutable(); @@ -220,12 +203,11 @@ } return raw.splice(index, 1)[0]; - }; + }, "index"); - spec.takeAt = function($index) { + spec.takeAt = fn(function($index) { var raw = this._; var index, ret, instead; - $index = utils.defaultValue$Nil($index); this._ThrowIfImmutable(); @@ -241,20 +223,18 @@ } return ret; - }; + }, "index"); - spec.indexOf = function($item) { + spec.indexOf = fn(function($item) { var index; - $item = utils.defaultValue$Nil($item); index = this._.indexOf($item); return index === -1 ? $nil : $SC.Integer(index); - }; + }, "item"); - spec.indexOfGreaterThan = function($val) { + spec.indexOfGreaterThan = fn(function($val) { var raw = this._; var val, i, imax = raw.length; - $val = utils.defaultValue$Nil($val); val = $val.__num__(); for (i = 0; i < imax; ++i) { @@ -264,12 +244,11 @@ } return $nil; - }; + }, "val"); - spec.takeThese = function($func) { + spec.takeThese = fn(function($func) { var raw = this._; var i = 0, $i; - $func = utils.defaultValue$Nil($func); $i = $SC.Integer(i); while (i < raw.length) { @@ -281,12 +260,10 @@ } return this; - }; + }, "func"); - spec.replace = function($find, $replace) { + spec.replace = fn(function($find, $replace) { var $index, $out, $array; - $find = utils.defaultValue$Nil($find); - $replace = utils.defaultValue$Nil($replace); this._ThrowIfImmutable(); @@ -302,7 +279,7 @@ })); return $out ["++"] ($array); - }; + }, "find; replace"); spec.slotSize = function() { return this.size(); @@ -327,34 +304,29 @@ }; spec.setSlots = function($array) { - $array = utils.defaultValue$Nil($array); return this.overWrite($array); }; - spec.atModify = function($index, $function) { + spec.atModify = fn(function($index, $function) { this.put($index, $function.value(this.at($index), $index)); return this; - }; + }, "index; function"); - spec.atInc = function($index, $inc) { - $inc = utils.defaultValue$Integer($inc, 1); + spec.atInc = fn(function($index, $inc) { this.put($index, this.at($index) ["+"] ($inc)); return this; - }; + }, "index; inc=1"); - spec.atDec = function($index, $dec) { - $dec = utils.defaultValue$Integer($dec, 1); + spec.atDec = fn(function($index, $dec) { this.put($index, this.at($index) ["-"] ($dec)); return this; - }; + }, "index; dec=1"); spec.isArray = utils.alwaysReturn$true; spec.asArray = utils.nop; - spec.copyRange = function($start, $end) { + spec.copyRange = fn(function($start, $end) { var start, end, instance, raw; - $start = utils.defaultValue$Nil($start); - $end = utils.defaultValue$Nil($end); if ($start === $nil) { start = 0; @@ -371,13 +343,10 @@ instance = new this.__Spec(); instance._ = raw; return instance; - }; + }, "start; end"); - spec.copySeries = function($first, $second, $last) { + spec.copySeries = fn(function($first, $second, $last) { var i, first, second, last, step, instance, raw; - $first = utils.defaultValue$Nil($first); - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); raw = []; if ($first === $nil) { @@ -411,14 +380,10 @@ instance = new this.__Spec(); instance._ = raw; return instance; - }; + }, "first; second; last"); - spec.putSeries = function($first, $second, $last, $value) { + spec.putSeries = fn(function($first, $second, $last, $value) { var i, first, second, last, step; - $first = utils.defaultValue$Nil($first); - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); - $value = utils.defaultValue$Nil($value); this._ThrowIfImmutable(); @@ -453,20 +418,17 @@ } return this; - }; - - spec.add = function($item) { - $item = utils.defaultValue$Nil($item); + }, "first; second; last; value"); + spec.add = fn(function($item) { this._ThrowIfImmutable(); this._.push(this.__elem__($item)); return this; - }; + }, "item"); - spec.addAll = function($aCollection) { + spec.addAll = fn(function($aCollection) { var $this = this; - $aCollection = utils.defaultValue$Nil($aCollection); this._ThrowIfImmutable(); @@ -479,12 +441,10 @@ } return this; - }; + }, "aCollection"); - spec.putEach = function($keys, $values) { + spec.putEach = fn(function($keys, $values) { var keys, values, i, imax; - $keys = utils.defaultValue$Nil($keys); - $values = utils.defaultValue$Nil($values); this._ThrowIfImmutable(); @@ -498,14 +458,11 @@ } return this; - }; + }, "keys; values"); - spec.extend = function($size, $item) { + spec.extend = fn(function($size, $item) { var instance, raw, size, i; - $size = utils.defaultValue$Nil($size); - $item = utils.defaultValue$Nil($item); - raw = this._.slice(); size = $size.__int__(); if (raw.length > size) { @@ -519,13 +476,10 @@ instance = new this.__Spec(); instance._ = raw; return instance; + }, "size; item"); - }; - - spec.insert = function($index, $item) { + spec.insert = fn(function($index, $item) { var index; - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); this._ThrowIfImmutable(); @@ -533,15 +487,14 @@ this._.splice(index, 0, this.__elem__($item)); return this; - }; + }, "index; item"); spec.move = function($fromIndex, $toIndex) { return this.insert($toIndex, this.removeAt($fromIndex)); }; - spec.addFirst = function($item) { + spec.addFirst = fn(function($item) { var instance, raw; - $item = utils.defaultValue$Nil($item); raw = this._.slice(); raw.unshift(this.__elem__($item)); @@ -549,17 +502,15 @@ instance = new this.__Spec(); instance._ = raw; return instance; - }; - - spec.addIfNotNil = function($item) { - $item = utils.defaultValue$Nil($item); + }, "item"); + spec.addIfNotNil = fn(function($item) { if ($item === $nil) { return this; } return this.addFirst(this.__elem__($item)); - }; + }, "item"); spec.pop = function() { if (this._.length === 0) { @@ -586,10 +537,8 @@ // TODO: implements grow // TODO: implements growClear - spec.seriesFill = function($start, $step) { + spec.seriesFill = fn(function($start, $step) { var i, imax; - $start = utils.defaultValue$Nil($start); - $step = utils.defaultValue$Nil($step); for (i = 0, imax = this._.length; i < imax; ++i) { this.put($SC.Integer(i), $start); @@ -597,11 +546,10 @@ } return this; - }; + }, "start; step"); - spec.fill = function($value) { + spec.fill = fn(function($value) { var raw, i, imax; - $value = utils.defaultValue$Nil($value); this._ThrowIfImmutable(); @@ -613,7 +561,7 @@ } return this; - }; + }, "value"); spec.do = function($function) { iterator.execute( @@ -660,33 +608,31 @@ return this ["*"] (this.sum().reciprocal()); }; - spec.normalize = function($min, $max) { + spec.normalize = fn(function($min, $max) { var $minItem, $maxItem; - $min = utils.defaultValue$Float($min, 0.0); - $max = utils.defaultValue$Float($max, 1.0); $minItem = this.minItem(); $maxItem = this.maxItem(); return this.collect($SC.Function(function($el) { return $el.linlin($minItem, $maxItem, $min, $max); })); - }; + }, "min=0.0; max=1.0"); // TODO: implements asciiPlot // TODO: implements perfectShuffle // TODO: implements performInPlace - spec.clipExtend = function($length) { + spec.clipExtend = fn(function($length) { var last = this._[this._.length - 1] || $nil; return this.extend($length, last); - }; + }, "length"); spec.rank = function() { return $int_1 ["+"] (this.first().rank()); }; spec.shape = function() { - return $SC.Array([ this.size() ]) ["++"] (this.at(0).shape()); + return $SC.Array([ this.size() ]) ["++"] (this.at($int_0).shape()); }; spec.reshape = function() { @@ -708,10 +654,8 @@ return $result; }; - spec.reshapeLike = function($another, $indexing) { + spec.reshapeLike = fn(function($another, $indexing) { var $index, $flat; - $another = utils.defaultValue$Nil($another); - $indexing = utils.defaultValue$Symbol($indexing, "wrapAt"); $index = $int_0; $flat = this.flat(); @@ -721,34 +665,28 @@ $index = $index.__inc__(); return $item; })); - }; + }, "another; indexing=\\wrapAt"); // TODO: implements deepCollect // TODO: implements deepDo - spec.unbubble = function($depth, $levels) { - $depth = utils.defaultValue$Integer($depth , 0); - $levels = utils.defaultValue$Integer($levels, 1); - + spec.unbubble = fn(function($depth, $levels) { if ($depth.__num__() <= 0) { if (this.size().__int__() > 1) { return this; } if ($levels.__int__() <= 1) { - return this.at(0); + return this.at($int_0); } - return this.at(0).unbubble($depth, $levels.__dec__()); + return this.at($int_0).unbubble($depth, $levels.__dec__()); } return this.collect($SC.Function(function($item) { return $item.unbubble($depth.__dec__()); })); - }; - - spec.bubble = function($depth, $levels) { - $depth = utils.defaultValue$Integer($depth , 0); - $levels = utils.defaultValue$Integer($levels, 1); + }, "depth=0; levels=1"); + spec.bubble = fn(function($depth, $levels) { if ($depth.__int__() <= 0) { if ($levels.__int__() <= 1) { return $SC.Array([ this ]); @@ -759,7 +697,7 @@ return this.collect($SC.Function(function($item) { return $item.bubble($depth.__dec__(), $levels); })); - }; + }, "depth=0; levels=1"); spec.slice = fn(function($$cuts) { var $firstCut, $list; @@ -770,7 +708,7 @@ return this.copy(); } - $firstCut = $$cuts.at(0); + $firstCut = $$cuts.at($int_0); if ($firstCut === $nil) { $list = this.copy(); } else { diff --git a/src/sc/lang/classlib/Collections/Collection.js b/src/sc/lang/classlib/Collections/Collection.js index 81a46a1..f29a200 100644 --- a/src/sc/lang/classlib/Collections/Collection.js +++ b/src/sc/lang/classlib/Collections/Collection.js @@ -15,9 +15,8 @@ var $int_1 = utils.$int_1; var SCArray = $SC("Array"); - spec.$newFrom = function($aCollection) { + spec.$newFrom = fn(function($aCollection) { var $newCollection; - $aCollection = utils.defaultValue$Nil($aCollection); $newCollection = this.new($aCollection.size()); $aCollection.do($SC.Function(function($item) { @@ -25,7 +24,7 @@ })); return $newCollection; - }; + }, "aCollection"); spec.$with = fn(function($$args) { var $newColl; @@ -36,11 +35,9 @@ return $newColl; }, "*args"); - spec.$fill = function($size, $function) { + spec.$fill = fn(function($size, $function) { var $obj; var size, i; - $size = utils.defaultValue$Nil($size); - $function = utils.defaultValue$Nil($function); if (BOOL($size.isSequenceableCollection())) { return this.fillND($size, $function); @@ -54,14 +51,11 @@ } return $obj; - }; + }, "size; function"); - spec.$fill2D = function($rows, $cols, $function) { + spec.$fill2D = fn(function($rows, $cols, $function) { var $this = this, $obj, $obj2, $row, $col; var rows, cols, i, j; - $rows = utils.defaultValue$Nil($rows); - $cols = utils.defaultValue$Nil($cols); - $function = utils.defaultValue$Nil($function); $obj = this.new($rows); @@ -79,15 +73,11 @@ } return $obj; - }; + }, "rows; cols; function"); - spec.$fill3D = function($planes, $rows, $cols, $function) { + spec.$fill3D = fn(function($planes, $rows, $cols, $function) { var $this = this, $obj, $obj2, $obj3, $plane, $row, $col; var planes, rows, cols, i, j, k; - $planes = utils.defaultValue$Nil($planes); - $rows = utils.defaultValue$Nil($rows); - $cols = utils.defaultValue$Nil($cols); - $function = utils.defaultValue$Nil($function); $obj = this.new($planes); @@ -111,7 +101,7 @@ } return $obj; - }; + }, "planes; rows; cols; function"); var fillND = function($this, $dimensions, $function, $args) { var $n, $obj, $argIndex; @@ -135,11 +125,9 @@ return $obj; }; - spec.$fillND = function($dimensions, $function) { - $dimensions = utils.defaultValue$Nil($dimensions); - $function = utils.defaultValue$Nil($function); + spec.$fillND = fn(function($dimensions, $function) { return fillND(this, $dimensions, $function, $SC.Array([])); - }; + }, "dimensions; function"); spec["@"] = function($index) { return this.at($index); @@ -207,38 +195,36 @@ return this._subclassResponsibility("add"); }; - spec.addAll = function($aCollection) { + spec.addAll = fn(function($aCollection) { var $this = this; - $aCollection = utils.defaultValue$Nil($aCollection); $aCollection.asCollection().do($SC.Function(function($item) { return $this.add($item); })); return this; - }; + }, "aCollection"); spec.remove = function() { return this._subclassResponsibility("remove"); }; - spec.removeAll = function($list) { + spec.removeAll = fn(function($list) { var $this = this; - $list = utils.defaultValue$Nil($list); $list.do($SC.Function(function($item) { $this.remove($item); })); return this; - }; + }, "list"); - spec.removeEvery = function($list) { + spec.removeEvery = fn(function($list) { this.removeAllSuchThat($SC.Function(function($_) { return $list.includes($_); })); return this; - }; + }, "list"); spec.removeAllSuchThat = function($function) { var $this = this, $removedItems, $copy; @@ -255,18 +241,16 @@ return $removedItems; }; - spec.atAll = function($keys) { + spec.atAll = fn(function($keys) { var $this = this; return $keys.collect($SC.Function(function($index) { return $this.at($index); })); - }; + }, "keys"); - spec.putEach = function($keys, $values) { + spec.putEach = fn(function($keys, $values) { var keys, values, i, imax; - $keys = utils.defaultValue$Nil($keys); - $values = utils.defaultValue$Nil($values); $keys = $keys.asArray(); $values = $values.asArray(); @@ -278,11 +262,10 @@ } return this; - }; + }, "keys; values"); - spec.includes = function($item1) { + spec.includes = fn(function($item1) { var $res = null; - $item1 = utils.defaultValue$Nil($item1); this.do($SC.Function(function($item2) { if ($item1 === $item2) { @@ -292,11 +275,10 @@ })); return $res || $false; - }; + }, "item1"); - spec.includesEqual = function($item1) { + spec.includesEqual = fn(function($item1) { var $res = null; - $item1 = utils.defaultValue$Nil($item1); this.do($SC.Function(function($item2) { if (BOOL( $item1 ["=="] ($item2) )) { @@ -306,11 +288,10 @@ })); return $res || $false; - }; + }, "item1"); - spec.includesAny = function($aCollection) { + spec.includesAny = fn(function($aCollection) { var $this = this, $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); $aCollection.do($SC.Function(function($item) { if (BOOL($this.includes($item))) { @@ -320,11 +301,10 @@ })); return $res || $false; - }; + }, "aCollection"); - spec.includesAll = function($aCollection) { + spec.includesAll = fn(function($aCollection) { var $this = this, $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); $aCollection.do($SC.Function(function($item) { if (!BOOL($this.includes($item))) { @@ -334,11 +314,11 @@ })); return $res || $true; - }; + }, "aCollection"); - spec.matchItem = function($item) { + spec.matchItem = fn(function($item) { return this.includes($item); - }; + }, "item"); spec.collect = function($function) { return this.collectAs($function, this.species()); @@ -352,10 +332,8 @@ return this.rejectAs($function, this.species()); }; - spec.collectAs = function($function, $class) { + spec.collectAs = fn(function($function, $class) { var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); $res = $class.new(this.size()); this.do($SC.Function(function($elem, $i) { @@ -363,12 +341,10 @@ })); return $res; - }; + }, "function; class"); - spec.selectAs = function($function, $class) { + spec.selectAs = fn(function($function, $class) { var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); $res = $class.new(this.size()); this.do($SC.Function(function($elem, $i) { @@ -378,12 +354,10 @@ })); return $res; - }; + }, "function; class"); - spec.rejectAs = function($function, $class) { + spec.rejectAs = fn(function($function, $class) { var $res; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); $res = $class.new(this.size()); this.do($SC.Function(function($elem, $i) { @@ -393,11 +367,10 @@ })); return $res; - }; + }, "function; class"); spec.detect = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { @@ -411,7 +384,6 @@ spec.detectIndex = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { @@ -422,59 +394,49 @@ return $res || $nil; }; - spec.doMsg = function($selector) { + spec.doMsg = function() { var args = arguments; - args[0] = utils.defaultValue$Nil($selector); this.do($SC.Function(function($item) { $item.perform.apply($item, args); })); return this; }; - spec.collectMsg = function($selector) { + spec.collectMsg = function() { var args = arguments; - args[0] = utils.defaultValue$Nil($selector); return this.collect($SC.Function(function($item) { return $item.perform.apply($item, args); })); }; - spec.selectMsg = function($selector) { + spec.selectMsg = function() { var args = arguments; - args[0] = utils.defaultValue$Nil($selector); return this.select($SC.Function(function($item) { return $item.perform.apply($item, args); })); }; - spec.rejectMsg = function($selector) { + spec.rejectMsg = function() { var args = arguments; - args[0] = utils.defaultValue$Nil($selector); return this.reject($SC.Function(function($item) { return $item.perform.apply($item, args); })); }; spec.detectMsg = fn(function($selector, $$args) { - $selector = utils.defaultValue$Nil($selector); - return this.detect($SC.Function(function($item) { return $item.performList($selector, $$args); })); - }, "selector,*args"); + }, "selector; *args"); spec.detectIndexMsg = fn(function($selector, $$args) { - $selector = utils.defaultValue$Nil($selector); - return this.detectIndex($SC.Function(function($item) { return $item.performList($selector, $$args); })); - }, "selector,*args"); + }, "selector; *args"); spec.lastForWhich = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); - this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { $res = $elem; @@ -488,8 +450,6 @@ spec.lastIndexForWhich = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); - this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { $res = $i; @@ -501,10 +461,8 @@ return $res || $nil; }; - spec.inject = function($thisValue, $function) { + spec.inject = fn(function($thisValue, $function) { var $nextValue; - $thisValue = utils.defaultValue$Nil($thisValue); - $function = utils.defaultValue$Nil($function); $nextValue = $thisValue; this.do($SC.Function(function($item, $i) { @@ -512,12 +470,10 @@ })); return $nextValue; - }; + }, "thisValue; function"); - spec.injectr = function($thisValue, $function) { + spec.injectr = fn(function($thisValue, $function) { var $this = this, size, $nextValue; - $thisValue = utils.defaultValue$Nil($thisValue); - $function = utils.defaultValue$Nil($function); size = this.size().__int__(); $nextValue = $thisValue; @@ -527,12 +483,10 @@ })); return $nextValue; - }; + }, "thisValue; function"); spec.count = function($function) { var sum = 0; - $function = utils.defaultValue$Nil($function); - this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { sum++; @@ -542,9 +496,8 @@ return $SC.Integer(sum); }; - spec.occurrencesOf = function($obj) { + spec.occurrencesOf = fn(function($obj) { var sum = 0; - $obj = utils.defaultValue$Nil($obj); this.do($SC.Function(function($elem) { if (BOOL($elem ["=="] ($obj))) { @@ -553,11 +506,10 @@ })); return $SC.Integer(sum); - }; + }, "obj"); spec.any = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); this.do($SC.Function(function($elem, $i) { if (BOOL($function.value($elem, $i))) { @@ -571,7 +523,6 @@ spec.every = function($function) { var $res = null; - $function = utils.defaultValue$Nil($function); this.do($SC.Function(function($elem, $i) { if (!BOOL($function.value($elem, $i))) { @@ -583,9 +534,8 @@ return $res || $true; }; - spec.sum = function($function) { + spec.sum = fn(function($function) { var $sum; - $function = utils.defaultValue$Nil($function); $sum = $int_0; if ($function === $nil) { @@ -599,15 +549,14 @@ } return $sum; - }; + }, "function"); spec.mean = function($function) { return this.sum($function) ["/"] (this.size()); }; - spec.product = function($function) { + spec.product = fn(function($function) { var $product; - $function = utils.defaultValue$Nil($function); $product = $int_1; if ($function === $nil) { @@ -621,7 +570,7 @@ } return $product; - }; + }, "function"); spec.sumabs = function() { var $sum; @@ -637,9 +586,8 @@ return $sum; }; - spec.maxItem = function($function) { + spec.maxItem = fn(function($function) { var $maxValue, $maxElement; - $function = utils.defaultValue$Nil($function); $maxValue = $nil; $maxElement = $nil; @@ -668,11 +616,10 @@ } return $maxElement; - }; + }, "function"); - spec.minItem = function($function) { + spec.minItem = fn(function($function) { var $minValue, $minElement; - $function = utils.defaultValue$Nil($function); $minValue = $nil; $minElement = $nil; @@ -701,11 +648,10 @@ } return $minElement; - }; + }, "function"); - spec.maxIndex = function($function) { + spec.maxIndex = fn(function($function) { var $maxValue, $maxIndex; - $function = utils.defaultValue$Nil($function); $maxValue = $nil; $maxIndex = $nil; @@ -736,11 +682,10 @@ } return $maxIndex; - }; + }, "function"); - spec.minIndex = function($function) { + spec.minIndex = fn(function($function) { var $maxValue, $minIndex; - $function = utils.defaultValue$Nil($function); $maxValue = $nil; $minIndex = $nil; @@ -771,11 +716,10 @@ } return $minIndex; - }; + }, "function"); - spec.maxValue = function($function) { + spec.maxValue = fn(function($function) { var $maxValue, $maxElement; - $function = utils.defaultValue$Nil($function); $maxValue = $nil; $maxElement = $nil; @@ -794,11 +738,10 @@ })); return $maxValue; - }; + }, "function"); - spec.minValue = function($function) { + spec.minValue = fn(function($function) { var $minValue, $minElement; - $function = utils.defaultValue$Nil($function); $minValue = $nil; $minElement = $nil; @@ -817,11 +760,10 @@ })); return $minValue; - }; + }, "function"); - spec.maxSizeAtDepth = function($rank) { + spec.maxSizeAtDepth = fn(function($rank) { var rank, maxsize = 0; - $rank = utils.defaultValue$Nil($rank); rank = $rank.__num__(); if (rank === 0) { @@ -841,11 +783,10 @@ })); return $SC.Integer(maxsize); - }; + }, "rank"); - spec.maxDepth = function($max) { + spec.maxDepth = fn(function($max) { var $res; - $max = utils.defaultValue$Integer($max, 1); $res = $max; this.do($SC.Function(function($elem) { @@ -855,14 +796,9 @@ })); return $res; - }; - - spec.deepCollect = function($depth, $function, $index, $rank) { - $depth = utils.defaultValue$Integer($depth, 1); - $function = utils.defaultValue$Nil($function); - $index = utils.defaultValue$Integer($index, 0); - $rank = utils.defaultValue$Integer($rank, 0); + }, "max=1"); + spec.deepCollect = fn(function($depth, $function, $index, $rank) { if ($depth === $nil) { $rank = $rank.__inc__(); return this.collect($SC.Function(function($item, $i) { @@ -878,14 +814,9 @@ return this.collect($SC.Function(function($item, $i) { return $item.deepCollect($depth, $function, $i, $rank); })); - }; - - spec.deepDo = function($depth, $function, $index, $rank) { - $depth = utils.defaultValue$Integer($depth, 1); - $function = utils.defaultValue$Nil($function); - $index = utils.defaultValue$Integer($index, 0); - $rank = utils.defaultValue$Integer($rank, 0); + }, "depth=1; function; index=0; rank=0"); + spec.deepDo = fn(function($depth, $function, $index, $rank) { if ($depth === $nil) { $rank = $rank.__inc__(); return this.do($SC.Function(function($item, $i) { @@ -902,11 +833,10 @@ return this.do($SC.Function(function($item, $i) { $item.deepDo($depth, $function, $i, $rank); })); - }; + }, "depth=1; function; index=0; rank=0"); - spec.invert = function($axis) { + spec.invert = fn(function($axis) { var $index; - $axis = utils.defaultValue$Nil($axis); if (BOOL(this.isEmpty())) { return this.species().new(); @@ -918,11 +848,10 @@ } return $index ["-"] (this); - }; + }, "axis"); - spec.sect = function($that) { + spec.sect = fn(function($that) { var $result; - $that = utils.defaultValue$Nil($that); $result = this.species().new(); this.do($SC.Function(function($item) { @@ -932,11 +861,10 @@ })); return $result; - }; + }, "that"); - spec.union = function($that) { + spec.union = fn(function($that) { var $result; - $that = utils.defaultValue$Nil($that); $result = this.copy(); $that.do($SC.Function(function($item) { @@ -946,15 +874,14 @@ })); return $result; - }; + }, "that"); - spec.difference = function($that) { + spec.difference = fn(function($that) { return this.copy().removeAll($that); - }; + }, "that"); - spec.symmetricDifference = function($that) { + spec.symmetricDifference = fn(function($that) { var $this = this, $result; - $that = utils.defaultValue$Nil($that); $result = this.species().new(); $this.do($SC.Function(function($item) { @@ -969,12 +896,11 @@ })); return $result; - }; + }, "that"); - spec.isSubsetOf = function($that) { - $that = utils.defaultValue$Nil($that); + spec.isSubsetOf = fn(function($that) { return $that.includesAll(this); - }; + }, "that"); spec.asArray = function() { return SCArray.new(this.size()).addAll(this); diff --git a/src/sc/lang/classlib/Collections/SequenceableCollection.js b/src/sc/lang/classlib/Collections/SequenceableCollection.js index 34e58cf..2c62d75 100644 --- a/src/sc/lang/classlib/Collections/SequenceableCollection.js +++ b/src/sc/lang/classlib/Collections/SequenceableCollection.js @@ -4,7 +4,8 @@ require("./Collection"); var slice = [].slice; - var $SC = sc.lang.$SC; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; sc.lang.klass.refine("SequenceableCollection", function(spec, utils) { var BOOL = utils.BOOL; @@ -26,11 +27,8 @@ return this.foldAt($index); }; - spec.$series = function($size, $start, $step) { + spec.$series = fn(function($size, $start, $step) { var $obj, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Integer($start, 0); - $step = utils.defaultValue$Integer($step, 1); $obj = this.new($size); for (i = 0, imax = $size.__int__(); i < imax; ++i) { @@ -38,13 +36,10 @@ } return $obj; - }; + }, "size; start=0; step=1"); - spec.$geom = function($size, $start, $grow) { + spec.$geom = fn(function($size, $start, $grow) { var $obj, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Nil($start); - $grow = utils.defaultValue$Nil($grow); $obj = this.new($size); for (i = 0, imax = $size.__int__(); i < imax; ++i) { @@ -53,13 +48,10 @@ } return $obj; - }; + }, "size; start; grow"); - spec.$fib = function($size, $a, $b) { + spec.$fib = fn(function($size, $a, $b) { var $obj, $temp, i, imax; - $size = utils.defaultValue$Nil($size); - $a = utils.defaultValue$Float($a, 0.0); - $b = utils.defaultValue$Float($b, 1.0); $obj = this.new($size); for (i = 0, imax = $size.__int__(); i < imax; ++i) { @@ -70,17 +62,14 @@ } return $obj; - }; + }, "size; a=0.0; b=1.0"); // TODO: implements $rand // TODO: implements $rand2 // TODO: implements $linrand - spec.$interpolation = function($size, $start, $end) { + spec.$interpolation = fn(function($size, $start, $end) { var $obj, $step, i, imax; - $size = utils.defaultValue$Nil($size); - $start = utils.defaultValue$Float($start, 0.0); - $end = utils.defaultValue$Float($end , 1.0); $obj = this.new($size); if ($size.__int__() === 1) { @@ -93,11 +82,10 @@ } return $obj; - }; + }, "size; start=0.0; end=1.0"); spec["++"] = function($aSequenceableCollection) { var $newlist; - $aSequenceableCollection = utils.defaultValue$Nil($aSequenceableCollection); $newlist = this.species().new(this.size() ["+"] ($aSequenceableCollection.size())); $newlist = $newlist.addAll(this).addAll($aSequenceableCollection); @@ -113,14 +101,12 @@ return this.at(this.size().rand()); }; - spec.wchoose = function($weights) { - $weights = utils.defaultValue$Nil($weights); + spec.wchoose = fn(function($weights) { return this.at($weights.windex()); - }; + }, "weights"); spec["=="] = function($aCollection) { var $res = null; - $aCollection = utils.defaultValue$Nil($aCollection); if ($aCollection.class() !== this.class()) { return $false; @@ -140,10 +126,8 @@ // TODO: implements hash - spec.copyRange = function($start, $end) { + spec.copyRange = fn(function($start, $end) { var $newColl, i, end; - $start = utils.defaultValue$Nil($start); - $end = utils.defaultValue$Nil($end); i = $start.__int__(); end = $end.__int__(); @@ -153,11 +137,10 @@ } return $newColl; - }; + }, "start; end"); - spec.keep = function($n) { + spec.keep = fn(function($n) { var n, size; - $n = utils.defaultValue$Nil($n); n = $n.__int__(); if (n >= 0) { @@ -166,11 +149,10 @@ size = this.size().__int__(); return this.copyRange($SC.Integer(size + n), $SC.Integer(size - 1)); - }; + }, "n"); - spec.drop = function($n) { + spec.drop = fn(function($n) { var n, size; - $n = utils.defaultValue$Nil($n); n = $n.__int__(); size = this.size().__int__(); @@ -179,19 +161,18 @@ } return this.copyRange($int_0, $SC.Integer(size + n - 1)); - }; + }, "n"); - spec.copyToEnd = function($start) { + spec.copyToEnd = fn(function($start) { return this.copyRange($start, $SC.Integer(this.size().__int__() - 1)); - }; + }, "start"); - spec.copyFromStart = function($end) { + spec.copyFromStart = fn(function($end) { return this.copyRange($int_0, $end); - }; + }, "end"); - spec.indexOf = function($item) { + spec.indexOf = fn(function($item) { var $ret = null; - $item = utils.defaultValue$Nil($item); this.do($SC.Function(function($elem, $i) { if ($item === $elem) { @@ -201,11 +182,10 @@ })); return $ret || $nil; - }; + }, "item"); - spec.indicesOfEqual = function($item) { + spec.indicesOfEqual = fn(function($item) { var indices = []; - $item = utils.defaultValue$Nil($item); this.do($SC.Function(function($elem, $i) { if ($item === $elem) { @@ -214,13 +194,11 @@ })); return indices.length ? $SC.Array(indices) : $nil; - }; + }, "item"); - spec.find = function($sublist, $offset) { + spec.find = fn(function($sublist, $offset) { var $subSize_1, $first, $index; var size, offset, i, imax; - $sublist = utils.defaultValue$Nil($sublist); - $offset = utils.defaultValue$Integer($offset, 0); $subSize_1 = $sublist.size().__dec__(); $first = $sublist.first(); @@ -237,12 +215,10 @@ } return $nil; - }; + }, "sublist; offset=0"); - spec.findAll = function($arr, $offset) { + spec.findAll = fn(function($arr, $offset) { var $this = this, $indices, $i; - $arr = utils.defaultValue$Nil($arr); - $offset = utils.defaultValue$Integer($offset, 0); $indices = $nil; $i = $int_0; @@ -253,18 +229,16 @@ } return $indices; - }; + }, "arr; offset=0"); - spec.indexOfGreaterThan = function($val) { - $val = utils.defaultValue$Nil($val); + spec.indexOfGreaterThan = fn(function($val) { return this.detectIndex($SC.Function(function($item) { return $SC.Boolean($item > $val); })); - }; + }, "val"); - spec.indexIn = function($val) { + spec.indexIn = fn(function($val) { var $i, $j; - $val = utils.defaultValue$Nil($val); $j = this.indexOfGreaterThan($val); if ($j === $nil) { @@ -281,11 +255,10 @@ } return $j; - }; + }, "val"); - spec.indexInBetween = function($val) { + spec.indexInBetween = fn(function($val) { var $a, $b, $div, $i; - $val = utils.defaultValue$Nil($val); if (BOOL(this.isEmpty())) { return $nil; @@ -308,11 +281,10 @@ // } return (($val ["-"] ($a)) ["/"] ($div)) ["+"] ($i.__dec__()); - }; + }, "val"); - spec.isSeries = function($step) { + spec.isSeries = fn(function($step) { var $res = null; - $step = utils.defaultValue$Nil($step); if (this.size() <= 1) { return $true; @@ -328,11 +300,10 @@ })); return $res || $true; - }; + }, "step"); - spec.resamp0 = function($newSize) { + spec.resamp0 = fn(function($newSize) { var $this = this, $factor; - $newSize = utils.defaultValue$Nil($newSize); $factor = ( this.size().__dec__() @@ -343,11 +314,10 @@ return this.species().fill($newSize, $SC.Function(function($i) { return $this.at($i ["*"] ($factor).round($SC.Float(1.0)).asInteger()); })); - }; + }, "newSize"); - spec.resamp1 = function($newSize) { + spec.resamp1 = fn(function($newSize) { var $this = this, $factor; - $newSize = utils.defaultValue$Nil($newSize); $factor = ( this.size().__dec__() @@ -358,11 +328,10 @@ return this.species().fill($newSize, $SC.Function(function($i) { return $this.blendAt($i ["*"] ($factor)); })); - }; + }, "newSize"); - spec.remove = function($item) { + spec.remove = fn(function($item) { var $index; - $item = utils.defaultValue$Nil($item); $index = this.indexOf($item); if ($index !== $nil) { @@ -370,21 +339,19 @@ } return $nil; - }; + }, "item"); - spec.removing = function($item) { + spec.removing = fn(function($item) { var $coll; - $item = utils.defaultValue$Nil($item); $coll = this.copy(); $coll.remove($item); return $coll; - }; + }, "item"); - spec.take = function($item) { + spec.take = fn(function($item) { var $index; - $item = utils.defaultValue$Nil($item); $index = this.indexOf($item); if ($index !== $nil) { @@ -392,7 +359,7 @@ } return $nil; - }; + }, "item"); spec.lastIndex = function() { var size = this.size().__int__(); @@ -448,7 +415,7 @@ return this.last(); }; - spec.putFirst = function($obj) { + spec.putFirst = fn(function($obj) { var size = this.size().__int__(); if (size > 0) { @@ -456,9 +423,9 @@ } return this; - }; + }, "obj"); - spec.putLast = function($obj) { + spec.putLast = fn(function($obj) { var size = this.size().__int__(); if (size > 0) { @@ -466,12 +433,10 @@ } return this; - }; + }, "obj"); - spec.obtain = function($index, $default) { + spec.obtain = fn(function($index, $default) { var $res; - $index = utils.defaultValue$Nil($index); - $default = utils.defaultValue$Nil($default); $res = this.at($index); if ($res === $nil) { @@ -479,13 +444,10 @@ } return $res; - }; + }, "index; default"); - spec.instill = function($index, $item, $default) { + spec.instill = fn(function($index, $item, $default) { var $res; - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); - $default = utils.defaultValue$Nil($default); if ($index.__num__() >= this.size()) { $res = this.extend($index.__inc__(), $default); @@ -494,11 +456,10 @@ } return $res.put($index, $item); - }; + }, "index; item; default"); spec.pairsDo = function($function) { var $this = this, $int2 = $SC.Integer(2); - $function = utils.defaultValue$Nil($function); $int_0.forBy(this.size() ["-"] ($int2), $int2, $SC.Function(function($i) { return $function.value($this.at($i), $this.at($i.__inc__()), $i); @@ -514,7 +475,6 @@ spec.doAdjacentPairs = function($function) { var $i; var size, i, imax; - $function = utils.defaultValue$Nil($function); size = this.size().__int__(); for (i = 0, imax = size - 1; i < imax; ++i) { @@ -525,9 +485,8 @@ return this; }; - spec.separate = function($function) { + spec.separate = fn(function($function) { var $this = this, $list, $sublist; - $function = utils.defaultValue$Boolean($function, true); $list = $SC.Array(); $sublist = this.species().new(); @@ -544,11 +503,10 @@ $list = $list.add($sublist); return $list; - }; + }, "function=true"); spec.delimit = function($function) { var $this = this, $list, $sublist; - $function = utils.defaultValue$Nil($function); $list = $SC.Array(); $sublist = this.species().new(); @@ -565,9 +523,8 @@ return $list; }; - spec.clump = function($groupSize) { + spec.clump = fn(function($groupSize) { var $this = this, $list, $sublist; - $groupSize = utils.defaultValue$Nil($groupSize); $list = $SC.Array(); $sublist = this.species().new($groupSize); @@ -583,11 +540,10 @@ } return $list; - }; + }, "groupSize"); - spec.clumps = function($groupSizeList) { + spec.clumps = fn(function($groupSizeList) { var $this = this, $list, $subSize, $sublist, i = 0; - $groupSizeList = utils.defaultValue$Nil($groupSizeList); $list = $SC.Array(); $subSize = $groupSizeList.at($int_0); @@ -605,21 +561,19 @@ } return $list; - }; + }, "groupSizeList"); - spec.curdle = function($probability) { - $probability = utils.defaultValue$Nil($probability); + spec.curdle = fn(function($probability) { return this.separate($SC.Function(function() { return $probability.coin(); })); - }; + }, "probability"); - spec.flatten = function($numLevels) { - $numLevels = utils.defaultValue$Integer($numLevels, 1); + spec.flatten = fn(function($numLevels) { return this._flatten($numLevels.__num__()); - }; + }, "numLevels=1"); - spec._flatten = function(numLevels) { + spec._flatten = fn(function(numLevels) { var $list; if (numLevels <= 0) { @@ -637,13 +591,13 @@ })); return $list; - }; + }, "numLevels"); spec.flat = function() { return this._flat(this.species().new(this.flatSize())); }; - spec._flat = function($list) { + spec._flat = fn(function($list) { this.do($SC.Function(function($item) { if ($item._flat) { $list = $item._flat($list); @@ -652,12 +606,11 @@ } })); return $list; - }; + }, "list"); - spec.flatIf = function($func) { - $func = utils.defaultValue$Nil($func); + spec.flatIf = fn(function($func) { return this._flatIf($func); - }; + }, "func"); spec._flatIf = function($func) { var $list; @@ -710,9 +663,8 @@ return $list; }; - spec.flopWith = function($func) { + spec.flopWith = fn(function($func) { var $this = this, $maxsize; - $func = utils.defaultValue$Nil($func); $maxsize = this.maxValue($SC.Function(function($sublist) { if (BOOL($sublist.isSequenceableCollection())) { @@ -730,7 +682,7 @@ } }))); })); - }; + }, "func"); // TODO: implements flopTogether // TODO: implements flopDeep @@ -1224,17 +1176,13 @@ }; spec.performBinaryOp = function($aSelector, $theOperand, $adverb) { - $theOperand = utils.defaultValue$Nil($theOperand); return $theOperand.performBinaryOpOnSeqColl($aSelector, this, $adverb); }; spec.performBinaryOpOnSeqColl = function($aSelector, $theOperand, $adverb) { var adverb; - $aSelector = utils.defaultValue$Nil($aSelector); - $theOperand = utils.defaultValue$Nil($theOperand); - $adverb = utils.defaultValue$Nil($adverb); - if ($adverb === $nil) { + if ($adverb === $nil || !$adverb) { return _performBinaryOpOnSeqColl_adverb_nil( this, $aSelector, $theOperand ); @@ -1384,14 +1332,12 @@ } spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber, $adverb) { - $aNumber = utils.defaultValue$Nil($aNumber); return this.collect($SC.Function(function($item) { return $aNumber.perform($aSelector, $item, $adverb); })); }; spec.performBinaryOpOnComplex = function($aSelector, $aComplex, $adverb) { - $aComplex = utils.defaultValue$Nil($aComplex); return this.collect($SC.Function(function($item) { return $aComplex.perform($aSelector, $item, $adverb); })); @@ -1611,17 +1557,15 @@ // TODO: implements quickSort // TODO: implements order - spec.swap = function($i, $j) { + spec.swap = fn(function($i, $j) { var $temp; - $i = utils.defaultValue$Nil($i); - $j = utils.defaultValue$Nil($j); $temp = this.at($i); this.put($i, this.at($j)); this.put($j, $temp); return this; - }; + }, "i; j"); // TODO: implements quickSortRange // TODO: implements mergeSort @@ -1635,18 +1579,15 @@ // TODO: implements $streamContensts // TODO: implements $streamContenstsLimit - spec.wrapAt = function($index) { - $index = utils.defaultValue$Nil($index); + spec.wrapAt = fn(function($index) { $index = $index ["%"] (this.size()); return this.at($index); - }; + }, "index"); - spec.wrapPut = function($index, $value) { - $index = utils.defaultValue$Nil($index); - $value = utils.defaultValue$Nil($value); + spec.wrapPut = fn(function($index, $value) { $index = $index ["%"] (this.size()); return this.put($index, $value); - }; + }, "index; value"); // TODO: implements reduce // TODO: implements join diff --git a/src/sc/lang/classlib/Collections/String.js b/src/sc/lang/classlib/Collections/String.js index 336048d..6a02f46 100644 --- a/src/sc/lang/classlib/Collections/String.js +++ b/src/sc/lang/classlib/Collections/String.js @@ -3,6 +3,7 @@ require("./ArrayedCollection"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; sc.lang.klass.refine("String", function(spec, utils) { @@ -72,10 +73,8 @@ // TODO: implements stripHTML // TODO: implements $scDir - spec.compare = function($aString, $ignoreCase) { - var araw, braw, length, i, a, b, cmp, fn; - $aString = utils.defaultValue$Nil($aString); - $ignoreCase = utils.defaultValue$Boolean($ignoreCase, false); + spec.compare = fn(function($aString, $ignoreCase) { + var araw, braw, length, i, a, b, cmp, func; if ($aString.__tag !== sc.C.TAG_STR) { return $nil; @@ -86,17 +85,17 @@ length = Math.min(araw.length, braw.length); if ($ignoreCase.__bool__()) { - fn = function(ch) { + func = function(ch) { return ch.toLowerCase(); }; } else { - fn = function(ch) { + func = function(ch) { return ch; }; } for (i = 0; i < length; i++) { - a = fn(araw[i]._).charCodeAt(0); - b = fn(braw[i]._).charCodeAt(0); + a = func(araw[i]._).charCodeAt(0); + b = func(braw[i]._).charCodeAt(0); cmp = a - b; if (cmp !== 0) { return $SC.Integer(cmp < 0 ? -1 : +1); @@ -110,7 +109,7 @@ } return $SC.Integer(cmp); - }; + }, "aString; ignoreCase=false"); spec["<"] = function($aString) { return $SC.Boolean( @@ -151,12 +150,10 @@ // TODO: implements hash spec.performBinaryOpOnSimpleNumber = function($aSelector, $aNumber) { - $aNumber = utils.defaultValue$Nil($aNumber); return $aNumber.asString().perform($aSelector, this); }; spec.performBinaryOpOnComplex = function($aSelector, $aComplex) { - $aComplex = utils.defaultValue$Nil($aComplex); return $aComplex.asString().perform($aSelector, this); }; diff --git a/src/sc/lang/classlib/Core/AbstractFunction.js b/src/sc/lang/classlib/Core/AbstractFunction.js index 4788c07..06fe5e7 100644 --- a/src/sc/lang/classlib/Core/AbstractFunction.js +++ b/src/sc/lang/classlib/Core/AbstractFunction.js @@ -3,9 +3,10 @@ require("./Object"); - var $SC = sc.lang.$SC; - var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var fn = sc.lang.fn; var utils = sc.lang.klass.utils; + var $nil = utils.$nil; sc.lang.klass.refine("AbstractFunction", function(spec, utils) { spec.composeUnaryOp = function($aSelector) { @@ -301,7 +302,6 @@ }; spec.max = function($function, $adverb) { - $function = utils.defaultValue$Integer($function, 0); return this.composeBinaryOp($SC.Symbol("max"), $function, $adverb); }; @@ -502,97 +502,75 @@ return this.composeNAryOp($SC.Symbol("fold"), $SC.Array([ $lo, $hi ])); }; - spec.blend = function($that, $blendFrac) { - $blendFrac = utils.defaultValue$Float($blendFrac, 0.5); + spec.blend = fn(function($that, $blendFrac) { return this.composeNAryOp( $SC.Symbol("blend"), $SC.Array([ $that, $blendFrac ]) ); - }; + }, "that; blendFrac=0.5"); - spec.linlin = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.linlin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("linlin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) ); - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.linexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.linexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("linexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) ); - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.explin = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.explin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("explin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) ); - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.expexp = function($inMin, $inMax, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.expexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("expexp"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $clip ]) ); - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.lincurve = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.lincurve = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { return this.composeNAryOp( $SC.Symbol("lincurve"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) ); - }; + }, "inMin=0; inMax=1; outMin=1; outMax=1; curve=-4; clip=\\minmax"); - spec.curvelin = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.curvelin = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { return this.composeNAryOp( $SC.Symbol("curvelin"), $SC.Array([ $inMin, $inMax, $outMin, $outMax, $curve, $clip ]) ); - }; + }, "inMin=0; inMax=1; outMin=1; outMax=1; curve=-4; clip=\\minmax"); - spec.bilin = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.bilin = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("bilin"), $SC.Array([ $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip ]) ); - }; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.biexp = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { - $clip = utils.defaultValue$Symbol($clip, "minmax"); + spec.biexp = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { return this.composeNAryOp( $SC.Symbol("biexp"), $SC.Array([ $inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip ]) ); - }; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.moddif = function($function, $mod) { - $function = utils.defaultValue$Float($function, 0.0); - $mod = utils.defaultValue$Float($mod , 1.0); + spec.moddif = fn(function($function, $mod) { return this.composeNAryOp( $SC.Symbol("moddif"), $SC.Array([ $function, $mod ]) ); - }; + }, "function; mod"); - spec.degreeToKey = function($scale, $stepsPerOctave) { - $stepsPerOctave = utils.defaultValue$Integer($stepsPerOctave, 12); + spec.degreeToKey = fn(function($scale, $stepsPerOctave) { return this.composeNAryOp( $SC.Symbol("degreeToKey"), $SC.Array([ $scale, $stepsPerOctave ]) ); - }; + }, "scale; stepsPerOctave=12"); spec.degrad = function() { return this.composeUnaryOp($SC.Symbol("degrad")); @@ -634,8 +612,8 @@ function SCUnaryOpFunction(args) { this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; } sc.lang.klass.define(SCUnaryOpFunction, "UnaryOpFunction : AbstractFunction", function(spec) { @@ -661,10 +639,10 @@ function SCBinaryOpFunction(args) { this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); - this.$b = utils.defaultValue$Nil(args[2]); - this.$adverb = utils.defaultValue$Nil(args[3]); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; + this.$b = args[2] || /* istanbul ignore next */ $nil; + this.$adverb = args[3] || /* istanbul ignore next */ $nil; } sc.lang.klass.define(SCBinaryOpFunction, "BinaryOpFunction : AbstractFunction", function(spec) { @@ -691,9 +669,9 @@ function SCNAryOpFunction(args) { this.__initializeWith__("AbstractFunction"); - this.$selector = utils.defaultValue$Nil(args[0]); - this.$a = utils.defaultValue$Nil(args[1]); - this.$arglist = utils.defaultValue$Nil(args[2]); + this.$selector = args[0] || /* istanbul ignore next */ $nil; + this.$a = args[1] || /* istanbul ignore next */ $nil; + this.$arglist = args[2] || /* istanbul ignore next */ $nil; } sc.lang.klass.define(SCNAryOpFunction, "NAryOpFunction : AbstractFunction", function(spec) { @@ -725,7 +703,7 @@ function SCFunctionList(args) { this.__initializeWith__("AbstractFunction"); - this.$array = utils.defaultValue$Nil(args[0]); + this.$array = args[0] || /* istanbul ignore next */ $nil; this._flopped = false; } @@ -736,11 +714,10 @@ return this.$array; }; - spec.array_ = function($value) { - $value = utils.defaultValue$Nil($value); + spec.array_ = fn(function($value) { this.$array = $value; return this; - }; + }, "value"); spec.flopped = function() { return $SC.Boolean(this._flopped); diff --git a/src/sc/lang/classlib/Core/Boolean.js b/src/sc/lang/classlib/Core/Boolean.js index 07de81a..ab8db4f 100644 --- a/src/sc/lang/classlib/Core/Boolean.js +++ b/src/sc/lang/classlib/Core/Boolean.js @@ -3,6 +3,7 @@ require("./Object"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; sc.lang.klass.refine("Boolean", function(spec, utils) { @@ -56,10 +57,9 @@ throw new Error("True.new is illegal, should use literal."); }; - spec.if = function($trueFunc) { - $trueFunc = utils.defaultValue$Nil($trueFunc); + spec.if = fn(function($trueFunc) { return $trueFunc.value(); - }; + }, "trueFunc"); spec.not = utils.alwaysReturn$false; @@ -69,16 +69,15 @@ spec["||"] = utils.nop; - spec.and = function($that) { - $that = utils.defaultValue$Nil($that); + spec.and = fn(function($that) { return $that.value(); - }; + }, "that"); + spec.or = spec["||"]; - spec.nand = function($that) { - $that = utils.defaultValue$Nil($that); + spec.nand = fn(function($that) { return $that.value().not(); - }; + }, "that"); spec.asInteger = utils.alwaysReturn$int_1; spec.binaryValue = utils.alwaysReturn$int_1; @@ -89,9 +88,9 @@ throw new Error("False.new is illegal, should use literal."); }; - spec.if = function($trueFunc, $falseFunc) { + spec.if = fn(function($trueFunc, $falseFunc) { return $falseFunc.value(); - }; + }, "trueFunc; falseFunc"); spec.not = utils.alwaysReturn$true; @@ -103,10 +102,9 @@ spec.and = utils.nop; - spec.or = function($that) { - $that = utils.defaultValue$Nil($that); + spec.or = fn(function($that) { return $that.value(); - }; + }, "that"); spec.nand = utils.alwaysReturn$true; spec.asInteger = utils.alwaysReturn$int_0; diff --git a/src/sc/lang/classlib/Core/Function.js b/src/sc/lang/classlib/Core/Function.js index 5e34aa9..395eedc 100644 --- a/src/sc/lang/classlib/Core/Function.js +++ b/src/sc/lang/classlib/Core/Function.js @@ -4,7 +4,8 @@ require("./AbstractFunction"); var slice = [].slice; - var $SC = sc.lang.$SC; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; sc.lang.klass.refine("Function", function(spec, utils) { var BOOL = utils.BOOL; @@ -41,7 +42,6 @@ }; spec.valueArray = function($args) { - $args = utils.defaultValue$Nil($args); return this._.apply(this, $args.asArray()._); }; @@ -61,10 +61,9 @@ return $SC("Routine").new(this); }; - spec.dup = function($n) { - $n = utils.defaultValue$Integer($n, 2); + spec.dup = fn(function($n) { return SCArray.fill($n, this); - }; + }, "n=2"); // TODO: implements sum // TODO: implements defer @@ -127,16 +126,13 @@ // TODO: implements makeFlopFunc // TODO: implements inEnvir - spec.while = function($body) { - $body = utils.defaultValue$Nil($body); - + spec.while = fn(function($body) { sc.lang.iterator.execute( sc.lang.iterator.function$while(this), $body ); - return this; - }; + }, "body"); }); })(sc); diff --git a/src/sc/lang/classlib/Core/Nil.js b/src/sc/lang/classlib/Core/Nil.js index 82f4f92..3720558 100644 --- a/src/sc/lang/classlib/Core/Nil.js +++ b/src/sc/lang/classlib/Core/Nil.js @@ -4,7 +4,8 @@ require("./Object"); var slice = [].slice; - var $SC = sc.lang.$SC; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; sc.lang.klass.refine("Nil", function(spec, utils) { var $nil = utils.$nil; @@ -45,15 +46,13 @@ spec.asBoolean = utils.alwaysReturn$false; spec.booleanValue = utils.alwaysReturn$false; - spec.push = function($function) { - $function = utils.defaultValue$Nil($function); + spec.push = fn(function($function) { return $function.value(); - }; + }, "function"); - spec.appendStream = function($stream) { - $stream = utils.defaultValue$Nil($stream); + spec.appendStream = fn(function($stream) { return $stream; - }; + }, "stream"); spec.pop = utils.nop; spec.source = utils.nop; @@ -84,26 +83,22 @@ spec.release = utils.nop; spec.update = utils.nop; - spec.transformEvent = function($event) { - $event = utils.defaultValue$Nil($event); + spec.transformEvent = fn(function($event) { return $event; - }; + }, "event"); spec.awake = utils.alwaysReturn$nil; spec.play = utils.nop; - spec.nextTimeOnGrid = function($clock) { - $clock = utils.defaultValue$Nil($clock); - + spec.nextTimeOnGrid = fn(function($clock) { if ($clock === $nil) { return $clock; } - return $SC.Function(function() { return $clock.nextTimeOnGrid(); }); - }; + }, "clock"); spec.asQuant = function() { return $SC("Quant").default(); @@ -112,32 +107,27 @@ spec.swapThisGroup = utils.nop; spec.performMsg = utils.nop; - spec.printOn = function($stream) { - $stream = utils.defaultValue$Nil($stream); + spec.printOn = fn(function($stream) { $stream.putAll($SC.String("nil")); return this; - }; + }, "stream"); - spec.storeOn = function($stream) { - $stream = utils.defaultValue$Nil($stream); + spec.storeOn = fn(function($stream) { $stream.putAll($SC.String("nil")); return this; - }; + }, "stream"); spec.matchItem = utils.alwaysReturn$true; - spec.add = function($value) { - $value = utils.defaultValue$Nil($value); + spec.add = fn(function($value) { return $SC.Array([ $value ]); - }; + }, "value"); - spec.addAll = function($array) { - $array = utils.defaultValue$Nil($array); + spec.addAll = fn(function($array) { return $array.asArray(); - }; + }, "array"); spec["++"] = function($array) { - $array = utils.defaultValue$Nil($array); return $array.asArray(); }; @@ -149,10 +139,9 @@ spec.set = utils.nop; - spec.get = function($prevVal) { - $prevVal = utils.defaultValue$Nil($prevVal); + spec.get = fn(function($prevVal) { return $prevVal; - }; + }, "prevVal"); spec.addFunc = function() { var functions = slice.call(arguments); diff --git a/src/sc/lang/classlib/Core/Object.js b/src/sc/lang/classlib/Core/Object.js index b35c458..338ef50 100644 --- a/src/sc/lang/classlib/Core/Object.js +++ b/src/sc/lang/classlib/Core/Object.js @@ -4,8 +4,8 @@ require("../../classlib"); var slice = [].slice; - var $SC = sc.lang.$SC; - var fn = sc.lang.fn; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; sc.lang.klass.refine("Object", function(spec, utils) { var BOOL = utils.BOOL; @@ -61,8 +61,6 @@ spec.flatSize = utils.alwaysReturn$int_1; spec.do = function($function) { - $function = utils.defaultValue$Nil($function); - sc.lang.iterator.execute( sc.lang.iterator.object$do(this), $function @@ -71,28 +69,24 @@ return this; }; - spec.generate = function($function, $state) { - $state = utils.defaultValue$Nil($state); - + spec.generate = fn(function($function, $state) { this.do($function); return $state; - }; + }, "function; state"); // already defined: class // already defined: isKindOf // already defined: isMemberOf - spec.respondsTo = function($aSymbol) { - $aSymbol = utils.defaultValue$Nil($aSymbol); + spec.respondsTo = fn(function($aSymbol) { return $SC.Boolean(typeof this[$aSymbol.__sym__()] === "function"); - }; + }, "aSymbol"); // TODO: implements performMsg spec.perform = function($selector) { var selector, method; - $selector = utils.defaultValue$Nil($selector); selector = $selector.__sym__(); method = this[selector]; @@ -106,8 +100,6 @@ spec.performList = function($selector, $arglist) { var selector, method; - $selector = utils.defaultValue$Nil($selector); - $arglist = utils.defaultValue$Nil($arglist); selector = $selector.__sym__(); method = this[selector]; @@ -166,11 +158,10 @@ // TODO: implements copyImmutable // TODO: implements deepCopy - spec.dup = function($n) { + spec.dup = fn(function($n) { var $this = this; var $array, i, imax; - $n = utils.defaultValue$Integer($n, 2); if (BOOL($n.isSequenceableCollection())) { return SCArray.fillND($n, $SC.Function(function() { return $this.copy(); @@ -183,7 +174,7 @@ } return $array; - }; + }, "n=2"); spec["!"] = function($n) { return this.dup($n); @@ -228,12 +219,10 @@ spec.next = utils.nop; spec.reset = utils.nop; - spec.first = function($inval) { - $inval = utils.defaultValue$Nil($inval); - + spec.first = fn(function($inval) { this.reset(); return this.next($inval); - }; + }, "inval"); spec.iter = function() { return $SC("OneShotStream").new(this); @@ -260,10 +249,9 @@ spec.eventAt = utils.alwaysReturn$nil; - spec.composeEvents = function($event) { - $event = utils.defaultValue$Nil($event); + spec.composeEvents = fn(function($event) { return $event.copy(); - }; + }, "event"); spec.finishEvent = utils.nop; spec.atLimit = utils.alwaysReturn$false; @@ -274,7 +262,6 @@ spec["??"] = utils.nop; spec["!?"] = function($obj) { - $obj = utils.defaultValue$Nil($obj); return $obj.value(this); }; @@ -292,17 +279,15 @@ spec.isException = utils.alwaysReturn$false; spec.isFunction = utils.alwaysReturn$false; - spec.matchItem = function($item) { - $item = utils.defaultValue$Nil($item); + spec.matchItem = fn(function($item) { return this ["==="] ($item); - }; + }, "item"); spec.trueAt = utils.alwaysReturn$false; - spec.falseAt = function($key) { - $key = utils.defaultValue$Nil($key); + spec.falseAt = fn(function($key) { return this.trueAt($key).not(); - }; + }, "key"); // TODO: implements pointsTo // TODO: implements mutable @@ -358,10 +343,9 @@ // TODO: implements storeArgs // TODO: implements storeModifiersOn - spec.as = function($aSimilarClass) { - $aSimilarClass = utils.defaultValue$Nil($aSimilarClass); + spec.as = fn(function($aSimilarClass) { return $aSimilarClass.newFrom(this); - }; + }, "aSimilarClass"); spec.dereference = utils.nop; @@ -383,24 +367,21 @@ spec.rank = utils.alwaysReturn$int_0; - spec.deepCollect = function($depth, $function, $index, $rank) { - $function = utils.defaultValue$Nil($function); + spec.deepCollect = fn(function($depth, $function, $index, $rank) { return $function.value(this, $index, $rank); - }; + }, "depth; function; index; rank"); - spec.deepDo = function($depth, $function, $index, $rank) { - $function = utils.defaultValue$Nil($function); + spec.deepDo = fn(function($depth, $function, $index, $rank) { $function.value(this, $index, $rank); return this; - }; + }, "depth; function; index; rank"); spec.slice = utils.nop; spec.shape = utils.alwaysReturn$nil; spec.unbubble = utils.nop; - spec.bubble = function($depth, $levels) { + spec.bubble = fn(function($depth, $levels) { var levels, a; - $levels = utils.defaultValue$Integer($levels, 1); levels = $levels.__int__(); if (levels <= 1) { @@ -412,29 +393,23 @@ } return $SC.Array(a); - }; - - spec.obtain = function($index, $default) { - $index = utils.defaultValue$Nil($index); - $default = utils.defaultValue$Nil($default); + }, "depth; levels"); + spec.obtain = fn(function($index, $default) { if ($index.__num__() === 0) { return this; } else { return $default; } - }; - - spec.instill = function($index, $item, $default) { - $index = utils.defaultValue$Nil($index); - $item = utils.defaultValue$Nil($item); + }, "index; defaults"); + spec.instill = fn(function($index, $item, $default) { if ($index.__num__() === 0) { return $item; } else { return this.asArray().instill($index, $item, $default); } - }; + }, "index; item; default"); spec.addFunc = fn(function($$functions) { return $SC("FunctionList").new(this ["++"] ($$functions)); @@ -447,20 +422,18 @@ return this; }; - spec.replaceFunc = function($find, $replace) { - $replace = utils.defaultValue$Nil($replace); + spec.replaceFunc = fn(function($find, $replace) { if (this === $find) { return $replace; } return this; - }; + }, "find; replace"); // TODO: implements addFuncTo // TODO: implements removeFuncFrom - spec.while = function($body) { + spec.while = fn(function($body) { var $this = this; - $body = utils.defaultValue$Nil($body); $SC.Function(function() { return $this.value(); @@ -469,7 +442,7 @@ })); return this; - }; + }, "body"); spec.switch = function() { var args, i, imax; @@ -551,29 +524,22 @@ return this.asInteger(); }; - spec.blend = function($that, $blendFrac) { - $that = utils.defaultValue$Nil($that); - $blendFrac = utils.defaultValue$Float($blendFrac, 0.5); + spec.blend = fn(function($that, $blendFrac) { return this ["+"] ($blendFrac ["*"] ($that ["-"] (this))); - }; + }, "that; blendFrac=0.5"); - spec.blendAt = function($index, $method) { + spec.blendAt = fn(function($index, $method) { var $iMin; - $index = utils.defaultValue$Nil($index); - $method = utils.defaultValue$Symbol($method, "clipAt"); $iMin = $index.roundUp($int_1).asInteger().__dec__(); return this.perform($method, $iMin).blend( this.perform($method, $iMin.__inc__()), $index.absdif($iMin) ); - }; + }, "index; method=\\clipAt"); - spec.blendPut = function($index, $val, $method) { + spec.blendPut = fn(function($index, $val, $method) { var $iMin, $ratio; - $index = utils.defaultValue$Nil($index); - $val = utils.defaultValue$Nil($val); - $method = utils.defaultValue$Symbol($method, "wrapPut"); $iMin = $index.floor().asInteger(); $ratio = $index.absdif($iMin); @@ -581,30 +547,25 @@ this.perform($method, $iMin.__inc__(), $val ["*"] ($ratio)); return this; - }; - - spec.fuzzyEqual = function($that, $precision) { - $that = utils.defaultValue$Nil($that); - $precision = utils.defaultValue$Float($precision, 1.0); + }, "index; val; method=\\wrapPut"); + spec.fuzzyEqual = fn(function($that, $precision) { return $SC.Float(0.0).max( $SC.Float(1.0) ["-"] ( (this ["-"] ($that).abs()) ["/"] ($precision) ) ); - }; + }, "that; precision=1.0"); spec.isUGen = utils.alwaysReturn$false; spec.numChannels = utils.alwaysReturn$int_1; - spec.pair = function($that) { - $that = utils.defaultValue$Nil($that); + spec.pair = fn(function($that) { return $SC.Array([ this, $that ]); - }; + }, "that"); - spec.pairs = function($that) { + spec.pairs = fn(function($that) { var $list; - $that = utils.defaultValue$Nil($that); $list = $SC.Array(); this.asArray().do($SC.Function(function($a) { @@ -614,18 +575,17 @@ })); return $list; - }; + }, "that"); - spec.awake = function($beats) { + spec.awake = fn(function($beats) { return this.next($beats); - }; + }, "beats"); spec.beats_ = utils.nop; spec.clock_ = utils.nop; spec.performBinaryOpOnSomething = function($aSelector) { var aSelector; - $aSelector = utils.defaultValue$Nil($aSelector); aSelector = $aSelector.__sym__(); if (aSelector === "==") { diff --git a/src/sc/lang/classlib/Core/Ref.js b/src/sc/lang/classlib/Core/Ref.js index 0b8fb03..d4c6dad 100644 --- a/src/sc/lang/classlib/Core/Ref.js +++ b/src/sc/lang/classlib/Core/Ref.js @@ -3,6 +3,7 @@ require("./Object"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; function SCRef(args) { @@ -19,18 +20,17 @@ return this._value; }; - spec.value_ = function($value) { + spec.value_ = fn(function($value) { this._value = $value; return this; - }; + }, "value"); // $new - spec.set = function($thing) { - $thing = utils.defaultValue$Nil($thing); + spec.set = fn(function($thing) { this._value = $thing; return this; - }; + }, "thing"); spec.get = function() { return this._value; diff --git a/src/sc/lang/classlib/Math/Float.js b/src/sc/lang/classlib/Math/Float.js index 604ab71..8d9bb2d 100644 --- a/src/sc/lang/classlib/Math/Float.js +++ b/src/sc/lang/classlib/Math/Float.js @@ -4,9 +4,10 @@ require("./SimpleNumber"); require("./bop"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; var iterator = sc.lang.iterator; - var mathlib = sc.libs.mathlib; + var mathlib = sc.libs.mathlib; sc.lang.klass.refine("Float", function(spec, utils) { spec.toString = function() { @@ -79,10 +80,7 @@ spec[items[0]] = sc.lang.classlib.bop.apply(null, items); }); - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - + spec.clip = fn(function($lo, $hi) { // <-- _ClipFloat --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -94,12 +92,9 @@ return $SC.Float( mathlib.clip(this._, $lo.__num__(), $hi.__num__()) ); - }; - - spec.wrap = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + }, "lo; hi"); + spec.wrap = fn(function($lo, $hi) { // <-- _WrapInt --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -111,12 +106,9 @@ return $SC.Float( mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) ); - }; - - spec.fold = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + }, "lo; hi"); + spec.fold = fn(function($lo, $hi) { // <-- _FoldFloat --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -128,7 +120,7 @@ return $SC.Float( mathlib.fold(this._, $lo.__num__(), $hi.__num__()) ); - }; + }, "lo; hi"); // TODO: implements coin // TODO: implements xrand2 @@ -160,23 +152,23 @@ ); }; - spec.$from32Bits = function($word) { + spec.$from32Bits = fn(function($word) { // <-- _From32Bits --> return $SC.Float( new Float32Array( new Int32Array([ $word.__num__() ]).buffer )[0] ); - }; + }, "word"); - spec.$from64Bits = function($hiWord, $loWord) { + spec.$from64Bits = fn(function($hiWord, $loWord) { // <-- _From64Bits --> return $SC.Float( new Float64Array( new Int32Array([ $loWord.__num__(), $hiWord.__num__() ]).buffer )[0] ); - }; + }, "hiWord; loWord"); spec.do = function($function) { iterator.execute( diff --git a/src/sc/lang/classlib/Math/Integer.js b/src/sc/lang/classlib/Math/Integer.js index db8ae85..17aa11d 100644 --- a/src/sc/lang/classlib/Math/Integer.js +++ b/src/sc/lang/classlib/Math/Integer.js @@ -4,9 +4,10 @@ require("./SimpleNumber"); require("./bop"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; var iterator = sc.lang.iterator; - var mathlib = sc.libs.mathlib; + var mathlib = sc.libs.mathlib; sc.lang.klass.refine("Integer", function(spec, utils) { var $nil = utils.$nil; @@ -107,10 +108,7 @@ ); }; - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); - + spec.clip = fn(function($lo, $hi) { // <-- _ClipInt --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -127,12 +125,9 @@ return $SC.Float( mathlib.clip(this._, $lo.__num__(), $hi.__num__()) ); - }; - - spec.wrap = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + }, "lo; hi"); + spec.wrap = fn(function($lo, $hi) { // <-- _WrapInt --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -149,12 +144,9 @@ return $SC.Float( mathlib.wrap(this._, $lo.__num__(), $hi.__num__()) ); - }; - - spec.fold = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + }, "lo; hi"); + spec.fold = fn(function($lo, $hi) { // <-- _FoldInt --> if ($lo.__tag === sc.C.TAG_SYM) { return $lo; @@ -171,7 +163,7 @@ return $SC.Float( mathlib.fold(this._, $lo.__num__(), $hi.__num__()) ); - }; + }, "lo; hi"); spec.even = function() { return $SC.Boolean(!(this._ & 1)); @@ -181,14 +173,12 @@ return $SC.Boolean(!!(this._ & 1)); }; - spec.xrand = function($exclude) { - $exclude = utils.defaultValue$Integer($exclude, 0); + spec.xrand = fn(function($exclude) { return ($exclude ["+"] (this.__dec__().rand()) ["+"] ($int_1)) ["%"] (this); - }; + }, "exclude=0"); - spec.xrand2 = function($exclude) { + spec.xrand2 = fn(function($exclude) { var raw, res; - $exclude = utils.defaultValue$Integer($exclude, 0); raw = this._; res = (mathlib.rand((2 * raw))|0) - raw; @@ -198,14 +188,11 @@ } return $SC.Integer(res); - }; - - spec.degreeToKey = function($scale, $stepsPerOctave) { - $scale = utils.defaultValue$Nil($scale); - $stepsPerOctave = utils.defaultValue$Integer($stepsPerOctave, 12); + }, "exclude=0"); + spec.degreeToKey = fn(function($scale, $stepsPerOctave) { return $scale.performDegreeToKey(this, $stepsPerOctave); - }; + }, "scale; stepsPerOctave=12"); spec.do = function($function) { iterator.execute( @@ -216,18 +203,15 @@ }; spec.generate = function($function) { - $function = utils.defaultValue$Nil($function); $function.value(this); return this; }; - spec.collectAs = function($function, $class) { + spec.collectAs = fn(function($function, $class) { var $res; var i, imax; - $function = utils.defaultValue$Nil($function); - $class = utils.defaultValue$Nil($class); if ($class === $nil) { $class = SCArray; @@ -239,7 +223,7 @@ } return $res; - }; + }, "function; class"); spec.collect = function($function) { return this.collectAs($function, SCArray); @@ -253,26 +237,25 @@ return this; }; - spec.for = function($endval, $function) { + spec.for = fn(function($endval, $function) { iterator.execute( iterator.integer$for(this, $endval), $function ); return this; - }; + }, "endval; function"); - spec.forBy = function($endval, $stepval, $function) { + spec.forBy = fn(function($endval, $stepval, $function) { iterator.execute( iterator.integer$forBy(this, $endval, $stepval), $function ); return this; - }; + }, "endval; stepval; function"); - spec.to = function($hi, $step) { - $step = utils.defaultValue$Integer($step, 1); + spec.to = fn(function($hi, $step) { return $SC("Interval").new(this, $hi, $step); - }; + }, "hi; step=1"); spec.asAscii = function() { // <-- _AsAscii --> @@ -296,9 +279,8 @@ throw new Error("Integer: asDigit must be 0 <= this <= 35"); }; - spec.asBinaryDigits = function($numDigits) { + spec.asBinaryDigits = fn(function($numDigits) { var raw, array, numDigits, i; - $numDigits = utils.defaultValue$Integer($numDigits, 8); raw = this._; numDigits = $numDigits.__int__(); @@ -308,13 +290,11 @@ } return $SC.Array(array); - }; + }, "numDigits=8"); - spec.asDigits = function($base, $numDigits) { + spec.asDigits = fn(function($base, $numDigits) { var $num; var array, numDigits, i; - $base = utils.defaultValue$Integer($base, 10); - $numDigits = utils.defaultValue$Nil($numDigits); $num = this; if ($numDigits === $nil) { @@ -332,7 +312,7 @@ } return $SC.Array(array); - }; + }, "base=10; numDigits"); // TODO: implements nextPowerOfTwo // TODO: implements isPowerOfTwo @@ -354,15 +334,13 @@ // TODO: implements asIPString // TODO: implements archiveAsCompileString - spec.geom = function($start, $grow) { + spec.geom = fn(function($start, $grow) { return SCArray.geom(this, $start, $grow); - }; + }, "start; grow"); - spec.fib = function($a, $b) { - $a = utils.defaultValue$Float($a, 0.0); - $b = utils.defaultValue$Float($b, 1.0); + spec.fib = fn(function($a, $b) { return SCArray.fib(this, $a, $b); - }; + }, "a=0.0; b=1.0"); // TODO: implements factors // TODO: implements pidRunning diff --git a/src/sc/lang/classlib/Math/Magnitude.js b/src/sc/lang/classlib/Math/Magnitude.js index 639f856..0548f5a 100644 --- a/src/sc/lang/classlib/Math/Magnitude.js +++ b/src/sc/lang/classlib/Math/Magnitude.js @@ -3,9 +3,10 @@ require("../Core/Object"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; - sc.lang.klass.refine("Magnitude", function(spec, utils) { + sc.lang.klass.refine("Magnitude", function(spec) { spec["=="] = function($aMagnitude) { return $SC.Boolean(this.valueOf() === $aMagnitude.valueOf()); }; @@ -34,33 +35,25 @@ return $SC.Boolean(this >= $aMagnitude); }; - spec.exclusivelyBetween = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec.exclusivelyBetween = fn(function($lo, $hi) { return $SC.Boolean($lo < this && this < $hi); - }; + }, "lo; hi"); - spec.inclusivelyBetween = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec.inclusivelyBetween = fn(function($lo, $hi) { return $SC.Boolean($lo <= this && this <= $hi); - }; + }, "lo; hi"); - spec.min = function($aMagnitude) { - $aMagnitude = utils.defaultValue$Nil($aMagnitude); + spec.min = fn(function($aMagnitude) { return this <= $aMagnitude ? this : $aMagnitude; - }; + }, "aMagnitude"); - spec.max = function($aMagnitude) { - $aMagnitude = utils.defaultValue$Nil($aMagnitude); + spec.max = fn(function($aMagnitude) { return this >= $aMagnitude ? this : $aMagnitude; - }; + }, "aMagnitude"); - spec.clip = function($lo, $hi) { - $lo = utils.defaultValue$Nil($lo); - $hi = utils.defaultValue$Nil($hi); + spec.clip = fn(function($lo, $hi) { return this <= $lo ? $lo : this >= $hi ? $hi : this; - }; + }, "lo; hi"); }); })(sc); diff --git a/src/sc/lang/classlib/Math/Number.js b/src/sc/lang/classlib/Math/Number.js index f9e9996..bbfa517 100644 --- a/src/sc/lang/classlib/Math/Number.js +++ b/src/sc/lang/classlib/Math/Number.js @@ -3,6 +3,7 @@ require("./Magnitude"); + var fn = sc.lang.fn; var $SC = sc.lang.$SC; var iterator = sc.lang.iterator; @@ -39,7 +40,6 @@ spec.performBinaryOpOnSeqColl = function($aSelector, $aSeqColl, $adverb) { var $this = this; - $aSeqColl = utils.defaultValue$Nil($aSeqColl); return $aSeqColl.collect($SC.Function(function($item) { return $item.perform($aSelector, $this, $adverb); @@ -64,29 +64,29 @@ // TODO: implements complex // TODO: implements polar - spec.for = function($endValue, $function) { + spec.for = fn(function($endValue, $function) { iterator.execute( iterator.number$for(this, $endValue), $function ); return this; - }; + }, "endValue; function"); - spec.forBy = function($endValue, $stepValue, $function) { + spec.forBy = fn(function($endValue, $stepValue, $function) { iterator.execute( iterator.number$forBy(this, $endValue, $stepValue), $function ); return this; - }; + }, "endValue; stepValue; function"); - spec.forSeries = function($second, $last, $function) { + spec.forSeries = fn(function($second, $last, $function) { iterator.execute( iterator.number$forSeries(this, $second, $last), $function ); return this; - }; + }, "second; last; function"); }); })(sc); diff --git a/src/sc/lang/classlib/Math/SimpleNumber.js b/src/sc/lang/classlib/Math/SimpleNumber.js index fb8f7aa..aa79a19 100644 --- a/src/sc/lang/classlib/Math/SimpleNumber.js +++ b/src/sc/lang/classlib/Math/SimpleNumber.js @@ -3,7 +3,8 @@ require("./Number"); - var $SC = sc.lang.$SC; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; var rand = sc.libs.random; function prOpSimpleNumber(selector, func) { @@ -373,7 +374,6 @@ // bitXor: implemented by subclass spec.bitTest = function($bit) { - $bit = utils.defaultValue$Nil($bit); return $SC.Boolean( this.bitAnd($int_1.leftShift($bit)).valueOf() !== 0 ); @@ -430,11 +430,9 @@ return a >= b; }); - spec.equalWithPrecision = function($that, $precision) { - $that = utils.defaultValue$Nil($that); - $precision = utils.defaultValue$Float($precision, 0.0001); + spec.equalWithPrecision = fn(function($that, $precision) { return this.absdif($that) ["<"] ($precision); - }; + }, "that; precision=0.0001"); // TODO: implements hash @@ -467,12 +465,11 @@ ); }; - spec.nextPowerOf = function($base) { - $base = utils.defaultValue$Nil($base); + spec.nextPowerOf = fn(function($base) { return $base.pow( (this.log() ["/"] ($base.log())).ceil() ); - }; + }, "base"); spec.nextPowerOfThree = function() { return $SC.Float( @@ -480,18 +477,14 @@ ); }; - spec.previousPowerOf = function($base) { - $base = utils.defaultValue$Nil($base); + spec.previousPowerOf = fn(function($base) { return $base.pow( (this.log() ["/"] ($base.log())).ceil().__dec__() ); - }; + }, "base"); - spec.quantize = function($quantum, $tolerance, $strength) { + spec.quantize = fn(function($quantum, $tolerance, $strength) { var $round, $diff; - $quantum = utils.defaultValue$Float($quantum, 1.0); - $tolerance = utils.defaultValue$Float($tolerance, 0.05); - $strength = utils.defaultValue$Float($strength, 1.0); $round = this.round($quantum); $diff = $round ["-"] (this); @@ -501,15 +494,10 @@ } return this; - }; + }, "quantum=1.0; tolerance=0.05; strength=1.0"); - spec.linlin = function($inMin, $inMax, $outMin, $outMax, $clip) { + spec.linlin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -520,15 +508,10 @@ } return $res; - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.linexp = function($inMin, $inMax, $outMin, $outMax, $clip) { + spec.linexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -540,15 +523,10 @@ } return $res; - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.explin = function($inMin, $inMax, $outMin, $outMax, $clip) { + spec.explin = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -559,15 +537,10 @@ } return $res; - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.expexp = function($inMin, $inMax, $outMin, $outMax, $clip) { + spec.expexp = fn(function($inMin, $inMax, $outMin, $outMax, $clip) { var $res = null; - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -579,16 +552,10 @@ } return $res; - }; + }, "inMin; inMax; outMin; outMax; clip=\\minmax"); - spec.lincurve = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + spec.lincurve = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { var $res = null, $grow, $a, $b, $scaled; - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -606,16 +573,10 @@ } return $res; - }; + }, "inMin=0; inMax=1; outMin=0; outMax=1; curve=-4; clip=\\minmax"); - spec.curvelin = function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { + spec.curvelin = fn(function($inMin, $inMax, $outMin, $outMax, $curve, $clip) { var $res = null, $grow, $a, $b; - $inMin = utils.defaultValue$Integer($inMin, 0); - $inMax = utils.defaultValue$Integer($inMax, 1); - $outMin = utils.defaultValue$Integer($outMin, 0); - $outMax = utils.defaultValue$Integer($outMax, 1); - $curve = utils.defaultValue$Integer($curve, -4); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -633,17 +594,10 @@ } return $res; - }; + }, "inMin=0; inMax=1; outMin=0; outMax=1; curve=-4; clip=\\minmax"); - spec.bilin = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + spec.bilin = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { var $res = null; - $inCenter = utils.defaultValue$Nil($inCenter); - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outCenter = utils.defaultValue$Nil($outCenter); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -656,17 +610,10 @@ } return $res; - }; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.biexp = function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { + spec.biexp = fn(function($inCenter, $inMin, $inMax, $outCenter, $outMin, $outMax, $clip) { var $res = null; - $inCenter = utils.defaultValue$Nil($inCenter); - $inMin = utils.defaultValue$Nil($inMin); - $inMax = utils.defaultValue$Nil($inMax); - $outCenter = utils.defaultValue$Nil($outCenter); - $outMin = utils.defaultValue$Nil($outMin); - $outMax = utils.defaultValue$Nil($outMax); - $clip = utils.defaultValue$Symbol($clip, "minmax"); $res = clip_for_map(this, $inMin, $inMax, $outMin, $outMax, $clip); @@ -679,25 +626,19 @@ } return $res; - }; + }, "inCenter; inMin; inMax; outCenter; outMin; outMax; clip=\\minmax"); - spec.moddif = function($aNumber, $mod) { + spec.moddif = fn(function($aNumber, $mod) { var $diff, $modhalf; - $aNumber = utils.defaultValue$Float($aNumber, 0.0); - $mod = utils.defaultValue$Float($mod , 1.0); $diff = this.absdif($aNumber) ["%"] ($mod); $modhalf = $mod ["*"] ($SC.Float(0.5)); return $modhalf ["-"] ($diff.absdif($modhalf)); - }; + }, "aNumber=0.0; mod=1.0"); - spec.lcurve = function($a, $m, $n, $tau) { + spec.lcurve = fn(function($a, $m, $n, $tau) { var $rTau, $x; - $a = utils.defaultValue$Float($a, 1.0); - $m = utils.defaultValue$Float($m, 0.0); - $n = utils.defaultValue$Float($n, 1.0); - $tau = utils.defaultValue$Float($tau, 1.0); $x = this.neg(); @@ -716,26 +657,21 @@ $n ["*"] ($x.exp()) ["*"] ($rTau).__inc__() ); } - }; + }, "a=1.0; m=0.0; n=1.0; tau=1.0"); - spec.gauss = function($standardDeviation) { - $standardDeviation = utils.defaultValue$Nil($standardDeviation); - // ^((((-2*log(1.0.rand)).sqrt * sin(2pi.rand)) * standardDeviation) + this) + spec.gauss = fn(function($standardDeviation) { + // ^((((-2*log(1.0.rand)).sqrt * sin(2pi.rand)) * standardDeviation) + this) return ($SC.Float(-2.0) ["*"] ($SC.Float(1.0).rand().log()).sqrt() ["*"] ( $SC.Float(2 * Math.PI).rand().sin() ) ["*"] ($standardDeviation)) ["+"] (this); - }; - - spec.gaussCurve = function($a, $b, $c) { - $a = utils.defaultValue$Float($a, 1.0); - $b = utils.defaultValue$Float($b, 0.0); - $c = utils.defaultValue$Float($c, 1.0); + }, "standardDeviation"); + spec.gaussCurve = fn(function($a, $b, $c) { // ^a * (exp(squared(this - b) / (-2.0 * squared(c)))) return $a ["*"] (( (this ["-"] ($b).squared()) ["/"] ($SC.Float(-2.0) ["*"] ($c.squared())) ).exp()); - }; + }, "a=1.0; b=0.0; c=1.0"); // TODO: implements asPoint // TODO: implements asWarp @@ -760,12 +696,9 @@ return $SC("DC").ar(this); }; - spec.madd = function($mul, $add) { - $mul = utils.defaultValue$Nil($mul); - $add = utils.defaultValue$Nil($add); - + spec.madd = fn(function($mul, $add) { return (this ["*"] ($mul)) ["+"] ($add); - }; + }, "mul; add"); spec.lag = utils.nop; spec.lag2 = utils.nop; @@ -778,11 +711,9 @@ // TODO: implements writeInputSpec - spec.series = function($second, $last) { + spec.series = fn(function($second, $last) { var $step; var last, step, size; - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); if ($second === $nil) { if (this.valueOf() < $last.valueOf()) { @@ -798,7 +729,7 @@ size = (Math.floor((last - this._) / step + 0.001)|0) + 1; return SCArray.series($SC.Integer(size), this, $step); - }; + }, "second; last"); // TODO: implements seriesIter // TODO: implements degreeToKey diff --git a/src/sc/lang/codegen.js b/src/sc/lang/codegen.js index aee348b..b65cd11 100644 --- a/src/sc/lang/codegen.js +++ b/src/sc/lang/codegen.js @@ -421,6 +421,21 @@ ]; }; + var format_argument = function(node) { + switch (node.valueType) { + case Token.NilLiteral : return "nil"; + case Token.TrueLiteral : return "true"; + case Token.FalseLiteral : return "false"; + case Token.CharLiteral : return "$" + node.value; + case Token.SymbolLiteral: return "\\" + node.value; + } + switch (node.value) { + case "Infinity" : return "inf"; + case "-Infinity": return "-inf"; + } + return node.value; + }; + CodeGen.prototype._FunctionMetadata = function(info) { var keys, vals; var args, result; @@ -436,7 +451,13 @@ var result = [ keys[i] ]; if (vals[i]) { - result.push("=", vals[i].value); // TODO #[] + if (vals[i].type === Syntax.ListExpression) { + result.push("=[ ", this.stitchWith(vals[i].elements, ", ", function(item) { + return format_argument(item); + }), " ]"); + } else { + result.push("=", format_argument(vals[i])); + } } return result; diff --git a/src/sc/lang/compiler_test.js b/src/sc/lang/compiler_test.js index 3cab2b0..4bc7e24 100644 --- a/src/sc/lang/compiler_test.js +++ b/src/sc/lang/compiler_test.js @@ -58,7 +58,7 @@ "-10pi": { compiled: [ "SCScript(function($this, $SC) {", - " return $SC.Float(-10 * Math.PI);", + " return $SC.Float(-31.41592653589793);", "});", ], ast: { @@ -66,7 +66,7 @@ body: [ { type: Syntax.Literal, - value: "-10 * Math.PI", + value: "-31.41592653589793", valueType: Token.FloatLiteral, range: [ 0, 5 ], loc: { @@ -573,7 +573,7 @@ "a = 2pi": { compiled: [ "SCScript(function($this, $SC) {", - " return $this.a_($SC.Float(2 * Math.PI));", + " return $this.a_($SC.Float(6.283185307179586));", "});", ], ast: { @@ -593,7 +593,7 @@ }, right: { type: Syntax.Literal, - value: "2 * Math.PI", + value: "6.283185307179586", valueType: Token.FloatLiteral, range: [ 4, 7 ], loc: { @@ -3535,6 +3535,223 @@ } } }, + "{|a=#[ nil, true, false ], b= #[ inf, -inf ], c=#[ 0, 0.0, 2pi, $a, \\sym ]|}": { + compiled: [ + "SCScript(function($this, $SC) {", + " return $SC.Function(function($a, $b, $c) {", + " return $SC.Nil();", + " }, 'a=[ nil, true, false ]; " + + "b=[ inf, -inf ]; c=[ 0, 0.0, 6.283185307179586, $a, \\sym ]');", + "});", + ], + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + body: [], + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + init: { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "null", + valueType: Token.NilLiteral, + range: [ 7, 10 ], + loc: { + start: { line: 1, column: 7 }, + end : { line: 1, column: 10 } + } + }, + { + type: Syntax.Literal, + value: "true", + valueType: "True", + range: [ 12, 16 ], + loc: { + start: { line: 1, column: 12 }, + end : { line: 1, column: 16 } + } + }, + { + type: Syntax.Literal, + value: "false", + valueType: "False", + range: [ 18, 23 ], + loc: { + start: { line: 1, column: 18 }, + end : { line: 1, column: 23 } + } + } + ], + immutable: true, + range: [ 4, 25 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 25 } + } + }, + range: [ 2, 25 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 25 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "b", + range: [ 27, 28 ], + loc: { + start: { line: 1, column: 27 }, + end : { line: 1, column: 28 } + } + }, + init: { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "Infinity", + valueType: "Float", + range: [ 33, 36 ], + loc: { + start: { line: 1, column: 33 }, + end : { line: 1, column: 36 } + } + }, + { + type: Syntax.Literal, + value: "-Infinity", + valueType: Token.FloatLiteral, + range: [ 38, 42 ], + loc: { + start: { line: 1, column: 38 }, + end : { line: 1, column: 42 } + } + } + ], + immutable: true, + range: [ 30, 44 ], + loc: { + start: { line: 1, column: 30 }, + end : { line: 1, column: 44 } + } + }, + range: [ 27, 44 ], + loc: { + start: { line: 1, column: 27 }, + end : { line: 1, column: 44 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "c", + range: [ 46, 47 ], + loc: { + start: { line: 1, column: 46 }, + end : { line: 1, column: 47 } + } + }, + init: { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 51, 52 ], + loc: { + start: { line: 1, column: 51 }, + end : { line: 1, column: 52 } + } + }, + { + type: Syntax.Literal, + value: "0.0", + valueType: Token.FloatLiteral, + range: [ 54, 57 ], + loc: { + start: { line: 1, column: 54 }, + end : { line: 1, column: 57 } + } + }, + { + type: Syntax.Literal, + value: "6.283185307179586", + valueType: Token.FloatLiteral, + range: [ 59, 62 ], + loc: { + start: { line: 1, column: 59 }, + end : { line: 1, column: 62 } + } + }, + { + type: Syntax.Literal, + value: "a", + valueType: Token.CharLiteral, + range: [ 64, 66 ], + loc: { + start: { line: 1, column: 64 }, + end : { line: 1, column: 66 } + } + }, + { + type: Syntax.Literal, + value: "sym", + valueType: Token.SymbolLiteral, + range: [ 68, 72 ], + loc: { + start: { line: 1, column: 68 }, + end : { line: 1, column: 72 } + } + } + ], + immutable: true, + range: [ 48, 74 ], + loc: { + start: { line: 1, column: 48 }, + end : { line: 1, column: 74 } + } + }, + range: [ 46, 74 ], + loc: { + start: { line: 1, column: 46 }, + end : { line: 1, column: 74 } + } + } + ] + }, + range: [ 0, 76 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 76 } + } + } + ], + range: [ 0, 76 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 76 } + } + } + }, "var level=0, slope=1, curve=1;": { compiled: [ "SCScript(function($this, $SC) {", diff --git a/src/sc/lang/fn.js b/src/sc/lang/fn.js index ebc5f8f..bdcd8cc 100644 --- a/src/sc/lang/fn.js +++ b/src/sc/lang/fn.js @@ -2,32 +2,81 @@ "use strict"; require("./dollarSC"); + require("./compiler"); + require("./parser"); var slice = [].slice; var $SC = sc.lang.$SC; + var _getDefaultValue = function(value) { + var ch; + + switch (value) { + case "nil": + return $SC.Nil(); + case "true": + return $SC.True(); + case "false": + return $SC.False(); + case "inf": + return $SC.Float(Infinity); + case "-inf": + return $SC.Float(-Infinity); + } + + ch = value.charAt(0); + switch (ch) { + case "$": + return $SC.Char(value.charAt(1)); + case "\\": + return $SC.Symbol(value.substr(1)); + } + + if (value.indexOf(".") !== -1) { + return $SC.Float(+value); + } + + return $SC.Integer(+value); + }; + + var getDefaultValue = function(value) { + if (value.charAt(0) === "[") { + return $SC.Array(value.slice(1, -2).split(",").map(function(value) { + return _getDefaultValue(value.trim()); + })); + } + return _getDefaultValue(value); + }; + var fn = function(func, def) { - var argNames, remain, wrapper; + var argItems, argNames, argVals; + var remain, wrapper; - argNames = def.split(/\s*,\s*/); - if (argNames[argNames.length - 1].charAt(0) === "*") { - remain = !!argNames.pop(); + argItems = def.split(/\s*;\s*/); + if (argItems[argItems.length - 1].charAt(0) === "*") { + remain = !!argItems.pop(); } + argNames = new Array(argItems.length); + argVals = new Array(argItems.length); + + argItems.forEach(function(items, i) { + items = items.split("="); + argNames[i] = items[0].trim(); + argVals [i] = getDefaultValue(items[1] || "nil"); + }); + wrapper = function() { var given, args; - var i, imax; given = slice.call(arguments); - args = new Array(argNames.length); + args = argVals.slice(); if (isDictionary(given[given.length - 1])) { setKeywordArguments(args, argNames, given.pop()); } - for (i = 0, imax = Math.min(argNames.length, given.length); i < imax; ++i) { - args[i] = given[i]; - } + copy(args, given, Math.min(argNames.length, given.length)); if (remain) { args.push($SC.Array(given.slice(argNames.length))); @@ -36,6 +85,9 @@ return func.apply(this, args); }; + wrapper._argNames = argNames; + wrapper._argVals = argVals; + return wrapper; }; @@ -43,18 +95,21 @@ return !!(obj && obj.constructor === Object); }; - var setKeywordArguments = function(args, argNames, dict) { - var keys, name, index; - var i, imax; + var copy = function(args, given, length) { + for (var i = 0; i < length; ++i) { + if (given[i]) { + args[i] = given[i]; + } + } + }; - keys = Object.keys(dict); - for (i = 0, imax = keys.length; i < imax; ++i) { - name = keys[i]; - index = argNames.indexOf(name); + var setKeywordArguments = function(args, argNames, dict) { + Object.keys(dict).forEach(function(key) { + var index = argNames.indexOf(key); if (index !== -1) { - args[index] = dict[name]; + args[index] = dict[key]; } - } + }); }; sc.lang.fn = fn; diff --git a/src/sc/lang/fn_test.js b/src/sc/lang/fn_test.js index d4671f0..0091daf 100644 --- a/src/sc/lang/fn_test.js +++ b/src/sc/lang/fn_test.js @@ -2,59 +2,103 @@ "use strict"; require("./fn"); + require("./klass-utils"); - var fn = sc.lang.fn; + var fn = sc.lang.fn; + var $SC = sc.lang.$SC; + var $nil = sc.lang.klass.utils.$nil; describe("sc.lang.fn", function() { - it("'a, b, c': call(1, 2) should pass [ 1, 2 ]", function() { + it("default arguments", function() { var instance, spy; spy = sinon.spy(); instance = { - func: fn(spy, "a, b, c") + func: fn(spy, "a; b=nil; c=true; d=false; e=0; f=0.0; g=inf; h=-inf; i=\\symbol; j=$j") }; - instance.func(1, 2); + instance.func(null, null, null, null); - expect(spy).to.be.calledWith(1, 2); + expect(spy.args[0][0]).to.be.a("SCNil"); + expect(spy.args[0][1]).to.be.a("SCNil"); + expect(spy.args[0][2]).to.be.a("SCBoolean").that.is.true; + expect(spy.args[0][3]).to.be.a("SCBoolean").that.is.false; + expect(spy.args[0][4]).to.be.a("SCInteger").that.equals(0); + expect(spy.args[0][5]).to.be.a("SCFloat").that.equals(0.0); + expect(spy.args[0][6]).to.be.a("SCFloat").that.equals(Infinity); + expect(spy.args[0][7]).to.be.a("SCFloat").that.equals(-Infinity); + expect(spy.args[0][8]).to.be.a("SCSymbol").that.equals("symbol"); + expect(spy.args[0][9]).to.be.a("SCChar").that.equals("j"); }); - it("'a, b, c': call(1, { c: 3 }) should pass [ 1, undef, 3 ]", function() { + it("default arguments (list)", function() { var instance, spy; spy = sinon.spy(); instance = { - func: fn(spy, "a, b, c") + func: fn(spy, "a=[ 0, 1, 2 ]") }; - instance.func(1, { c: 3 }); + instance.func(); - expect(spy).to.be.calledWith(1, undefined, 3); + expect(spy.args[0][0]).to.be.a("SCArray").that.eqls([ 0, 1, 2 ]); }); - it("'a, b, c': call(1, { x: 3 }) should pass [ 1, undef, undef ]", function() { + it("meta data", function() { + var func; + + func = fn(function() {}, "a=1; b=1.0"); + + expect(func._argNames).to.be.a("JSArray").that.eqls([ "a", "b" ]); + expect(func._argVals ).to.be.a("JSArray").that.eqls([ $SC.Integer(1), $SC.Float(1.0) ]); + }); + it("'a, b, c': call($arg1, { c: $argC }) should pass [ $arg1, $nil, $argC ]", function() { var instance, spy; + var $arg1, $argC, $argD; + + $arg1 = sc.test.object(); + $argC = sc.test.object(); + $argD = sc.test.object(); spy = sinon.spy(); instance = { - func: fn(spy, "a, b, c") + func: fn(spy, "a; b; c") }; - instance.func(1, { x: 3 }); + instance.func($arg1, { c: $argC, d: $argD }); - expect(spy).to.be.calledWith(1, undefined, undefined); + expect(spy).to.be.calledWith($arg1, $nil, $argC); + }); + it("'*a'", function() { + var instance, spy; + + spy = sinon.spy(); + instance = { + func: fn(spy, "*a") + }; + + instance.func(); + + expect(spy.args[0][0]).to.be.a("SCArray").that.eqls([ ]); }); it("'a, b, *c': call(1, 2, 3, 4, 5) should pass [ 1, 2, [ 3, 4, 5 ] ]", function() { var instance, spy; + var $arg1, $arg2, $arg3, $arg4, $arg5; + + $arg1 = sc.test.object(); + $arg2 = sc.test.object(); + $arg3 = sc.test.object(); + $arg4 = sc.test.object(); + $arg5 = sc.test.object(); spy = sinon.spy(); instance = { - func: fn(spy, "a, b, *c") + func: fn(spy, "a; b; *c") }; - instance.func(1, 2, 3, 4, 5); + instance.func($arg1, $arg2, $arg3, $arg4, $arg5); - expect(spy.args[0][0]).to.equal(1); - expect(spy.args[0][1]).to.equal(2); - expect(spy.args[0][2]).to.be.a("SCArray").that.eqls([ 3, 4, 5 ]); + expect(spy.args[0][0]).to.equal($arg1); + expect(spy.args[0][1]).to.equal($arg2); + expect(spy.args[0][2]).to.be.a("SCArray").that.eqls([ $arg3, $arg4, $arg5 ]); }); }); })(); diff --git a/src/sc/lang/iterator.js b/src/sc/lang/iterator.js index 57d0898..dfa4658 100644 --- a/src/sc/lang/iterator.js +++ b/src/sc/lang/iterator.js @@ -34,7 +34,6 @@ // TODO: async function iterator.execute = function(iter, $function) { var $item, ret, i = 0; - $function = utils.defaultValue$Nil($function); while (($item = iter.next()) !== null) { if (Array.isArray($item)) { @@ -125,7 +124,6 @@ iterator.number$for = function($start, $end) { var $step; - $end = utils.defaultValue$Nil($end); $step = ($start <= $end) ? $int_1 : $SC.Integer(-1); @@ -133,20 +131,15 @@ }; iterator.number$forBy = function($start, $end, $step) { - $end = utils.defaultValue$Nil($end); - $step = utils.defaultValue$Nil($step); - return sc_numeric_iter($start, $end, $step); }; iterator.number$forSeries = function($start, $second, $last) { - var $end, $step; + var $step; - $second = utils.defaultValue$Nil($second); - $end = utils.defaultValue$Nil($last); $step = $second ["-"] ($start); - return sc_numeric_iter($start, $end, $step); + return sc_numeric_iter($start, $last, $step); }; var js_incremental_iter = function(start, end, step, type) { @@ -200,9 +193,6 @@ }; var js_numeric_iter$for = function($startval, $endval, type) { - $startval = utils.defaultValue$Nil($startval); - $endval = utils.defaultValue$Nil($endval); - var start = type($startval.__num__()).valueOf(); var end = type($endval .__num__()).valueOf(); var step = (start <= end) ? +1 : -1; @@ -211,9 +201,6 @@ }; var js_numeric_iter$forBy = function($startval, $endval, $stepval, type) { - $endval = utils.defaultValue$Nil($endval); - $stepval = utils.defaultValue$Nil($stepval); - var start = type($startval.__num__()).valueOf(); var end = type($endval .__num__()).valueOf(); var step = type($stepval .__num__()).valueOf(); @@ -222,9 +209,6 @@ }; var js_numeric_iter$forSeries = function($startval, $second, $last, type) { - $second = utils.defaultValue$Nil($second); - $last = utils.defaultValue$Nil($last); - var start = type($startval.__num__()).valueOf(); var second = type($second .__num__()).valueOf(); var end = type($last .__num__()).valueOf(); diff --git a/src/sc/lang/klass-utils.js b/src/sc/lang/klass-utils.js index bbaa28e..98c69b2 100644 --- a/src/sc/lang/klass-utils.js +++ b/src/sc/lang/klass-utils.js @@ -30,21 +30,6 @@ alwaysReturn$int_1: function() { return utils.$int_1; }, - defaultValue$Nil: function($obj) { - return $obj || utils.$nil; - }, - defaultValue$Boolean: function($obj, value) { - return $obj || $SC.Boolean(value); - }, - defaultValue$Integer: function($obj, value) { - return $obj || $SC.Integer(value); - }, - defaultValue$Float: function($obj, value) { - return $obj || $SC.Float(value); - }, - defaultValue$Symbol: function($obj, value) { - return $obj || $SC.Symbol(value); - }, getMethod: function(className, methodName) { return klass.get(className)._Spec.prototype[methodName]; } diff --git a/src/sc/lang/klass-utils_test.js b/src/sc/lang/klass-utils_test.js index a1660a2..abe2e65 100644 --- a/src/sc/lang/klass-utils_test.js +++ b/src/sc/lang/klass-utils_test.js @@ -57,46 +57,6 @@ test = utils.alwaysReturn$int_1(); expect(test).to.be.a("SCInteger").that.equals(1); }); - it("defaultValue$Nil", function() { - var $obj = {}; - test = utils.defaultValue$Nil(undefined); - expect(test).to.be.a("SCNil"); - - test = utils.defaultValue$Nil($obj); - expect(test).to.equals($obj); - }); - it("defaultValue$Boolean", function() { - var $obj = {}; - test = utils.defaultValue$Boolean(undefined, true); - expect(test).to.be.a("SCBoolean").that.is.true; - - test = utils.defaultValue$Nil($obj); - expect(test).to.equals($obj); - }); - it("defaultValue$Integer", function() { - var $obj = {}; - test = utils.defaultValue$Integer(undefined, 1); - expect(test).to.be.a("SCInteger").that.equals(1); - - test = utils.defaultValue$Integer($obj, 1); - expect(test).to.equals($obj); - }); - it("defaultValue$Float", function() { - var $obj = {}; - test = utils.defaultValue$Float(undefined, 1.0); - expect(test).to.be.a("SCFloat").that.equals(1.0); - - test = utils.defaultValue$Float($obj, 1.0); - expect(test).to.equals($obj); - }); - it("defaultValue$Symbol", function() { - var $obj = {}; - test = utils.defaultValue$Symbol(undefined, "symbol"); - expect(test).to.be.a("SCSymbol").that.equals("symbol"); - - test = utils.defaultValue$Symbol($obj, "symbol"); - expect(test).to.equals($obj); - }); it("getMethod", function() { var test = utils.getMethod("Object", "class"); expect(test).to.be.a("JSFunction"); diff --git a/src/sc/lang/parser.js b/src/sc/lang/parser.js index ce7c613..b059b13 100644 --- a/src/sc/lang/parser.js +++ b/src/sc/lang/parser.js @@ -428,7 +428,7 @@ break; case "pi": type = Token.FloatLiteral; - value = "Math.PI"; + value = String(Math.PI); break; case "nil": type = Token.NilLiteral; @@ -478,10 +478,10 @@ if (ch1 + ch2 === "pi") { this.index += 3; - value = -Math.PI; + value = String(-Math.PI); } else if (ch1 + ch2 + ch3 === "inf") { this.index += 4; - value = -Infinity; + value = "-Infinity"; } if (value !== null) { @@ -533,7 +533,7 @@ if (pi) { type = Token.FloatLiteral; - value = value + " * Math.PI"; + value = value * Math.PI; } if (type === Token.FloatLiteral && value === (value|0)) { @@ -602,7 +602,7 @@ } if (pi) { - value = value + " * Math.PI"; + value = value * Math.PI; } if (type === Token.FloatLiteral && value === (value|0)) { @@ -1040,8 +1040,13 @@ }; SCParser.prototype.parseFunctionArgumentElement = function() { - // literal or immurable array of literals - return this._parseArgVarElement("arg", "parseUnaryExpression"); + var node = this._parseArgVarElement("arg", "parseArgumentableValue"); + + if (node.init && !isValidArgumentValue(node.init)) { + this.throwUnexpected(this.lookahead); + } + + return node; }; // 2.3 Function Body @@ -1836,8 +1841,39 @@ }; // 4.8 Primary Expressions + SCParser.prototype.parseArgumentableValue = function() { + var expr, stamp; + + this.skipComment(); + this.markStart(); + + stamp = this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type; + + switch (stamp) { + case "#": + expr = this.parsePrimaryHashedExpression(); + break; + case Token.CharLiteral: + case Token.FloatLiteral: + case Token.FalseLiteral: + case Token.IntegerLiteral: + case Token.NilLiteral: + case Token.SymbolLiteral: + case Token.TrueLiteral: + expr = this.createLiteral(this.lex()); + break; + } + + if (!expr) { + expr = {}; + this.throwUnexpected(this.lex()); + } + + return this.markEnd(expr); + }; + SCParser.prototype.parsePrimaryExpression = function(node) { - var expr; + var expr, stamp; if (node) { return node; @@ -1850,8 +1886,8 @@ this.lex(); expr = this.createGlobalExpression(this.parseIdentifier()); } else { - - switch (this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type) { + stamp = this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type; + switch (stamp) { case "(": expr = this.parseParentheses(); break; @@ -1861,35 +1897,29 @@ case "[": expr = this.parseListInitialiser(); break; - case "#": - expr = this.parsePrimaryHashedExpression(); - break; case Token.Keyword: expr = this.parsePrimaryKeywordExpression(); break; case Token.Identifier: expr = this.parsePrimaryIdentifier(); break; - case Token.CharLiteral: - case Token.FloatLiteral: - case Token.FalseLiteral: - case Token.IntegerLiteral: - case Token.NilLiteral: - case Token.SymbolLiteral: - case Token.TrueLiteral: - expr = this.createLiteral(this.lex()); - break; case Token.StringLiteral: expr = this.parsePrimaryStringExpression(); break; + default: + // case "#": + // case Token.CharLiteral: + // case Token.FloatLiteral: + // case Token.FalseLiteral: + // case Token.IntegerLiteral: + // case Token.NilLiteral: + // case Token.SymbolLiteral: + // case Token.TrueLiteral: + expr = this.parseArgumentableValue(stamp); + break; } } - if (!expr) { - expr = {}; - this.throwUnexpected(this.lex()); - } - return this.markEnd(expr); }; @@ -2514,6 +2544,19 @@ } }; + function isValidArgumentValue(node) { + if (node.type === Syntax.Literal) { + return true; + } + if (node.type === Syntax.ListExpression) { + return node.elements.every(function(node) { + return node.type === Syntax.Literal; + }); + } + + return false; + } + parser.parse = function(source, opts) { var instance, ast;