Resolve variables at parse time#1429
Conversation
b659dc3 to
ccfff3d
Compare
09e24f7 to
059ab3c
Compare
| unless the type is intentionally overridden via `extends`. | ||
|
|
||
| [source%tested,{pkl}] | ||
| [source%parsed,{pkl}] |
There was a problem hiding this comment.
Currently, amends "..." REPL statements don't do anything. In this PR, the header still mostly does nothing, but it will throw if the amends has a relative path.
This is because our REPL logic has changed; before the AstBuilder can visit an expression, it first needs to visit the module to collect names. In the process of visiting the module, it will validate this module header.
| import com.oracle.truffle.api.source.SourceSection; | ||
| import org.pkl.core.ast.ExpressionNode; | ||
|
|
||
| @NodeChild(value = "enclosingFrame", type = GetEnclosingFrameNode.class) |
There was a problem hiding this comment.
Optimization: move logic around finding the enclosing frame into its own node so that we don't keep re-executing the traversal logic every time we get a FrameSlotTypeException
| new ReplResponse.InternalError(new IllegalStateException("Unexpected parse result"))); | ||
| } | ||
| } catch (VmException e) { | ||
| // TODO: patch stack trace for constants |
There was a problem hiding this comment.
This is an existing TODO, not newly introduced by this PR (GitHub isn't able to track that the code just got shuffled around).
| * A wrapper for Truffle's {@link FrameDescriptor.Builder}, but also lets us find the slot of a | ||
| * given {@link Identifier}. | ||
| */ | ||
| public class FrameDescriptorBuilder { |
There was a problem hiding this comment.
When we resolve frame slot variables, we need to know the names of each slot. The FrameDescriptor.Builder API keeps these names inside private fields. So, we use our own builder abstraction that exposes the slot names.
059ab3c to
495ff89
Compare
| import org.pkl.parser.Parser; | ||
| import org.pkl.parser.syntax.Modifier.ModifierValue; | ||
|
|
||
| public final class BaseModuleMemberRegistryGenerator { |
There was a problem hiding this comment.
This generates a class called BaseModuleMembers, and gets called as part of java compilation.
This generates a class that looks something like:
public final class BaseModuleMembers {
private BaseModuleMembers() {
}
public static boolean hasProperty(String name) {
return switch (name) {
case "AlsoKnownAs",
"Annotation",
"Any",
"BaseValueRenderer",
"Boolean",
"Bytes",
"BytesRenderer",
"Char",
"Charset",
"Class",
"Collection",
"Comparable",
"ConvertProperty",
// etc
"YamlRenderer" -> true;
default -> false;
}
}
}This is used by SymbolTable to figure out if some name is defined on the base module or not.
This is much faster than looking up members on BaseModule.getModule().
f0daa78 to
78b689a
Compare
78b689a to
c5941de
Compare
This replaces
ResolveVariableNodeandResolveMethodNodewith their resolution. When we build the truffle node tree, we determine whether names resolve to:Then, we use this information to directly construct the underlying nodes (
ReadPropertyNode,ReadLocalPropertyNode, etc).Additionally,
AstBuilderdetermines whether the property access must be const or not.This introduces a
BaseModuleMembersregistry, which gets generated as part of Java compilation.Closes #1154
NOTE: this introduces a regression in the REPL. Currently, this works:
Now,
:f fooproduces an error, becausebazis resolved to implicit this.