Skip to content

Commit c8a5b1b

Browse files
committed
[Tolk] Fire an error on using ++/-- operators
Before, `++i` was valid (and did nothing, --1 is 1), probably unexpected
1 parent 3feba11 commit c8a5b1b

File tree

7 files changed

+59
-11
lines changed

7 files changed

+59
-11
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
fun main() {
3+
var z = 5;
4+
++z;
5+
return z;
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr Tolk has no increment operator
11+
@stderr hint: use `i += 1`, not `i++`
12+
*/
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
struct A {
3+
f: int;
4+
}
5+
6+
fun main(a: A) {
7+
a.f--;
8+
}
9+
10+
/**
11+
@compilation_should_fail
12+
@stderr Tolk has no decrement operator
13+
@stderr hint: use `i -= 1`, not `i--`
14+
*/

tolk-tester/tests/no-spaces.tolk

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ fun just10(): int { return int10; }
44
fun eq(v: int): int { return`v` }
55

66
@method_id(101,) fun `get_-1` (): int {return-1}
7-
@method_id(102,) fun `get_--1` (): int {return--1}
8-
@method_id(103,) fun `get_---1`(): int {return---1}
9-
@method_id(104,) fun `get_+++1`(): int {return+++1}
7+
@method_id(102,) fun `get_--1` (): int {return- -1}
8+
@method_id(103,) fun `get_---1`(): int {return-(-(-1))}
9+
@method_id(104,) fun `get_+++1`(): int {return+(+(+1))}
1010
@method_id(105,) fun `get_+-+1`(): int {return+-+1}
1111

1212
global `some()var`:int;
1313

1414
@method_id(110) fun `some_math`(): int {
15-
`some()var`=--6;
16-
return 1*-2*-3*-4*just10()*-5+-`some()var`+--`some()var`---`some()var`;
15+
`some()var`=- -6;
16+
return 1*-2*-3*-4*just10()*-5+-`some()var`+-(-`some()var`)-(-(-`some()var`));
1717
}
1818

1919
@method_id(111) fun `negative_nums`(a:int):int {
2020
var m$0:int=1;
2121
var m1:int=-(+0x1)*m$0;
22-
return `a`*-1*-(1)*---(1)*+just10()+-`just10`()*m1*-m1+-eq(m1)----0x1;
22+
return `a`*-1*-(1)*-(1)*+just10()+-`just10`()*m1*-m1+-eq(m1)-(-0x1);
2323
}
2424

2525
@method_id(112) fun `bitwise~ops`(flags:int):[bool,bool] {
2626
return[
27-
(just10()-3==just10()-(4)--1)|((2==2)&(eq(eq(10)) -3==just10()--13)),
27+
(just10()-3==just10()-(4)- -1)|((2==2)&(eq(eq(10)) -3==just10()-(-13))),
2828
((flags&0xFF)!=0)
2929
]
3030
}

tolk-tester/tests/numbers-tests.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fun main() {
2626
0b0 == 0,
2727
-0b1010100001010101010-0b1+0b1 == -344746,
2828
0b00001 == 1,
29-
--0b00101111101100 == 3052
29+
-(-0b00101111101100) == 3052
3030
);
3131
}
3232

tolk/ast-from-tokens.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ static void fire_error_mix_and_or_no_parenthesis(SrcLocation loc, std::string_vi
6969
"Use parenthesis to emphasize operator precedence.");
7070
}
7171

72+
// fire an error "Tolk does not have ++i operator"
73+
GNU_ATTRIBUTE_NORETURN GNU_ATTRIBUTE_COLD
74+
static void fire_error_no_increment_operator(SrcLocation loc, bool is_increment) {
75+
std::string op_name = is_increment ? "increment" : "decrement";
76+
std::string op_wrong = is_increment ? "++" : "--";
77+
std::string op_right = is_increment ? "+=" : "-=";
78+
throw ParseError(loc, std::string("Tolk has no ") + op_name + " operator\n" +
79+
"hint: use `i " + op_right + " 1`, not `i" + op_wrong + "`");
80+
}
81+
7282
// diagnose when bitwise operators are used in a probably wrong way due to tricky precedence
7383
// example: "flags & 0xFF != 0" is equivalent to "flags & 1", most likely it's unexpected
7484
// the only way to suppress this error for the programmer is to use parenthesis
@@ -847,14 +857,16 @@ static AnyExprV parse_expr100(Lexer& lex) {
847857
}
848858
}
849859

850-
// parse E(...) and E! having parsed E already (left-to-right)
860+
// parse E(...) / E! / E++ / E-- having parsed E already (left-to-right)
851861
static AnyExprV parse_fun_call_postfix(Lexer& lex, AnyExprV lhs) {
852862
while (true) {
853863
if (lex.tok() == tok_oppar) {
854864
lhs = createV<ast_function_call>(lhs->loc, lhs, parse_argument_list(lex));
855865
} else if (lex.tok() == tok_logical_not) {
856866
lex.next();
857867
lhs = createV<ast_not_null_operator>(lhs->loc, lhs);
868+
} else if (lex.tok() == tok_double_plus || lex.tok() == tok_double_minus) {
869+
fire_error_no_increment_operator(lex.cur_location(), lex.tok() == tok_double_plus);
858870
} else {
859871
break;
860872
}
@@ -865,7 +877,7 @@ static AnyExprV parse_fun_call_postfix(Lexer& lex, AnyExprV lhs) {
865877
// parse E(...) and E! (left-to-right)
866878
static AnyExprV parse_expr90(Lexer& lex) {
867879
AnyExprV res = parse_expr100(lex);
868-
if (lex.tok() == tok_oppar || lex.tok() == tok_logical_not) {
880+
if (lex.tok() == tok_oppar || lex.tok() == tok_logical_not || lex.tok() == tok_double_plus || lex.tok() == tok_double_minus) {
869881
res = parse_fun_call_postfix(lex, res);
870882
}
871883
return res;
@@ -892,7 +904,7 @@ static AnyExprV parse_expr80(Lexer& lex) {
892904
lex.unexpected("method name");
893905
}
894906
lhs = createV<ast_dot_access>(loc, lhs, v_ident, v_instantiationTs);
895-
if (lex.tok() == tok_oppar || lex.tok() == tok_logical_not) {
907+
if (lex.tok() == tok_oppar || lex.tok() == tok_logical_not || lex.tok() == tok_double_plus || lex.tok() == tok_double_minus) {
896908
lhs = parse_fun_call_postfix(lex, lhs);
897909
}
898910
}
@@ -909,6 +921,12 @@ static AnyExprV parse_expr75(Lexer& lex) {
909921
AnyExprV rhs = parse_expr75(lex);
910922
return createV<ast_unary_operator>(loc, operator_name, t, rhs);
911923
}
924+
if (t == tok_double_minus || t == tok_double_plus) {
925+
SrcLocation loc = lex.cur_location();
926+
lex.next();
927+
parse_expr75(lex);
928+
fire_error_no_increment_operator(loc, t == tok_double_plus);
929+
}
912930
return parse_expr80(lex);
913931
}
914932

tolk/lexer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ struct TolkLanguageGrammar {
523523
register_token("^=", 2, tok_set_bitwise_xor);
524524
register_token("->", 2, tok_arrow);
525525
register_token("=>", 2, tok_double_arrow);
526+
register_token("++", 2, tok_double_plus);
527+
register_token("--", 2, tok_double_minus);
526528
register_token("<=>", 3, tok_spaceship);
527529
register_token("~>>", 3, tok_rshiftR);
528530
register_token("^>>", 3, tok_rshiftC);

tolk/lexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ enum TokenType {
6464
tok_set_div,
6565
tok_mod,
6666
tok_set_mod,
67+
tok_double_plus,
68+
tok_double_minus,
6769
tok_lshift,
6870
tok_set_lshift,
6971
tok_rshift,

0 commit comments

Comments
 (0)