pub use std::collections::HashMap;
use std::fmt::Debug;
use crate::Instance;
#[repr(C)]
pub struct FuncTable {
pub intern: fn(&[u8])-> Ident,
pub err: fn(&str)->!,
pub find_var: fn(Scope, Ident)-> Option<LitrRef>,
pub let_var: fn(Scope, Ident, Litr),
pub const_var: fn(Scope, Ident),
pub using: fn(Scope, Ident, crate::Class),
pub call_local: fn(&LocalFunc, Vec<Litr>)-> Litr,
pub call_at: fn(Scope, *mut Litr, &LocalFunc, Vec<Litr>)-> Litr,
pub get_self: fn(Scope)-> *mut Litr,
pub get_parent: fn(Scope)-> Option<Scope>,
pub outlive_inc: fn(Scope),
pub outlive_dec: fn(Scope),
pub symcls: fn()-> crate::Class,
pub wait_inc: fn(),
pub wait_dec: fn(),
pub planet_new: fn()-> (*mut (), crate::Class),
pub planet_ok: fn(*mut (), Litr),
pub local_instance_clone: fn(&[usize;3])-> [usize;3],
pub local_instance_drop: fn(&mut[usize;3]),
}
pub static mut FUNCTABLE:*const FuncTable = std::ptr::null();
pub fn intern(s:&[u8])-> Ident {
unsafe{ ((*FUNCTABLE).intern)(s) }
}
#[no_mangle]
extern fn premain(table: &FuncTable) {
std::panic::set_hook(Box::new(|inf|{
let s = if let Some(s) = inf.payload().downcast_ref::<String>() {s}
else if let Some(s) = inf.payload().downcast_ref::<&str>() {s}else {"错误"};
unsafe{((*FUNCTABLE).err)(s)};
}));
unsafe {
FUNCTABLE = table;
}
}
#[derive(Debug, Clone, Copy)]
pub struct Ident {
pub p: &'static Box<[u8]>
}
impl Ident {
pub fn str(&self)-> String {
String::from_utf8_lossy(&self.p).into_owned()
}
pub fn slice(&self)-> &[u8] {
self
}
}
impl std::ops::Deref for Ident {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&*self.p
}
}
impl std::fmt::Display for Ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.str())
}
}
#[derive(Debug, Clone, Copy)]
pub struct Scope(*mut ());
impl Scope {
pub fn find_var(self, s:&str)-> Option<LitrRef> {
unsafe{((*FUNCTABLE).find_var)(self, intern(s.as_bytes()))}
}
pub fn let_var(self, s:&str, v:Litr) {
unsafe{((*FUNCTABLE).let_var)(self, intern(s.as_bytes()), v)}
}
pub fn const_var(self, s:&str) {
unsafe{((*FUNCTABLE).const_var)(self, intern(s.as_bytes()))}
}
pub fn get_self(self)-> *mut Litr {
unsafe{((*FUNCTABLE).get_self)(self)}
}
pub fn get_parent(self)-> Option<Scope> {
unsafe{((*FUNCTABLE).get_parent)(self)}
}
pub fn using(self, name:&str, cls:crate::Class) {
unsafe{((*FUNCTABLE).using)(self, intern(name.as_bytes()), cls)}
}
}
unsafe impl Send for Scope {}
#[derive(Debug, Clone)]
pub enum Litr {
Uninit,
Int (isize),
Uint (usize),
Float (f64),
Bool (bool),
Func (Function),
Str (String),
Buf (Vec<u8>),
List (Vec<Litr>),
Obj (HashMap<Ident, Litr>),
Inst ([usize;3]),
Ninst (Instance)
}
unsafe impl Send for Litr {}
unsafe impl Sync for Litr {}
#[derive(Debug, Clone)]
pub enum Function {
Native(crate::NativeFn),
Local(LocalFunc),
Extern([usize;4])
}
impl Function {
pub fn call(&self, args:Vec<LitrRef>, cx:Scope)-> Litr {
match self {
Function::Local(f)=> unsafe{
let args = args.into_iter().map(|n|n.own()).collect();
((*FUNCTABLE).call_at)(cx, cx.get_self(), f, args)
}
Function::Native(f)=> f(args, cx),
_=> Litr::Uninit
}
}
}
#[derive(Debug)]
#[repr(C)]
pub struct LocalFunc {
ptr:*const (),
scope: Scope,
}
unsafe impl Send for LocalFunc {}
impl Clone for LocalFunc {
fn clone(&self) -> Self {
let scope = self.scope;
crate::outlive_inc(scope);
LocalFunc { ptr: self.ptr, scope }
}
}
impl Drop for LocalFunc {
fn drop(&mut self) {
crate::outlive_dec(self.scope)
}
}
impl LocalFunc {
pub fn call(&self, args:Vec<Litr>)-> Litr {
unsafe{((*FUNCTABLE).call_local)(self, args)}
}
pub fn call_at(&self, scope:Scope, kself:*mut Litr, args:Vec<Litr>)-> Litr {
unsafe{((*FUNCTABLE).call_at)(scope, kself, self, args)}
}
pub fn scope(&self)-> Scope {
self.scope
}
}
struct LocalInstance([usize;3]);
impl Clone for LocalInstance {
fn clone(&self) -> Self {
LocalInstance((unsafe{&*FUNCTABLE}.local_instance_clone)(&self.0))
}
}
impl Drop for LocalInstance {
fn drop(&mut self) {
(unsafe{&*FUNCTABLE}.local_instance_drop)(&mut self.0)
}
}
pub struct Sym;
impl Sym {
pub const ITER_END:usize = 1;
pub fn is_sym(v:&Instance)-> bool {
v.cls == (unsafe{&*FUNCTABLE}.symcls)()
}
pub fn iter_end()-> Litr {
(unsafe{&*FUNCTABLE}.symcls)().create(Self::ITER_END, 0)
}
}
pub enum LitrRef {
Ref(*mut Litr),
Own(Litr)
}
impl LitrRef {
pub fn own(self)-> Litr {
match self {
LitrRef::Ref(p)=> unsafe {(*p).clone()}
LitrRef::Own(v)=> v
}
}
}
impl std::ops::Deref for LitrRef {
type Target = Litr;
fn deref(&self) -> &Self::Target {
match self {
LitrRef::Ref(p)=> unsafe{&**p},
LitrRef::Own(b)=> b
}
}
}
impl std::ops::DerefMut for LitrRef {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
LitrRef::Ref(p)=> unsafe{&mut **p},
LitrRef::Own(b)=> b
}
}
}
impl Debug for LitrRef {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:?}", &**self))
}
}
pub struct PlanetCaller(*mut ());
impl PlanetCaller {
pub fn ok(&self, v:Litr) {
unsafe {((*FUNCTABLE).planet_ok)(self.0, v)}
}
}
unsafe impl Send for PlanetCaller {}
unsafe impl Sync for PlanetCaller {}
pub struct Planet;
impl Planet {
pub fn new(f:impl FnOnce(PlanetCaller))-> Litr {
let (planet, planet_cls) = unsafe {((*FUNCTABLE).planet_new)()};
f(PlanetCaller(planet));
Litr::Ninst(Instance {cls:planet_cls, v:planet as _, w:0})
}
}