pr47 0.1.4-CHARLIE

A semi-experimental programming language. Still working in progress.
Documentation
use std::any::TypeId;
use std::marker::{PhantomData, PhantomPinned};
use std::ptr::NonNull;

use xjbutil::mem::move_to_heap;
use xjbutil::void::Void;

use crate::data::generic::GenericTypeVT;
use crate::data::traits::{ChildrenType, StaticBase};
use crate::data::tyck::{TyckInfo, TyckInfoPool};
use crate::data::Value;
use crate::data::wrapper::Wrapper;

#[repr(transparent)]
pub struct VMGenericVec {
    pub inner: Vec<Value>,
    _pinned: PhantomPinned
}

impl VMGenericVec {
    fn new() -> Self {
        Self {
            inner: Vec::new(),
            _pinned: PhantomPinned
        }
    }
}

impl StaticBase<VMGenericVec> for Void {
    fn tyck_info(tyck_info_pool: &mut TyckInfoPool) -> NonNull<TyckInfo> {
        tyck_info_pool.create_container_type(
            TypeId::of::<VMGenericVec>(),
            &[tyck_info_pool.get_any_type()]
        )
    }

    fn tyck(tyck_info: &TyckInfo) -> bool {
        if let TyckInfo::Container(container_tyck_info) = tyck_info {
            if container_tyck_info.type_id != TypeId::of::<VMGenericVec>() {
                return false;
            }

            unsafe {
                container_tyck_info.params.as_ref()[0].as_ref().is_any()
            }
        } else {
            false
        }
    }

    fn children(vself: *const VMGenericVec) -> ChildrenType {
        unsafe {
            let iter = Box::new((*vself).inner.iter().copied());
            Some(iter)
        }
    }
}

#[repr(transparent)]
pub struct VMVec<T: 'static> {
    pub(crate) repr: VMGenericVec,
    _phantom: PhantomData<T>
}

impl<T> StaticBase<VMVec<T>> for Void
    where T: 'static,
          Void: StaticBase<T>
{
    fn tyck_info(tyck_info_pool: &mut TyckInfoPool) -> NonNull<TyckInfo> {
        tyck_info_pool.create_container_type(
            TypeId::of::<VMVec<T>>(),
            &[tyck_info_pool.get_any_type()]
        )
    }

    fn tyck(tyck_info: &TyckInfo) -> bool {
        if let TyckInfo::Container(container_tyck_info) = tyck_info {
            if container_tyck_info.type_id != TypeId::of::<VMGenericVec>() {
                return false;
            }

            unsafe {
                let child_tyck_info: &TyckInfo = container_tyck_info.params.as_ref()[0].as_ref();
                !child_tyck_info.is_any() && <Void as StaticBase<T>>::tyck(child_tyck_info)
            }
        } else {
            false
        }
    }

    fn children(vself: *const VMVec<T>) -> ChildrenType {
        unsafe {
            let iter = Box::new((*vself).repr.inner.iter().copied());
            Some(iter)
        }
    }
}

pub fn create_vm_vec_vt(
    tyck_info_pool: &mut TyckInfoPool,
    arg_type: NonNull<TyckInfo>
) -> GenericTypeVT {
    let tyck_info: NonNull<TyckInfo> =
        tyck_info_pool.create_container_type(TypeId::of::<VMGenericVec>(), &[arg_type]);

    use crate::data::generic::gen_impls;
    GenericTypeVT {
        tyck_info: unsafe { tyck_info.as_ref().get_container_tyck_info_unchecked() },
        type_name: "vector".to_string(),
        #[cfg(debug_assertions)]
        move_out_fn: gen_impls::generic_move_out_ck::<VMGenericVec>,
        #[cfg(not(debug_assertions))]
        move_out_fn: gen_impls::generic_move_out::<VMGenericVec>,
        children_fn: gen_impls::generic_children::<VMGenericVec>,
        drop_fn: gen_impls::generic_drop::<VMGenericVec>
    }
}

pub fn vec_ctor() -> *mut Wrapper<()> {
    move_to_heap(Wrapper::new_owned(VMGenericVec::new())).as_ptr() as *mut _
}