Skip to content

Commit ea68a1f

Browse files
committed
Expand RootNodeCompiler documentation and fix: allow await as element of coroutines in async functions
1 parent 0554614 commit ea68a1f

File tree

1 file changed

+29
-7
lines changed
  • graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl

1 file changed

+29
-7
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/compiler/bytecode_dsl/RootNodeCompiler.java

+29-7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import java.util.function.Consumer;
5555
import java.util.function.Function;
5656

57+
import com.oracle.graal.python.PythonLanguage;
5758
import com.oracle.graal.python.builtins.objects.PNone;
5859
import com.oracle.graal.python.builtins.objects.code.PCode;
5960
import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis;
@@ -116,11 +117,28 @@
116117
import com.oracle.truffle.api.strings.TruffleString;
117118

118119
/**
119-
* Visitor that compiles a top-level AST (modules, functions, classes, etc.) to a root node.
120-
* Produces a {@link BytecodeDSLCompilerResult}.
120+
* Compiles a top-level AST (modules, functions, classes, etc.) to a root node. Produces a
121+
* {@link BytecodeDSLCompilerResult}. Every instance is associated with corresponding
122+
* {@link SSTNode} that represents the compiled top level AST.
121123
* <p>
122-
* This visitor is a small wrapper that calls into another visitor, {@link StatementCompiler}, to
123-
* produce bytecode for the various statements/expressions within the AST.
124+
* The class implements SST visitor, so that it can have a separate handler for each top-level AST
125+
* node type, the handler (one of the {@code visit} methods) then creates a lambda of type
126+
* {@link BytecodeParser}, which captures the node being compiled and the instance of
127+
* {@link RootNodeCompiler}, and it uses the {@link RootNodeCompiler} to do the parsing itself. The
128+
* {@link BytecodeParser} instance is passed to Truffle API
129+
* {@link PBytecodeDSLRootNodeGen#create(PythonLanguage, BytecodeConfig, BytecodeParser)} to trigger
130+
* the parsing. Truffle keeps the lambda, and it may invoke it again when it needs to perform the
131+
* parsing of the given node again.
132+
* <p>
133+
* The parsing must happen within the {@link BytecodeParser} lambda invocation.
134+
* <p>
135+
* This visitor also captures compilation unit state, such as the map of local variables, and serves
136+
* the same purpose as the {@code compiler_unit} struct in the CPython compiler. Instead of explicit
137+
* stack of compiler units, we use implicitly Java stack and new instances of
138+
* {@link RootNodeCompiler}.
139+
* <p>
140+
* For the parsing of the body of the top level AST element, this visitor delegates to the
141+
* {@link StatementCompiler}, which does all the heavy lifting.
124142
*/
125143
public final class RootNodeCompiler implements BaseBytecodeDSLVisitor<BytecodeDSLCompilerResult> {
126144
/**
@@ -144,7 +162,8 @@ public final class RootNodeCompiler implements BaseBytecodeDSLVisitor<BytecodeDS
144162
private final int[] cell2arg;
145163
private final String selfCellName;
146164

147-
// Updated idempotently
165+
// Updated idempotently: the keys are filled during first parsing, on subsequent parsings the
166+
// values will be just overridden, but no new keys should be added.
148167
private final Map<String, BytecodeLocal> locals = new HashMap<>();
149168
private final Map<String, BytecodeLocal> cellLocals = new HashMap<>();
150169
private final Map<String, BytecodeLocal> freeLocals = new HashMap<>();
@@ -212,12 +231,13 @@ private static CompilationScope getScopeType(Scope scope, SSTNode rootNode) {
212231
return CompilationScope.Lambda;
213232
} else if (rootNode instanceof AsyncFunctionDef) {
214233
return CompilationScope.AsyncFunction;
234+
} else if (rootNode instanceof DictComp || rootNode instanceof ListComp || rootNode instanceof SetComp || rootNode instanceof GeneratorExp) {
235+
return CompilationScope.Comprehension;
215236
} else {
216237
return CompilationScope.Function;
217238
}
218239
} else {
219-
assert rootNode instanceof DictComp || rootNode instanceof ListComp || rootNode instanceof SetComp || rootNode instanceof GeneratorExp;
220-
return CompilationScope.Comprehension;
240+
throw new IllegalStateException("Unexpected scope: " + scope);
221241
}
222242
}
223243

@@ -1326,6 +1346,8 @@ public Void visit(ExprTy.Attribute node) {
13261346

13271347
@Override
13281348
public Void visit(ExprTy.Await node) {
1349+
// TODO if !IS_TOP_LEVEL_AWAIT
1350+
// TODO handle await in comprehension correctly (currently, it is always allowed)
13291351
if (!scope.isFunction()) {
13301352
ctx.errorCallback.onError(ErrorType.Syntax, currentLocation, "'await' outside function");
13311353
}

0 commit comments

Comments
 (0)