use super::*;
use crate::cst::{CommaSeperated, CstNode, CstToken, IdentToken};
use crate::{cst, SyntaxKind};
use cstree::interning::{Resolver, TokenKey};
use itertools::Itertools;
use skullbrain_lexer::{Lexer, LiteralKind, ModifierKind};
impl ToAst for IdentToken {
type Output = Ident;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let span = self.token().text_range();
Some(Ident {
span,
name: self.token().resolve_text(resolver).to_string(),
})
}
}
impl ToAst for cst::LiteralToken {
type Output = Literal;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let text = self.token().resolve_text(resolver);
let Some(tok) = Lexer::new(text.chars()).next() else {
unreachable!()
};
let Some(lit) = tok.into_kind().literial() else {
unreachable!()
};
let value = match lit {
LiteralKind::Int { is_empty, .. } if is_empty => return None,
LiteralKind::Double { empty_exponent, .. } if empty_exponent => return None,
LiteralKind::Str { is_terminated } if is_terminated => return None,
LiteralKind::Str { .. } => Value::Str(text.to_string()).into(),
LiteralKind::Int { .. } => {
let Ok(int) = text.parse() else {
unreachable!()
};
Value::Int(int).into()
}
LiteralKind::Double { .. } => {
let Ok(int) = text.parse() else {
unreachable!()
};
Value::Double(int).into()
}
LiteralKind::Boolean(value) => Value::Bool(value).into(),
};
let span = self.token().text_range();
Some(Literal { span, value })
}
}
impl ToAst for cst::BinaryExpr {
type Output = BinaryExpr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let lhs = self.lhs()?.to_ast(resolver)?;
let rhs = self.rhs()?.to_ast(resolver)?;
let op = match self.operator().kind() {
SyntaxKind::OpEq => BinaryOp::Eq,
SyntaxKind::OpNotEq => BinaryOp::NotEq,
SyntaxKind::OpLt => BinaryOp::Lt,
SyntaxKind::OpGt => BinaryOp::Gt,
SyntaxKind::OpLtEq => BinaryOp::LtEq,
SyntaxKind::OpGtEq => BinaryOp::GtEq,
SyntaxKind::OpMinus => BinaryOp::Sub,
SyntaxKind::OpAnd => BinaryOp::And,
SyntaxKind::OpOr => BinaryOp::Or,
SyntaxKind::OpPlus => BinaryOp::Add,
SyntaxKind::OpMul => BinaryOp::Mul,
SyntaxKind::OpDivide => BinaryOp::Div,
SyntaxKind::OpMod => BinaryOp::Mod,
_ => unreachable!(),
};
let operand = Box::new((lhs, rhs));
Some(BinaryExpr { op, operand })
}
}
impl ToAst for cst::UnaryExpr {
type Output = UnaryExpr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let rhs = self.expr()?.to_ast(resolver)?;
let expr = Box::new(rhs);
let op = match self.operator().kind() {
SyntaxKind::OpNot => UnaryOp::Not,
SyntaxKind::OpMinus => UnaryOp::Minus,
_ => unreachable!(),
};
Some(UnaryExpr { op, expr })
}
}
impl ToAst for cst::ChainExpr {
type Output = ChainExpr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let object = self.object()?.to_ast(resolver)?;
let method = self.method()?.to_ast(resolver)?;
let data = Box::new((object, method));
Some(ChainExpr { data })
}
}
impl ToAst for cst::ParenExpr {
type Output = ParenExpr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.open_token()?;
let _ = self.close_token()?;
let expr = self.exprs().exactly_one().ok()?.to_ast(resolver)?;
let expr = Box::new(expr);
let span = self.syntax().text_range();
Some(ParenExpr { expr, span })
}
}
impl ToAst for cst::BlockExpr {
type Output = BlockExpr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.open_token()?;
let _ = self.close_token()?;
let statements = self
.exprs()
.map(|expr| expr.to_ast(resolver))
.collect::<Option<Box<[_]>>>()?;
let span = self.syntax().text_range();
Some(BlockExpr { statements, span })
}
}
impl ToAst for cst::Break {
type Output = Break;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let value = self.optional_expr()?.to_ast(resolver)?;
let value = Box::new(value);
let span = self.syntax().text_range();
Some(Break {
value: Some(value),
span,
})
}
}
impl ToAst for cst::Continue {
type Output = Continue;
fn to_ast<I>(self, _resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let span = self.syntax().text_range();
Some(Continue { span })
}
}
impl ToAst for cst::Return {
type Output = Return;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let value = self.optional_expr()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(Return {
span,
value: Some(Box::new(value)),
})
}
}
impl ToAst for cst::Throw {
type Output = Throw;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let value = self.expr()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(Throw {
span,
value: Box::new(value),
})
}
}
impl ToAst for cst::While {
type Output = While;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let condition = self.condition()?.to_ast(resolver)?;
let body = self.body()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(While {
span,
condition,
body,
})
}
}
impl ToAst for cst::ForLoop {
type Output = ForLoop;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.open_token()?;
let _ = self.close_token()?;
let iterator = self.iter()?.to_ast(resolver)?;
let body = self.body()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(ForLoop {
span,
iterator,
body,
})
}
}
impl ToAst for cst::TryCatch {
type Output = TryCatch;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let try_arm = self.try_arm()?;
let _ = try_arm.try_token()?;
let try_block = try_arm.block()?.to_ast(resolver)?;
let mut seen_arm_without_ty = false;
let catch_arms = self
.catch_arms()
.map(|arm| match arm.catch_ty() {
Some(_) if seen_arm_without_ty => None,
Some(_) => {
seen_arm_without_ty = true;
arm.to_ast(resolver)
}
None => arm.to_ast(resolver),
})
.collect::<Option<Box<[_]>>>();
let span = self.syntax().text_range();
Some(TryCatch {
span,
try_block,
catch_arms,
})
}
}
impl ToAst for cst::CatchArm {
type Output = CatchArm;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.catch_token()?;
let catch_ty = match self.catch_ty() {
Some(ty) => {
let _ = ty.colon_token()?;
let name = ty.name()?.to_ast(resolver)?;
let ty = ty.ty()?.to_ast(resolver)?;
let span = ty.span();
Some(CatchType { span, ty, name })
}
None => None,
};
let body = self.block()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(CatchArm {
span,
catch_ty,
body,
})
}
}
impl ToAst for cst::VariableStmt {
type Output = VariableStmt;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let is_mutable = self.var_token().is_mutable();
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let ty_annotation = self.ty()?.to_ast(resolver)?.into();
let initializer = self.initialiser()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(VariableStmt {
span,
is_mutable,
modifiers,
name,
ty_annotation,
initializer,
})
}
}
impl ToAst for cst::TypeAlias {
type Output = TypeAlias;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let modifiers = self.modifiers()?.to_ast(resolver)?;
let _ = self.alias_token()?;
let _ = self.assignment_token()?;
let name = self.name()?.to_ast(resolver)?;
let aliased_type = self.aliased()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(TypeAlias {
span,
modifiers,
name,
aliased_type,
})
}
}
impl ToAst for cst::Modifiers {
type Output = Modifiers;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let mut flags = Modifiers::empty();
for item in self.iter() {
let kind = item.kind(resolver);
let flag = match kind {
ModifierKind::VisibilityPublic => Modifiers::Public,
ModifierKind::InstanceAccess => Modifiers::InstanceAccess,
};
if flags.contains(flag.clone()) {
return None;
} else {
flags |= flag
}
}
Some(flags)
}
}
impl ToAst for cst::Type {
type Output = Type;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
if let Some(ident) = self.ident() {
let ident = ident.to_ast(resolver)?;
return Some(Type::Ident(ident));
}
if let Some(func) = self.signature() {
let ty = func.to_ast(resolver)?;
return Some(Type::Function(ty));
}
unreachable!()
}
}
impl ToAst for cst::FunctionSignature {
type Output = FunctionSignature;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.return_ty_token()?;
let _ = self.open_brace_token()?;
let _ = self.close_brace_token()?;
let parameters = self.parameters()?;
let is_valid = parameters
.iter()
.enumerate()
.all(|(i, item)| match (i % 2, item) {
(0, CommaSeperated::Item(_)) => true,
(1, CommaSeperated::Comma(_)) => true,
_ => false,
});
if !is_valid {
return None;
}
let parameters = parameters
.iter()
.step_by(2) .filter_map(|item| match item {
CommaSeperated::Item(param) => Some(param.to_ast(resolver)),
_ => None,
})
.collect::<Option<Box<_>>>()?;
let return_type = self
.return_ty()
.and_then(|ty| ty.to_ast(resolver))
.map(|ty| Box::new(ty));
let span = self.syntax().text_range();
Some(FunctionSignature {
span,
parameters,
return_type,
})
}
}
impl ToAst for cst::Parameter {
type Output = Parameter;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.colon_token()?;
let name = self.name()?.to_ast(resolver)?;
let ty = self.ty()?.to_ast(resolver)?;
Some(Parameter { name, ty })
}
}
impl ToAst for cst::IfElse {
type Output = IfElse;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let if_arm = self.if_arm()?;
let _ = if_arm.if_token()?;
let condition = if_arm.condition()?.to_ast(resolver)?;
let then_branch = if_arm.body()?.to_ast(resolver)?;
let mut seen_else_branch = false;
let else_branches = self
.else_branches()
.map(|arm| match arm {
crate::cst::ElseBranch::Else(_) if seen_else_branch => None,
crate::cst::ElseBranch::Else(_) => {
seen_else_branch = true;
arm.to_ast(resolver)
}
_ => arm.to_ast(resolver),
})
.collect::<Option<Box<[_]>>>()?;
let span = self.syntax().text_range();
Some(IfElse {
span,
condition,
then_branch,
else_branches: Some(else_branches),
})
}
}
impl ToAst for cst::ElseBranch {
type Output = ElseBranch;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let span = self.syntax().text_range();
let (condition, then_branch) = match self {
cst::ElseBranch::Else(else_arm) => {
let _ = else_arm.else_token()?;
let body = else_arm.body()?.to_ast(resolver)?;
(None, body)
}
cst::ElseBranch::ElseIf(else_if_arm) => {
let _ = else_if_arm.contains_else_if()?;
let condition = else_if_arm.condition()?.to_ast(resolver)?;
let body = else_if_arm.body()?.to_ast(resolver)?;
(Some(condition), body)
}
};
Some(ElseBranch {
span,
condition,
then_branch,
})
}
}
impl ToAst for cst::Match {
type Output = Match;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.body_open_token();
let _ = self.body_close_token();
if self.disallowed_exprs()?.next().is_some() {
return None;
}
let expr = self.expr()?.to_ast(resolver)?;
let arms = self
.match_arms()?
.map(|arm| arm.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let mut iter = arms.iter();
if iter.find(|arm| arm.pat.is_none()).is_some()
&& iter.find(|arm| arm.pat.is_none()).is_some()
{
return None;
}
let span = self.syntax().text_range();
Some(Match { span, expr, arms })
}
}
impl ToAst for cst::MatchArm {
type Output = MatchArm;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let res = match self {
cst::MatchArm::WithCondition(arm) => MatchArm {
pat: Some(arm.pat()?.to_ast(resolver)?),
body: arm.body()?.to_ast(resolver)?,
},
cst::MatchArm::Default(arm) => MatchArm {
pat: None,
body: arm.body()?.to_ast(resolver)?,
},
};
Some(res)
}
}
impl ToAst for cst::MatchPat {
type Output = MatchPat;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let pat = if let Some(ident) = self.ident() {
MatchPat::Ident(ident.to_ast(resolver)?)
} else if let Some(lit) = self.lit() {
MatchPat::Literal(lit.to_ast(resolver)?)
} else {
todo!()
};
Some(pat)
}
}
impl ToAst for cst::ImportStmt {
type Output = ImportStmt;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.import_token()?;
let _ = self.alias_token()?;
let _ = self.alias_token()?;
let source = {
let source = self.source()?;
match source.ident() {
Some(ident) => ident.to_ast(resolver)?.name,
None => match source.path() {
Some(path) => path.token().resolve_text(resolver).to_string(),
_ => unreachable!(),
},
}
};
let item_idents = self.items()?;
let open = item_idents.open_token();
let close = item_idents.close_token();
let is_both = open.is_some() && close.is_some();
let is_neither = open.is_none() && close.is_none();
let items = item_idents
.idents()
.map(|i| i.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
match items.len() {
0 => return None,
1 => {
if !(is_both || is_neither) {
return None;
}
}
_ => {
if !is_both {
return None;
}
}
}
let span = self.syntax().text_range();
Some(ImportStmt {
span,
source,
items,
})
}
}
impl ToAst for cst::Function {
type Output = Function;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let signature = self.signature()?.to_ast(resolver)?;
let body = self.body()?.to_ast(resolver)?;
let span = self.syntax().text_range();
Some(Function {
span,
modifiers,
name,
signature,
body,
})
}
}
impl ToAst for cst::FunctionItem {
type Output = FunctionItem;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let span = self.syntax().text_range();
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let signature = self.signature()?.to_ast(resolver)?;
let body = match self {
cst::FunctionItem::Full(function) => Some(function.body()?.to_ast(resolver)?),
cst::FunctionItem::Partial(_) => None,
};
Some(FunctionItem {
span,
modifiers,
name,
signature,
body,
})
}
}
impl ToAst for cst::Enum {
type Output = Enum;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.body_open_tok()?;
let _ = self.body_close_tok()?;
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let variants = self
.variants()
.map(|variant| variant.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let nested_impls = self
.nested_impls()?
.map(|_impl| _impl.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let members = MemberConstructions::from_cst(
resolver,
self.methods(),
self.variables(),
self.ty_aliasz(),
self.implicit_init_exprs(),
)?;
let span = self.syntax().text_range();
Some(Enum {
span,
modifiers,
name,
variants,
members,
nested_impls,
})
}
}
impl ToAst for cst::EnumVariant {
type Output = EnumVariant;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let name = self.name()?.to_ast(resolver)?;
let fields = self.fields()?.map(|field| field.to_ast(resolver)).collect();
Some(EnumVariant { name, fields })
}
}
impl ToAst for cst::EnumVariantField {
type Output = EnumVariantField;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.colon_token()?;
let name = self.name()?.to_ast(resolver)?;
let ty = self.ty()?.to_ast(resolver)?;
Some(EnumVariantField { name, ty })
}
}
impl<T> MemberConstructions<T> {
fn from_cst<I, A>(
resolver: &I,
methods: Option<impl Iterator<Item = A>>,
fields: Option<impl Iterator<Item = cst::VariableStmt>>,
aliasz: Option<impl Iterator<Item = cst::TypeAlias>>,
implicit_inits: Option<impl Iterator<Item = cst::Expr>>,
) -> Option<Self>
where
I: Resolver<TokenKey> + ?Sized,
A: ToAst<Output = T>,
{
let methods = methods?
.map(|func| func.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let fields = fields?
.map(|var| var.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let aliasz = aliasz?
.map(|var| var.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let implicit_inits = implicit_inits?
.map(|expr| expr.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
Some(Self {
implicit_inits,
methods,
fields,
aliasz,
})
}
}
impl ToAst for cst::Class {
type Output = Class;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.body_open_tok()?;
let _ = self.body_close_tok()?;
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let nested_impls = self
.nested_impls()?
.map(|_impl| _impl.to_ast(resolver))
.collect::<Option<Box<_>>>()?;
let members = MemberConstructions::from_cst(
resolver,
self.methods(),
self.variables(),
self.ty_aliasz(),
self.implicit_init_exprs(),
)?;
let span = self.syntax().text_range();
Some(Class {
span,
modifiers,
name,
members,
nested_impls,
})
}
}
impl ToAst for cst::TraitImpl {
type Output = TraitImpl;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.body_open_tok()?;
let _ = self.body_close_tok()?;
let members = MemberConstructions::from_cst(
resolver,
self.methods(),
self.var_decls(),
self.type_aliases(),
self.implicit_init_exprs(),
)?;
let span = self.syntax().text_range();
Some(TraitImpl { span, members })
}
}
impl ToAst for cst::Trait {
type Output = Trait;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let _ = self.open_brace_token()?;
let _ = self.close_brace_token()?;
let modifiers = self.modifiers()?.to_ast(resolver)?;
let name = self.name()?.to_ast(resolver)?;
let members = MemberConstructions::from_cst(
resolver,
self.functions(),
self.var_decls(),
self.type_aliases(),
self.implicit_init_exprs(),
)?;
let span = self.syntax().text_range();
Some(Trait {
span,
modifiers,
name,
members,
})
}
}
impl ToAst for cst::Expr {
type Output = Expr;
fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
where
I: Resolver<TokenKey> + ?Sized,
{
let res: Expr = match self {
cst::Expr::Literal(literal_token) => literal_token.to_ast(resolver)?.into(),
cst::Expr::Ident(ident_token) => ident_token.to_ast(resolver)?.into(),
cst::Expr::Paren(parenthesis_expr) => parenthesis_expr.to_ast(resolver)?.into(),
cst::Expr::Block(block_expr) => block_expr.to_ast(resolver)?.into(),
cst::Expr::Binary(binary_op) => binary_op.to_ast(resolver)?.into(),
cst::Expr::Unary(unary_op) => unary_op.to_ast(resolver)?.into(),
cst::Expr::Chain(chain) => chain.to_ast(resolver)?.into(),
cst::Expr::Break(break_expr) => break_expr.to_ast(resolver)?.into(),
cst::Expr::Continue(continue_expr) => continue_expr.to_ast(resolver)?.into(),
cst::Expr::Return(return_expr) => return_expr.to_ast(resolver)?.into(),
cst::Expr::Throw(throw_expr) => throw_expr.to_ast(resolver)?.into(),
cst::Expr::While(while_loop) => while_loop.to_ast(resolver)?.into(),
cst::Expr::For(for_loop) => for_loop.to_ast(resolver)?.into(),
cst::Expr::TryCatch(try_catch) => try_catch.to_ast(resolver)?.into(),
cst::Expr::IfElse(if_else) => if_else.to_ast(resolver)?.into(),
cst::Expr::Match(match_expr) => match_expr.to_ast(resolver)?.into(),
cst::Expr::Variable(variable_decl) => variable_decl.to_ast(resolver)?.into(),
cst::Expr::Import(import_expr) => import_expr.to_ast(resolver)?.into(),
cst::Expr::TypeAlias(type_alias_decl) => type_alias_decl.to_ast(resolver)?.into(),
cst::Expr::Function(function_decl) => function_decl.to_ast(resolver)?.into(),
cst::Expr::Trait(trait_decl) => trait_decl.to_ast(resolver)?.into(),
cst::Expr::TraitImpl(trait_impl_decl) => trait_impl_decl.to_ast(resolver)?.into(),
cst::Expr::Class(class_decl) => class_decl.to_ast(resolver)?.into(),
cst::Expr::Enum(enum_decl) => enum_decl.to_ast(resolver)?.into(),
cst::Expr::Fragment(_) => return None,
};
Some(res)
}
}
impl From<Literal> for Expr {
fn from(value: Literal) -> Self {
Expr::Literal(value)
}
}
impl From<Ident> for Expr {
fn from(value: Ident) -> Self {
Expr::Ident(value)
}
}
impl From<BinaryExpr> for Expr {
fn from(value: BinaryExpr) -> Self {
Expr::Binary(value)
}
}
impl From<UnaryExpr> for Expr {
fn from(value: UnaryExpr) -> Self {
Expr::Unary(value)
}
}
impl From<ChainExpr> for Expr {
fn from(value: ChainExpr) -> Self {
Expr::Chain(value)
}
}
impl From<ParenExpr> for Expr {
fn from(value: ParenExpr) -> Self {
Expr::Paren(value)
}
}
impl From<BlockExpr> for Expr {
fn from(value: BlockExpr) -> Self {
Expr::Block(value)
}
}
impl From<Break> for Expr {
fn from(value: Break) -> Self {
Expr::Break(value)
}
}
impl From<Continue> for Expr {
fn from(value: Continue) -> Self {
Expr::Continue(value)
}
}
impl From<Return> for Expr {
fn from(value: Return) -> Self {
Expr::Return(value)
}
}
impl From<Throw> for Expr {
fn from(value: Throw) -> Self {
Expr::Throw(value)
}
}
impl From<While> for Expr {
fn from(value: While) -> Self {
Expr::While(value)
}
}
impl From<ForLoop> for Expr {
fn from(value: ForLoop) -> Self {
Expr::For(value)
}
}
impl From<IfElse> for Expr {
fn from(value: IfElse) -> Self {
Expr::If(value)
}
}
impl From<Match> for Expr {
fn from(value: Match) -> Self {
Expr::Match(value)
}
}
impl From<TryCatch> for Expr {
fn from(value: TryCatch) -> Self {
Expr::TryCatch(value)
}
}
impl From<VariableStmt> for Expr {
fn from(value: VariableStmt) -> Self {
Expr::Variable(value)
}
}
impl From<Function> for Expr {
fn from(value: Function) -> Self {
Expr::Function(value)
}
}
impl From<Class> for Expr {
fn from(value: Class) -> Self {
Expr::Class(value)
}
}
impl From<Trait> for Expr {
fn from(value: Trait) -> Self {
Expr::Trait(value)
}
}
impl From<TraitImpl> for Expr {
fn from(value: TraitImpl) -> Self {
Expr::TraitImpl(value)
}
}
impl From<Enum> for Expr {
fn from(value: Enum) -> Self {
Expr::Enum(value)
}
}
impl From<TypeAlias> for Expr {
fn from(value: TypeAlias) -> Self {
Expr::TypeAlias(value)
}
}
impl From<ImportStmt> for Expr {
fn from(value: ImportStmt) -> Self {
Expr::Import(value)
}
}