Conditional Accessor is done.

This commit is contained in:
Onoshko Dan 2014-08-15 03:34:04 +07:00
parent c3df8f1d3f
commit c9f4a2cd12
3 changed files with 112 additions and 7 deletions

View File

@ -377,7 +377,7 @@ Future plans
Object data = someData;
int data.getFriendsCount() => this.friends.length;
- operator `?.`
- operator `?.`. status: done
- Negate array accessor ( getter )
arr[-1]; // last element

View File

@ -147,7 +147,7 @@ Cola.WHITESPACE_CHARS = Cola.makePredicate(Cola.characters(" \u00a0\n\r\t\f\u000
Cola.cPUNC_BEFORE_EXPRESSION = Cola.makePredicate(Cola.characters("[{(,.;:").concat(["::", "?."]));
Cola.PUNC_BEFORE_EXPRESSION = Cola.makePredicate(Cola.characters("[{(,.;:"));
Cola.PUNC_CHARS = Cola.makePredicate(Cola.characters("[]{}(),;:?"));
Cola.PUNC_CHARS = Cola.makePredicate(Cola.characters("[]{}(),;:"));
Cola.REGEXP_MODIFIERS = Cola.makePredicate(Cola.characters("gmsiy"));
@ -710,7 +710,6 @@ Cola.Tokenizer.prototype.next_token = function (force_regexp) {
if (Cola.PUNC_CHARS(ch)){
if (!this.is_js && ch == ":" && this.peek(1) == ":") return this.next(), this.next(), this.token("punc", "::");
if (!this.is_js && ch == "?" && this.peek(1) == ".") return this.next(), this.next(), this.token("punc", "?.");
if (!this.is_js && this.S.string.at[this.S.string.level].inside && (this.S.string.at[this.S.string.level].inside_at || this.S.string.at[this.S.string.level].inside_braces)) {
if (ch == '{') this.S.string.at[this.S.string.level].balance++;
@ -728,6 +727,7 @@ Cola.Tokenizer.prototype.next_token = function (force_regexp) {
}
if (!this.is_js) {
if (ch == "?" && this.peek(1) == ".") return this.next(), this.next(), this.token("punc", "?.");
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 == '@') return this.read_at();
@ -2099,6 +2099,7 @@ Cola.Parser.prototype.maybe_unary = function(allow_calls) {
return ex;
}
var val = this.expr_atom(allow_calls);
while (this.is("operator") && this.UNARY_POSTFIX(this.S.token.value) && !this.S.token.nlb) {
if(!this.is_js && this.is("operator", "?") &&
!(this.next_is("punc", ";") || this.next_is("punc", ",") || this.next_is("punc", ":") ||
@ -2169,6 +2170,7 @@ Cola.Parser.prototype.expr_ops = function (no_in) {
Cola.Parser.prototype.maybe_conditional = function(no_in) {
var start = this.S.token;
var expr = this.expr_ops(no_in);
if (this.is("operator", "?")) {
this.next();

View File

@ -361,12 +361,17 @@ Cola.Constructions.NamedVarDef = function(name, type, defval, key){
});
};
Cola.CondAccessContains = function(node){
Cola.ContainCondAccess = function(node){
if(!(node instanceof Cola.AST_Call || node instanceof Cola.AST_PropAccess)) return false;
if(node instanceof Cola.AST_CondAccess) return node.expression;
var expr = node;
while(expr.expression instanceof Cola.AST_Call || expr.expression instanceof Cola.AST_PropAccess){
expr = expr.expression;
if(expr instanceof Cola.AST_CondAccess) return expr.expression;
}
return false;
};
@ -472,11 +477,109 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
to
typeof a.b === "undefined" && a.b === null ? undefined : a.b.c();
if(a.b === "undefined" && a.b === null) a.b.c();
*/
if(node instanceof ){
if(node instanceof Cola.AST_SimpleStatement && (props = Cola.ContainCondAccess(node.body))){
if(node.body instanceof Cola.AST_CondAccess) node.body = new Cola.AST_Dot(node.body);
else {
var expr = node.body;
while(expr.expression instanceof Cola.AST_Call || expr.expression instanceof Cola.AST_PropAccess){
if(expr.expression instanceof Cola.AST_CondAccess){
expr.expression = new Cola.AST_Dot(expr.expression);
break;
}
expr = expr.expression;
}
}
node = new Cola.AST_If({
condition : Cola.Constructions.IsntSet(props),
body : node
});
} else
/*
alert(a.b?.c());
to
alert(typeof a.b === "undefined" && a.b === null ? undefined : a.b.c());
*/
if(props = Cola.ContainCondAccess(node)){
if(node instanceof Cola.AST_CondAccess) node = new Cola.AST_Dot(node);
else {
var expr = node;
while(expr.expression instanceof Cola.AST_Call || expr.expression instanceof Cola.AST_PropAccess){
if(expr.expression instanceof Cola.AST_CondAccess){
expr.expression = new Cola.AST_Dot(expr.expression);
break;
}
expr = expr.expression;
}
}
node = new Cola.AST_Conditional({
condition : Cola.Constructions.IsntSet(props),
consequent : new Cola.AST_Undefined,
alternative : node
});
} else
/*
a.b?.c = 123;
to
if(a.b === "undefined" && a.b === null) a.b.c = 123;
*/
if(node instanceof Cola.AST_SimpleStatement && node.body instanceof Cola.AST_Assign && (props = Cola.ContainCondAccess(node.body.left))){
if(node.body.left instanceof Cola.AST_CondAccess) node.body.left = new Cola.AST_Dot(node.body.left);
else {
var expr = node.body.left;
while(expr.expression instanceof Cola.AST_Call || expr.expression instanceof Cola.AST_PropAccess){
if(expr.expression instanceof Cola.AST_CondAccess){
expr.expression = new Cola.AST_Dot(expr.expression);
break;
}
expr = expr.expression;
}
}
node = new Cola.AST_If({
condition : Cola.Constructions.IsntSet(props),
body : node
});
} else
/*
alert(a.b?.c = 123);
to
alert(typeof a.b === "undefined" && a.b === null ? undefined : a.b?.c = 123);
*/
if(node instanceof Cola.AST_Assign && (props = Cola.ContainCondAccess(node.left))){
if(node.left instanceof Cola.AST_CondAccess) node.left = new Cola.AST_Dot(node.left);
else {
var expr = node.left;
while(expr.expression instanceof Cola.AST_Call || expr.expression instanceof Cola.AST_PropAccess){
if(expr.expression instanceof Cola.AST_CondAccess){
expr.expression = new Cola.AST_Dot(expr.expression);
break;
}
expr = expr.expression;
}
}
node = new Cola.AST_Conditional({
condition : Cola.Constructions.IsntSet(props),
consequent : new Cola.AST_Undefined,
alternative : node
});
} else
/*
@ -1457,7 +1560,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
var skiped = false, k = 0, is_arrayt = def instanceof Cola.AST_Array || def instanceof Cola.AST_ArrayTemplate, _ = is_arrayt ? def.elements : def.properties;
_.forEach( is_arrayt
? function(el, j){
if((el instanceof Cola.AST_SymbolRef || el instanceof Cola.AST_PropAccess && el.splated){
if((el instanceof Cola.AST_SymbolRef || el instanceof Cola.AST_PropAccess) && el.splated){
skiped = true;
defs.push(new Cola.AST_VarDef({
type : "int",