Skip to content

Commit 8c52e3a

Browse files
committed
[lexer,parser,interpreter] Remove elif from the language.
While doing some research on how `case` and `cond` could be implemented, I noticed that Elixir doesn't have a singular `else if` construct. I can't be sure of the exact reason for this, but at the same time, I noticed that any use of an `else if` construct could easily be replaced with a `cond`, and would actually be shorter and more legible. Because of that, I'm deciding to remove the corresponding `elif` construct from Myst, under the assumption that either `case` or `cond` will be implemented next.
1 parent aa01532 commit 8c52e3a

File tree

11 files changed

+13
-148
lines changed

11 files changed

+13
-148
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ The following is a roadmap for a `v0.1.0` of Myst. It is _not necessarily_ compr
2424
- [X] strings
2525
- [X] symbols
2626
- [ ] Flow control and dependency loading
27-
- [X] `if`/`unless`/`elif`/`else`
27+
- [X] `if`/`unless`/`else`
2828
- [X] `while`/`until`
2929
- [ ] `break`
3030
- [ ] `return`

SYNTAX.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ begin
3535
break
3636
continue
3737
def
38-
elif
3938
else
4039
end
4140
ensure
@@ -270,10 +269,8 @@ Myst's flow control structures are almost directly taken from Ruby. However, the
270269
# conditions as blocks
271270
if a
272271
# only if `a` is truthy
273-
elif b
274-
# only if `a` is falsey and `b` is truthy
275272
else
276-
# only if neither of the above runs
273+
# only if the above does not run
277274
end
278275
unless b
279276
# only if `b` is falsey

examples/conditionals.mt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ def fib(n)
1515
end
1616
end
1717

18-
puts(fib(10))
18+
IO.puts(fib(10))
1919

2020
unless 1 == 2
21-
puts("1 is not 2")
21+
IO.puts("1 is not 2")
2222
end
2323

2424
x = 5
2525

2626
until x == 0
27-
puts(x)
27+
IO.puts(x)
2828
x = x - 1
2929
end
3030

3131
while fib(x) < 10
32-
puts(fib(x))
32+
IO.puts(fib(x))
3333
x = x + 1
3434
end

spec/syntax/elif_expression_spec.cr

Lines changed: 0 additions & 66 deletions
This file was deleted.

spec/syntax/else_expression_spec.cr

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -56,59 +56,7 @@ describe "Else Expression" do
5656
assert_invalid %q(
5757
if false
5858
else
59-
elif wrong
60-
end
61-
)
62-
end
63-
end
64-
65-
66-
describe "when following an `elif` block" do
67-
it "is valid with an empty body" do
68-
assert_valid %q(
69-
if false
70-
elif false
71-
else
72-
end
73-
)
74-
end
75-
76-
it "is valid with a single-expression body" do
77-
assert_valid %q(
78-
if true
79-
elif true
80-
else
81-
1 + 1
82-
end
83-
)
84-
end
85-
86-
it "is valid with a multi-expression body" do
87-
assert_valid %q(
88-
if true
89-
elif true
90-
else
91-
a = 1
92-
b = 1
93-
a + b
94-
end
95-
)
96-
end
97-
98-
it "allows a single expression immediately following the `else`" do
99-
assert_valid %q(
10059
if false
101-
elif false
102-
else wrong end
103-
)
104-
end
105-
106-
it "is invalid with a succeeding conditional block" do
107-
assert_invalid %q(
108-
if false
109-
elif wrong
110-
else
111-
elif wrong
11260
end
11361
)
11462
end
@@ -155,7 +103,7 @@ describe "Else Expression" do
155103
assert_invalid %q(
156104
unless false
157105
else
158-
elif wrong
106+
if wrong
159107
end
160108
)
161109
end

spec/syntax/keyword_spec.cr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ describe "Tokenizer" do
1515
"do" => Token::Type::DO,
1616
"if" => Token::Type::IF,
1717
"unless" => Token::Type::UNLESS,
18-
"elif" => Token::Type::ELIF,
1918
"else" => Token::Type::ELSE,
2019
"while" => Token::Type::WHILE,
2120
"until" => Token::Type::UNTIL,

src/myst/ast.cr

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ module Myst
120120
body : Block,
121121
alternative : Node?
122122

123-
ast_node ElifExpression,
124-
condition : Node,
125-
body : Block,
126-
alternative : Node?
127-
128123
ast_node ElseExpression,
129124
body : Block
130125

src/myst/interpreter/visitors/conditionals.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class Myst::Interpreter
2-
def visit(node : AST::IfExpression | AST::ElifExpression)
2+
def visit(node : AST::IfExpression)
33
recurse(node.condition.not_nil!)
44
if stack.pop().truthy?
55
recurse(node.body)

src/myst/parser.cr

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,14 @@ module Myst
271271
when Token::Type::IF
272272
advance
273273
condition = parse_expression
274-
body = parse_block([Token::Type::ELSE, Token::Type::ELIF])
274+
body = parse_block([Token::Type::ELSE])
275275
alternative = parse_conditional_alternative
276276
expect(Token::Type::END)
277277
return AST::IfExpression.new(condition, body, alternative)
278278
when Token::Type::UNLESS
279279
advance
280280
condition = parse_expression
281-
body = parse_block([Token::Type::ELSE, Token::Type::ELIF])
281+
body = parse_block([Token::Type::ELSE])
282282
alternative = parse_conditional_alternative
283283
expect(Token::Type::END)
284284
return AST::UnlessExpression.new(condition, body, alternative)
@@ -289,20 +289,14 @@ module Myst
289289

290290
def parse_conditional_alternative
291291
case current_token.type
292-
when Token::Type::ELIF
293-
advance
294-
condition = parse_expression
295-
body = parse_block([Token::Type::ELSE, Token::Type::ELIF])
296-
alternative = parse_conditional_alternative
297-
return AST::ElifExpression.new(condition, body, alternative)
298292
when Token::Type::ELSE
299293
advance
300294
body = parse_block
301295
return AST::ElseExpression.new(body)
302296
when Token::Type::END
303297
return nil
304298
else
305-
raise ParseError.new(current_token, [Token::Type::ELSE, Token::Type::ELIF, Token::Type::END])
299+
raise ParseError.new(current_token, [Token::Type::ELSE, Token::Type::END])
306300
end
307301
end
308302

src/myst/parser/token.cr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ module Myst
1616
DO # do
1717
IF # if
1818
UNLESS # unless
19-
ELIF # elif
2019
ELSE # else
2120
WHILE # while
2221
UNTIL # until
@@ -68,7 +67,7 @@ module Myst
6867

6968

7069
def self.keywords
71-
[REQUIRE, INCLUDE, MODULE, DEF, DO, IF, UNLESS, ELIF, ELSE, END, WHILE, UNTIL, TRUE, FALSE]
70+
[REQUIRE, INCLUDE, MODULE, DEF, DO, IF, UNLESS, ELSE, END, WHILE, UNTIL, TRUE, FALSE]
7271
end
7372

7473

@@ -81,7 +80,6 @@ module Myst
8180
"do" => DO,
8281
"if" => IF,
8382
"unless" => UNLESS,
84-
"elif" => ELIF,
8583
"else" => ELSE,
8684
"end" => END,
8785
"while" => WHILE,

src/myst/visitors/tree_dump_visitor.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ module Myst
5454
recurse [node.pattern, node.value]
5555
end
5656

57-
visit AST::IfExpression, AST::UnlessExpression, AST::ElifExpression do
57+
visit AST::IfExpression, AST::UnlessExpression do
5858
io << "#{node.type_name}\n".colorize(:blue)
5959
recurse [node.condition, node.body, node.alternative].compact
6060
end

0 commit comments

Comments
 (0)