-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scaffolding for gradual migration to AST::Expression
#240
base: prism
Are you sure you want to change the base?
Conversation
bfecfca
to
ce43b1a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notes to self and future readers :)
static_assert(std::is_final<To>::value, "To is not final"); | ||
// static_assert(std::is_final<To>::value, "To is not final"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to temporarily disable this, since the classes we're checking against are no longer final
:/
@@ -704,6 +704,12 @@ ExpressionPtr node2TreeImpl(DesugarContext dctx, unique_ptr<parser::Node> what) | |||
if (what.get() == nullptr) { | |||
return MK::EmptyTree(); | |||
} | |||
|
|||
if (auto expr = what->getCachedDesugaredExpr()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The translations we implement in the Translator
will fill this in, which we can use here to short-circuit the logic below.
Thinking goes that once we've implemented it for all nodes, none of the code below will be used anymore, and we can just delete and inline all this stuff.
return Prism::Translator(parser, gs).translate(std::move(root)); | ||
return Prism::Translator(std::move(parser), gs).translate(std::move(root)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just saves one reference count bump on the shared_ptr
within the parser
. Won't someone think of those poor poor clock cycles?!
@@ -1,6 +1,7 @@ | |||
#ifndef SORBET_PARSER_NODE_H | |||
#define SORBET_PARSER_NODE_H | |||
|
|||
#include "ast/Trees.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needed for ast::ExpressionPtr
out << "class " << node.name << " final : public Node {" << '\n'; | ||
out << "class " << node.name << " : public Node {" << '\n'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For us to be able to make the NodeAndExpr
subclasses of these code-genned classes, they can't be final
anymore. We can undo this once our migration is done.
// Allocates a new `NodeAndExpr`, that's a subclass of `SorbetNode`, with no pre-computed `ExpressionPtr` AST. | ||
template <typename SorbetNode, typename... TArgs> unique_ptr<NodeAndExpr<SorbetNode>> make_node(TArgs &&...args) { | ||
return std::make_unique<NodeAndExpr<SorbetNode>>(std::forward<TArgs>(args)...); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This helper doesn't pull much weight, but it saved me from needing to change all the call-sites below as I tweak all the details of exactly how NodeAndExpr
works.
return translateSimpleKeyword<pm_true_node, parser::True>(node); | ||
auto sorbetNode = translateSimpleKeyword<pm_true_node, parser::True>(node); | ||
|
||
sorbetNode->cacheDesugaredExpr(MK::True(sorbetNode->loc)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a simple example of how migrating a Prism Node to an ast:ExpressionPtr
would look like. This is a simple case because it's just a leaf node, with not much other information.
We stash this expr into the NodeAndExpr sorbetNode
, which will later be consumed by either a parent Node (which uses it to construct its own AST expression), or node2TreeImpl
in Desugar.cc
.
@@ -1036,15 +1079,25 @@ std::unique_ptr<parser::Node> Translator::translateConstantPath(pm_constant_path | |||
parent = translate(node->parent); | |||
} else { // This is a fully qualified constant reference, like `::A`. | |||
pm_location_t *delimiterLoc = &node->delimiter_loc; // The location of the `::` | |||
parent = make_unique<parser::Cbase>(parser.translateLocation(delimiterLoc)); | |||
parent = make_node<parser::Cbase>(parser.translateLocation(delimiterLoc)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In retrospect, parent
is a kind of ambiguous term here. To clarify, it's a parent part of the path, e.g. the A
in A::B
, but it's a child node, as far as the Prism AST structure goes.
} | ||
|
||
sorbetNode->cacheDesugaredExpr(MK::UnresolvedConstant(sorbetNode->loc, std::move(parentExpr), sorbetName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an example where producing one Node's AST Expression requires consuming its children's AST Expressions. In this case, we can only make the AST Expression for the C
in ::A::B::C
after we've made it for its child node that represents ::A::B
::A::B:C // <- Making this guy steals the `desugarExpr` out of the `::A::B` node below it.
/ \
::A::B C
/ \
::A B
/ \
CBase A
ce43b1a
to
6248b0b
Compare
6248b0b
to
8b3ee1f
Compare
Motivation
Test plan
See included automated tests.