use brink_syntax::ast::{self, AstNode};
use crate::{DiagnosticCode, Expr, Path};
use super::super::context::{LowerScope, LowerSink, Lowered};
use super::super::helpers::{lower_path, make_name};
use super::LowerExpr;
impl LowerExpr for ast::Path {
fn lower_expr(&self, _scope: &LowerScope, _sink: &mut impl LowerSink) -> Lowered<Expr> {
let p = lower_path(self);
Ok(Expr::Path(p))
}
}
impl LowerExpr for ast::FunctionCall {
fn lower_expr(&self, scope: &LowerScope, sink: &mut impl LowerSink) -> Lowered<Expr> {
let range = self.syntax().text_range();
let ident = self
.identifier()
.ok_or_else(|| sink.diagnose(range, DiagnosticCode::E017))?;
let name_text = ident
.name()
.ok_or_else(|| sink.diagnose(range, DiagnosticCode::E017))?;
let ident_range = ident.syntax().text_range();
let path = Path {
segments: vec![make_name(name_text.clone(), ident_range)],
range: ident_range,
crosses_module_wall: false,
};
let args: Vec<Expr> = self
.arg_list()
.map(|al| {
al.args()
.filter_map(|a| a.lower_expr(scope, sink).ok())
.collect()
})
.unwrap_or_default();
Ok(Expr::Call(path, args))
}
}
impl LowerExpr for ast::CallExpr {
fn lower_expr(&self, _scope: &LowerScope, sink: &mut impl LowerSink) -> Lowered<Expr> {
let range = self.syntax().text_range();
Err(sink.diagnose(range, DiagnosticCode::E104))
}
}
impl LowerExpr for ast::DivertTargetExpr {
fn lower_expr(&self, _scope: &LowerScope, _sink: &mut impl LowerSink) -> Lowered<Expr> {
let Some(ast_path) = self.target() else {
unreachable!("parser guarantees PATH node in DivertTargetExpr")
};
let path = lower_path(&ast_path);
Ok(Expr::DivertTarget(path))
}
}
impl LowerExpr for ast::ListExpr {
fn lower_expr(&self, _scope: &LowerScope, _sink: &mut impl LowerSink) -> Lowered<Expr> {
let items: Vec<Path> = self.items().map(|p| lower_path(&p)).collect();
Ok(Expr::ListLiteral(items))
}
}