Skip to content

Commit 500099e

Browse files
committed
Warn on integers in flip-flops
1 parent bbbbe85 commit 500099e

File tree

4 files changed

+50
-17
lines changed

4 files changed

+50
-17
lines changed

include/prism/diagnostic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ typedef enum {
309309
PM_WARN_DUPLICATED_HASH_KEY,
310310
PM_WARN_DUPLICATED_WHEN_CLAUSE,
311311
PM_WARN_FLOAT_OUT_OF_RANGE,
312+
PM_WARN_INTEGER_IN_FLIP_FLOP,
312313

313314
// This is the number of diagnostic codes.
314315
PM_DIAGNOSTIC_ID_LEN,

src/diagnostic.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
310310
[PM_WARN_DUPLICATED_WHEN_CLAUSE] = { "duplicated 'when' clause with line %" PRIi32 " is ignored", PM_WARNING_LEVEL_VERBOSE },
311311
[PM_WARN_EQUAL_IN_CONDITIONAL] = { "found `= literal' in conditional, should be ==", PM_WARNING_LEVEL_DEFAULT },
312312
[PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT },
313-
[PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE }
313+
[PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE },
314+
[PM_WARN_INTEGER_IN_FLIP_FLOP] = { "integer literal in flip-flop", PM_WARNING_LEVEL_DEFAULT }
314315
};
315316

316317
static inline const char *

src/prism.c

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,15 @@ pm_parser_warn_token(pm_parser_t *parser, const pm_token_t *token, pm_diagnostic
584584
pm_parser_warn(parser, token->start, token->end, diag_id);
585585
}
586586

587+
/**
588+
* Append a warning to the list of warnings on the parser using the location of
589+
* the given node.
590+
*/
591+
static inline void
592+
pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id_t diag_id) {
593+
pm_parser_warn(parser, node->location.start, node->location.end, diag_id);
594+
}
595+
587596
/******************************************************************************/
588597
/* Node-related functions */
589598
/******************************************************************************/
@@ -725,6 +734,17 @@ pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) {
725734
}
726735
}
727736

737+
/**
738+
* Check one side of a flip-flop for integer literals. If -e was not supplied at
739+
* the command-line, then warn.
740+
*/
741+
static inline void
742+
pm_flip_flop_predicate(pm_parser_t *parser, pm_node_t *node) {
743+
if (PM_NODE_TYPE_P(node, PM_INTEGER_NODE) && !(parser->command_line & PM_OPTIONS_COMMAND_LINE_E)) {
744+
pm_parser_warn_node(parser, node, PM_WARN_INTEGER_IN_FLIP_FLOP);
745+
}
746+
}
747+
728748
/**
729749
* The predicate of conditional nodes can change what would otherwise be regular
730750
* nodes into specialized nodes. For example:
@@ -735,37 +755,40 @@ pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) {
735755
* if /foo #{bar}/ => InterpolatedRegularExpressionNode becomes InterpolatedMatchLastLineNode
736756
*/
737757
static void
738-
pm_conditional_predicate(pm_node_t *node) {
758+
pm_conditional_predicate(pm_parser_t *parser, pm_node_t *node) {
739759
switch (PM_NODE_TYPE(node)) {
740760
case PM_AND_NODE: {
741761
pm_and_node_t *cast = (pm_and_node_t *) node;
742-
pm_conditional_predicate(cast->left);
743-
pm_conditional_predicate(cast->right);
762+
pm_conditional_predicate(parser, cast->left);
763+
pm_conditional_predicate(parser, cast->right);
744764
break;
745765
}
746766
case PM_OR_NODE: {
747767
pm_or_node_t *cast = (pm_or_node_t *) node;
748-
pm_conditional_predicate(cast->left);
749-
pm_conditional_predicate(cast->right);
768+
pm_conditional_predicate(parser, cast->left);
769+
pm_conditional_predicate(parser, cast->right);
750770
break;
751771
}
752772
case PM_PARENTHESES_NODE: {
753773
pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node;
754774

755775
if ((cast->body != NULL) && PM_NODE_TYPE_P(cast->body, PM_STATEMENTS_NODE)) {
756776
pm_statements_node_t *statements = (pm_statements_node_t *) cast->body;
757-
if (statements->body.size == 1) pm_conditional_predicate(statements->body.nodes[0]);
777+
if (statements->body.size == 1) pm_conditional_predicate(parser, statements->body.nodes[0]);
758778
}
759779

760780
break;
761781
}
762782
case PM_RANGE_NODE: {
763783
pm_range_node_t *cast = (pm_range_node_t *) node;
784+
764785
if (cast->left) {
765-
pm_conditional_predicate(cast->left);
786+
pm_flip_flop_predicate(parser, cast->left);
787+
pm_conditional_predicate(parser, cast->left);
766788
}
767789
if (cast->right) {
768-
pm_conditional_predicate(cast->right);
790+
pm_flip_flop_predicate(parser, cast->right);
791+
pm_conditional_predicate(parser, cast->right);
769792
}
770793

771794
// Here we change the range node into a flip flop node. We can do
@@ -3778,7 +3801,7 @@ pm_if_node_create(pm_parser_t *parser,
37783801
pm_node_t *consequent,
37793802
const pm_token_t *end_keyword
37803803
) {
3781-
pm_conditional_predicate(predicate);
3804+
pm_conditional_predicate(parser, predicate);
37823805
pm_predicate_check(parser, predicate);
37833806
pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t);
37843807

@@ -3818,7 +3841,7 @@ pm_if_node_create(pm_parser_t *parser,
38183841
*/
38193842
static pm_if_node_t *
38203843
pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *if_keyword, pm_node_t *predicate) {
3821-
pm_conditional_predicate(predicate);
3844+
pm_conditional_predicate(parser, predicate);
38223845
pm_predicate_check(parser, predicate);
38233846
pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t);
38243847

@@ -3851,7 +3874,7 @@ pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_t
38513874
static pm_if_node_t *
38523875
pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_token_t *qmark, pm_node_t *true_expression, const pm_token_t *colon, pm_node_t *false_expression) {
38533876
pm_assert_value_expression(parser, predicate);
3854-
pm_conditional_predicate(predicate);
3877+
pm_conditional_predicate(parser, predicate);
38553878
pm_predicate_check(parser, predicate);
38563879

38573880
pm_statements_node_t *if_statements = pm_statements_node_create(parser);
@@ -6161,7 +6184,7 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) {
61616184
*/
61626185
static pm_unless_node_t *
61636186
pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) {
6164-
pm_conditional_predicate(predicate);
6187+
pm_conditional_predicate(parser, predicate);
61656188
pm_predicate_check(parser, predicate);
61666189
pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
61676190

@@ -6197,7 +6220,7 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t
61976220
*/
61986221
static pm_unless_node_t *
61996222
pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *unless_keyword, pm_node_t *predicate) {
6200-
pm_conditional_predicate(predicate);
6223+
pm_conditional_predicate(parser, predicate);
62016224
pm_predicate_check(parser, predicate);
62026225
pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
62036226

@@ -16317,7 +16340,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1631716340
arguments.closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
1631816341
} else {
1631916342
receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_NOT_EXPRESSION);
16320-
pm_conditional_predicate(receiver);
16343+
pm_conditional_predicate(parser, receiver);
1632116344
pm_predicate_check(parser, receiver);
1632216345

1632316346
if (!parser->recovering) {
@@ -16328,7 +16351,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1632816351
}
1632916352
} else {
1633016353
receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_NOT_EXPRESSION);
16331-
pm_conditional_predicate(receiver);
16354+
pm_conditional_predicate(parser, receiver);
1633216355
pm_predicate_check(parser, receiver);
1633316356
}
1633416357

@@ -17006,7 +17029,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1700617029
pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER);
1700717030
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!");
1700817031

17009-
pm_conditional_predicate(receiver);
17032+
pm_conditional_predicate(parser, receiver);
1701017033
pm_predicate_check(parser, receiver);
1701117034
return (pm_node_t *) node;
1701217035
}

test/prism/command_line_test.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,13 @@ def test_command_line_l
5757
assert_equal :$/, arguments.first.name
5858
assert_equal "chomp", arguments.last.elements.first.key.unescaped
5959
end
60+
61+
def test_command_line_e
62+
result = Prism.parse("1 if 2..3")
63+
assert_equal 2, result.warnings.length
64+
65+
result = Prism.parse("1 if 2..3", command_line: "e")
66+
assert_equal 0, result.warnings.length
67+
end
6068
end
6169
end

0 commit comments

Comments
 (0)