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}