From 7bdb095ceeb87689860923eacdf6e8f0af396e9c Mon Sep 17 00:00:00 2001 From: Onoshko Dan Date: Sun, 20 Apr 2014 14:31:03 +0700 Subject: [PATCH] New features added. Operator `clone` and anonymous function definition `(){}`. --- README.md | 4 +++- demo.cola | 11 +++++++++++ lib/ast.js | 2 +- lib/index.html | 11 +++++++++++ lib/parse.js | 26 +++++++++++++++++++++++--- lib/std.js | 39 ++++++++++++++++++++++++++++++++++++++- lib/translate.js | 16 ++++++++++++++++ lib/utils.js | 3 +-- 8 files changed, 104 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 59a4f2d0..b2ba3045 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,14 @@ ColaScript is a language that compiles in JavaScript. This language is similar t bool exist = SOME??; bool exist2 = isset SOME; -- `clone` +- `clone`, status: done a = []; b = []; Array b = clone a; b[0] = 584; // a == [] + + if object have method `__clone__`, object will be copied with it. ### Binary diff --git a/demo.cola b/demo.cola index a45d9099..80d530c4 100644 --- a/demo.cola +++ b/demo.cola @@ -20,6 +20,17 @@ main(){ console.log(a = c ? b); b = undefined; + + Array x, y; + x = [123]; + y = clone x; + y.push(321); + console.log('original:',x,'cloned:',y); + + y.forEach((val){ + console.log(val); + }); + console.log("a is {{isset a ? 'set' : 'undefiend'}}, b is {{b?? ? 'set' : 'undefined'}}"); console.log(`is:`, location.href is String, `; isnt:`, 123 isnt Number, ";"); diff --git a/lib/ast.js b/lib/ast.js index 443785e5..f71dd52c 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -383,7 +383,7 @@ Cola.AST_Accessor = Cola.DEFNODE("Accessor", null, { $documentation: "A setter/getter function. The `name` property is always null." }, Cola.AST_Lambda); -Cola.AST_Function = Cola.DEFNODE("Function", null, { +Cola.AST_Function = Cola.DEFNODE("Function", "type", { $documentation: "A function expression" }, Cola.AST_Lambda); diff --git a/lib/index.html b/lib/index.html index 8ec43e9b..1c860aca 100644 --- a/lib/index.html +++ b/lib/index.html @@ -66,6 +66,17 @@ console.log(a = c ? b); b = undefined; + + Array x, y; + x = [123]; + y = clone x; + y.push(321); + console.log('original:',x,'cloned:',y); + + y.forEach((val){ + console.log(val); + }); + console.log("a is {{isset a ? 'set' : 'undefiend'}}, b is {{b?? ? 'set' : 'undefined'}}"); console.log(`is:`, location.href is String, `; isnt:`, 123 isnt Number, ";"); diff --git a/lib/parse.js b/lib/parse.js index 0eb9e9a4..c83720e6 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -49,7 +49,7 @@ !window.Cola && (window.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', '') + ' isset is isnt class singleton injector'; +Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' clone isset is isnt class singleton injector'; Cola.KEYWORDS_ATOM = 'false null true'; Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no'; @@ -123,6 +123,7 @@ Cola.OPERATORS = [ "&&", "||", // ColaScript + "clone", "isset", "is", "isnt", @@ -134,7 +135,7 @@ Cola.OPERATORS = [ ]; Cola.cOPERATORS = Cola.makePredicate(Cola.OPERATORS); -Cola.OPERATORS = Cola.OPERATORS.slice(0, Cola.OPERATORS.length - 7); +Cola.OPERATORS = Cola.OPERATORS.slice(0, Cola.OPERATORS.length - 8); Cola.OPERATORS.push('void'); Cola.OPERATORS = Cola.makePredicate(Cola.OPERATORS); @@ -730,6 +731,7 @@ Cola.UNARY_PREFIX = Cola.makePredicate([ "+" ]); Cola.cUNARY_PREFIX = Cola.makePredicate([ + "clone", "isset", "typeof", "delete", @@ -1214,7 +1216,7 @@ Cola.Parser.prototype.for_in = function (init) { Cola.Parser.prototype.function_ = function(ctor, type) { !type && (type = "dynamic"); - + var in_statement = ctor === Cola.AST_Defun, _this = this; var name = this.is("name") ? this.as_symbol(in_statement ? Cola.AST_SymbolDefun : Cola.AST_SymbolLambda) : null; if (in_statement && !name) @@ -1491,6 +1493,24 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) { if (this.is("punc")) { switch (start.value) { case "(": + if(!this.is_js){ + var _this = this, balance = 1, isfun = false; + this.dumpS(); + + this.next(); + this.next_until(function(){ + if(_this.is('punc', '(')) balance++; + else if(_this.is('punc', ')')) balance--; + + return balance == 0 || _this.is('eof'); + }); + isfun = (this.next(), this.is('punc','{')); + + this.restoreS(); + + if(isfun) return this.function_(Cola.AST_Function); + } + this.next(); var ex = this.expression(true); ex.start = start; diff --git a/lib/std.js b/lib/std.js index dbbc53af..0ddecf0e 100644 --- a/lib/std.js +++ b/lib/std.js @@ -59,4 +59,41 @@ function $_cola_isntset(_object){ } $_cola_isntset.i = 4; -$_cola = $_cola_is + $_cola_isnt + $_cola_modulo + $_cola_isset + $_cola_isntset; +function $_cola_clone(_item) { + if (_item === undefined || _item === null) return _item; + if (_item.__clone__ instanceof Function) return _item.__clone__(); + + var result, types = [ Number, String, Boolean ]; + for (var i in types) + if(types.hasOwnProperty(i) && _item instanceof types[i]) + return type( _item ); + + if (_item.__proto__ === Array.prototype) { + result = []; + _item.forEach(function(child, index, array) { + result[index] = $_cola_clone( child ); + }); + + return result; + } + + if (!(_item instanceof Object)) return _item; + + if (_item.nodeType && _item.cloneNode instanceof Function) return _item.cloneNode( true ); + + if (!_item.prototype) { + if (_item instanceof Date) return new Date(_item); + if (_item instanceof Function) return _item; + + result = {}; + for (var i in _item) result[i] = $_cola_clone( _item[i] ); + result.__proto__ = _item.__proto__; + + return result; + } + + return _item; +} +$_cola_clone.i = 5; + +$_cola = $_cola_is + $_cola_isnt + $_cola_modulo + $_cola_isset + $_cola_isntset + $_cola_clone; diff --git a/lib/translate.js b/lib/translate.js index 1275ceed..043bddf8 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -191,6 +191,22 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(){ node = new Cola.AST_Call(props); } else + if(node instanceof Cola.AST_UnaryPrefix && node.operator == 'clone'){ + $_cola_hash[$_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 : ')' }) + }; + props.expression = new Cola.AST_SymbolRef({ + name : '$_cola_clone', + start : props.start, + end : props.start + }); + + node = new Cola.AST_Call(props); + } else + if(node instanceof Cola.AST_StringTemplate){ newNode = new Cola.AST_Binary({ operator : '+', diff --git a/lib/utils.js b/lib/utils.js index 21b5b465..2354014e 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -304,9 +304,9 @@ Cola.Dictionary.prototype = { Cola.clone = function (item) { if (item === undefined || item === null) return item; + if (item.__clone__ instanceof Function) return item.__clone__(); var result, types = [ Number, String, Boolean ]; - for (var i in types) if(types.hasOwnProperty(i) && item instanceof types[i]) return type( item ); @@ -327,7 +327,6 @@ Cola.clone = function (item) { if (!item.prototype) { if (item instanceof Date) return new Date(item); if (item instanceof Function) return item; - if (item.clone instanceof Function) return item.clone(); result = {}; for (var i in item) result[i] = Cola.clone( item[i] );