1#![feature(const_ptr_is_null)]
9#![allow(unused)]
10
11use std::{cell::UnsafeCell, collections::HashMap, mem::transmute};
12
13pub mod key;
14use key::*;
15
16#[derive(Debug)]
18#[repr(C)]
19pub struct Instance {
20 pub v: usize,
22 pub w: usize,
24 pub cls: Class
26}
27
28impl Clone for Instance {
29 fn clone(&self) -> Self {
31 unsafe{((**self.cls.p.get()).onclone)(self)}
32 }
33}
34impl Drop for Instance {
35 fn drop(&mut self) {
37 unsafe{((**self.cls.p.get()).ondrop)(self)}
38 }
39}
40
41fn default_onclone(v:&Instance)-> Instance {
43 v.clone()
44}
45
46impl Instance {
47 pub fn read<T>(&self)-> &mut T {
51 unsafe { &mut*(self.v as *mut T) }
52 }
53 pub fn readw<T>(&self)-> &mut T {
55 unsafe { &mut*(self.w as *mut T) }
56 }
57
58 pub fn set<T>(&mut self, v:T) {
62 self.dropv::<T>();
63 self.v = to_ptr(v);
64 }
65 pub fn setw<T>(&mut self, w:T) {
67 self.dropw::<T>();
68 self.w = to_ptr(w);
69 }
70
71 fn dealloc<T>(&self, p:*mut T) {
73 assert!(!p.is_null(), "无法析构空指针.{}\n 详见https://docs.subkey.top/native/4.class", {
74 if unsafe{&**self.cls.p.get()}.onclone == default_onclone
75 {"\n 你或许应该为class定义onclone"}else {""}
76 });
77 unsafe {
78 std::ptr::drop_in_place(p);
79 let lo = std::alloc::Layout::new::<T>();
80 std::alloc::dealloc(p as _, lo);
81 }
82 }
83 pub fn dropv<T>(&mut self) {
85 self.dealloc(self.v as *mut T);
86 self.v = 0;
87 }
88 pub fn dropw<T>(&mut self) {
90 self.dealloc(self.w as *mut T);
91 self.w = 0;
92 }
93}
94
95
96pub type NativeFn = fn(Vec<LitrRef>, Scope)-> Litr;
98pub type NativeMethod = fn(&mut Instance, args:Vec<LitrRef>, Scope)-> Litr;
100
101#[derive(Debug, Clone)]
103#[repr(C)]
104struct ClassInner {
105 statics: Vec<(Ident, NativeFn)>,
106 methods: Vec<(Ident, NativeMethod)>,
107 name: Ident,
108 getter: fn(&Instance, get:Ident)-> Litr,
109 setter: fn(&mut Instance, set:Ident, to:Litr),
110 index_get: fn(&Instance, LitrRef)-> Litr,
111 index_set: fn(&mut Instance, LitrRef, Litr),
112 next: fn(&mut Instance)-> Litr,
113 to_str: fn(&Instance)-> String,
114 onclone: fn(&Instance)-> Instance,
115 ondrop: fn(&mut Instance)
116}
117
118#[repr(transparent)]
120#[derive(Debug)]
121pub struct Class {
122 p: UnsafeCell<*mut ClassInner>
123}
124impl Clone for Class {
125 fn clone(&self) -> Self {
126 Class {p: UnsafeCell::new(unsafe{*self.p.get()})}
127 }
128}
129
130unsafe impl Send for Class {}
131unsafe impl Sync for Class {}
132
133macro_rules! impl_class_setter {($($doc:literal $f:ident($t:ty);)*) => {
134 $(
135 #[doc = $doc]
136 pub fn $f(&self, f:$t) {
137 self.assert();
138 unsafe{(**self.p.get()).$f = f;}
139 }
140 )*
141}}
142impl Class {
143 pub const fn uninit()-> Self {
147 Class { p: UnsafeCell::new(std::ptr::null_mut()) }
148 }
149 #[inline]
150 const fn assert(&self) {
152 unsafe{
153 assert!(!(
154 *((&self.p) as *const UnsafeCell<*mut ClassInner> as *const *mut ClassInner)
155 ).is_null(), "请先为Class调用new方法"
156 )}
157 }
158 pub fn new(&self, name:&str) {
162 let v = ClassInner {
163 getter:|_,_|Litr::Uninit,
164 setter:|_,_,_|(),
165 statics: Vec::new(),
166 methods: Vec::new() ,
167 index_get:|_,_|Litr::Uninit,
168 index_set:|_,_,_|(),
169 next:|_|key::Sym::iter_end(),
170 to_str: |v|format!("{} {{ Native }}", unsafe{&**v.cls.p.get()}.name),
171 onclone:default_onclone,
172 ondrop:|_|(),
173 name:intern(name.as_bytes())
174 };
175 let p = Box::into_raw(Box::new(v));
176 unsafe{*self.p.get() = p}
177 }
178 pub fn create_raw(&self, v:usize, w:usize)-> Instance {
182 self.assert();
183 Instance { cls: self.clone(), v, w }
184 }
185 pub fn create(&self, v:usize, w:usize)-> Litr {
189 Litr::Ninst(self.create_raw(v, w))
190 }
191 impl_class_setter!{
192 "设置getter, 用来处理`.`运算符"
193 getter(fn(&Instance, get:Ident)-> Litr);
194 "设置setter, 用来处理a.b = c的写法"
195 setter(fn(&mut Instance, set:Ident, to:Litr));
196 "设置index getter, 返回a[i]的值"
197 index_get(fn(&Instance, LitrRef)-> Litr);
198 "设置index setter, 处理a[i] = b"
199 index_set(fn(&mut Instance, LitrRef, Litr));
200 "设置迭代器, 处理for n:instance {}"
201 next(fn(&mut Instance)-> Litr);
202 "自定义复制行为(往往是赋值和传参)"
203 onclone(fn(&Instance)-> Instance);
204 "自定义垃圾回收回收行为(只需要写额外工作,不需要drop此指针)"
205 ondrop(fn(&mut Instance));
206 "自定义Str::from得到的字符串"
207 to_str(fn(&Instance)-> String);
208 }
209 pub fn method(&self, name:&str, f:NativeMethod) {
211 self.assert();
212 unsafe{(**self.p.get()).methods.push((intern(name.as_bytes()), f));}
213 }
214 pub fn static_method(&self, name:&str, f:NativeFn) {
216 self.assert();
217 unsafe{(**self.p.get()).statics.push((intern(name.as_bytes()), f));}
218 }
219}
220
221impl PartialEq for Class {
222 fn eq(&self, other: &Self) -> bool {
223 unsafe{*self.p.get() == *other.p.get()}
224 }
225}
226
227
228#[repr(C)]
230pub struct NativeModule {
231 funcs: *mut Vec<(Ident, NativeFn)>,
232 classes: *mut Vec<Class>
233}
234impl NativeModule {
235 pub fn export_fn(&mut self, name:&str, f:NativeFn) {
237 unsafe{&mut *self.funcs}.push((intern(name.as_bytes()), f))
238 }
239 pub fn export_cls(&mut self, cls:Class) {
243 cls.assert();
244 unsafe{&mut *self.classes}.push(cls);
245 }
246}
247
248#[macro_export]
249macro_rules! get_arg {
250 ($args:ident[$i:literal]?)=> {
251 $args.get($i).map_or(&Litr::Uninit, |n|&**n)
252 };
253 ($args:ident[$i:literal])=> {
254 match $args.get($i) {
255 Some(v)=> &**v,
256 _=> panic!("至少需要{}个参数", $i+1)
257 }
258 };
259 ($args:ident[$i:literal]:$t:ident)=> {
260 match $args.get($i) {
261 Some(v)=> match &**v {
262 Litr::$t(v)=> v,
263 _=> panic!("第{}个参数必须是{}", $i+1, stringify!($t))
264 },
265 _=> panic!("至少需要{}个参数", $i+1)
266 }
267 };
268 ($args:ident[$i:literal]:$t:ident?$def:expr)=> {
269 $args.get($i).map_or($def, |val|{
270 match &**val {
271 Litr::$t(n)=> *n as u64,
272 _=> $def
273 }
274 });
275 }
276}
277
278#[inline]
280pub fn to_ptr<T>(v:T)-> usize {
281 Box::into_raw(Box::new(v)) as usize
282}
283
284pub fn outlive_inc(s:Scope) {
290 unsafe{((*FUNCTABLE).outlive_inc)(s)};
291}
292pub fn outlive_dec(s:Scope) {
294 unsafe{((*FUNCTABLE).outlive_dec)(s)};
295}
296
297pub fn wait_inc() {
299 unsafe{((*FUNCTABLE).wait_inc)()};
300}
301pub fn wait_dec() {
303 unsafe{((*FUNCTABLE).wait_dec)()};
304}
305
306pub mod prelude {
307 pub use crate::key::{Litr, LitrRef, Scope, Ident};
308 pub use crate::{NativeModule, Class, get_arg, Instance, to_ptr};
309}