From f88a7e12d95e34bf39a5866191e3f407d2d9ee52 Mon Sep 17 00:00:00 2001 From: Onoshko Dan Date: Tue, 22 Apr 2014 20:33:43 +0700 Subject: [PATCH] Array sugar added. --- README.md | 15 ++- lib/ast.js | 16 ++- lib/compress.js | 58 +++++++++- lib/index.html | 17 ++- lib/output.js | 12 +-- lib/parse.js | 42 +++++++- lib/scope.js | 10 +- lib/sourcemap.js | 2 +- lib/std.js | 56 +++++++--- lib/transform.js | 3 +- lib/translate.js | 274 ++++++++++++++++++++++++++++++++--------------- lib/utils.js | 6 +- 12 files changed, 378 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index ac58f894..7d8b5643 100644 --- a/README.md +++ b/README.md @@ -190,12 +190,17 @@ ColaScript is a language that compiles in JavaScript. This language is similar t arr[] = 4; // [3, 5, 6, 7, 4] console.log(arr[]); // 4 -- part assigment +- part assigment, status: done arr[0..2] = [0,1]; // [0, 1, 7, 4] - arr[0..2] = []; // [7, 4] + arr[0..2] = []; // [7, 4] + +- slice, status: done + + arr = arr[0..2]; + -- inline array ranging +- inline array ranging, status: done arr = [10..1]; // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] arr = [1..10]; // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] @@ -320,5 +325,5 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ### Statistic -- 30 feature ( without classes ) -- 18 done +- 34 feature ( without classes ) +- 22 done diff --git a/lib/ast.js b/lib/ast.js index f71dd52c..b7366fbc 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -45,7 +45,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.DEFNODE = function (type, props, methods, base) { if (arguments.length < 4) base = Cola.AST_Node; @@ -742,6 +742,20 @@ Cola.AST_Array = Cola.DEFNODE("Array", "elements", { } }); +Cola.AST_ArrayRange = Cola.DEFNODE("ArrayRange", "from to", { + $documentation: "An array range.", + $propdoc: { + from: "[AST_Node] range from", + to: "[AST_Node] range to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.from._walk(visitor); + this.to._walk(visitor); + }); + } +}); + Cola.AST_Object = Cola.DEFNODE("Object", "properties", { $documentation: "An object literal", $propdoc: { diff --git a/lib/compress.js b/lib/compress.js index 479b0f8e..3efe7ae5 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.Compressor = function (options, false_by_default) { if (!(this instanceof Cola.Compressor)) @@ -76,9 +76,9 @@ Cola.Compressor = function (options, false_by_default) { angular : false, warnings : true, - global_defs : {}, + global_defs : {} - is_js : false + ,is_js : false }, true); }; @@ -107,6 +107,27 @@ Cola.merge(Cola.Compressor.prototype, { } }); +Cola.Compressor.MathFuncs = { + abs: true, + acos: true, + asin: true, + atan: true, + atan2: true, + ceil: true, + cos: true, + exp: true, + floor: true, + imul: true, + log: true, + max: true, + min: true, + pow: true, + round: true, + sin: true, + sqrt: true, + tan: true +}; + (function(){ function OPT(node, optimizer) { @@ -1668,6 +1689,33 @@ Cola.merge(Cola.Compressor.prototype, { }); OPT(Cola.AST_Call, function(self, compressor){ + if (compressor.option("evaluate")) { + if (self.expression instanceof Cola.AST_Dot && Cola.Compressor.MathFuncs[self.expression.property] && + self.expression.expression instanceof Cola.AST_SymbolRef && self.expression.expression.name == "Math") { + var args = [], allstatic = true, val; + self.args.some(function(arg){ + if(arg instanceof Cola.AST_Constant) args.push(arg.value); + else return !(allstatic = false); + }); + if (allstatic) { + val = Math[self.expression.property].apply({}, args); + if((""+val).length <= 15) return make_node(Cola.AST_Number, self, { value : val }).transform(compressor); + } + } else + + if (!compressor.option("is_js") && self.expression instanceof Cola.AST_SymbolRef && Cola.Compressor.StdFuncs[self.expression.name] && self.args[0] instanceof Cola.AST_Constant) { + if (self.expression.name == "$_cola_isset" || self.expression.name == "$_cola_isntset") + return make_node(Cola.AST_Boolean, self, { value : Cola[self.expression.name](self.args[0].value) }).transform(compressor); + + if ((self.expression.name == "$_cola_is" || self.expression.name == "$_cola_isnt") && + self.args[1] instanceof Cola.AST_SymbolRef && + (self.args[1].value == "Number" || self.args[1].value == "Boolean" || self.args[1].value == "String")) + return make_node(Cola.AST_Boolean, self, { value : Cola[self.expression.name](self.args[0].value, eval(self.args[1].value)) }).transform(compressor); + + if (self.expression.name == "$_cola_modulo" && self.args[1] instanceof Cola.AST_Constant) + return make_node(Cola.AST_Number, self, { value : Cola.$_cola_modulo(self.args[0].value, self.args[1].value) }).transform(compressor); + } + } if (compressor.option("unsafe")) { var exp = self.expression; if (exp instanceof Cola.AST_SymbolRef && exp.undeclared()) { @@ -1999,7 +2047,7 @@ Cola.merge(Cola.Compressor.prototype, { // result. hence, force switch. if (!(self.left instanceof Cola.AST_Binary - && (compressor.option("is_js") ? Cola.PRECEDENCE : Cola.cPRECEDENCE)[self.left.operator] >= (compressor.option("is_js") ? Cola.PRECEDENCE : Cola.cPRECEDENCE)[self.operator])) { + && Cola.PRECEDENCE[self.left.operator] >= Cola.PRECEDENCE[self.operator])) { reverse(null, true); } } @@ -2348,7 +2396,7 @@ Cola.merge(Cola.Compressor.prototype, { var prop = self.property; if (prop instanceof Cola.AST_String && compressor.option("properties")) { prop = prop.getValue(); - if ((compressor.option("is_js") ? Cola.RESERVED_WORDS : Cola.cRESERVED_WORDS)(prop) ? compressor.option("screw_ie8") : Cola.is_identifier_string(prop)) { + if (Cola.RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : Cola.is_identifier_string(prop)) { return make_node(Cola.AST_Dot, self, { expression : self.expression, property : prop diff --git a/lib/index.html b/lib/index.html index 46577da0..08ae9c27 100644 --- a/lib/index.html +++ b/lib/index.html @@ -118,6 +118,7 @@ main();
 
+ @@ -139,7 +140,7 @@ main(); localStorage.source = source; localStorage.isjs = isjs.checked ? "t" : "f"; - stream = new Cola.OutputStream({ beautify : true, is_js : isjs.checked }); + stream = new Cola.OutputStream({ beautify : true }); compressor = new Cola.Compressor({ is_js : isjs.checked }); try { @@ -156,9 +157,9 @@ main(); // 3. mangle ast.figure_out_scope(); ast.compute_char_frequency(); - ast.mangle_names({ is_js : isjs.checked, sort : true, toplevel : true }); + ast.mangle_names({ sort : true, toplevel : true }); - stream = new Cola.OutputStream({ is_js : isjs.checked }); + stream = new Cola.OutputStream(); ast.print(stream); resultArea.value = stream.toString(); } catch(e){ @@ -171,6 +172,16 @@ main(); document.querySelector('#lenstat').innerHTML = sourceArea.value.length+" : "+translationArea.value.length+" : "+resultArea.value.length; } + function benchmark(){ + console.time("Uncompressed"); + eval(translationArea.result); + console.timeEnd("Uncompressed"); + + console.time("Compressed"); + eval(resultArea.result); + console.timeEnd("Compressed"); + } + function exec(){ eval(resultArea.value) } diff --git a/lib/output.js b/lib/output.js index 55b20d19..b1f88c47 100644 --- a/lib/output.js +++ b/lib/output.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.OutputStream = function (options) { @@ -63,8 +63,8 @@ Cola.OutputStream = function (options) { comments : false, preserve_line : false, screw_ie8 : false, - preamble : null, - is_js : false + preamble : null + //,is_js : false }, true); this.indentation = 0; @@ -463,8 +463,8 @@ Cola.OutputStream.prototype.parent = function(n) { return true; // this deals with precedence: 3 * (2 + 1) if (p instanceof Cola.AST_Binary) { - var po = p.operator, pp = (output.option("is_js") ? Cola.PRECEDENCE : Cola.cPRECEDENCE)[po]; - var so = this.operator, sp = (output.option("is_js") ? Cola.PRECEDENCE : Cola.cPRECEDENCE)[so]; + var po = p.operator, pp = Cola.PRECEDENCE[po]; + var so = this.operator, sp = Cola.PRECEDENCE[so]; if (pp > sp || (pp == sp && this === p.right)) { @@ -1051,7 +1051,7 @@ Cola.OutputStream.prototype.parent = function(n) { && +key + "" == key) && parseFloat(key) >= 0) { output.print(make_num(key)); - } else if ((output.option("is_js") ? Cola.RESERVED_WORDS : Cola.cRESERVED_WORDS)(key) ? output.option("screw_ie8") : Cola.is_identifier_string(key)) { + } else if (Cola.RESERVED_WORDS(key) ? output.option("screw_ie8") : Cola.is_identifier_string(key)) { output.print_name(key); } else { output.print_string(key); diff --git a/lib/parse.js b/lib/parse.js index f9d0e879..f7803ccf 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -46,7 +46,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' clone isset is isnt class singleton injector'; @@ -388,7 +388,7 @@ Cola.Tokenizer.prototype.parse_error = function (err) { }; Cola.Tokenizer.prototype.read_num = function (prefix) { - var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".", _this = this; var num = this.read_while(function(ch, i){ var code = ch.charCodeAt(0); switch (code) { @@ -401,6 +401,7 @@ Cola.Tokenizer.prototype.read_num = function (prefix) { case 43: // + return after_e; case (after_e = false, 46): // . + if(!_this.is_js && _this.peek(1) == '.') return false; return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; } return Cola.is_alphanumeric_char(code); @@ -642,6 +643,7 @@ Cola.Tokenizer.prototype.handle_slash = function () { Cola.Tokenizer.prototype.handle_dot = function () { this.next(); + if (!this.is_js && this.peek() == '.') return this.next(), this.token("punc", ".."); return Cola.is_digit(this.peek().charCodeAt(0)) ? this.read_num(".") : this.token("punc", "."); @@ -709,7 +711,6 @@ Cola.Tokenizer.prototype.next_token = function (force_regexp) { if (!this.is_js) { if (ch == 'r' && (this.peek(1) == '"' || this.peek(1) == "'" || this.peek(1) == '`')) return this.next(), this.read_string(true); if (ch + this.peek(1) == '=>') return this.next(), this.next(), this.token("punc", "=>"); - if (ch + this.peek(1) == '..') return this.next(), this.next(), this.token("punc", ".."); if (ch == '@') return this.read_at(); } @@ -1575,6 +1576,22 @@ Cola.Parser.prototype.expr_list = function (closing, allow_trailing_comma, allow Cola.Parser.prototype.array_ = Cola.Parser.embed_tokens(function() { this.expect("["); + + if(!this.is_js && !this.is("punc","]")){ + this.dumpS(); + var tmp, from = this.expression(true); + if(this.is("punc","..")){ + this.next(); + return new Cola.AST_ArrayRange({ + from : from, + to : (tmp = this.expression(true), this.expect("]"), tmp), + start : from.start, + end : this.prev() + }); + } + this.restoreS(); + } + return new Cola.AST_Array({ elements: this.expr_list("]", !this.options.strict, true) }); @@ -1685,7 +1702,24 @@ Cola.Parser.prototype.subscripts = function(expr, allow_calls) { } if (this.is("punc", "[")) { this.next(); - var prop = !this.is_js && this.is("punc", "]") ? new Cola.AST_Noop() : this.expression(true); + + var prop; + if(this.is_js) prop = this.expression(true); + else if(this.is("punc","]")) prop = new Cola.AST_Noop(); + else { + prop = this.expression(true); + this.dumpS(); + if(this.is("punc","..")){ + this.next(); + prop = new Cola.AST_ArrayRange({ + from : prop, + to : this.expression(true), + start : prop.start, + end : this.prev() + }); + } else this.restoreS(); + } + this.expect("]"); return this.subscripts(new Cola.AST_Sub({ start : start, diff --git a/lib/scope.js b/lib/scope.js index d2fd1b2e..4d9f13c1 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.SymbolDef = function (scope, index, orig) { this.name = orig.name; @@ -246,7 +246,7 @@ Cola.AST_Scope.DEFMETHOD("next_mangled", function(options){ var ext = this.enclosed; out: while (true) { var m = Cola.base54(++this.cname); - if (!Cola.is_identifier(m, options.is_js)) continue; // skip over "do" + if (!Cola.is_identifier(m, true)) continue; // skip over "do" // https://github.com/mishoo/UglifyJS2/issues/242 -- do not // shadow a name excepted from mangling. @@ -327,8 +327,8 @@ Cola.AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ eval : false, sort : false, toplevel : false, - screw_ie8 : false, - is_js : false + screw_ie8 : false + //,is_js : false }); }); @@ -363,7 +363,7 @@ Cola.AST_Toplevel.DEFMETHOD("mangle_names", function(options){ } if (node instanceof Cola.AST_Label) { var name; - do name = Cola.base54(++lname); while (!Cola.is_identifier(name, options.is_js)); + do name = Cola.base54(++lname); while (!Cola.is_identifier(name, true)); node.mangled_name = name; return true; } diff --git a/lib/sourcemap.js b/lib/sourcemap.js index 4a83bc6e..24b1487e 100644 --- a/lib/sourcemap.js +++ b/lib/sourcemap.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); // a small wrapper around fitzgen's source-map library Cola.SourceMap = function (options) { diff --git a/lib/std.js b/lib/std.js index c06336ae..0071873d 100644 --- a/lib/std.js +++ b/lib/std.js @@ -34,32 +34,32 @@ ***********************************************************************/ -function $_cola_is(_object, _type){ - return _object instanceof _type || _object.__proto__ === _type.prototype; +Cola.$_cola_is = function $_cola_is(_object, _type){ + return _object === _type || _type.prototype && (_object instanceof _type || _object.__proto__ === _type.prototype) || isNaN(_object) && isNaN(_type); } -$_cola_is.i = 0; +Cola.$_cola_is.i = 0; -function $_cola_isnt(_object, _type){ - return !(_object instanceof _type || _object.__proto__ === _type.prototype); +Cola.$_cola_isnt = function $_cola_isnt(_object, _type){ + return !(_object === _type || _type.prototype && (_object instanceof _type || _object.__proto__ === _type.prototype) || isNaN(_object) && isNaN(_type)); } -$_cola_isnt.i = 1; +Cola.$_cola_isnt.i = 1; -function $_cola_modulo(_a, _b){ +Cola.$_cola_modulo = function $_cola_modulo(_a, _b){ return (_a % _b + +_b) % _b; } -$_cola_modulo.i = 2; +Cola.$_cola_modulo.i = 2; -function $_cola_isset(_object){ +Cola.$_cola_isset = function $_cola_isset(_object){ return !(typeof _object === "undefined" || _object === null); } -$_cola_isset.i = 3; +Cola.$_cola_isset.i = 3; -function $_cola_isntset(_object){ +Cola.$_cola_isntset = function $_cola_isntset(_object){ return (typeof _object === "undefined" || _object === null); } -$_cola_isntset.i = 4; +Cola.$_cola_isntset.i = 4; -function $_cola_clone(_item){ +Cola.$_cola_clone = function $_cola_clone(_item){ if (_item === undefined || _item === null) return _item; if (_item.__clone__ instanceof Function) return _item.__clone__(); @@ -94,11 +94,33 @@ function $_cola_clone(_item){ return _item; } -$_cola_clone.i = 5; +Cola.$_cola_clone.i = 5; -function $_cola_array_last(_array){ +Cola.$_cola_array_last = function $_cola_array_last(_array){ return _array[_array.length - 1]; } -$_cola_array_last.i = 6; +Cola.$_cola_array_last.i = 6; -$_cola = $_cola_is + $_cola_isnt + $_cola_modulo + $_cola_isset + $_cola_isntset + $_cola_clone + $_cola_array_last; +Cola.$_cola_array_range = function $_cola_array_range(_from, _to){ + var range = []; + if(_from <= _to) for(var i = _from; i <= _to; i++) range.push(i); + else for(var i = _from; i >= _to; i--) range.push(i); + return range; +} +Cola.$_cola_array_range.i = 7; + +Cola.$_cola_array_asplice = function $_cola_array_asplice(_array, _from, _to, _a){ + _to = _to - _from + 1; + return [].splice.apply(_array, [_from, _to + 1].concat(_a)), _a; +} +Cola.$_cola_array_asplice.i = 8; + +Cola.$_cola = Cola.$_cola_is + Cola.$_cola_isnt + Cola.$_cola_modulo + Cola.$_cola_isset + Cola.$_cola_isntset + Cola.$_cola_clone + Cola.$_cola_array_last + Cola.$_cola_array_range + Cola.$_cola_array_asplice; + +Cola.Compressor.StdFuncs = { + $_cola_is : true, + $_cola_isnt : true, + $_cola_modulo : true, + $_cola_isset : true, + $_cola_isntset : true +}; diff --git a/lib/transform.js b/lib/transform.js index 1d7000d4..09d27e89 100644 --- a/lib/transform.js +++ b/lib/transform.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); // Tree transformer helpers. @@ -56,6 +56,7 @@ Cola.TreeTransformer.prototype = new Cola.TreeWalker; (function(undefined){ function _(node, descend) { + node.DEFMETHOD("_descend", descend); node.DEFMETHOD("transform", function(tw, in_list){ var x, y; tw.push(this); diff --git a/lib/translate.js b/lib/translate.js index 32659923..4948b657 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -35,89 +35,124 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.AST_Toplevel.prototype.toJavaScript = function(){ if(this.language == 'js') return this; this.language = 'js'; - var $_cola_ast = Cola.parse($_cola, { is_js : true}), $_cola_hash = {}, _this, - tt = new Cola.TreeTransformer(null, function(node){ - var newNode, props, parent = this.parent(); + var $_cola_ast = Cola.parse(Cola.$_cola, { is_js : true}), $_cola_hash = {}, _this, + tt = new Cola.TreeTransformer(function(node, descend){ + var newNode, props = {}, parent = this.parent(); + node = node.clone(); if(node instanceof Cola.AST_Binary && node.operator == '**'){ props = { args : [node.left, node.right], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : 'Math' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : 'Math' }), + end : node.left //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_Dot({ property : 'pow', - start : props.start, - end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }), + //start : props.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }), expression : new Cola.AST_SymbolRef({ name : 'Math', start : props.start, end : props.start }) }); node = new Cola.AST_Call(props); + } else if(node instanceof Cola.AST_Binary && node.operator == '%%'){ - $_cola_hash[$_cola_modulo.i] = true; + $_cola_hash[Cola.$_cola_modulo.i] = true; props = { args : [node.left, node.right], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_modulo', - start : props.start, - end : props.start + name : '$_cola_modulo' + //start : props.start, + //end : props.start }); - + node = new Cola.AST_Call(props); + } else if(node instanceof Cola.AST_SimpleStatement && node.body instanceof Cola.AST_Assign && node.body.operator == '?='){ - $_cola_hash[$_cola_isntset.i] = true; + if(node.body.left instanceof Cola.AST_Sub && node.body.left.property instanceof Cola.AST_Noop){ + props = { + property : "length", + //start : node.left.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), + expression : node.body.left.expression + }; + props = { + operator : "-", + left : new Cola.AST_Dot(props), + right : new Cola.AST_Number({ value : 1}) + }; + + node.body.left.property = new Cola.AST_Binary(props); + } + + $_cola_hash[Cola.$_cola_isntset.i] = true; node.body.operator = '='; props = { - args : [node.body.left], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + args : [node.body.left] + //start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), + //end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_isntset', - start : props.start, - end : props.start + name : '$_cola_isntset' + //start : props.start, + //end : props.start }); node = new Cola.AST_If({ body : node.clone(), - start : new Cola.AST_Token({ nlb : false, type : 'keyword', value : 'if' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ';' }), + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'keyword', value : 'if' }), + end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ';' }), condition : new Cola.AST_Call(props) }); } else - if(node instanceof Cola.AST_Assign && node.operator == '?='){ - $_cola_hash[$_cola_isntset.i] = true; + if(node instanceof Cola.AST_Assign && node.operator == '?='/* && !(parent instanceof Cola.AST_SimpleStatement)*/){ + if(node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){ + props = { + property : "length", + //start : node.left.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), + expression : node.left.expression + }; + props = { + operator : "-", + left : new Cola.AST_Dot(props), + right : new Cola.AST_Number({ value : 1}) + }; + + node.left.property = new Cola.AST_Binary(props); + } + + $_cola_hash[Cola.$_cola_isntset.i] = true; node.operator = '='; props = { - args : [node.left], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + args : [node.left] + //start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }), + //end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_isntset', - start : props.start, - end : props.start + name : '$_cola_isntset' + //start : props.start, + //end : props.start }); node = new Cola.AST_Conditional({ - start : new Cola.AST_Token({ nlb : false, type : 'punc', value : '(' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'punc', value : '(' }), + end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), condition : new Cola.AST_Call(props), consequent : node.clone(), alternative : node.left @@ -125,17 +160,17 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ } else if(node instanceof Cola.AST_Conditional && node.alternative instanceof Cola.AST_Noop){ - $_cola_hash[$_cola_isset.i] = true; + $_cola_hash[Cola.$_cola_isset.i] = true; props = { args : [node.condition], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_isset', - start : props.start, - end : props.start + name : '$_cola_isset' + //start : props.start, + //end : props.start }); node.alternative = node.consequent; @@ -144,99 +179,166 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ } else if(node instanceof Cola.AST_Binary && node.operator == 'is'){ - $_cola_hash[$_cola_is.i] = true; + $_cola_hash[Cola.$_cola_is.i] = true; props = { args : [node.left, node.right], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_is', - start : props.start, - end : props.start + name : '$_cola_is' + //start : props.start, + //end : props.start }); node = new Cola.AST_Call(props); } else if(node instanceof Cola.AST_Binary && node.operator == 'isnt'){ - $_cola_hash[$_cola_isnt.i] = true; + $_cola_hash[Cola.$_cola_isnt.i] = true; props = { args : [node.left, node.right], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_isnt', - start : props.start, - end : props.start + name : '$_cola_isnt' + //start : props.start, + //end : props.start }); node = new Cola.AST_Call(props); } else if(node instanceof Cola.AST_UnaryPostfix && node.operator == '??' || node instanceof Cola.AST_UnaryPrefix && node.operator == 'isset'){ - $_cola_hash[$_cola_isset.i] = true; + $_cola_hash[Cola.$_cola_isset.i] = true; props = { args : [node.expression], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_isset', - start : props.start, - end : props.start + name : '$_cola_isset' + //start : props.start, + //end : props.start }); node = new Cola.AST_Call(props); } else if(node instanceof Cola.AST_UnaryPrefix && node.operator == 'clone'){ - $_cola_hash[$_cola_clone.i] = true; + $_cola_hash[Cola.$_cola_clone.i] = true; props = { args : [node.expression], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_clone', - start : props.start, - end : props.start + name : '$_cola_clone' + //start : props.start, + //end : props.start }); node = new Cola.AST_Call(props); } else - if(node instanceof Cola.AST_Assign && node.operator == "=" && - node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){ - + if(node instanceof Cola.AST_Assign && node.operator == "=" && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){ props = { property : "push", - start : node.left.start, - end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), + //start : node.left.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), expression : node.left.expression }; props = { args : [node.right], - start : props.start, - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), + start : node.start, //props.start, + end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), expression : new Cola.AST_Dot(props) }; node = new Cola.AST_Call(props); } else - if(node instanceof Cola.AST_Sub && node.property instanceof Cola.AST_Noop && !(parent instanceof Cola.AST_Assign) && parent.operator != "=" && node != parent.left){ - $_cola_hash[$_cola_array_last.i] = true; + if(node instanceof Cola.AST_Assign && node.operator != "=" && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){ + props = { + property : "length", + //start : node.left.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), + expression : node.left.expression + }; + props = { + operator : "-", + left : new Cola.AST_Dot(props), + right : new Cola.AST_Number({ value : 1}) + }; + + node.left.property = new Cola.AST_Binary(props); + } else + + if(node instanceof Cola.AST_Sub && node.property instanceof Cola.AST_Noop){ + $_cola_hash[Cola.$_cola_array_last.i] = true; props = { args : [node.expression], - start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_array_last' }), - end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_array_last' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) }; props.expression = new Cola.AST_SymbolRef({ - name : '$_cola_array_last', - start : props.start, - end : props.start + name : '$_cola_array_last' + //start : props.start, + //end : props.start + }); + + node = new Cola.AST_Call(props); + } else + + if(node instanceof Cola.AST_Assign && node.operator == '=' && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_ArrayRange){ + $_cola_hash[Cola.$_cola_array_asplice.i] = true; + props = { + args : [node.left.expression, node.left.property.from, node.left.property.to, node.right], + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_array_last' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + }; + props.expression = new Cola.AST_SymbolRef({ + name : '$_cola_array_asplice' + //start : props.start, + //end : props.start + }); + + node = new Cola.AST_Call(props); + } else + + if(node instanceof Cola.AST_Sub && node.property instanceof Cola.AST_ArrayRange){ + props = { + property : "slice", + //start : node.left.start, + //end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }), + expression : node.expression + }; + props = { + args : [node.property.from, new Cola.AST_Binary({ + operator : "+", + left : node.property.to, + right : new Cola.AST_Number({ value : 1}) + })], + start : node.start, //props.start, + end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }), + expression : new Cola.AST_Dot(props) + }; + + node = new Cola.AST_Call(props); + } else + + if(node instanceof Cola.AST_ArrayRange){ + $_cola_hash[Cola.$_cola_array_range.i] = true; + props = { + args : [node.from, node.to], + start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }), + end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }) + }; + props.expression = new Cola.AST_SymbolRef({ + name : '$_cola_array_range' + //start : props.start, + //end : props.start }); node = new Cola.AST_Call(props); @@ -246,19 +348,22 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ newNode = new Cola.AST_Binary({ operator : '+', left : node.body[0], - right : node.body[1], - start : node.body[0].start, - end : node.body[1].end + right : node.body[1] + //start : node.body[0].start, + //end : node.body[1].end }); for(var i = 2; i < node.body.length; i++) newNode = new Cola.AST_Binary({ operator : '+', left : newNode, - right : node.body[i], - start : newNode.start, - end : node.body[i].end + right : node.body[i] + //start : newNode.start, + //end : node.body[i].end }); + newNode.start = node.start; + newNode.end = node.end; + node = newNode; } else @@ -266,6 +371,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ node.value = node.value.replace(/[\r\n\s]/g,'').replace(/(\/[\w]*)x([\w]*$)/, '$1$2'); } + node._descend(node, this); return node; }); diff --git a/lib/utils.js b/lib/utils.js index 2354014e..5276ddbd 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -42,7 +42,7 @@ ***********************************************************************/ "use strict"; -!window.Cola && (window.Cola = {}); +!this.Cola && (this.Cola = {}); Cola.array_to_hash = function (a) { var ret = Object.create(null); @@ -336,4 +336,8 @@ Cola.clone = function (item) { } return item; +}; + +Cola.nodeCompare = function(_a, _b){ + return _a.__proto__ === _b.__proto__ && _a.start.pos === _b.start.pos && _a.end.pos === _b.end.pos; }; \ No newline at end of file