self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
}
- /// Returns `None` if the expression is `#[cfg]`d out.
+ /// Returns `None` if and only if the expression is `#[cfg]`d out.
fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
let syntax_ptr = AstPtr::new(&expr);
self.check_cfg(&expr)?;
if self.check_cfg(&stmt).is_none() {
return;
}
-
+ let has_semi = stmt.semicolon_token().is_some();
// Note that macro could be expended to multiple statements
if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
let macro_ptr = AstPtr::new(&m);
statements.statements().for_each(|stmt| this.collect_stmt(stmt));
if let Some(expr) = statements.expr() {
let expr = this.collect_expr(expr);
- this.statements_in_scope.push(Statement::Expr(expr));
+ this.statements_in_scope
+ .push(Statement::Expr { expr, has_semi });
}
}
None => {
let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
- this.statements_in_scope.push(Statement::Expr(expr));
+ this.statements_in_scope.push(Statement::Expr { expr, has_semi });
}
},
);
} else {
let expr = self.collect_expr_opt(stmt.expr());
- self.statements_in_scope.push(Statement::Expr(expr));
+ self.statements_in_scope.push(Statement::Expr { expr, has_semi });
}
}
ast::Stmt::Item(item) => {
let prev_statements = std::mem::take(&mut self.statements_in_scope);
block.statements().for_each(|s| self.collect_stmt(s));
-
- let tail = block.tail_expr().map(|e| self.collect_expr(e));
+ block.tail_expr().and_then(|e| {
+ let expr = self.maybe_collect_expr(e)?;
+ Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false }))
+ });
+
+ let mut tail = None;
+ if let Some(Statement::Expr { expr, has_semi: false }) = self.statements_in_scope.last() {
+ tail = Some(*expr);
+ self.statements_in_scope.pop();
+ }
+ let tail = tail;
let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
let syntax_node_ptr = AstPtr::new(&block.into());
let expr_id = self.alloc_expr(
impl From<ast::LiteralKind> for Literal {
fn from(ast_lit_kind: ast::LiteralKind) -> Self {
match ast_lit_kind {
+ // FIXME: these should have actual values filled in, but unsure on perf impact
LiteralKind::IntNumber(lit) => {
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
return Literal::Float(Default::default(), builtin);
} else if let builtin @ Some(_) =
lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it))
{
- Literal::Int(Default::default(), builtin)
+ Literal::Int(lit.value().unwrap_or(0) as i128, builtin)
} else {
let builtin = lit.suffix().and_then(|it| BuiltinUint::from_suffix(&it));
- Literal::Uint(Default::default(), builtin)
+ Literal::Uint(lit.value().unwrap_or(0), builtin)
}
}
LiteralKind::FloatNumber(lit) => {
let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it));
Literal::Float(Default::default(), ty)
}
- LiteralKind::ByteString(_) => Literal::ByteString(Default::default()),
+ LiteralKind::ByteString(bs) => {
+ let text = bs.value().map(Vec::from).unwrap_or_else(Default::default);
+ Literal::ByteString(text)
+ }
LiteralKind::String(_) => Literal::String(Default::default()),
LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
LiteralKind::Bool(val) => Literal::Bool(val),