Skip to content

Commit eb1798a

Browse files
changed blocks
removed terminated flag added tail_expr field for blocks
1 parent 7885c0d commit eb1798a

6 files changed

Lines changed: 36 additions & 41 deletions

File tree

src/semantics/resolved_ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct Stmt {
1717
#[derive(Debug, Clone, PartialEq)]
1818
pub enum StmtKind {
1919
Let { sym: SymbolId, value: Expr },
20-
Expr { expr: Expr, terminated: bool },
20+
Expr(Expr),
2121
Empty,
2222
Error,
2323
}
@@ -33,6 +33,6 @@ pub enum ExprKind {
3333
Number { value: f64, unit: Option<Unit> },
3434
Identifier { sym: SymbolId },
3535
BinaryOp { op: BinaryOp, left: Box<Expr>, right: Box<Expr> },
36-
Block { stmts: Vec<Stmt> },
36+
Block { stmts: Vec<Stmt>, tail_expr: Option<Box<Expr>> },
3737
Error,
3838
}

src/semantics/resolver.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,7 @@ impl<'d, D: DiagnosticSink> Resolver<'d, D> {
195195
let sym = self.scopes.lookup(self.current_scope, name).unwrap();
196196
r::StmtKind::Let { sym, value }
197197
}
198-
p::StmtKind::Expr { expr, terminated } => r::StmtKind::Expr {
199-
expr: self.resolve_expr(expr),
200-
terminated
201-
},
198+
p::StmtKind::Expr(expr) => r::StmtKind::Expr(self.resolve_expr(expr)),
202199
p::StmtKind::Empty => r::StmtKind::Empty,
203200
p::StmtKind::Error => r::StmtKind::Error,
204201
};
@@ -220,7 +217,7 @@ impl<'d, D: DiagnosticSink> Resolver<'d, D> {
220217
let right = Box::new(self.resolve_expr(*right));
221218
r::ExprKind::BinaryOp { op, left, right }
222219
}
223-
p::ExprKind::Block { stmts } => {
220+
p::ExprKind::Block { stmts, tail_expr } => {
224221
let outer = self.current_scope;
225222
self.current_scope = self.scopes.new_scope(Some(outer));
226223

@@ -232,9 +229,11 @@ impl<'d, D: DiagnosticSink> Resolver<'d, D> {
232229
.into_iter()
233230
.map(|stmt| self.resolve_stmt(stmt))
234231
.collect();
232+
233+
let resolved_expr = tail_expr.map(|expr| self.resolve_expr(expr));
235234

236235
self.current_scope = outer;
237-
r::ExprKind::Block { stmts: resolved_stmts }
236+
r::ExprKind::Block { stmts: resolved_stmts, tail_expr: resolved_expr }
238237
}
239238
p::ExprKind::Error => r::ExprKind::Error,
240239
};
@@ -312,14 +311,14 @@ mod tests {
312311
span: Span { start: 0, end: 10 }
313312
},
314313
p::Stmt {
315-
kind: p::StmtKind::Expr { expr: p::Expr {
314+
kind: p::StmtKind::Expr(p::Expr {
316315
kind: p::ExprKind::BinaryOp {
317316
op: p::BinaryOp::Add,
318317
left: Box::new(p::Expr { kind: p::ExprKind::Identifier { name: "x" }, span: Span::new(11, 12) }),
319318
right: Box::new(p::Expr { kind: p::ExprKind::Identifier { name: "x" }, span: Span::new(15, 16) }),
320319
},
321320
span: Span::new(11, 16)
322-
}, terminated: true },
321+
}),
323322
span: Span::new(11, 17)
324323
}
325324
],
@@ -339,14 +338,14 @@ mod tests {
339338
span: Span { start: 0, end: 10 }
340339
},
341340
r::Stmt {
342-
kind: r::StmtKind::Expr { expr: r::Expr {
341+
kind: r::StmtKind::Expr(r::Expr {
343342
kind: r::ExprKind::BinaryOp {
344343
op: r::BinaryOp::Add,
345344
left: Box::new(r::Expr { kind: r::ExprKind::Identifier { sym: SymbolId(0) }, span: Span::new(11, 12) }),
346345
right: Box::new(r::Expr { kind: r::ExprKind::Identifier { sym: SymbolId(0) }, span: Span::new(15, 16) }),
347346
},
348347
span: Span::new(11, 16)
349-
}, terminated: true },
348+
}),
350349
span: Span::new(11, 17)
351350
}
352351
],

src/semantics/typechecker.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ impl TypeChecker<'_> {
5858
self.symbols.get_mut(sym).ty = Some(value.ty.clone());
5959
t::StmtKind::Let { sym, value }
6060
}
61-
r::StmtKind::Expr { expr, terminated } => t::StmtKind::Expr {
62-
expr: self.infer(expr),
63-
terminated
64-
},
61+
r::StmtKind::Expr(expr) => t::StmtKind::Expr(self.infer(expr)),
6562
r::StmtKind::Empty => t::StmtKind::Empty,
6663
r::StmtKind::Error => t::StmtKind::Error,
6764
};
@@ -103,22 +100,21 @@ impl TypeChecker<'_> {
103100
}
104101
}
105102

106-
r::ExprKind::Block { stmts } => {
103+
r::ExprKind::Block { stmts, tail_expr } => {
107104
let typed_stmts: Vec<t::Stmt> = stmts
108105
.into_iter()
109106
.map(|stmt| self.check_stmt(stmt))
110107
.collect();
111108

112-
let ty = match typed_stmts.first() {
113-
Some(t::Stmt {
114-
kind: t::StmtKind::Expr { expr, terminated: false },
115-
..
116-
}) => expr.ty.clone(),
117-
_ => Type::Unit,
118-
};
109+
let typed_expr = tail_expr.map(|expr| self.infer(expr));
110+
111+
let ty = typed_expr.map(|e| e.ty.clone()).unwrap_or(Type::Unit);
119112

120113
t::Expr {
121-
kind: t::ExprKind::Block { stmts: typed_stmts },
114+
kind: t::ExprKind::Block {
115+
stmts: typed_stmts,
116+
tail_expr: typed_expr,
117+
},
122118
span: expr.span,
123119
ty,
124120
}

src/semantics/typed_ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct Stmt {
2020
#[derive(Debug, Clone, PartialEq)]
2121
pub enum StmtKind {
2222
Let { sym: SymbolId, value: Expr },
23-
Expr { expr: Expr, terminated: bool },
23+
Expr(Expr),
2424
Empty,
2525
Error,
2626
}
@@ -37,6 +37,6 @@ pub enum ExprKind {
3737
Number { value: f64, unit: Option<Unit> },
3838
Identifier { sym: SymbolId },
3939
BinaryOp { op: BinaryOp, left: Box<Expr>, right: Box<Expr> },
40-
Block { stmts: Vec<Stmt> },
40+
Block { stmts: Vec<Stmt>, tail_expr: Option<Box<Expr>> },
4141
Error,
4242
}

src/syntax/parsed_ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub struct Stmt<'a> {
1515
#[derive(Debug, Clone, PartialEq)]
1616
pub enum StmtKind<'a> {
1717
Let { name: &'a str, value: Expr<'a> },
18-
Expr { expr: Expr<'a>, terminated: bool },
18+
Expr(Expr<'a>),
1919
Empty,
2020
Error,
2121
}
@@ -31,7 +31,7 @@ pub enum ExprKind<'a> {
3131
Number { value: f64, unit: Option<Unit> },
3232
Identifier { name: &'a str },
3333
BinaryOp { op: BinaryOp, left: Box<Expr<'a>>, right: Box<Expr<'a>> },
34-
Block { stmts: Vec<Stmt<'a>> },
34+
Block { stmts: Vec<Stmt<'a>>, tail_expr: Option<Box<Expr<'a>>> },
3535
Error,
3636
}
3737

src/syntax/parser.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,25 +148,18 @@ impl<'a, 'd, D: DiagnosticSink> Parser<'a, 'd, D> {
148148

149149
fn parse_expr_stmt(&mut self) -> Stmt<'a> {
150150
let expr = self.parse_expression(0);
151-
let terminator = match self.expect_terminator();
151+
let terminator = self.expect_terminator();
152152

153153
let span = terminator.map(|t| t.span.concat(&expr.span)).unwrap_or(expr.span);
154154

155-
Stmt { kind: StmtKind::Expr { expr, terminated: terminator.is_some() }, span }
155+
Stmt { kind: StmtKind::Expr(expr), span }
156156
}
157157

158158
fn expect_terminator(&mut self) -> Option<Token> {
159-
let save = self.stream.get_position();
160-
self.skip_newlines();
161159
match self.peek_token() {
162-
Token { kind: TokenKind::Semicolon, .. } => self.stream.next(),
163-
Token { kind: TokeKind::RBrace | TokenKind::EOF, .. } => None,
160+
Token { kind: TokenKind::Semicolon | TokenKind::Newline, .. } => self.stream.next(),
161+
Token { kind: TokenKind::RBrace | TokenKind::EOF, .. } => None,
164162
other => {
165-
// skipped at least one newline
166-
if save != self.stream.get_position() {
167-
self.stream.set_position(save);
168-
return self.stream.next();
169-
}
170163
self.diags.emit(
171164
Diagnostic::error("missing statement terminator")
172165
.with_span(other.span)
@@ -326,8 +319,10 @@ impl<'a, 'd, D: DiagnosticSink> Parser<'a, 'd, D> {
326319
fn parse_block(&mut self, tok: Token) -> Expr<'a> {
327320
let mut stmts = Vec::new();
328321

322+
self.skip_newlines();
329323
while !matches!(self.peek_token().kind, TokenKind::RBrace | TokenKind::EOF) {
330324
stmts.push(self.parse_statement());
325+
self.skip_newlines();
331326
}
332327

333328
let closing_tok = match self.peek_token() {
@@ -347,8 +342,13 @@ impl<'a, 'd, D: DiagnosticSink> Parser<'a, 'd, D> {
347342

348343
let span = closing_tok.map(|t| t.span.concat(&tok.span)).unwrap_or(tok.span);
349344

345+
let tail_expr = match stmts.pop() {
346+
Some(Stmt { kind: StmtKind::Expr(expr), span }) if expr.span != span => Some(Box::new(expr)),
347+
other => { stmts.push(other); None }
348+
}
349+
350350
Expr {
351-
kind: ExprKind::Block { stmts },
351+
kind: ExprKind::Block { stmts, tail_expr },
352352
span,
353353
}
354354
}

0 commit comments

Comments
 (0)