sphinx/runtime/types/
dispatch.rs

1///! Enum-based static dispatch for `MetaObject`
2
3use crate::language::{IntType, FloatType};
4use crate::runtime::Variant;
5use crate::runtime::gc::Gc;
6use crate::runtime::function::{Call, Function, NativeFunction};
7use crate::runtime::strings::StringValue;
8use crate::runtime::iter::IterState;
9use crate::runtime::types::{Type, MetaObject, Tuple, UserData, Nil, Marker, UserIterator};
10use crate::runtime::errors::{ExecResult, RuntimeError};
11
12
13/// Newtype wrapper for `Variant` that impls `MetaObject` using enum-based static dispatch.
14struct MetaDispatch<'a>(&'a Variant);
15
16impl Variant {
17    #[inline]
18    pub fn as_meta(&self) -> impl MetaObject + '_ {
19        MetaDispatch(self)
20    }
21    
22    pub fn type_tag(&self) -> Type {
23        self.as_meta().type_tag()
24    }
25    
26    pub fn type_name(&self) -> ExecResult<StringValue> {
27        self.as_meta().type_name()
28    }
29}
30
31macro_rules! static_dispatch {
32    { fn $name:tt ( $( $arg:tt : $argty:ty ),* ) -> $return:ty } => {
33        fn $name (&self, $( $arg : $argty ),* ) -> $return {
34            match self.0 {
35                Variant::Nil => <Nil as MetaObject>::$name(&Nil, $( $arg ),* ),
36                Variant::BoolTrue => <bool as MetaObject>::$name(&true, $( $arg ),* ),
37                Variant::BoolFalse => <bool as MetaObject>::$name(&false, $( $arg ),* ),
38                
39                Variant::Marker(marker) => <Marker as MetaObject>::$name(marker, $( $arg ),* ),
40                
41                Variant::Integer(value) => <IntType as MetaObject>::$name(value, $( $arg ),* ),
42                Variant::Float(value) => <FloatType as MetaObject>::$name(value, $( $arg ),* ),
43                
44                Variant::InternStr(symbol) => <StringValue as MetaObject>::$name(&(*symbol).into(), $( $arg ),* ),
45                Variant::InlineStr(inline) => <StringValue as MetaObject>::$name(&(*inline).into(), $( $arg ),* ),
46                Variant::GCStr(gc_str) => <StringValue as MetaObject>::$name(&(*gc_str).into(), $( $arg ),* ),
47                
48                Variant::Tuple(tuple) => <Tuple as MetaObject>::$name(tuple, $( $arg ),* ),
49                
50                Variant::Function(fun) => <Gc<Function> as MetaObject>::$name(fun, $( $arg ),* ),
51                Variant::NativeFunction(fun) => <Gc<NativeFunction> as MetaObject>::$name(fun, $( $arg ),* ),
52                
53                Variant::Error(error) => <Gc<RuntimeError> as MetaObject>::$name(error, $( $arg ),* ),
54                
55                Variant::Iterator(iter) => <Gc<dyn UserIterator> as MetaObject>::$name(iter, $( $arg ),* ),
56                
57                Variant::UserData(data) => <(dyn UserData + 'static) as MetaObject>::$name(&**data, $( $arg ),* ),
58            }
59        }
60    };
61}
62
63impl MetaObject for MetaDispatch<'_> {
64    
65    static_dispatch!{ fn type_tag() -> Type }
66    static_dispatch!{ fn type_name() -> ExecResult<StringValue> }
67    
68    static_dispatch!{ fn fmt_repr() -> ExecResult<StringValue> }
69    
70    static_dispatch!{ fn as_bool() -> ExecResult<bool> }
71    static_dispatch!{ fn as_bits() -> Option<ExecResult<IntType>> }
72    static_dispatch!{ fn as_int() -> Option<ExecResult<IntType>> }
73    static_dispatch!{ fn as_float() -> Option<ExecResult<FloatType>> }
74    
75    // iterators
76    static_dispatch!{ fn iter_init() -> Option<ExecResult<IterState>> }
77    static_dispatch!{ fn iter_get(state: &Variant) -> Option<ExecResult<Variant>> }
78    static_dispatch!{ fn iter_next(state: &Variant) -> Option<ExecResult<Variant>> }
79    
80    // collections
81    static_dispatch!{ fn len() -> Option<ExecResult<usize>> }
82    
83    // callable
84    static_dispatch!{ fn invoke(args: &[Variant]) -> Option<ExecResult<Call>> }
85    
86    // unary operators
87    static_dispatch!{ fn op_neg() -> Option<ExecResult<Variant>> }
88    static_dispatch!{ fn op_pos() -> Option<ExecResult<Variant>> }
89    static_dispatch!{ fn op_inv() -> Option<ExecResult<Variant>> }
90
91    // arithmetic operators
92    static_dispatch!{ fn op_mul(rhs: &Variant) -> Option<ExecResult<Variant>> }
93    static_dispatch!{ fn op_rmul(lhs: &Variant) -> Option<ExecResult<Variant>> }
94    
95    static_dispatch!{ fn op_div(rhs: &Variant) -> Option<ExecResult<Variant>> }
96    static_dispatch!{ fn op_rdiv(lhs: &Variant) -> Option<ExecResult<Variant>> }
97    
98    static_dispatch!{ fn op_mod(rhs: &Variant) -> Option<ExecResult<Variant>> }
99    static_dispatch!{ fn op_rmod(lhs: &Variant) -> Option<ExecResult<Variant>> }
100    
101    static_dispatch!{ fn op_add(rhs: &Variant) -> Option<ExecResult<Variant>> }
102    static_dispatch!{ fn op_radd(lhs: &Variant) -> Option<ExecResult<Variant>> }
103    
104    static_dispatch!{ fn op_sub(rhs: &Variant) -> Option<ExecResult<Variant>> }
105    static_dispatch!{ fn op_rsub(lhs: &Variant) -> Option<ExecResult<Variant>> }
106    
107    // bitwise operators
108    static_dispatch!{ fn op_and(rhs: &Variant) -> Option<ExecResult<Variant>> }
109    static_dispatch!{ fn op_rand(lhs: &Variant) -> Option<ExecResult<Variant>> }
110    
111    static_dispatch!{ fn op_xor(rhs: &Variant) -> Option<ExecResult<Variant>> }
112    static_dispatch!{ fn op_rxor(lhs: &Variant) -> Option<ExecResult<Variant>> }
113    
114    static_dispatch!{ fn op_or(rhs: &Variant) -> Option<ExecResult<Variant>> }
115    static_dispatch!{ fn op_ror(lhs: &Variant) -> Option<ExecResult<Variant>> }
116    
117    static_dispatch!{ fn op_shl(rhs: &Variant) -> Option<ExecResult<Variant>> }
118    static_dispatch!{ fn op_rshl(lhs: &Variant) -> Option<ExecResult<Variant>> }
119    
120    static_dispatch!{ fn op_shr(rhs: &Variant) -> Option<ExecResult<Variant>> }
121    static_dispatch!{ fn op_rshr(lhs: &Variant) -> Option<ExecResult<Variant>> }
122    
123    // comparisons
124    
125    static_dispatch!{ fn cmp_eq(other: &Variant) -> Option<ExecResult<bool>> }
126    static_dispatch!{ fn cmp_lt(other: &Variant) -> Option<ExecResult<bool>> }
127    static_dispatch!{ fn cmp_le(other: &Variant) -> Option<ExecResult<bool>> }
128    
129    
130}