ES6 for ...of is added

This commit is contained in:
Dan Onoshko 2015-01-02 02:41:48 +07:00
parent 2a31e4a52c
commit 4db28f7851
5 changed files with 105 additions and 21 deletions

View File

@ -547,7 +547,8 @@ Future plans
console.log(name); console.log(name);
}, this); }, this);
- `@use client` and `@use server` commands - `@use client` and `@use server` commands, status: done
- control flows without braces, status: done
- static typing - static typing
- `@use` expressions - `@use` expressions

View File

@ -281,6 +281,23 @@ Cola.AST_ForIn = Cola.DEFNODE("ForIn", "init name object", {
} }
}, Cola.AST_IterationStatement); }, Cola.AST_IterationStatement);
Cola.AST_ForOf = Cola.DEFNODE("ForOf", "init name object", {
$iscola: true,
$documentation: "A `for ... of` statement",
$propdoc: {
init: "[AST_Node] the `for/in` initialization code",
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
object: "[AST_Node] the object that we're looping through"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
this.init._walk(visitor);
this.object._walk(visitor);
this.body._walk(visitor);
});
}
}, Cola.AST_IterationStatement);
Cola.AST_With = Cola.DEFNODE("With", "expression", { Cola.AST_With = Cola.DEFNODE("With", "expression", {
$documentation: "A `with` statement", $documentation: "A `with` statement",
$propdoc: { $propdoc: {

View File

@ -2243,19 +2243,19 @@ Cola.Compressor.MathFuncs = {
return self; return self;
}); });
OPT(AST_Infinity, function (self, compressor) { OPT(Cola.AST_Infinity, function (self, compressor) {
return make_node(AST_Binary, self, { return make_node(Cola.AST_Binary, self, {
operator : '/', operator : '/',
left : make_node(AST_Number, null, {value: 1}), left : make_node(Cola.AST_Number, null, {value: 1}),
right : make_node(AST_Number, null, {value: 0}) right : make_node(Cola.AST_Number, null, {value: 0})
}); });
}); });
OPT(AST_NaN, function (self, compressor) { OPT(Cola.AST_NaN, function (self, compressor) {
return make_node(AST_Binary, self, { return make_node(Cola.AST_Binary, self, {
operator : '/', operator : '/',
left : make_node(AST_Number, null, {value: 0}), left : make_node(Cola.AST_Number, null, {value: 0}),
right : make_node(AST_Number, null, {value: 0}) right : make_node(Cola.AST_Number, null, {value: 0})
}); });
}); });

View File

@ -49,7 +49,7 @@
!this.Cola && (this.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.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', '') + ' static covert export async get set when clone is isnt class extends singleton resolve reject await'; Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' static covert export async get set when clone of is isnt class extends singleton resolve reject await';
Cola.KEYWORDS_ATOM = 'false null true'; Cola.KEYWORDS_ATOM = 'false null true';
Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no'; Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no';
@ -127,6 +127,7 @@ Cola.OPERATORS = [ // d - different left and right types of vars, s - same
// ColaScript // ColaScript
"await", "await",
"clone", "clone",
"of",
"is", "is",
"isnt", "isnt",
"**", "**",
@ -813,7 +814,7 @@ Cola.cPRECEDENCE = Cola.mergeTokens(
["^"], ["^"],
["&"], ["&"],
["==", "===", "!=", "!=="], ["==", "===", "!=", "!=="],
["<", ">", "<=", ">=", "in", "instanceof", "is", "isnt"], ["<", ">", "<=", ">=", "in", "of", "instanceof", "is", "isnt"],
[">>", "<<", ">>>"], [">>", "<<", ">>>"],
["+", "-"], ["+", "-"],
["*", "/", "%", "**", "%%"] ["*", "/", "%", "**", "%%"]
@ -840,7 +841,8 @@ Cola.Parser = function ($TEXT, options) {
toplevel : null, toplevel : null,
expression : false, expression : false,
html5_comments : true, html5_comments : true,
is_js : false is_js : false,
braces_free : true
}); });
this.is_js = !!this.options.is_js; this.is_js = !!this.options.is_js;
@ -972,14 +974,14 @@ Cola.Parser.prototype.unexpected = function (token) {
this.token_error(token, "Unexpected token: " + token.type + " `" + token.value + "`"); this.token_error(token, "Unexpected token: " + token.type + " `" + token.value + "`");
}; };
Cola.Parser.prototype.expect_token = function (type, val) { Cola.Parser.prototype.expect_token = function (type, val, stay) {
if (this.is(type, val)) { if (this.is(type, val)) {
return this.next(); return stay ? undefined : this.next();
} }
this.token_error(this.S.token, "Unexpected token " + this.S.token.type + " `" + this.S.token.value + "`" + ", expected " + type + " `" + val + "`"); this.token_error(this.S.token, "Unexpected token " + this.S.token.type + " `" + this.S.token.value + "`" + ", expected " + type + " `" + val + "`");
}; };
Cola.Parser.prototype.expect = function (punc) { return this.expect_token("punc", punc); }; Cola.Parser.prototype.expect = function (punc, stay) { return this.expect_token("punc", punc, stay); };
Cola.Parser.prototype.can_insert_semicolon = function () { Cola.Parser.prototype.can_insert_semicolon = function () {
if(!this.is_js) return false; if(!this.is_js) return false;
@ -994,9 +996,10 @@ Cola.Parser.prototype.semicolon = function () {
}; };
Cola.Parser.prototype.parenthesised = function () { Cola.Parser.prototype.parenthesised = function () {
this.expect("("); if (this.is_js || !this.options.braces_free) this.expect("(");
var exp = this.expression(true); var exp = this.expression(true);
this.expect(")"); if (this.is_js || !this.options.braces_free) this.expect(")");
else this.expect("{", true);
return exp; return exp;
}; };
@ -1519,17 +1522,24 @@ Cola.Parser.prototype.break_cont = function (type) {
}; };
Cola.Parser.prototype.for_ = function () { Cola.Parser.prototype.for_ = function () {
this.expect("("); if (this.is_js || !this.options.braces_free) this.expect("(");
var init = null; var init = null;
if (!this.is("punc", ";")) { if (!this.is("punc", ";")) {
init = this.is("keyword", "var") || !this.is_js && this.is("name") && this.next_is("name") init = this.is("keyword", "var") || !this.is_js && this.is("name") && this.next_is("name")
? (this.next(), this.var_(true, this.prev().value)) ? (this.next(), this.var_(true, this.prev().value))
: this.expression(true, true); : this.expression(true, true);
if (this.is("operator", "in")) { if (this.is("operator", "in")) {
if (init instanceof Cola.AST_Var && init.definitions.length > 1) if (init instanceof Cola.AST_Var && init.definitions.length > 1)
this.croak("Only one variable declaration allowed in for..in loop"); this.croak("Only one variable declaration allowed in for..in loop");
this.next(); this.next();
return this.for_in(init); return this.for_in(init);
} else
if (!this.is_js && this.is("operator", "of")) {
if (init instanceof Cola.AST_Var && init.definitions.length > 1)
this.croak("Only one variable declaration allowed in for..of loop");
this.next();
return this.for_of(init);
} }
} }
return this.regular_for(init); return this.regular_for(init);
@ -1540,7 +1550,8 @@ Cola.Parser.prototype.regular_for = function (init) {
var test = this.is("punc", ";") ? null : this.expression(true); var test = this.is("punc", ";") ? null : this.expression(true);
this.expect(";"); this.expect(";");
var step = this.is("punc", ")") ? null : this.expression(true); var step = this.is("punc", ")") ? null : this.expression(true);
this.expect(")"); if (this.is_js || !this.options.braces_free) this.expect(")");
else this.expect("{", true);
var _this = this; var _this = this;
return new Cola.AST_For({ return new Cola.AST_For({
init : init, init : init,
@ -1553,7 +1564,8 @@ Cola.Parser.prototype.regular_for = function (init) {
Cola.Parser.prototype.for_in = function (init) { Cola.Parser.prototype.for_in = function (init) {
var lhs = init instanceof Cola.AST_Var ? init.definitions[0].name : null; var lhs = init instanceof Cola.AST_Var ? init.definitions[0].name : null;
var obj = this.expression(true); var obj = this.expression(true);
this.expect(")"); if (this.is_js || !this.options.braces_free) this.expect(")");
else this.expect("{", true);
var _this = this; var _this = this;
return new Cola.AST_ForIn({ return new Cola.AST_ForIn({
init : init, init : init,
@ -1563,6 +1575,20 @@ Cola.Parser.prototype.for_in = function (init) {
}); });
}; };
Cola.Parser.prototype.for_of = function (init) {
var lhs = init instanceof Cola.AST_Var ? init.definitions[0].name : null;
var obj = this.expression(true);
if (!this.options.braces_free) this.expect(")");
else this.expect("{", true);
var _this = this;
return new Cola.AST_ForOf({
init : init,
name : lhs,
object : obj,
body : this.in_loop(function(){ return this.statement() })
});
};
Cola.Parser.prototype.class_ = function(mods){ Cola.Parser.prototype.class_ = function(mods){
if(this.S.in_class) if(this.S.in_class)
this.token_error(this.prev(), "You can define class or singleton only in root scope."); this.token_error(this.prev(), "You can define class or singleton only in root scope.");
@ -2579,7 +2605,7 @@ Cola.Parser.prototype.make_unary = function (ctor, op, expr) {
*/ */
Cola.Parser.prototype.expr_op = function(left, min_prec, no_in, is_comp, rightest) { Cola.Parser.prototype.expr_op = function(left, min_prec, no_in, is_comp, rightest) {
var op = this.is("operator") ? this.S.token.value : null, cop = Cola.COMPARISON(op); var op = this.is("operator") ? this.S.token.value : null, cop = Cola.COMPARISON(op);
if (op == "in" && no_in) op = null; if ((op == "in" || op == "of") && no_in) op = null;
var prec = op != null ? this.PRECEDENCE[op] : null; var prec = op != null ? this.PRECEDENCE[op] : null;
if (!this.is_js && is_comp && cop) { if (!this.is_js && is_comp && cop) {
this.next(); this.next();

View File

@ -2991,6 +2991,46 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node = branches; node = branches;
} else } else
/*
for _ of [0...9] {
}
to
var _ColaRuntime$$forOfHolder;
for (_ in [0...9]) {
_ = _ColaRuntime$$forOfHolder[_];
}
*/
if(node instanceof Cola.AST_ForOf){
node = new Cola.AST_ForIn(node);
newNode = [new Cola.AST_Var({
type : "dynamic",
definitions : [new Cola.AST_VarDef({
type : "dynamic",
name : new Cola.AST_SymbolVar({ name: '_ColaRuntime$$forOfHolder' })
})]}), node];
node.object = new Cola.AST_Assign({
operator : '=',
left : new Cola.AST_SymbolRef({ name : "_ColaRuntime$$forOfHolder" }),
right : node.object
});
node.body.body.unshift(new Cola.AST_SimpleStatement({ body : new Cola.AST_Assign({
operator : '=',
left : new Cola.AST_SymbolRef(node.name || node.init),
right : new Cola.AST_Sub({
expression : new Cola.AST_SymbolRef({ name : "_ColaRuntime$$forOfHolder" }),
property : new Cola.AST_SymbolRef(node.name || node.init)
})
})}));
node = newNode;
} else
/* /*
MyClass::prop = (){ MyClass::prop = (){