pr47 0.1.4-CHARLIE

A semi-experimental programming language. Still working in progress.
Documentation
use std::hint::unreachable_unchecked;

use crate::sema::decl::{FuncDecl, ObjectDecl};
use crate::sema::expr::{
    AsExpr,
    AwaitExpr,
    BinaryExpr,
    FieldRefExpr,
    IdRefExpr,
    LiteralExpr,
    SubscriptExpr,
    UnaryExpr
};

pub enum ASTNode<'s> {
    ObjectDeclNode(ObjectDecl<'s>),
    FuncDeclNode(FuncDecl<'s>),
    LiteralExprNode(LiteralExpr<'s>),
    IdRefExprNode(IdRefExpr<'s>),
    UnaryExprNode(UnaryExpr<'s>),
    BinaryExprNode(BinaryExpr<'s>),
    SubscriptExprNode(SubscriptExpr<'s>),
    FieldRefExprNode(FieldRefExpr<'s>),
    AwaitExprNode(AwaitExpr<'s>),
    AsExprNode(AsExpr<'s>)
}

pub unsafe trait DynCast<T> {
    fn cast_from(data: T) -> Self;
    unsafe fn dyn_cast(&self) -> &T;
    unsafe fn dyn_cast_mut(&mut self) -> &mut T;
}

macro_rules! impl_dyn_cast {
    ($e:ident, $t:ident) => {
        unsafe impl<'s> DynCast<$t<'s>> for ASTNode<'s> {
            #[inline(always)]
            fn cast_from(data: $t<'s>) -> Self {
                ASTNode::$e(data)
            }

            #[inline(always)]
            unsafe fn dyn_cast(&self) -> &$t<'s> {
                if let ASTNode::$e(obj) = self { obj } else { unreachable_unchecked() }
            }

            #[inline(always)]
            unsafe fn dyn_cast_mut(&mut self) -> &mut $t<'s> {
                if let ASTNode::$e(obj) = self { obj } else { unreachable_unchecked() }
            }
        }
    }
}

impl_dyn_cast!(ObjectDeclNode, ObjectDecl);
impl_dyn_cast!(FuncDeclNode, FuncDecl);
impl_dyn_cast!(LiteralExprNode, LiteralExpr);
impl_dyn_cast!(IdRefExprNode, IdRefExpr);
impl_dyn_cast!(UnaryExprNode, UnaryExpr);
impl_dyn_cast!(BinaryExprNode, BinaryExpr);
impl_dyn_cast!(SubscriptExprNode, SubscriptExpr);
impl_dyn_cast!(FieldRefExprNode, FieldRefExpr);
impl_dyn_cast!(AwaitExprNode, AwaitExpr);
impl_dyn_cast!(AsExprNode, AsExpr);