diff --git a/README.md b/README.md index c95cd583..25e2ddf7 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ### Multiple -- `..:` +- `..:`, status: done Object profile = { name : "dan", @@ -104,7 +104,7 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ## Expressions -- `switch` assigmention +- `switch` assignment String weather = switch(temperature){ case -10: 'cold'; @@ -133,7 +133,7 @@ ColaScript is a language that compiles in JavaScript. This language is similar t Object obj = {}; String str = ""; -- multiple assigment +- multiple assignment [a, b, c] = [b, c, a]; {poet: {String name, address: [street, city]}} = futurists; @@ -190,7 +190,7 @@ 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, status: done +- part assignment, status: done arr[0..2] = [0,1]; // [0, 1, 7, 4] arr[0..2] = []; // [7, 4] @@ -325,5 +325,5 @@ ColaScript is a language that compiles in JavaScript. This language is similar t ### Statistic -- 34 feature ( without classes ) -- 26 done +- 34 features ( without classes ) +- 27 done diff --git a/demo.cola b/demo.cola index d1ab38e6..5a6bbaa2 100644 --- a/demo.cola +++ b/demo.cola @@ -20,7 +20,7 @@ main(){ // `modulo` operator console.log("10 %% 4 = ", 10 %% 4); - // `isset` conditional assigment + // `isset` conditional assignment int a, b = 4; console.log("`a` is", a, ", now `a` is", a ?= b); console.log("`a` is", a, ", now `a` still", a ?= 584); @@ -65,25 +65,36 @@ main(){ console.log("@email {{ isEmail.test(email) ? "is" : "isnt" }} valid email adress"); // Arrays - // Empty getter and setter ( pushig ) + // Empty getter and setter ( pushing ) Array arr = [2, 4, 8, 16, 32]; console.log("Last element of `arr` is", arr[]), arr[] = 64; console.log("Now last element of `arr` is", arr[]); - // Splice assigment + // Splice assignment arr[2..4] = [3, 2, 1]; console.log("`arr` is", arr); // Range console.log("`[0..10]` is", [0..10]); - // Calling function - console.log(Profile( - "Dan", "Green", + // Calling function + Object pro; + console.log(pro = Profile( + "Dan", "Green", "Russia", "HTML5", "JavaScript", "Dart", "PHP", "CSS3", "LESS", "Qt", age : 19, petName : "Felix" )); + + // Cascade operator + pro + ..firstName += "iil" + ..secondName = "Onoshko" + ..skills: + ..[1] = "JS"; + ; + + console.log(pro); } // Functions @@ -100,3 +111,5 @@ Object Profile(String firstName, String secondName, String country = "Russia", A petName : petName }; } + +main(); \ No newline at end of file diff --git a/lib/ast.js b/lib/ast.js index fa35cef8..af5f0475 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -675,6 +675,22 @@ Cola.AST_Dot = Cola.DEFNODE("Dot", null, { } }, Cola.AST_PropAccess); +Cola.AST_Cascade = Cola.DEFNODE("Cascade", "expression subexpressions", { + $documentation: "Base class for properties access expressions, i.e. `a..foo..bar`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + subexpressions: "[AST_Node*] actions with properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.subexpressions.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + Cola.AST_Sub = Cola.DEFNODE("Sub", null, { $documentation: "Index-style property access, i.e. `a[\"foo\"]`", _walk: function(visitor) { diff --git a/lib/index.html b/lib/index.html index c3a3ebac..7d889dd7 100644 --- a/lib/index.html +++ b/lib/index.html @@ -31,10 +31,12 @@ box-sizing: border-box; width: 33.333%; height: 100%; - font-size: 12px; + font-size: 15px; float: left; font-family: "Andale Mono"; padding: 0 5px 26px 5px; + background-color: #272A32; + color: #D6D7D9; } #controls { @@ -51,6 +53,9 @@ left: 0; width: 100%; height: 100%; + -moz-box-sizing: border-box; + box-sizing: border-box; + margin: 2px 0 0 2px; } #controls .bg { @@ -60,12 +65,12 @@ width: 100%; height: 100%; background-color: white; - opacity: 0.5; + opacity: 0.8; } #lenstat { float: right; - margin: 5px 8px 0 0; + margin: 2px 10px; } @@ -93,7 +98,7 @@ main(){ // `modulo` operator console.log("10 %% 4 = ", 10 %% 4); - // `isset` conditional assigment + // `isset` conditional assignment int a, b = 4; console.log("`a` is", a, ", now `a` is", a ?= b); console.log("`a` is", a, ", now `a` still", a ?= 584); @@ -138,25 +143,36 @@ main(){ console.log("@email {{ isEmail.test(email) ? "is" : "isnt" }} valid email adress"); // Arrays - // Empty getter and setter ( pushig ) + // Empty getter and setter ( pushing ) Array arr = [2, 4, 8, 16, 32]; console.log("Last element of `arr` is", arr[]), arr[] = 64; console.log("Now last element of `arr` is", arr[]); - // Splice assigment + // Splice assignment arr[2..4] = [3, 2, 1]; console.log("`arr` is", arr); // Range console.log("`[0..10]` is", [0..10]); - // Calling function - console.log(Profile( - "Dan", "Green", + // Calling function + Object pro; + console.log(pro = Profile( + "Dan", "Green", "Russia", "HTML5", "JavaScript", "Dart", "PHP", "CSS3", "LESS", "Qt", age : 19, petName : "Felix" )); + + // Cascade operator + pro + ..firstName += "iil" + ..secondName = "Onoshko" + ..skills: + ..[1] = "JS"; + ; + + console.log(pro); } // Functions @@ -173,14 +189,16 @@ Object Profile(String firstName, String secondName, String country = "Russia", A petName : petName }; } - + +main();
 
- + + @@ -239,10 +257,16 @@ Object Profile(String firstName, String secondName, String country = "Russia", A document.querySelector('#lenstat').innerHTML = sourceArea.value.length+" : "+translationArea.value.length+" : "+resultArea.value.length; } - function benchmark(){ - console.time("ColaScript"); - eval(resultArea.result); - console.timeEnd("ColaScript"); + function benchmarkResult(){ + console.time("Result"); + eval(resultArea.value); + console.timeEnd("Result"); + } + + function benchmarkTranslate(){ + console.time("Translation"); + eval(translationArea.value); + console.timeEnd("Translation"); } function exec(){ diff --git a/lib/parse.js b/lib/parse.js index 546abbb5..3b2d370c 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1648,12 +1648,12 @@ Cola.Parser.prototype.array_ = Cola.Parser.embed_tokens(function() { if(!this.is_js && !this.is("punc","]")){ this.dumpS(); - var tmp, from = this.expression(true); + var tmp, from = this.expression(true, false, true); if(this.is("punc","..")){ this.next(); return new Cola.AST_ArrayRange({ from : from, - to : (tmp = this.expression(true), this.expect("]"), tmp), + to : (tmp = this.expression(true, false, true), this.expect("]"), tmp), start : from.start, end : this.prev() }); @@ -1776,13 +1776,13 @@ Cola.Parser.prototype.subscripts = function(expr, allow_calls) { if(this.is_js) prop = this.expression(true); else if(this.is("punc","]")) prop = new Cola.AST_Noop(); else { - prop = this.expression(true); + prop = this.expression(true, false, true); this.dumpS(); if(this.is("punc","..")){ this.next(); prop = new Cola.AST_ArrayRange({ from : prop, - to : this.expression(true), + to : this.expression(true, false, true), start : prop.start, end : this.prev() }); @@ -1900,9 +1900,39 @@ Cola.Parser.prototype.maybe_assign = function(no_in) { return left; }; -Cola.Parser.prototype.expression = function(commas, no_in) { +Cola.Parser.prototype.cascade = function(expr, start) { + var last, props = { + start : start, + expression : expr, + subexpressions : [] + }; + while (this.next()) { + if (this.is("name") || this.is("punc","[")) { + last = this.expression(false, false, true); + if (this.is("punc", ":")) { + last = this.cascade(last, last.start); + this.next(); + } + props.subexpressions.push(last); + if (!( last instanceof Cola.AST_SymbolRef + || last instanceof Cola.AST_Binary + || last instanceof Cola.AST_Call + || last instanceof Cola.AST_Sub + || last instanceof Cola.AST_Dot + || last instanceof Cola.AST_Array + || last instanceof Cola.AST_Cascade + )) this.unexpected(); + } + if (!this.is("punc", "..")) break; + } + props.end = this.S.token; + return new Cola.AST_Cascade(props); +}; + +Cola.Parser.prototype.expression = function(commas, no_in, in_dd) { var start = this.S.token; var expr = this.maybe_assign(no_in); + if (!in_dd && !this.is_js && this.is("punc", "..")) return this.cascade(expr, start); if (commas && this.is("punc", ",")) { this.next(); return new Cola.AST_Seq({ diff --git a/lib/translate.js b/lib/translate.js index ad6a5e60..62df4fe7 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -571,7 +571,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ } else if(val.argtype == "splated"){ onfront = false; delQueue.push(i); - splated = { pos : pos++, after : 0, val : val }; + posed.push(splated = { pos : pos++, after : 0, val : val }); } }); @@ -587,8 +587,8 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ posed.forEach(function(val, i){ var pos = val.pos; val = val.val; - - if(splated && (pos - 1 == splated.pos || pos + 1 == splated.pos)){ + + if(val.argtype == "splated"){ aftersplated = 0; props.definitions.push(new Cola.AST_VarDef({ name : new Cola.AST_SymbolRef({ name : '$_cola_i' }), @@ -641,9 +641,8 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ }) }) })); - - splated = false; } + else if(val.defval instanceof Cola.AST_Noop) props.definitions.push(new Cola.AST_VarDef({ name : val.name, @@ -732,6 +731,115 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ } } else + /* + obj + ..[0] = yes + ..foo = bar + ..baz() + ..sub: + ..subfoo = no + ..subaz(); + ; + + to + + (function($_cola_ml_expr){ + $_cola_ml_expr[0] = yes; + $_cola_ml_expr.foo = bar; + $_cola_ml_expr.baz(); + + (function($_cola_ml_expr){ + $_cola_ml_expr.subfoo = no; + $_cola_ml_expr.subaz(); + + return $_cola_ml_expr; + })($_cola_ml_expr.sub); + + return $_cola_ml_expr; + })(obj); + + */ + if(node instanceof Cola.AST_Cascade){ + props = { + type : "dynamic", + body : [], + argnames : [new Cola.AST_Defarg({ + argtype : "positional", + type : "dynamic", + defval : new Cola.AST_Noop(), + name : new Cola.AST_SymbolFunarg({ name : "$_cola_ml_expr" }) + })] + }; + + var Expr, Parent = false; + node.subexpressions.forEach(function(expr){ + Expr = expr, Parent = false; + while(true) + if( expr instanceof Cola.AST_Call || expr instanceof Cola.AST_Dot || + expr instanceof Cola.AST_Sub || expr instanceof Cola.AST_Cascade){ + Parent = expr; + expr = expr.expression; + } else + if(expr instanceof Cola.AST_Binary){ + Parent = expr; + expr = expr.left; + } else + if(expr instanceof Cola.AST_Array || expr instanceof Cola.AST_ArrayRange || expr instanceof Cola.AST_SymbolRef) break; + + if(!Parent){ + if(expr instanceof Cola.AST_Array || expr instanceof Cola.AST_ArrayRange) Expr = new Cola.AST_Sub({ + start : Expr.start, + end : Expr.end, + expression : new Cola.AST_SymbolRef({ name : "$_cola_ml_expr" }), + property : expr instanceof Cola.AST_ArrayRange ? expr : ( expr.elements.length == 0 ? new Cola.AST_Noop() : expr.elements[0] ) + }); else + if(expr instanceof Cola.AST_SymbolRef) Expr = new Cola.AST_Dot({ + start : Expr.start, + end : Expr.end, + expression : new Cola.AST_SymbolRef({ name : "$_cola_ml_expr" }), + property : Expr.name + }); + } else { + if(expr instanceof Cola.AST_Array || expr instanceof Cola.AST_ArrayRange) + expr = new Cola.AST_Sub({ + start : expr.start, + end : expr.end, + expression : new Cola.AST_SymbolRef({ name : "$_cola_ml_expr" }), + property : expr instanceof Cola.AST_ArrayRange ? expr : ( expr.elements.length == 0 ? new Cola.AST_Noop() : expr.elements[0] ) + }); + else + expr = new Cola.AST_Dot({ + start : expr.start, + end : expr.end, + expression : new Cola.AST_SymbolRef({ name : "$_cola_ml_expr" }), + property : expr.name + }); + + if( Parent instanceof Cola.AST_Call || Parent instanceof Cola.AST_Dot || + Parent instanceof Cola.AST_Sub || Parent instanceof Cola.AST_Cascade) Parent.expression = expr; + else + if(Parent instanceof Cola.AST_Binary) Parent.left = expr; + } + + props.body.push(new Cola.AST_SimpleStatement({ + start : Expr.start, + end : Expr.end, + body : Expr + })); + }); + + props.body.push(new Cola.AST_Return({ + value : new Cola.AST_SymbolRef({ name : "$_cola_ml_expr" }) + })); + + node = new Cola.AST_Call({ + start : node.start, + end : node.end, + args : [node.expression], + expression : new Cola.AST_Function(props) + }); + } else + /* "test @a @{b} {{c}}"