sphinx/runtime/
types.rs

1use core::fmt;
2use crate::language::{IntType, FloatType};
3use crate::runtime::Variant;
4use crate::runtime::iter::IterState;
5use crate::runtime::function::Call;
6use crate::runtime::strings::{StringValue, static_symbol};
7use crate::runtime::errors::{ExecResult, RuntimeError};
8
9
10mod ops;
11mod dispatch;
12mod metatable;
13mod boolean;
14mod numeric;
15mod string;
16mod tuple;
17mod iterator;
18mod misc;
19
20pub use tuple::Tuple;
21pub use misc::{Marker, UserData};
22pub use numeric::{int_from_str, float_from_str};
23pub use iterator::UserIterator;
24
25use misc::Nil;
26
27
28// TODO replace this
29
30// Type tag for Sphinx's "primitive" types
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
32pub enum Type {
33    Nil,
34    Boolean,
35    Marker,
36    Integer,
37    Float,
38    String,
39    Tuple,
40    Function,
41    Iterator,
42    Metatable,
43    Object,
44    Error,
45    UserData,
46}
47
48impl Type {
49    pub fn name(&self) -> StringValue {
50        let name = match self {
51            Self::Nil => static_symbol!("nil"),
52            Self::Boolean => static_symbol!("bool"),
53            Self::Marker => static_symbol!("marker"),
54            Self::Integer => static_symbol!("int"),
55            Self::Float => static_symbol!("float"),
56            Self::String => static_symbol!("string"),
57            Self::Tuple => static_symbol!("tuple"),
58            Self::Function => static_symbol!("function"),
59            Self::Iterator => static_symbol!("iterator"),
60            Self::Metatable => static_symbol!("metatable"),
61            Self::Object => static_symbol!("object"),
62            Self::Error => static_symbol!("error"),
63            Self::UserData => static_symbol!("userdata"),
64        };
65        name.into()
66    }
67}
68
69impl fmt::Display for Type {
70    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
71        self.name().with_str(|s| fmt.write_str(s))
72    }
73}
74
75
76#[allow(unused_variables)]
77pub trait MetaObject {
78    fn type_tag(&self) -> Type;
79    
80    fn type_name(&self) -> ExecResult<StringValue> {
81        Ok(self.type_tag().name())
82    }
83    
84    // formatting
85    fn fmt_repr(&self) -> ExecResult<StringValue>;
86    
87    // primitive coercions
88    fn as_bool(&self) -> ExecResult<bool> { Ok(true) }
89    fn as_bits(&self) -> Option<ExecResult<IntType>> { self.as_int() }
90    fn as_int(&self) -> Option<ExecResult<IntType>> { None }
91    fn as_float(&self) -> Option<ExecResult<FloatType>> { None }
92    
93    // iterators
94    
95    // see iterator.rs for more detail on the iterator API
96    fn iter_init(&self) -> Option<ExecResult<IterState>> { None }
97    fn iter_next(&self, state: &Variant) -> Option<ExecResult<Variant>> { None }
98    fn iter_get(&self, state: &Variant) -> Option<ExecResult<Variant>> { None }
99    
100    // collections
101    fn len(&self) -> Option<ExecResult<usize>> { None }
102    //fn getitem(&self, item: &Variant) -> Option<ExecResult<Variant>> { None }
103    //fn setitem(&self, item: &Variant) -> Option<ExecResult<Variant>> { None }
104    
105    // callable
106    fn invoke(&self, args: &[Variant]) -> Option<ExecResult<Call>> { None }
107    
108    // unary operators
109    fn op_neg(&self) -> Option<ExecResult<Variant>> { None }
110    fn op_pos(&self) -> Option<ExecResult<Variant>> { None }
111    fn op_inv(&self) -> Option<ExecResult<Variant>> { None }
112
113    // arithmetic operators
114    fn op_mul(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
115    fn op_rmul(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
116    
117    fn op_div(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
118    fn op_rdiv(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
119    
120    fn op_mod(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
121    fn op_rmod(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
122    
123    fn op_add(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
124    fn op_radd(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
125    
126    fn op_sub(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
127    fn op_rsub(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
128    
129    // bitwise operators
130    fn op_and(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
131    fn op_rand(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
132    
133    fn op_xor(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
134    fn op_rxor(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
135    
136    fn op_or(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
137    fn op_ror(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
138    
139    fn op_shl(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
140    fn op_rshl(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
141    
142    fn op_shr(&self, rhs: &Variant) -> Option<ExecResult<Variant>> { None }
143    fn op_rshr(&self, lhs: &Variant) -> Option<ExecResult<Variant>> { None }
144    
145    // comparisons
146    
147    fn cmp_eq(&self, other: &Variant) -> Option<ExecResult<bool>> { None }
148    fn cmp_lt(&self, other: &Variant) -> Option<ExecResult<bool>> { None }
149    fn cmp_le(&self, other: &Variant) -> Option<ExecResult<bool>> { None }
150}
151
152
153impl Variant {
154    pub fn as_bool(&self) -> ExecResult<bool> { 
155        self.as_meta().as_bool()
156    }
157    
158    pub fn as_bits(&self) -> ExecResult<IntType> {
159        self.as_meta().as_bits()
160            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::AsBits))?
161    }
162    
163    pub fn as_int(&self) -> ExecResult<IntType> {
164        self.as_meta().as_int()
165            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::AsInt))?
166    }
167    
168    pub fn as_float(&self) -> ExecResult<FloatType> {
169        self.as_meta().as_float()
170            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::AsFloat))?
171    }
172}
173
174impl Variant {
175    pub fn len(&self) -> ExecResult<usize> {
176        self.as_meta().len()
177            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::Len))?
178    }
179    
180    pub fn is_empty(&self) -> ExecResult<bool> {
181        Ok(self.len()? == 0)
182    }
183    
184    pub fn iter_init(&self) -> ExecResult<IterState> {
185        self.as_meta().iter_init()
186            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::IterInit))?
187    }
188    
189    pub fn iter_next(&self, state: &Variant) -> ExecResult<Variant> {
190        self.as_meta().iter_next(state)
191            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::IterNext))?
192    }
193    
194    pub fn iter_get(&self, state: &Variant) -> ExecResult<Variant> {
195        self.as_meta().iter_get(state)
196            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::IterItem))?
197    }
198    
199    pub fn invoke(&self, args: &[Variant]) -> ExecResult<Call> {
200        self.as_meta().invoke(args)
201            .ok_or_else(|| RuntimeError::metamethod_not_supported(self, MethodTag::Invoke))?
202    }
203    
204    pub fn fmt_repr(&self) -> ExecResult<StringValue> {
205        self.as_meta().fmt_repr()
206    }
207}
208
209// Set of supported metamethods
210#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
211pub enum MethodTag {
212    Invoke,
213    Len,
214    IterInit,
215    IterNext,
216    IterItem,
217    AsBool,
218    AsBits,
219    AsInt,
220    AsFloat,
221    FmtRepr,
222}
223
224impl MethodTag {
225    pub fn method_name(&self) -> &'static str {
226        match self {
227            Self::Invoke => "call",
228            
229            // iterators and iterables
230            Self::IterInit => "iter_init",
231            Self::IterNext => "iter_next",
232            Self::IterItem => "iter_get",
233            
234            // sequences
235            Self::Len => "len",
236            
237            // primitive coercion
238            Self::AsBool => "bool",
239            Self::AsBits => "bits",
240            Self::AsInt => "int",
241            Self::AsFloat => "float",
242            
243            // misc
244            Self::FmtRepr => "repr",
245        }
246    }
247}
248
249impl fmt::Display for MethodTag {
250    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
251        fmt.write_str(self.method_name())
252    }
253}