From 5c9e1fd0882237429e840a65dd00462fa49b3d09 Mon Sep 17 00:00:00 2001 From: Dan Onoshko Date: Thu, 1 Jan 2015 23:23:14 +0700 Subject: [PATCH] await call is done --- README.md | 34 ++------- lib/parse.js | 2 + lib/scope.js | 3 +- lib/std.js | 37 ++++++---- lib/translate.js | 189 ++++++++++++++++++++++++++++++++++++----------- 5 files changed, 178 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 6788ffa3..66f95f26 100644 --- a/README.md +++ b/README.md @@ -497,7 +497,7 @@ Future plans @export each as forEach from "underscore" @export "mylib" -- `async` function modificator +- `async` function modificator, status: done async GET(String url) { var xhr = new XMLHttpRequest(); @@ -534,46 +534,26 @@ Future plans } -- `await` operator (only with Promise support) +- `await` operator (only with Promise support), status: done String name = await getNameFromServer(id); console.log(name); to - getNameFromServer(id).then(function(_ColaRuntime$$fulfilled, _ColaRuntime$$rejected) { + var _ColaRuntime$$arguments = arguments; + _ColaRuntime$$promise(getNameFromServer(id), function(_ColaRuntime$$fulfilled, _ColaRuntime$$rejected) { + arguments = _ColaRuntime$$arguments; if (_ColaRuntime$$rejected) throw _ColaRuntime$$rejected; - String name = __ColaRuntime$$fulfilled; + String name = _ColaRuntime$$fulfilled; console.log(name); - }); + }, this); - static typing - `@use` expressions @use strict closure - -- `@use await closure` wrapped code will be execute on `DOMContentLoaded`, `main` functions will triggered firstly: - - // cola - - @use await closure - - main(){ - alert('loaded!'); - } - - document.title = "Page"; - - // js - - document.addEventListener('DOMContentLoaded', function(){ - alert('loaded!'); - }, false); - - document.addEventListener('DOMContentLoaded', function(){ - document.title = "Page"; - }, false); - interface diff --git a/lib/parse.js b/lib/parse.js index 1f2541cb..b70d07af 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -125,6 +125,7 @@ Cola.OPERATORS = [ // d - different left and right types of vars, s - same "&&", // binary - s "||", // binary - s // ColaScript + "await", "clone", "is", "isnt", @@ -759,6 +760,7 @@ Cola.UNARY_PREFIX = Cola.makePredicate([ "+" ]); Cola.cUNARY_PREFIX = Cola.makePredicate([ + "await", "clone", "typeof", "delete", diff --git a/lib/scope.js b/lib/scope.js index 4d9f13c1..834f77a2 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -150,10 +150,11 @@ Cola.AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ func = prev_func; return true; } + if (node instanceof Cola.AST_SymbolRef) { var name = node.name; var sym = node.scope.find_variable(name); - if (!sym) { + if (!sym || func && name == "arguments") { var g; if (globals.has(name)) { g = globals.get(name); diff --git a/lib/std.js b/lib/std.js index 31df44fd..0be6f2ac 100644 --- a/lib/std.js +++ b/lib/std.js @@ -153,34 +153,34 @@ Cola._ColaRuntime$$proto = function _ColaRuntime$$proto(_proto) { }; Cola._ColaRuntime$$proto.i = 15; -Cola._ColaRuntime$$rootImport = function _ColaRuntime$$rootImport(module) { +Cola._ColaRuntime$$rootImport = function _ColaRuntime$$rootImport(_module) { var g = typeof window == "undefined" ? global : window; - for (var i in module) - if (module.hasOwnProperty(i)) g[i] = module[i]; + for (var i in _module) + if (_module.hasOwnProperty(i)) g[i] = _module[i]; }; Cola._ColaRuntime$$rootImport.i = 16; -Cola._ColaRuntime$$commonWrapper = function(modules, cache, ids) { +Cola._ColaRuntime$$commonWrapper = function(_modules, _cache, _ids) { function require(name) { - if (cache[name]) return cache[name].exports; - if (modules[name]) return call(name); + if (_cache[name]) return _cache[name].exports; + if (_modules[name]) return call(name); throw new Error('Cannot find module "' + name + '"'); } require.cola = true; - require.cache = cache; - require.modules = modules; + require.cache = _cache; + require.modules = _modules; function call(id) { - var module = cache[id] = { + var module = _cache[id] = { exports: {} }; - modules[id].call(module.exports, function(moduleName) { - var dependencies = ids[moduleName]; + _modules[id].call(module.exports, function(moduleName) { + var dependencies = _ids[moduleName]; return require(dependencies ? dependencies : moduleName); }, module, module.exports); @@ -191,13 +191,19 @@ Cola._ColaRuntime$$commonWrapper = function(modules, cache, ids) { }; Cola._ColaRuntime$$commonWrapper.i = 17; -Cola._ColaRuntime$$rootExport = function _ColaRuntime$$rootExport(exports, module) { - for (var i in module) - if (module.hasOwnProperty(i)) exports[i] = module[i]; +Cola._ColaRuntime$$rootExport = function _ColaRuntime$$rootExport(_exports, _module) { + for (var i in _module) + if (_module.hasOwnProperty(i)) _exports[i] = _module[i]; }; Cola._ColaRuntime$$rootExport.i = 18; -Cola._ColaRuntime$$arguments_def = { i : 19 }; +Cola._ColaRuntime$$promise = function _ColaRuntime$$promise(_promise, _then, _this) { + if (!_promise.then) throw new Error("Function is not async."); + _promise.then(_then.bind(_this)); +}; +Cola._ColaRuntime$$promise.i = 19; + +Cola._ColaRuntime$$arguments_def = { i : 20 }; Cola._ColaRuntime = Cola._ColaRuntime$$is + Cola._ColaRuntime$$isnt + Cola._ColaRuntime$$modulo + Cola._ColaRuntime$$isset + @@ -205,6 +211,7 @@ Cola._ColaRuntime = Cola._ColaRuntime$$array_asplice + Cola._ColaRuntime$$func_named_args + Cola._ColaRuntime$$func_set_named_args + Cola._ColaRuntime$$error + Cola._ColaRuntime$$array_negate_access + Cola._ColaRuntime$$array_modulo_access + Cola._ColaRuntime$$updateProperty + Cola._ColaRuntime$$proto + Cola._ColaRuntime$$rootImport + "(" + Cola._ColaRuntime$$commonWrapper + ")([],{},{});" + Cola._ColaRuntime$$rootExport + + Cola._ColaRuntime$$promise + "var arguments;"; Cola.Compressor.StdFuncs = { diff --git a/lib/translate.js b/lib/translate.js index 7d2a41a9..ff73932d 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -624,14 +624,62 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ var _ColaRuntime$$ast = Cola.parse(Cola._ColaRuntime, { is_js : true }), _ColaRuntime$$hash = options.std_hash, - _this = this, + _this = this, deep = 0, required = [], required_hash = {}, exports = [], + awaitData = { + "with" : false, + "level" : null, + "indent" : -1, + "expression" : [], + "origExpression" : [], + "body" : [], + }, tt = new Cola.TreeTransformer(function(node, descend, in_list){ var newNode, props = {}, parent = this.parent(); - node = node.clone(); - + node = node.clone(); + + /* + 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); + } + /* main(){ console.log("hello world"); @@ -1036,6 +1084,23 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ }); } else + /* + await a + + to + + _ColaRuntime$$fulfilled + + */ + if(node instanceof Cola.AST_UnaryPrefix && node.operator == 'await'){ + awaitData.with = true; + awaitData.expression.push(node.expression); + + node = new Cola.AST_SymbolRef({ name: "_ColaRuntime$$fulfilled" }); + + awaitData.origExpression.push(node); + } else + /* arr[] = 123 @@ -1292,46 +1357,6 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ }); } 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) @@ -3259,13 +3284,89 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ if (node instanceof Cola.AST_Defun && node.mods && node.mods.indexOf("export") != -1) exports.push(node.name.name); - + + ++deep; if(node instanceof Array){ _this = this; node.forEach(function(nd){ nd._descend(nd, _this); }) } else node._descend(node, this); + --deep; + + if (awaitData.level !== null && awaitData.level > deep) { + awaitData.level = null; + awaitData.indent = -1; + awaitData.body = []; + } + + if (parent instanceof Cola.AST_Scope && awaitData.with) { + _ColaRuntime$$hash[Cola._ColaRuntime$$arguments_def.i] = true; + _ColaRuntime$$hash[Cola._ColaRuntime$$promise.i] = true; + awaitData.level = deep; + awaitData.indent++; + + awaitData.with = false; + if (!(node instanceof Array)) node = [node]; + awaitData.body[awaitData.indent] = node; + node = []; + + node.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" }) + })] + })); + + var awaitBody = (awaitData.body[awaitData.indent].unshift(new Cola.AST_SimpleStatement({ + body : new Cola.AST_Assign({ + left : new Cola.AST_SymbolRef({ name: "arguments" }), + operator : "=", + right : new Cola.AST_SymbolRef({ name: "_ColaRuntime$$arguments" }) + }) + })), awaitData.body[awaitData.indent]); + + awaitData.expression = awaitData.expression.reverse(); + awaitData.origExpression = awaitData.origExpression.reverse(); + + awaitData.expression.forEach(function(expression, i) { + awaitBody = new Cola.AST_SimpleStatement({ body : new Cola.AST_Call({ + args : [expression, new Cola.AST_Function({ + body : awaitBody instanceof Array + ? awaitBody : [awaitBody], + argnames : [ + new Cola.AST_SymbolFunarg({ name : "_ColaRuntime$$fulfilled" + i }), + new Cola.AST_SymbolFunarg({ name : "_ColaRuntime$$rejected" + i }) + ] + }), new Cola.AST_This], + expression : new Cola.AST_SymbolRef({ name: "_ColaRuntime$$promise" }) + })}); + awaitData.origExpression[i].name += i; + }); + + node.push(awaitBody); + awaitData.expression = []; + awaitData.origExpression = []; + + if (awaitData.level !== null && awaitData.level == deep && awaitData.indent > 0) { + Array.prototype.push + .apply(awaitData.body[awaitData.indent - 1], node); + + return false; + } + } else + + if (awaitData.level !== null && awaitData.level == deep) { + if (node) + Array.prototype.push + .apply(awaitData.body[awaitData.indent], node instanceof Array + ? node : [node]); + + return false; + } return node; });