[K/JS] Compile Kotlin coroutines as JS generator ^KT-63038 Fixed

This commit is contained in:
Artem Kobzar
2023-12-18 17:13:07 +00:00
committed by Space Team
parent 4d07fdf97e
commit 2530cba82a
73 changed files with 2240 additions and 144 deletions
@@ -178,6 +178,7 @@ public class JsAstMapper {
return mapSetElem(node);
case TokenStream.FUNCTION:
case TokenStream.GENERATOR:
return mapFunction(node);
case TokenStream.BLOCK:
@@ -199,6 +200,9 @@ public class JsAstMapper {
case TokenStream.CONTINUE:
return mapContinue(node);
case TokenStream.YIELD:
return mapYield(node);
case TokenStream.OBJLIT:
return mapObjectLit(node);
@@ -387,6 +391,10 @@ public class JsAstMapper {
return new JsContinue(getTargetLabel(contNode));
}
private JsYield mapYield(Node yieldNode) {
return new JsYield(mapExpression(yieldNode.getFirstChild()));
}
private JsStatement mapDebuggerStatement(Node node) {
// Calls an optional method to invoke the debugger.
//
@@ -570,7 +578,7 @@ public class JsAstMapper {
public JsFunction mapFunction(Node fnNode) throws JsParserException {
int nodeType = fnNode.getType();
assert nodeType == TokenStream.FUNCTION: "Expected function node, got: " + TokenStream.tokenToName(nodeType);
assert nodeType == TokenStream.FUNCTION || nodeType == TokenStream.GENERATOR: "Expected function node, got: " + TokenStream.tokenToName(nodeType);
Node fromFnNameNode = fnNode.getFirstChild();
Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild();
Node fromBodyNode = fnNode.getFirstChild().getNext().getNext();
@@ -586,6 +594,10 @@ public class JsAstMapper {
JsFunction toFn = scopeContext.enterFunction();
toFn.setName(functionName);
if (nodeType == TokenStream.GENERATOR) {
toFn.getModifiers().add(JsFunction.Modifier.GENERATOR);
}
while (fromParamNode != null) {
String fromParamName = fromParamNode.getString();
JsName name = scopeContext.localNameFor(fromParamName);
@@ -180,6 +180,19 @@ public class IRFactory {
}
}
/**
* Yield (possibly with expression)
*/
public Node createYield(Node expression, CodePosition location) {
Node result = new Node(TokenStream.YIELD, location);
if (expression == null) {
return result;
} else {
result.addChildToBack(expression);
return result;
}
}
/**
* debugger
*/
@@ -197,11 +210,11 @@ public class IRFactory {
return new Node(TokenStream.BLOCK, location);
}
public Node createFunction(Node name, Node args, Node statements, CodePosition location) {
public Node createFunction(Node name, Node args, Node statements, boolean isGenerator, CodePosition location) {
if (name == null) {
name = createName("", location);
}
return new Node(TokenStream.FUNCTION, name, args, statements, location);
return new Node(isGenerator ? TokenStream.GENERATOR : TokenStream.FUNCTION, name, args, statements, location);
}
/**
@@ -186,6 +186,10 @@ public class Parser {
Node nameNode;
Node memberExprNode = null;
// For generators
boolean isGenerator = ts.matchToken(TokenStream.MUL);
if (ts.matchToken(TokenStream.NAME)) {
nameNode = nf.createName(ts.getString(), basePosition);
if (!ts.matchToken(TokenStream.LP)) {
@@ -248,7 +252,7 @@ public class Parser {
functionNumber = savedFunctionNumber;
}
Node pn = nf.createFunction(nameNode, args, body, basePosition);
Node pn = nf.createFunction(nameNode, args, body, isGenerator, basePosition);
if (memberExprNode != null) {
pn = nf.createBinary(TokenStream.ASSIGN, TokenStream.NOP, memberExprNode, pn, basePosition);
}
@@ -897,6 +901,9 @@ public class Parser {
CodePosition position = ts.tokenPosition;
switch (tt) {
case TokenStream.YIELD:
return nf.createUnary(TokenStream.YIELD, ts.getOp(), unaryExpr(ts), position);
case TokenStream.UNARYOP:
return nf.createUnary(TokenStream.UNARYOP, ts.getOp(), unaryExpr(ts), position);
@@ -254,6 +254,9 @@ public class TokenStream {
LAST_TOKEN = 147,
NUMBER_INT = 148,
GENERATOR = 149,
YIELD = 150,
// This value is only used as a return value for getTokenHelper,
// which is only called from getToken and exists to avoid an excessive
// recursion problem if a number of lines in a row are comments.
@@ -390,6 +393,7 @@ public class TokenStream {
case FOR: return "for";
case BREAK: return "break";
case CONTINUE: return "continue";
case YIELD: return "yield";
case VAR: return "var";
case WITH: return "with";
case CATCH: return "catch";
@@ -456,6 +460,7 @@ public class TokenStream {
KEYWORDS.put("break", BREAK);
KEYWORDS.put("case", CASE);
KEYWORDS.put("continue", CONTINUE);
KEYWORDS.put("yield", YIELD);
KEYWORDS.put("default", DEFAULT);
KEYWORDS.put("delete", DELPROP);
KEYWORDS.put("do", DO);