feat: implement async generators
This commit is contained in:
parent
8a0d309f0f
commit
7a745faacf
@ -20,7 +20,7 @@ interface FunctionConstructor extends Function {
|
|||||||
asyncGenerator<ArgsT extends any[], RetT>(
|
asyncGenerator<ArgsT extends any[], RetT>(
|
||||||
func: (await: <T>(val: T) => Awaited<T>, _yield: <T>(val: T) => void) => (...args: ArgsT) => RetT
|
func: (await: <T>(val: T) => Awaited<T>, _yield: <T>(val: T) => void) => (...args: ArgsT) => RetT
|
||||||
): (...args: ArgsT) => AsyncGenerator<RetT>;
|
): (...args: ArgsT) => AsyncGenerator<RetT>;
|
||||||
generator<ArgsT extends any[], T, RetT, TNext>(
|
generator<ArgsT extends any[], T = unknown, RetT = unknown, TNext = unknown>(
|
||||||
func: (_yield: <T>(val: T) => TNext) => (...args: ArgsT) => RetT
|
func: (_yield: <T>(val: T) => TNext) => (...args: ArgsT) => RetT
|
||||||
): (...args: ArgsT) => Generator<T, RetT, TNext>;
|
): (...args: ArgsT) => Generator<T, RetT, TNext>;
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ setProps(Function.prototype, {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
setProps(Function, {
|
setProps(Function, {
|
||||||
async<ArgsT extends any[], RetT>(func: (_yield: <T>(val: T) => Awaited<T>) => (...args: ArgsT) => RetT) {
|
async(func) {
|
||||||
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
|
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
|
||||||
|
|
||||||
return function (this: any) {
|
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<any[], ['await' | 'yield', any]>((_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: <any>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) {
|
generator(func) {
|
||||||
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
|
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; }
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
@ -981,7 +981,14 @@ public class Parsing {
|
|||||||
}
|
}
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static ParseRes<? extends Statement> parseSimple(String filename, List<Token> tokens, int i, boolean statement) {
|
public static ParseRes<? extends Statement> parseSimple(String filename, List<Token> 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),
|
parseVariable(filename, tokens, i),
|
||||||
parseLiteral(filename, tokens, i),
|
parseLiteral(filename, tokens, i),
|
||||||
parseString(filename, tokens, i),
|
parseString(filename, tokens, i),
|
||||||
@ -997,11 +1004,6 @@ public class Parsing {
|
|||||||
parseDelete(filename, tokens, i)
|
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));
|
return ParseRes.any(res.toArray(ParseRes[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1795,7 +1797,6 @@ public class Parsing {
|
|||||||
parseContinue(filename, tokens, i),
|
parseContinue(filename, tokens, i),
|
||||||
parseBreak(filename, tokens, i),
|
parseBreak(filename, tokens, i),
|
||||||
parseDebug(filename, tokens, i),
|
parseDebug(filename, tokens, i),
|
||||||
parseValueStatement(filename, tokens, i),
|
|
||||||
parseIf(filename, tokens, i),
|
parseIf(filename, tokens, i),
|
||||||
parseWhile(filename, tokens, i),
|
parseWhile(filename, tokens, i),
|
||||||
parseSwitch(filename, tokens, i),
|
parseSwitch(filename, tokens, i),
|
||||||
@ -1804,7 +1805,8 @@ public class Parsing {
|
|||||||
parseDoWhile(filename, tokens, i),
|
parseDoWhile(filename, tokens, i),
|
||||||
parseCatch(filename, tokens, i),
|
parseCatch(filename, tokens, i),
|
||||||
parseCompound(filename, tokens, i),
|
parseCompound(filename, tokens, i),
|
||||||
parseFunction(filename, tokens, i, true)
|
parseFunction(filename, tokens, i, true),
|
||||||
|
parseValueStatement(filename, tokens, i)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user