phoenix_lang/native/
native_methods.rs

1use lazy_static::lazy_static;
2use std::sync::Mutex;
3
4use crate::chunk::ModuleChunk;
5use crate::value::Value::*;
6use crate::value::{HeapObjVal, Value};
7use crate::vm::{VMState, VM};
8use std::collections::HashMap;
9
10/// Format: self, args, vm, vm_state, modules, if it returns none, this function doesnt support the type
11/// Note: self is not mutable, because its the Pointer to the object, or a "primitive" value
12pub type NativeMethod =
13    fn(Value, Vec<Value>, &VM, &mut VMState, &[ModuleChunk]) -> Option<Result<Value, String>>;
14
15lazy_static! {
16    /// Format: name, (arity, function) if arity is None, the function is variadic
17    pub static ref NATIVE_METHODS: Mutex<HashMap<&'static str, (Option<usize>, NativeMethod)>> =
18        Mutex::new(HashMap::from([
19            (
20                "to_string",
21                (Some(0), to_string as NativeMethod)
22            ),
23            (
24                "type",
25                (Some(0), |this,_,_,_,_| {
26                    Some(Ok(PhoenixString(this.get_type().to_string())))
27                })
28            ),
29            (
30                "push",
31                (Some(1), |this, args, vm, state, modules| {
32                    // prepare a string in case we need it
33                    let push_string = &args[0].to_string(vm, state, &modules.to_vec());
34                    match this {
35                        PhoenixPointer(ptr) => {
36                            let obj = state.deref_mut(ptr);
37                            match obj.obj {
38                                HeapObjVal::PhoenixList(ref mut list) => {
39                                    list.values.push(args[0].clone());
40                                    Some(Ok(Nil))
41                                }
42                                HeapObjVal::PhoenixString(ref mut string) => {
43                                    string.value.push_str(push_string);
44                                    Some(Ok(Nil))
45                                }
46                                _ => None
47                            }
48                        }
49                        _ => None
50                    }
51                })
52            ),
53            (
54                "pop",
55                (Some(0), |this,_,_,state,_| {
56                    match this {
57                        PhoenixPointer(ptr) => {
58                            let obj = state.deref_mut(ptr);
59                            match obj.obj {
60                                HeapObjVal::PhoenixList(ref mut list) => {
61                                    Some(Ok(list.values.pop().unwrap_or(Nil)))
62                                }
63                                HeapObjVal::PhoenixString(ref mut string) => {
64                                    Some(Ok(PhoenixString(string.value.pop().unwrap_or('\0').to_string())))
65                                }
66                                _ => None
67                            }
68                        }
69                        _ => None
70                    }
71                })
72            ),
73            (
74                "len",
75                (Some(0), |this,_,_,state,_| {
76                    match this {
77                        PhoenixPointer(ptr) => {
78                            let obj = state.deref_mut(ptr);
79                            match obj.obj {
80                                HeapObjVal::PhoenixList(ref mut list) => {
81                                    Some(Ok(Long(list.values.len() as i64)))
82                                }
83                                HeapObjVal::PhoenixString(ref mut string) => {
84                                    Some(Ok(Long(string.value.len() as i64)))
85                                }
86                                HeapObjVal::PhoenixHashMap(ref mut hashmap) => {
87                                    Some(Ok(Long(hashmap.map.len() as i64)))
88                                }
89                                _ => None
90                            }
91                        }
92                        _ => None
93                    }
94                })
95            ),
96            (
97                "sort",
98                (Some(0), |this,_,_,state,_| {
99                    match this {
100                        PhoenixPointer(ptr) => {
101                            let obj = state.deref_mut(ptr);
102                            match obj.obj {
103                                HeapObjVal::PhoenixList(ref mut list) => {
104                                    list.values.sort_by(|a, b| {
105                                        if let Value::Float(a) = a {
106                                            if let Value::Float(b) = b {
107                                                return a.partial_cmp(b).unwrap();
108                                            }
109                                        }
110                                        if let Value::Long(a) = a {
111                                            if let Value::Long(b) = b {
112                                                return a.partial_cmp(b).unwrap();
113                                            }
114                                        }
115                                        panic!("Attempted to sort a list with non-numeric values");
116                                    });
117                                    Some(Ok(Nil))
118                                }
119                                _ => None
120                            }
121                        }
122                        _ => None
123                    }
124                })
125            ),
126            (
127                "get",
128                (Some(1), |this,args,_,state,_| {
129                    match this {
130                        PhoenixPointer(ptr) => {
131                            let obj = state.deref_mut(ptr);
132                            match obj.obj {
133                                HeapObjVal::PhoenixHashMap(ref mut map) => {
134                                    println!("{:?}, arg: {:?}", map.map, args);
135                                    Some(Ok(map.map.get(&args[0]).unwrap_or(&Nil).clone()))
136                                }
137                                _ => None
138                            }
139                        }
140                        _ => None
141                    }
142                })
143            ),
144        ]));
145}
146
147fn to_string(
148    this: Value,
149    _args: Vec<Value>,
150    vm: &VM,
151    state: &mut VMState,
152    modules: &[ModuleChunk],
153) -> Option<Result<Value, String>> {
154    Some(Ok(PhoenixString(this.to_string(
155        vm,
156        state,
157        &modules.to_vec(),
158    ))))
159}