Skip to content

Commit

Permalink
Add hir lower for Expr
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Mar 21, 2023
1 parent a4636d2 commit f61edbd
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 78 deletions.
25 changes: 19 additions & 6 deletions crates/hir/src/hir_def/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ use super::{Body, IdentId, IntegerId, LitKind, MaybeInvalid, PatId, PathId, Stmt
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Expr {
Lit(LitKind),
BlockExpr(Vec<StmtId>),
Block(Vec<StmtId>),
/// The first `ExprId` is the lhs, the second is the rhs.
///
/// **NOTE:** The `AugAssign` statement is desugared to a `Assign` statement
/// and a `BinOp`.
Bin(ExprId, ExprId, MaybeInvalid<BinOp>),
Un(ExprId, UnOp),
Un(ExprId, MaybeInvalid<UnOp>),
/// The first `ExprId` is the callee, the second is the arguments.
Call(ExprId, Vec<ExprId>),
Call(ExprId, Vec<CallArg>),
/// The first `ExprId` is the method receiver, the second is the method
/// name, the third is the arguments.
MethodCall(ExprId, IdentId, Vec<ExprId>),
MethodCall(ExprId, MaybeInvalid<IdentId>, Vec<CallArg>),
Path(MaybeInvalid<PathId>),
/// The record construction expression.
/// The fist `PathId` is the record type, the second is the record fields.
Record(PathId, Vec<(IdentId, ExprId)>),
Record(MaybeInvalid<PathId>, Vec<RecordField>),
Field(ExprId, FieldIndex),
Tuple(Vec<ExprId>),
/// The first `ExprId` is the indexed expression, the second is the index.
Expand All @@ -29,10 +29,11 @@ pub enum Expr {

/// The size of the rep should be the body instead of expression, becuase it
/// should be resolved as a contatnt expressison.
ArrayRepExpr(ExprId, Body),
ArrayRepExpr(ExprId, MaybeInvalid<Body>),

/// The first `ExprId` is the condition, the second is the then branch, the
/// third is the else branch.
/// In case `else if`, the third is the lowered into `If` expression.
If(ExprId, ExprId, Option<ExprId>),

/// The first `ExprId` is the scrutinee, the second is the arms.
Expand Down Expand Up @@ -128,3 +129,15 @@ pub enum UnOp {
/// `~`
BitNot,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CallArg {
pub label: Option<IdentId>,
pub expr: ExprId,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RecordField {
pub label: Option<IdentId>,
pub expr: ExprId,
}
12 changes: 6 additions & 6 deletions crates/hir/src/lower/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ impl<'db> BodyCtxt<'db> {
expr_id
}

pub(super) fn push_invalid_expr(&mut self, origin: HirOriginKind<ast::Expr>) -> ExprId {
let expr_id = self.exprs.push(None.into());
self.expr_source_map[expr_id] = HirOrigin::new(self.fid, origin);
expr_id
}

pub(super) fn push_missing_expr(&mut self) -> ExprId {
let expr_id = self.exprs.push(None.into());
self.expr_source_map[expr_id] = HirOrigin::none(self.fid);
Expand All @@ -54,12 +60,6 @@ impl<'db> BodyCtxt<'db> {
pat_id
}

pub(super) fn push_pat_opt(&mut self, pat: Pat, origin: HirOriginKind<ast::Pat>) -> PatId {
let pat_id = self.pats.push(Some(pat).into());
self.pat_source_map[pat_id] = HirOrigin::new(self.fid, origin);
pat_id
}

pub(super) fn push_missing_pat(&mut self) -> PatId {
let pat_id = self.pats.push(None.into());
self.pat_source_map[pat_id] = HirOrigin::none(self.fid);
Expand Down
189 changes: 171 additions & 18 deletions crates/hir/src/lower/expr.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,197 @@
use fe_parser2::ast;

use crate::hir_def::expr::*;
use crate::{
hir_def::{expr::*, IdentId, LitKind, MaybeInvalid, PathId, Stmt},
span::HirOriginKind,
};

use super::body::BodyCtxt;

impl Expr {
pub(super) fn push_to_body(ctxt: &mut BodyCtxt<'_>, ast: ast::Expr) -> ExprId {
todo!()
let expr = match ast.kind() {
ast::ExprKind::Lit(lit) => {
if let Some(lit) = lit.lit() {
let lit = LitKind::from_ast(ctxt.db, lit);
Self::Lit(lit)
} else {
return ctxt.push_invalid_expr(HirOriginKind::raw(&ast));
}
}

ast::ExprKind::Block(block) => {
let mut stmts = vec![];
for stmt in block.stmts() {
let stmt = Stmt::push_to_body(ctxt, stmt);
stmts.push(stmt);
}
Self::Block(stmts)
}

ast::ExprKind::Bin(bin) => {
let lhs = Self::push_to_body_opt(ctxt, bin.lhs());
let rhs = Self::push_to_body_opt(ctxt, bin.rhs());
let op = bin.op().map(|op| BinOp::from_ast(op)).into();
Self::Bin(lhs, rhs, op)
}

ast::ExprKind::Un(un) => {
let expr = Self::push_to_body_opt(ctxt, un.expr());
let op = un.op().map(|op| UnOp::from_ast(op)).into();
Self::Un(expr, op)
}

ast::ExprKind::Call(call) => {
let callee = Self::push_to_body_opt(ctxt, call.callee());
let args = call
.args()
.map(|args| {
args.into_iter()
.map(|arg| CallArg::from_ast(ctxt, arg))
.collect()
})
.unwrap_or_default();
Self::Call(callee, args)
}

ast::ExprKind::MethodCall(method_call) => {
let receiver = Self::push_to_body_opt(ctxt, method_call.receiver());
let method_name = IdentId::maybe_from_token(ctxt.db, method_call.method_name());
let args = method_call
.args()
.map(|args| {
args.into_iter()
.map(|arg| CallArg::from_ast(ctxt, arg))
.collect()
})
.unwrap_or_default();
Self::MethodCall(receiver, method_name, args)
}

ast::ExprKind::Path(path) => {
let path = PathId::maybe_from_ast(ctxt.db, path.path());
Self::Path(path)
}

ast::ExprKind::RecordInit(record_init) => {
// let path = PathId::maybe_from_ast(ctxt.db, record_init.path());
todo!()
}

ast::ExprKind::Field(FieldExpr) => {
todo!()
}

ast::ExprKind::Index(IndexExpr) => {
todo!()
}

ast::ExprKind::Tuple(TupleExpr) => {
todo!()
}

ast::ExprKind::Array(ArrayExpr) => {
todo!()
}

ast::ExprKind::ArrayRep(ArrayRepExpr) => {
todo!()
}

ast::ExprKind::If(IfExpr) => {
todo!()
}

ast::ExprKind::Match(MatchExpr) => {
todo!()
}

ast::ExprKind::Paren(ParenExpr) => {
todo!()
}
};

ctxt.push_expr(expr, HirOriginKind::raw(&ast))
}

pub(super) fn push_to_body_opt(ctxt: &mut BodyCtxt<'_>, ast: Option<ast::Expr>) -> ExprId {
todo!()
if let Some(ast) = ast {
Expr::push_to_body(ctxt, ast)
} else {
ctxt.push_missing_expr()
}
}
}

impl BinOp {
pub fn from_ast(&self, ast: ast::BinOp) -> Self {
pub(super) fn from_ast(ast: ast::BinOp) -> Self {
match ast {
ast::BinOp::Arith(arith) => ArithBinOp::from_ast(arith).into(),
_ => {
todo!()
}
ast::BinOp::Comp(arith) => CompBinOp::from_ast(arith).into(),
ast::BinOp::Logical(arith) => LogicalBinOp::from_ast(arith).into(),
}
}
}

impl ArithBinOp {
pub(super) fn from_ast(ast: ast::ArithBinOp) -> Self {
match ast {
ast::ArithBinOp::Add(_) => ArithBinOp::Add,
ast::ArithBinOp::Sub(_) => ArithBinOp::Sub,
ast::ArithBinOp::Mul(_) => ArithBinOp::Mul,
ast::ArithBinOp::Div(_) => ArithBinOp::Div,
ast::ArithBinOp::Mod(_) => ArithBinOp::Mod,
ast::ArithBinOp::Pow(_) => ArithBinOp::Pow,
ast::ArithBinOp::LShift(_) => ArithBinOp::LShift,
ast::ArithBinOp::RShift(_) => ArithBinOp::RShift,
ast::ArithBinOp::BitAnd(_) => ArithBinOp::BitAnd,
ast::ArithBinOp::BitOr(_) => ArithBinOp::BitOr,
ast::ArithBinOp::BitXor(_) => ArithBinOp::BitXor,
ast::ArithBinOp::Add(_) => Self::Add,
ast::ArithBinOp::Sub(_) => Self::Sub,
ast::ArithBinOp::Mul(_) => Self::Mul,
ast::ArithBinOp::Div(_) => Self::Div,
ast::ArithBinOp::Mod(_) => Self::Mod,
ast::ArithBinOp::Pow(_) => Self::Pow,
ast::ArithBinOp::LShift(_) => Self::LShift,
ast::ArithBinOp::RShift(_) => Self::RShift,
ast::ArithBinOp::BitAnd(_) => Self::BitAnd,
ast::ArithBinOp::BitOr(_) => Self::BitOr,
ast::ArithBinOp::BitXor(_) => Self::BitXor,
}
}
}

impl CompBinOp {
pub(super) fn from_ast(ast: ast::CompBinOp) -> Self {
match ast {
ast::CompBinOp::Eq(_) => Self::Eq,
ast::CompBinOp::NotEq(_) => Self::NotEq,
ast::CompBinOp::Lt(_) => Self::Lt,
ast::CompBinOp::LtEq(_) => Self::LtEq,
ast::CompBinOp::Gt(_) => Self::Gt,
ast::CompBinOp::GtEq(_) => Self::GtEq,
}
}
}

impl LogicalBinOp {
pub(super) fn from_ast(ast: ast::LogicalBinOp) -> Self {
match ast {
ast::LogicalBinOp::And(_) => Self::And,
ast::LogicalBinOp::Or(_) => Self::Or,
}
}
}

impl UnOp {
pub(super) fn from_ast(ast: ast::UnOp) -> Self {
match ast {
ast::UnOp::Plus(_) => Self::Plus,
ast::UnOp::Minus(_) => Self::Minus,
ast::UnOp::Not(_) => Self::Not,
ast::UnOp::BitNot(_) => Self::BitNot,
}
}
}

impl CallArg {
fn from_ast(ctxt: &mut BodyCtxt<'_>, ast: ast::CallArg) -> Self {
let label = ast.label().map(|label| IdentId::from_token(ctxt.db, label));
let expr = Expr::push_to_body_opt(ctxt, ast.expr());
Self { label, expr }
}

fn from_ast_opt(ctxt: &mut BodyCtxt<'_>, ast: Option<ast::CallArg>) -> MaybeInvalid<Self> {
ast.map(|ast| Self::from_ast(ctxt, ast)).into()
}
}
6 changes: 3 additions & 3 deletions crates/hir/src/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ impl IdentId {
}

impl LitKind {
pub(super) fn from_ast(db: &dyn HirDb, ast: &ast::Lit) -> Self {
pub(super) fn from_ast(db: &dyn HirDb, ast: ast::Lit) -> Self {
match ast.kind() {
ast::LitKind::Int(int) => Self::Int(IntegerId::from_ast(db, &int)),
ast::LitKind::Int(int) => Self::Int(IntegerId::from_ast(db, int)),
ast::LitKind::String(string) => {
let text = string.token().text();
Self::String(StringId::new(db, text[1..text.len() - 1].to_string()))
Expand All @@ -46,7 +46,7 @@ impl LitKind {
}

impl IntegerId {
fn from_ast(db: &dyn HirDb, ast: &ast::LitInt) -> Self {
fn from_ast(db: &dyn HirDb, ast: ast::LitInt) -> Self {
let text = ast.token().text();
// Parser ensures that the text is valid pair with a radix and a number.
if text.len() < 2 {
Expand Down
2 changes: 1 addition & 1 deletion crates/hir/src/lower/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Pat {
ast::PatKind::Lit(lit_pat) => {
let lit_kind = lit_pat
.lit()
.map(|lit| LitKind::from_ast(ctxt.db, &lit))
.map(|lit| LitKind::from_ast(ctxt.db, lit))
.into();
Pat::Lit(lit_kind)
}
Expand Down
4 changes: 2 additions & 2 deletions crates/parser2/src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ ast_node! {
}
impl RecordInitExpr {
/// Returns the path of the record init expression.
pub fn path(&self) -> Option<super::PathExpr> {
pub fn path(&self) -> Option<super::Path> {
support::child(self.syntax())
}

Expand Down Expand Up @@ -336,6 +336,7 @@ impl ParenExpr {

#[derive(Debug, Clone, PartialEq, Eq, Hash, derive_more::From, derive_more::TryInto)]
pub enum ExprKind {
Lit(LitExpr),
Block(BlockExpr),
Bin(BinExpr),
Un(UnExpr),
Expand All @@ -348,7 +349,6 @@ pub enum ExprKind {
Tuple(TupleExpr),
Array(ArrayExpr),
ArrayRep(ArrayRepExpr),
Lit(LitExpr),
If(IfExpr),
Match(MatchExpr),
Paren(ParenExpr),
Expand Down
Loading

0 comments on commit f61edbd

Please sign in to comment.