From 7a745faacf5fb494364df32a8de2c512cfec71ef Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 26 Aug 2023 00:41:28 +0300 Subject: [PATCH] feat: implement async generators --- lib/values/function.ts | 51 +++++++++++++++++-- .../topchetoeu/jscript/parsing/Parsing.java | 18 ++++--- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/lib/values/function.ts b/lib/values/function.ts index 577c95d..52bbf43 100644 --- a/lib/values/function.ts +++ b/lib/values/function.ts @@ -20,7 +20,7 @@ interface FunctionConstructor extends Function { asyncGenerator( func: (await: (val: T) => Awaited, _yield: (val: T) => void) => (...args: ArgsT) => RetT ): (...args: ArgsT) => AsyncGenerator; - generator( + generator( func: (_yield: (val: T) => TNext) => (...args: ArgsT) => RetT ): (...args: ArgsT) => Generator; } @@ -90,7 +90,7 @@ setProps(Function.prototype, { }, }); setProps(Function, { - async(func: (_yield: (val: T) => Awaited) => (...args: ArgsT) => RetT) { + async(func) { if (typeof func !== 'function') throw new TypeError('Expected func to be function.'); return function (this: any) { @@ -121,8 +121,53 @@ setProps(Function, { }); }; }, + asyncGenerator(func) { + if (typeof func !== 'function') throw new TypeError('Expected func to be function.'); + + + return function(this: any) { + const gen = Function.generator((_yield) => func( + val => _yield(['await', val]) as any, + val => _yield(['yield', val]) + )).apply(this, arguments as any); + + const next = (resolve: Function, reject: Function, type: 'none' | 'val' | 'ret' | 'err', val?: any) => { + let res; + + try { + switch (type) { + case 'val': res = gen.next(val); break; + case 'ret': res = gen.return(val); break; + case 'err': res = gen.throw(val); break; + default: res = gen.next(); break; + } + } + catch (e) { return reject(e); } + + if (res.done) return { done: true, res: res }; + else if (res.value[0] === 'await') Promise.resolve(res.value[1]).then( + v => next(resolve, reject, 'val', v), + v => next(resolve, reject, 'err', v), + ) + else resolve({ done: false, value: res.value[1] }); + }; + + return { + next() { + const args = arguments; + if (arguments.length === 0) return new Promise((res, rej) => next(res, rej, 'none')); + else return new Promise((res, rej) => next(res, rej, 'val', args[0])); + }, + return: (value) => new Promise((res, rej) => next(res, rej, 'ret', value)), + throw: (value) => new Promise((res, rej) => next(res, rej, 'err', value)), + [Symbol.asyncIterator]() { return this; } + } + } + }, generator(func) { if (typeof func !== 'function') throw new TypeError('Expected func to be function.'); - return internals.makeGenerator(func); + return Object.assign(internals.makeGenerator(func), { + [Symbol.iterator]() { return this; } + }); } }) \ No newline at end of file diff --git a/src/me/topchetoeu/jscript/parsing/Parsing.java b/src/me/topchetoeu/jscript/parsing/Parsing.java index 6c816dc..dde815b 100644 --- a/src/me/topchetoeu/jscript/parsing/Parsing.java +++ b/src/me/topchetoeu/jscript/parsing/Parsing.java @@ -981,7 +981,14 @@ public class Parsing { } @SuppressWarnings("all") public static ParseRes parseSimple(String filename, List tokens, int i, boolean statement) { - var res = new ArrayList<>(List.of( + var res = new ArrayList<>(); + + if (!statement) { + res.add(parseObject(filename, tokens, i)); + res.add(parseFunction(filename, tokens, i, false)); + } + + res.addAll(List.of( parseVariable(filename, tokens, i), parseLiteral(filename, tokens, i), parseString(filename, tokens, i), @@ -997,11 +1004,6 @@ public class Parsing { parseDelete(filename, tokens, i) )); - if (!statement) { - res.add(parseObject(filename, tokens, i)); - res.add(parseFunction(filename, tokens, i, false)); - } - return ParseRes.any(res.toArray(ParseRes[]::new)); } @@ -1795,7 +1797,6 @@ public class Parsing { parseContinue(filename, tokens, i), parseBreak(filename, tokens, i), parseDebug(filename, tokens, i), - parseValueStatement(filename, tokens, i), parseIf(filename, tokens, i), parseWhile(filename, tokens, i), parseSwitch(filename, tokens, i), @@ -1804,7 +1805,8 @@ public class Parsing { parseDoWhile(filename, tokens, i), parseCatch(filename, tokens, i), parseCompound(filename, tokens, i), - parseFunction(filename, tokens, i, true) + parseFunction(filename, tokens, i, true), + parseValueStatement(filename, tokens, i) ); }