1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
//! Definition of fields for relational tuples.
//!
//! At the very core of the memquery engine is the `Col` trait,
//! and the `col!` macro that produces new column types that
//! implement the trait.
//!
//! Each `Col` is a transparent newtype that represents a
//! single data cell in a relational table.  It has very few
//! methods of its own and `Deref`s to its inner type, so you
//! can use a column cell in most places that expect the value
//! stored there.

use crate::prelude::*;

use crate::rename_col::RenameCol;

use core::ops::{Deref,DerefMut};
use core::borrow::{Borrow,BorrowMut};
use tylisp::LispId;

/// A trait to represent a relation field
///
/// It is intended to only be implemented via the `col!` macro,
/// which will define a new column type and implement all of
/// the required traits.
pub trait Col: 'static
             + Clone
             + From<<Self as Col>::Inner>
             + Into<<Self as Col>::Inner>
             + Deref<Target = <Self as Col>::Inner>
             + DerefMut
             + AsRef<<Self as Col>::Inner>
             + AsMut<<Self as Col>::Inner>
             + Borrow<<Self as Col>::Inner>
             + BorrowMut<<Self as Col>::Inner>
             + ColProxy< For=Self >
             + LispId
             + crate::record::Record<Cols=tylisp::sexpr!{Self}>
             + tylisp::engine::Eval<Result=Self>
{
    type Inner;

    /// Safely transmutes a shared reference to the
    /// inner datatype into a shared column reference
    fn wrap_ref(x: &Self::Inner)->&Self;

    /// Safely transmutes an exclusive reference to
    /// the inner datatype into an exclusive column reference
    fn wrap_mut(x: &mut Self::Inner)->&mut Self;

    fn inner_ref(&self)->&Self::Inner { self.deref() }

    /// Tags the inner variable with a different column wrapper
    fn rename<New: Col<Inner=Self::Inner>>(self)->New
    { New::from(<Self as Into<Self::Inner>>::into(self) ) }

    /// In-place renaming of a shared reference to this column
    /// as a different column name.
    fn rename_ref<New: Col<Inner=Self::Inner>>(&self)->&New
    { New::wrap_ref(self.deref()) }

    /// In-place renaming of an exclusive reference to this column
    /// as a different column name.
    fn rename_mut<New: Col<Inner=Self::Inner>>(&mut self)->&mut New
    { New::wrap_mut(self.deref_mut()) }
}

/// A value that stands in for a column
/// 
/// This trait should be implemented for smart pointers to columns,
/// in addition to the columns themselves.  This trait is often used
/// as a bound where you might ordinarily expect to see a column
/// reference so that the column value itself can be used in place
/// of the reference.
pub trait ColProxy {
    /// Which column does this proxy represent?
    type For: Col;

    /// Consume the proxy and produce an owned version of the
    /// column data.  This will often involve `clone()`ing the
    /// column value.
    fn into_col(self)->Self::For;

    /// Get a reference to the column value without consuming
    /// the pointer.
    fn col_ref(&self)->&Self::For;
}

/// A macro to define a field.
///
/// The `col!` macro defines a column type that will properly
/// interact with `memquery`.
/// The inner type must be `'static` and cannot take any generic
/// parameters.
///
/// Most derivable traits in `std` are automatically implemented
/// for the resulting type.
/// 
/// ```
/// # #![recursion_limit = "256"]
/// # #![cfg_attr(feature = "const", feature(const_generics, const_evaluatable_checked))]
/// # use ::mem_query::col;
/// col!{ pub TestField: u32 }
/// ```
#[macro_export]
macro_rules! col {
    ($viz:vis $name:ident : $ty:ty $(; $($derive:ident),*)?) => {
        #[repr(transparent)]
        #[derive(Debug, Copy, Clone, Hash, Default,
                 Ord, PartialOrd, Eq, PartialEq
                 $($(, $derive)*)?)]
        // Note: This is generic only to make the derive macros work.
        //       Using the resulting struct with any type other than
        //       the default is unlikely to be useful.
        $viz struct $name<T=$ty>(pub T);
        impl $crate::col::Col for $name {
            type Inner = $ty;

            fn wrap_ref(x: &Self::Inner)->&Self { x.into() }
            fn wrap_mut(x: &mut Self::Inner)->&mut Self { x.into() }
        }
        $crate::prelude::tylisp::non_calc_literal!{$name}
        impl ::core::convert::From<$ty> for $name {
            fn from(x:$ty)->Self { $name(x) }
        }
        impl ::core::convert::Into<$ty> for $name {
            fn into(self)->$ty { self.0 }
        }
        impl<T> ::core::borrow::Borrow<T> for $name
        where $ty: ::core::borrow::Borrow<T> {
            fn borrow(&self)->&T { <$ty as ::core::borrow::Borrow<T>>::borrow(&self.0) }
        }
        impl<T> ::core::borrow::BorrowMut<T> for $name
        where $ty: ::core::borrow::BorrowMut<T> {
            fn borrow_mut(&mut self)->&mut T { self.0.borrow_mut() }
        }
        impl ::core::ops::Deref for $name {
            type Target = $ty;
            fn deref(&self)->&$ty { &self.0 }
        }
        impl ::core::ops::DerefMut for $name {
            fn deref_mut(&mut self)->&mut $ty { &mut self.0 }
        }
        impl ::core::convert::AsRef<$ty> for $name {
            fn as_ref(&self)->&$ty { &self.0 }
        }
        impl ::core::convert::AsMut<$ty> for $name {
            fn as_mut(&mut self)->&mut $ty { &mut self.0 }
        }
        impl<AAAAA:$crate::col::Col, BBBBB:$crate::col::Col<Inner=AAAAA::Inner>, Renamed>
            $crate::rename_col::RenameCol<AAAAA,BBBBB> for $name
            where
            $crate::tylisp::sexpr!{$crate::tylisp::ops::If,
                {$crate::tylisp::ops::Is, @AAAAA, @$name},
                @BBBBB,
                @$name
            }: tylisp::engine::Eval<Result = Renamed>,
            Renamed: $crate::col::Col<Inner = $ty>
        {
            type Renamed = Renamed;
            fn rename_col(self)->Renamed { <Self as $crate::col::Col>::rename(self) }
        }
        impl<'a, AAAAA:$crate::col::Col, BBBBB:$crate::col::Col<Inner=AAAAA::Inner>, Renamed>
            $crate::rename_col::RenameCol<AAAAA,BBBBB> for &'a $name
            where
            $crate::tylisp::sexpr!{$crate::tylisp::ops::If,
                {$crate::tylisp::ops::Is, @AAAAA, @$name},
                @BBBBB,
                @$name
            }: tylisp::engine::Eval<Result = Renamed>,
            Renamed: $crate::col::Col<Inner = $ty>
        {
            type Renamed = &'a Renamed;
            fn rename_col(self)->&'a Renamed { <$name as $crate::col::Col>::rename_ref(self) }
        }
        impl<'a> ::core::convert::From<&'a $ty> for &'a $name {
            fn from(x: &'a $ty)->&'a $name {
                // Safety: Self is #[repr(transparent)] and columns
                // don't restrict their inner type, so transmuting
                // a reference should be sound
                unsafe { std::mem::transmute(x) }
            }
        }
        impl<'a> ::core::convert::From<&'a mut $ty> for &'a mut $name {
            fn from(x: &'a mut $ty)->&'a mut $name {
                // Safety: Self is #[repr(transparent)] and columns
                // don't restrict their inner type, so transmuting
                // a reference should be sound.
                //
                // No aliasing is introduced because the old reference
                // is destroyed in the transmute process.
                unsafe { std::mem::transmute(x) }
            }
        }


        impl $crate::col::ColProxy for $name {
            type For = Self;
            #[inline(always)]
            fn into_col(self)->Self::For { self }
            #[inline(always)]
            fn col_ref(&self)->&Self::For { self }
        }
        impl $crate::record::Record for $name {
            type Cols = $crate::tylisp::sexpr!{Self};
            
            #[inline(always)]
            fn into_cols(self)->Self::Cols {
                $crate::tylisp::sexpr_val!{self}
            }
            #[inline(always)]
            fn clone_cols(&self)->Self::Cols {
                $crate::tylisp::sexpr_val!{self.clone()}
            }
            #[inline(always)]
            fn col_ref<C:$crate::col::Col>(&self)->&C { //where Self::Cols: HasCol<C> {
                match self.col_opt() {
                    Some(x) => x,
                    None => { unreachable!() }
                }
            }
            #[inline(always)]
            fn col_opt<C:$crate::col::Col>(&self)->Option<&C> {
                (self as &dyn ::core::any::Any).downcast_ref()
            }
        }
        impl $crate::record::FromRecordImpl for $name {
            type Cols = $crate::tylisp::sexpr!{Self};

            fn from_rec_raw(rec: impl $crate::record::Record<Cols=Self::Cols>)->Self {
                rec.into_cols().head
            }
        }
        impl<'a> $crate::record::FromExternalRecord<'a> for $name {
            type Cols = $crate::tylisp::sexpr!{Self};

            fn from_ext_rec_raw(rec: impl $crate::record::ExternalRecord<'a,Cols=Self::Cols>)->Self {
                rec.into_cols().head
            }
        }
        impl<'a> $crate::record::FromExternalRecord<'a> for &'a $name {
            type Cols = $crate::tylisp::sexpr!{$name};

            fn from_ext_rec_raw(rec: impl $crate::record::ExternalRecord<'a,Cols=Self::Cols>)->Self {
                rec.ext_col_ref()
            }
        }
    }
}

macro_rules! proxy_impls {
    (< $param:tt > $( $ptr:ty ),* $(,)?) => {$(
        impl<$param:Col> ColProxy for $ptr {
            type For = $param;
            fn into_col(self)->Self::For { (*self).clone() }
            fn col_ref(&self)->&Self::For { self.deref() }
        }
    )*}
}

proxy_impls!{<C>
    &C,
    Box<C>,
}

proxy_impls!{<C>
    std::rc::Rc<C>,
    std::sync::Arc<C>,
}
    
/*
mod sealed {
    use crate::prelude::*;
    pub trait CmpColId<Other:Col>: Col {
        type IsSame;
    }

    impl<C1:Col, C2:Col> CmpColId<C1> for C2
    where C1::Id: typenum::IsEqual<C2::Id> {
        type IsSame = <C1::Id as typenum::IsEqual<C2::Id>>::Output;
    }
}

pub trait CmpColId<Other:Col>: sealed::CmpColId<Other> {
    type IsSame;
}

impl<A:Col,B:Col> CmpColId<B> for A where A: sealed::CmpColId<B> {
    type IsSame = <Self as sealed::CmpColId<B>>::IsSame;
}
*/
//pub trait Distinct<Other:Col>: Col
//    + sealed::CmpColId<Other, IsSame=typenum::False> {}

//impl<A:Col, B:Col> Distinct<B> for A
//where A: sealed::CmpColId<B, IsSame=typenum::False> {}



#[cfg(test)] mod test {
    use super::*;
    #[derive(Clone)]
    struct MyStruct;
    col!{ TestField2: MyStruct }

}