Skip to content

Commit

Permalink
Implement translation for PM_CONSTANT_PATH_WRITE_NODE
Browse files Browse the repository at this point in the history
  • Loading branch information
egiurleo committed Sep 11, 2024
1 parent 5bea295 commit 1f6ec1c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 19 deletions.
53 changes: 34 additions & 19 deletions parser/prism/Translator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@ std::unique_ptr<parser::Assign> Translator::translateAssignment(pm_node_t *untyp
auto node = reinterpret_cast<PrismAssignmentNode *>(untypedNode);
auto *loc = &node->base.location;

auto name = parser.resolveConstant(node->name);
auto rhs = translate(node->value);
unique_ptr<SorbetLHSNode> lhs;
unique_ptr<parser::Node> lhs;

if constexpr (std::is_same_v<PrismAssignmentNode, pm_constant_write_node>) {
auto nameLoc = &node->name_loc;
auto name = parser.resolveConstant(node->name);
auto nameRef = gs.enterNameConstant(name);

// Second argument is the scope, which is null for top-level constants
auto constNode = make_unique<parser::Const>(parser.translateLocation(loc), nullptr, nameRef);

lhs = make_unique<SorbetLHSNode>(parser.translateLocation(nameLoc), std::move(constNode->scope), nameRef);
} else if constexpr (std::is_same_v<PrismAssignmentNode, pm_constant_path_write_node>) {
auto isAssignment = true;
lhs = translateConstantPath(node->target, isAssignment);
} else {
auto name = parser.resolveConstant(node->name);
lhs = make_unique<SorbetLHSNode>(parser.translateLocation(&node->name_loc), gs.enterNameUTF8(name));
}

Expand Down Expand Up @@ -254,22 +258,11 @@ std::unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {
case PM_CONSTANT_PATH_NODE: {
// Part of a constant path, like the `A` in `A::B`. `B` is a `PM_CONSTANT_READ_NODE`
auto constantPathNode = reinterpret_cast<pm_constant_path_node *>(node);
pm_location_t *loc = &constantPathNode->base.location;

std::string_view name = parser.resolveConstant(constantPathNode->name);

std::unique_ptr<parser::Node> parent;
if (constantPathNode->parent) {
// This constant reference is chained onto another constant reference.
// E.g. if `node` is pointing to `B`, then then `A` is the `parent` in `A::B::C`.
parent = translate(constantPathNode->parent);
} else { // This is a fully qualified constant reference, like `::A`.
pm_location_t *delimiterLoc = &constantPathNode->delimiter_loc; // The location of the `::`
parent = make_unique<parser::Cbase>(parser.translateLocation(delimiterLoc));
}

return make_unique<parser::Const>(parser.translateLocation(loc), std::move(parent),
gs.enterNameConstant(name));
auto isAssignment = false;
return translateConstantPath(constantPathNode, isAssignment);
}
case PM_CONSTANT_PATH_WRITE_NODE: {
return translateAssignment<pm_constant_path_write_node, void>(node);
}
case PM_CONSTANT_READ_NODE: { // A single, unnested, non-fully qualified constant like "Foo"
auto constantReadNode = reinterpret_cast<pm_constant_read_node *>(node);
Expand Down Expand Up @@ -827,7 +820,6 @@ std::unique_ptr<parser::Node> Translator::translate(pm_node_t *node) {
case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE:
case PM_CONSTANT_PATH_OR_WRITE_NODE:
case PM_CONSTANT_PATH_TARGET_NODE:
case PM_CONSTANT_PATH_WRITE_NODE:
case PM_CONSTANT_TARGET_NODE:
case PM_DEFINED_NODE:
case PM_EMBEDDED_VARIABLE_NODE:
Expand Down Expand Up @@ -980,6 +972,29 @@ std::unique_ptr<parser::Node> Translator::translateStatements(pm_statements_node
return make_unique<parser::Begin>(parser.translateLocation(&stmtsNode->base.location), std::move(sorbetStmts));
}

std::unique_ptr<parser::Node> Translator::translateConstantPath(pm_constant_path_node *node, bool isAssignment) {
pm_location_t *loc = &node->base.location;

std::string_view name = parser.resolveConstant(node->name);

std::unique_ptr<parser::Node> parent;
if (node->parent) {
// This constant reference is chained onto another constant reference.
// E.g. if `node` is pointing to `B`, then then `A` is the `parent` in `A::B::C`.
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));
}

if (isAssignment) {
return make_unique<parser::ConstLhs>(parser.translateLocation(loc), std::move(parent),
gs.enterNameConstant(name));
} else {
return make_unique<parser::Const>(parser.translateLocation(loc), std::move(parent), gs.enterNameConstant(name));
}
}

// Translate a node that only has basic location information, and nothing else. E.g. `true`, `nil`, `it`.
template <typename PrismNode, typename SorbetNode>
std::unique_ptr<SorbetNode> Translator::translateSimpleKeyword(pm_node_t *untypedNode) {
Expand Down
1 change: 1 addition & 0 deletions parser/prism/Translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Translator final {
std::unique_ptr<parser::Node> translateCallWithBlock(pm_block_node *prismBlockNode,
std::unique_ptr<parser::Send> sendNode);
std::unique_ptr<parser::Node> translateStatements(pm_statements_node *stmtsNode, bool inlineIfSingle);
std::unique_ptr<parser::Node> translateConstantPath(pm_constant_path_node *node, bool isAssignment);
template <typename PrismNode, typename SorbetNode>
std::unique_ptr<SorbetNode> translateSimpleKeyword(pm_node_t *untypedNode);
template <typename PrismAssignmentNode, typename SorbetLHSNode>
Expand Down
32 changes: 32 additions & 0 deletions test/prism_regression/assign_to_constant_path.parse-tree.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
Begin {
stmts = [
Assign {
lhs = ConstLhs {
scope = Const {
scope = NULL
name = <C <U ConstantPath>>
}
name = <C <U RegularAssignment>>
}
rhs = Integer {
val = "1"
}
}
Assign {
lhs = ConstLhs {
scope = Const {
scope = Const {
scope = Cbase {
}
name = <C <U FullyQualified>>
}
name = <C <U ConstantPath>>
}
name = <C <U RegularAssignment>>
}
rhs = Integer {
val = "2"
}
}
]
}
5 changes: 5 additions & 0 deletions test/prism_regression/assign_to_constant_path.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# typed: false

# Regular assignment
ConstantPath::RegularAssignment = 1
::FullyQualified::ConstantPath::RegularAssignment = 2

0 comments on commit 1f6ec1c

Please sign in to comment.