async function definiton is done

This commit is contained in:
Dan Onoshko 2014-12-31 20:25:29 +07:00
parent d87a5db0fd
commit a8d8da556f
5 changed files with 223 additions and 18 deletions

View File

@ -497,6 +497,43 @@ Future plans
@export each as forEach from "underscore" @export each as forEach from "underscore"
@export "mylib" @export "mylib"
- `async` function modificator
async GET(String url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange() {
if (xhr.readyState != 4) return;
if (xhr.status == 200) resolve xhr.response;
reject false;
}
xhr.open("GET", url, true);
xhr.send();
}
to
function GET(url) {
var _ColaRuntime$$arguments = arguments;
return new Promise(function(_ColaRuntime$$resolve, _ColaRuntime$$reject) {
arguments = _ColaRuntime$$arguments;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.status == 200) return _ColaRuntime$$resolve(xhr.response);
return _ColaRuntime$$reject(false);
}
xhr.open("GET", url, true);
xhr.send();
}.bind(this));
}
- `await` operator (only with Promise support) - `await` operator (only with Promise support)
String name = await getNameFromServer(id); String name = await getNameFromServer(id);

View File

@ -503,6 +503,16 @@ Cola.AST_Throw = Cola.DEFNODE("Throw", null, {
$documentation: "A `throw` statement" $documentation: "A `throw` statement"
}, Cola.AST_Exit); }, Cola.AST_Exit);
Cola.AST_Resolve = Cola.DEFNODE("Resolve", null, {
$iscola: true,
$documentation: "A `resolve` statement"
}, Cola.AST_Exit);
Cola.AST_Reject = Cola.DEFNODE("Reject", null, {
$iscola: true,
$documentation: "A `reject` statement"
}, Cola.AST_Exit);
Cola.AST_LoopControl = Cola.DEFNODE("LoopControl", "label", { Cola.AST_LoopControl = Cola.DEFNODE("LoopControl", "label", {
$documentation: "Base class for loop control statements (`break` and `continue`)", $documentation: "Base class for loop control statements (`break` and `continue`)",
$propdoc: { $propdoc: {

View File

@ -49,17 +49,17 @@
!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 get set when clone is isnt class extends singleton'; Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' static covert export async get set when clone 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';
Cola.RESERVED_WORDS = 'abstract boolean byte char double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield'; Cola.RESERVED_WORDS = 'abstract boolean byte char double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield';
Cola.cRESERVED_WORDS = Cola.RESERVED_WORDS.replace(' class', '').replace(' extends', '').replace(' static', '') + " " + Cola.cKEYWORDS_ATOM + " " + Cola.cKEYWORDS; Cola.cRESERVED_WORDS = Cola.RESERVED_WORDS.replace(' class', '').replace(' extends', '').replace(' static', '').replace(' export', '') + " " + Cola.cKEYWORDS_ATOM + " " + Cola.cKEYWORDS;
Cola.RESERVED_WORDS += " " + Cola.KEYWORDS_ATOM + " " + Cola.KEYWORDS; Cola.RESERVED_WORDS += " " + Cola.KEYWORDS_ATOM + " " + Cola.KEYWORDS;
Cola.KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; Cola.KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
Cola.cKEYWORDS_BEFORE_EXPRESSION = Cola.KEYWORDS_BEFORE_EXPRESSION += ' when'; Cola.cKEYWORDS_BEFORE_EXPRESSION = Cola.KEYWORDS_BEFORE_EXPRESSION += ' when resolve reject await';
Cola.KEYWORDS = Cola.makePredicate(Cola.KEYWORDS); Cola.KEYWORDS = Cola.makePredicate(Cola.KEYWORDS);
Cola.cKEYWORDS = Cola.makePredicate(Cola.cKEYWORDS); Cola.cKEYWORDS = Cola.makePredicate(Cola.cKEYWORDS);
@ -770,7 +770,7 @@ Cola.cUNARY_PREFIX = Cola.makePredicate([
"+" "+"
]); ]);
Cola.cVARS_MODIFICATORS = Cola.makePredicate([ "const", "covert", "static", "export" ]); Cola.cVARS_MODIFICATORS = Cola.makePredicate([ "const", "covert", "static", "export", "async" ]);
Cola.UNARY_POSTFIX = Cola.makePredicate([ "--", "++" ]); Cola.UNARY_POSTFIX = Cola.makePredicate([ "--", "++" ]);
Cola.cUNARY_POSTFIX = Cola.makePredicate([ "--", "++", "?" ]); Cola.cUNARY_POSTFIX = Cola.makePredicate([ "--", "++", "?" ]);
@ -850,6 +850,7 @@ Cola.Parser = function ($TEXT, options) {
prev : null, prev : null,
peeked : null, peeked : null,
in_function : 0, in_function : 0,
in_async_function : 0,
in_directives : true, in_directives : true,
in_loop : 0, in_loop : 0,
labels : [] labels : []
@ -1330,10 +1331,18 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "if": case "if":
return this.if_(); return this.if_();
case "return": case "return": case "resolve": case "reject":
if (this.S.in_function == 0) if (this.S.in_function == 0)
this.croak("'return' outside of function"); this.croak("'" + tmp + "' outside of function");
return new Cola.AST_Return({
if (tmp != "return" && this.S.in_async_function == 0)
this.croak("'" + tmp + "' outside of async function");
var ctor = Cola.AST_Return;
if (tmp == "resolve") ctor = Cola.AST_Resolve;
else if (tmp == "reject") ctor = Cola.AST_Reject;
return new ctor({
value: ( this.is("punc", ";") value: ( this.is("punc", ";")
? (this.next(), null) ? (this.next(), null)
: this.can_insert_semicolon() : this.can_insert_semicolon()
@ -1733,12 +1742,12 @@ Cola.Parser.prototype.function_ = function(ctor, type, mods) {
if(!this.S.in_class){ if(!this.S.in_class){
if(name instanceof Cola.AST_Symbol){ if(name instanceof Cola.AST_Symbol){
if(mods.length > 1 || mods[0] && mods[0] != "export") if(!Cola.modsVerifi(mods, ["export", "async"]))
this.token_error(name.start, "Function definition outside of class can contain only `export` modifer"); this.token_error(name.start, "Function definition outside of class can contain only `export` and `async` modifers");
} }
else { else {
if(mods.length != 0 && (mods.indexOf("static") != -1 || mods.indexOf("export") != -1)) if(Cola.modsContains(mods, ["export", "static"]))
this.token_error(name.start, "Prop definition can't contain `static` and `export` modifers"); this.token_error(name.start, "Prop definition can't contain `static` and `export` modifers");
} }
} else if (mods.indexOf("export") != -1) } else if (mods.indexOf("export") != -1)
@ -1763,6 +1772,7 @@ Cola.Parser.prototype.function_ = function(ctor, type, mods) {
})(true, []), })(true, []),
body: (function(loop, labels){ body: (function(loop, labels){
++_this.S.in_function; ++_this.S.in_function;
if (mods.indexOf("async") != -1) ++_this.S.in_async_function;
_this.S.in_directives = true; _this.S.in_directives = true;
_this.S.in_loop = 0; _this.S.in_loop = 0;
_this.S.labels = []; _this.S.labels = [];
@ -1783,6 +1793,7 @@ Cola.Parser.prototype.function_ = function(ctor, type, mods) {
: _this.block_(); : _this.block_();
--_this.S.in_function; --_this.S.in_function;
if (mods.indexOf("async") != -1) --_this.S.in_async_function;
_this.S.in_loop = loop; _this.S.in_loop = loop;
_this.S.labels = labels; _this.S.labels = labels;
return a; return a;
@ -1922,6 +1933,9 @@ Cola.Parser.prototype.vardefs = function (no_in, in_const, type, mods) {
if (mods && mods.indexOf("export") != -1 && (!(last.name instanceof Cola.AST_Symbol) || this.S.in_class)) if (mods && mods.indexOf("export") != -1 && (!(last.name instanceof Cola.AST_Symbol) || this.S.in_class))
this.token_error(last.start, "Unexpected `export` modificator."); this.token_error(last.start, "Unexpected `export` modificator.");
if (mods && mods.indexOf("async") != -1)
this.token_error(last.start, "Unexpected `async` modificator.");
if (!this.is("punc", ",")) if (!this.is("punc", ","))
break; break;
this.next(); this.next();

View File

@ -482,6 +482,8 @@ Cola.DefFunWithMods = function(func, mods){
}); });
} }
if (mods.indexOf("async") != -1) func = Cola.FuncAsync(func);
var sname = func.name, dp = { properties : [ var sname = func.name, dp = { properties : [
new Cola.AST_ObjectKeyVal({ new Cola.AST_ObjectKeyVal({
key : (function(node){ key : (function(node){
@ -536,6 +538,55 @@ Cola.DefFunWithMods = function(func, mods){
}); });
}; };
Cola.FuncAsync = function(func) {
if (!func.body.length) return func;
var newBody = [];
if (func.argnames.length) newBody.push(new Cola.AST_Var({
mods : [],
type : "dynamic",
definitions : [new Cola.AST_VarDef({
type : "dynamic",
name : new Cola.AST_SymbolVar({ name: "_ColaRuntime$$arguments" }),
value : new Cola.AST_SymbolRef({ name: "arguments" })
})]
}));
newBody.push(new Cola.AST_Return({
value : new Cola.AST_New({
args : [],
expression : new Cola.AST_SymbolRef({ name: "Promise" })
})
}));
newBody[newBody.length - 1].value.args.push(new Cola.AST_Call({
args : [new Cola.AST_This],
expression : new Cola.AST_Dot({ expression: false, property: "bind" })
}));
func.body.unshift(new Cola.AST_SimpleStatement({
body : new Cola.AST_Assign({
left : new Cola.AST_SymbolRef({ name: "arguments" }),
operator : "=",
right : func.argnames.length
? new Cola.AST_SymbolRef({ name: "_ColaRuntime$$arguments" })
: new Cola.AST_Object
})
}));
newBody[newBody.length - 1].value.args[0].expression.expression = new Cola.AST_Function({
body : func.body,
argnames : [
new Cola.AST_SymbolFunarg({ name : "_ColaRuntime$$resolve" }),
new Cola.AST_SymbolFunarg({ name : "_ColaRuntime$$reject" })
]
});
func.body = newBody;
return func;
};
Cola.PushModuleToCommonWrapper = function(module, commonWrapper, name, id) { Cola.PushModuleToCommonWrapper = function(module, commonWrapper, name, id) {
commonWrapper.body.args[0].elements.push(new Cola.AST_Function({ commonWrapper.body.args[0].elements.push(new Cola.AST_Function({
body : module.body, body : module.body,
@ -669,7 +720,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
to to
if(a.b === "undefined" && a.b === null) a.b.c(); if(!(typeof a.b === "undefined" || a.b === null)) a.b.c();
*/ */
if(node instanceof Cola.AST_SimpleStatement && (props = Cola.ContainCondAccess(node.body))){ if(node instanceof Cola.AST_SimpleStatement && (props = Cola.ContainCondAccess(node.body))){
@ -686,7 +737,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
} }
node = new Cola.AST_If({ node = new Cola.AST_If({
condition : Cola.Constructions.IsntSet(props), condition : Cola.Constructions.IsSet(props),
body : node body : node
}); });
} else } else
@ -724,7 +775,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
to to
if(a.b === "undefined" && a.b === null) a.b.c = 123; 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 instanceof Cola.AST_SimpleStatement && node.body instanceof Cola.AST_Assign && (props = Cola.ContainCondAccess(node.body.left))){
@ -741,7 +792,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
} }
node = new Cola.AST_If({ node = new Cola.AST_If({
condition : Cola.Constructions.IsntSet(props), condition : Cola.Constructions.IsSet(props),
body : node body : node
}); });
} else } else
@ -951,6 +1002,40 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node = new Cola.AST_Call(props); node = new Cola.AST_Call(props);
} else } else
/*
resolve a
to
return _ColaRuntime$$resolve(a)
*/
if(node instanceof Cola.AST_Resolve){
node = new Cola.AST_Return({
value : new Cola.AST_Call({
args : [node.value],
expression : new Cola.AST_SymbolRef({ name: "_ColaRuntime$$resolve" })
})
});
} else
/*
reject a
to
return _ColaRuntime$$reject(a)
*/
if(node instanceof Cola.AST_Reject){
node = new Cola.AST_Return({
value : new Cola.AST_Call({
args : [node.value],
expression : new Cola.AST_SymbolRef({ name: "_ColaRuntime$$reject" })
})
});
} else
/* /*
arr[] = 123 arr[] = 123
@ -1207,6 +1292,46 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
}); });
} else } else
/*
async GET(String url) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange() {
if (xhr.readyState != 4) return;
if (xhr.status == 200) resolve xhr.response;
reject false;
}
xhr.open("GET", url, true);
xhr.send();
}
to
function GET(url) {
var _ColaRuntime$$arguments = arguments;
return new Promise(function(_ColaRuntime$$resolve, _ColaRuntime$$reject) {
arguments = _ColaRuntime$$arguments;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.status == 200) return _ColaRuntime$$resolve(xhr.response);
return _ColaRuntime$$reject(false);
}
xhr.open("GET", url, true);
xhr.send();
}.bind(this));
}
*/
if (node instanceof Cola.AST_Defun && node.mods.indexOf("async") != -1) {
node = Cola.FuncAsync(node);
} else
/* /*
func(a, b, name : name, c) func(a, b, name : name, c)
@ -3159,7 +3284,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
})})); })}));
}); });
if (options.root && !options.is_node) { if (options.root && !options.is_node && _this.requiredModules.length && !exports.length) {
var commonWrapper = _ColaRuntime$$ast.body[17].clone(), moduleId = 1; var commonWrapper = _ColaRuntime$$ast.body[17].clone(), moduleId = 1;
Cola.PushModuleToCommonWrapper(_this, commonWrapper); Cola.PushModuleToCommonWrapper(_this, commonWrapper);

View File

@ -162,6 +162,23 @@ Cola.bootstrap = function () {
window.dispatchEvent(event); window.dispatchEvent(event);
}; };
Cola.modsVerifi = function(mods, allowedMods) {
mods = mods.slice();
allowedMods.forEach(function(mod){
Cola.remove(mods, mod);
});
return !mods.length;
};
Cola.modsContains = function(mods, allowedMods) {
for (var i in allowedMods)
if (allowedMods.hasOwnProperty(i) && mods.indexOf(allowedMods[i]) != -1) return true;
return false;
};
"use strict"; "use strict";
Cola.array_to_hash = function (a) { Cola.array_to_hash = function (a) {
@ -298,9 +315,11 @@ Cola.string_template = function (text, props) {
}; };
Cola.remove = function (array, el) { Cola.remove = function (array, el) {
for (var i = array.length; --i >= 0;) { var i = array.indexOf(el);
if (array[i] === el) array.splice(i, 1); if (i > -1) array.splice(i, 1);
} // for (var i = array.length; --i >= 0;) {
// if (array[i] === el) array.splice(i, 1);
// }
}; };
Cola.mergeSort = function (array, cmp) { Cola.mergeSort = function (array, cmp) {