diff --git a/Cargo.lock b/Cargo.lock index 39218cdb..dfe05b7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1151,7 +1151,6 @@ dependencies = [ "rust-i18n", "rustyline", "shadow-rs", - "stdlib", "suffix_array", "sys-locale", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 606730c8..3cd1d850 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ num-bigint = "0.4" # llvm-sys = "170.0.1" derive = { path = "./derive" } libloading = "0.8" -stdlib = { path = "./stdlib" } +# stdlib = { path = "./stdlib" } rust-i18n = "3.0" sys-locale = "0.3" rustyline = { version = "14.0", features = ["with-file-history"] } diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 1f07ea8b..8808a789 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -160,11 +160,10 @@ pub fn trc_class(_: TokenStream, input: TokenStream) -> TokenStream { // 目前的实现策略是先提供一个由once_cell储存的usize数,表示在类型表中的索引,里面储存该类型的Rc指针 // 因为很可能某个函数的参数就是标准库中的某个类型,所以我们需要先将类型导入到class_table中 let ret = quote!(#input - use std::sync::OnceLock; impl #name { pub fn init_info(storage: Option<&mut ModuleStorage>) -> usize { use std::collections::hash_map::HashMap; - static CLASS_ID: OnceLock = OnceLock::new(); + static CLASS_ID: std::sync::OnceLock = std::sync::OnceLock::new(); *CLASS_ID.get_or_init(|| { let mut members = HashMap::new(); #( @@ -247,3 +246,31 @@ pub fn trc_const(_: TokenStream, input: TokenStream) -> TokenStream { input.expr = parse_str(&format!("stringify!({})", input.expr.to_token_stream(),)).unwrap(); quote!(#input).into() } + +#[proc_macro] +pub fn def_module_export(_t: TokenStream) -> TokenStream { + quote!( + fn import_lib() -> (&'static libcore::Module, &'static libcore::ModuleStorage) { + // this is for any type + static STDLIB_STORAGE: std::sync::OnceLock = std::sync::OnceLock::new(); + static RETURN_VAL: std::sync::OnceLock = std::sync::OnceLock::new(); + let stro = STDLIB_STORAGE.get_or_init(|| { + let mut storage = libcore::ModuleStorage::new(); + RETURN_VAL.get_or_init(|| module_init(&mut storage)); + storage + }); + (RETURN_VAL.get().unwrap(), stro) + } + + #[no_mangle] + pub fn get_lib() -> &'static libcore::Module { + import_lib().0 + } + + #[no_mangle] + pub fn get_storage() -> &'static libcore::ModuleStorage { + import_lib().1 + } + ) + .into() +} diff --git a/libcore/src/error.rs b/libcore/src/error.rs index e3329f59..6acf852e 100644 --- a/libcore/src/error.rs +++ b/libcore/src/error.rs @@ -47,6 +47,13 @@ pub fn symbol_redefined(name: &str) -> ErrorInfo { ErrorInfo::new(t!(SYMBOL_REDEFINED, "0" = name), t!(SYMBOL_ERROR)) } +pub fn module_not_found(module_name: &str) -> ErrorInfo { + ErrorInfo::new( + t!(MODULE_NOT_FOUND, "0" = module_name), + t!(MODULE_NOT_FOUND_ERROR), + ) +} + #[derive(Debug)] pub struct ErrorInfo { pub message: String, diff --git a/libcore/src/gc.rs b/libcore/src/gc.rs index b0b863be..ac6a1374 100644 --- a/libcore/src/gc.rs +++ b/libcore/src/gc.rs @@ -1,15 +1,18 @@ //! provide gc for trc #[derive(Default, Debug)] -pub struct GcMgr {} +pub struct GcMgr { + objs: Vec<*mut ()>, +} impl GcMgr { pub fn new() -> Self { - Self {} + Self { objs: Vec::new() } } pub fn alloc(&mut self, obj: T) -> *mut T { // unsafe { alloc(Layout::new::()) as *mut T } + // TODO: change it into alloc and change = into write Box::into_raw(Box::new(obj)) } } diff --git a/libcore/src/lib.rs b/libcore/src/lib.rs index a65f90f3..4a499e5c 100644 --- a/libcore/src/lib.rs +++ b/libcore/src/lib.rs @@ -11,4 +11,7 @@ pub use error::*; pub use libbasic::*; pub use types::*; +pub const GET_LIB_FUNC_NAME: &str = "get_lib"; +pub const GET_STORAGE_FUNC_NAME: &str = "get_storage"; + rust_i18n::i18n!("locales"); diff --git a/libcore/src/libbasic.rs b/libcore/src/libbasic.rs index 63c1e3ca..6c5d972d 100644 --- a/libcore/src/libbasic.rs +++ b/libcore/src/libbasic.rs @@ -7,7 +7,7 @@ use std::{ use super::{codegen::Opcode, error::*}; -type StdlibFunc = fn(&mut DynaData) -> RuntimeResult<()>; +pub type RustlibFunc = fn(&mut DynaData) -> RuntimeResult<()>; pub type ScopeAllocIdTy = usize; pub type TypeAllowNull = Option; @@ -55,7 +55,7 @@ pub type ArgsNameTy = Vec; pub struct RustFunction { pub name: String, pub buildin_id: usize, - pub ptr: StdlibFunc, + pub ptr: RustlibFunc, pub io: IOType, } @@ -110,6 +110,7 @@ pub trait FunctionInterface: Downcast + Debug { fn get_io(&self) -> &IOType; fn get_name(&self) -> &str; fn get_io_mut(&mut self) -> &mut IOType; + fn get_func_id(&self) -> usize; } impl_downcast!(FunctionInterface); @@ -144,6 +145,10 @@ impl FunctionInterface for RustFunction { fn get_name(&self) -> &str { &self.name } + + fn get_func_id(&self) -> usize { + self.buildin_id + } } #[derive(Debug, Clone)] @@ -235,8 +240,9 @@ impl Display for RustClass { /// 最基础的储存一个动态链接库中的函数和类的地方 #[derive(Default)] +#[repr(C)] pub struct ModuleStorage { - pub func_table: Vec, + pub func_table: Vec, pub class_table: Vec, } @@ -248,7 +254,7 @@ impl ModuleStorage { } } - pub fn add_func(&mut self, f: StdlibFunc) -> usize { + pub fn add_func(&mut self, f: RustlibFunc) -> usize { self.func_table.push(f); self.func_table.len() - 1 } @@ -267,7 +273,7 @@ impl ModuleStorage { impl RustFunction { pub fn new( name: impl Into, - ptr: StdlibFunc, + ptr: RustlibFunc, io: IOType, storage: &mut ModuleStorage, ) -> RustFunction { @@ -282,13 +288,14 @@ impl RustFunction { } #[derive(Debug, Clone)] +#[repr(C)] pub struct Module { - pub name: String, - pub sub_modules: HashMap, - pub functions: HashMap, + name: String, + sub_modules: HashMap, + functions: HashMap, // class name 和class id - pub classes: HashMap, - pub consts: HashMap, + classes: HashMap, + consts: HashMap, } impl Module { @@ -327,6 +334,46 @@ impl Module { let lock = self.sub_modules.get(&item.into()).unwrap(); lock.get_module(path) } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn set_name(&mut self, name: String) { + self.name = name; + } + + pub fn sub_modules(&self) -> &HashMap { + &self.sub_modules + } + + pub fn set_sub_modules(&mut self, sub_modules: HashMap) { + self.sub_modules = sub_modules; + } + + pub fn functions(&self) -> &HashMap { + &self.functions + } + + pub fn set_functions(&mut self, functions: HashMap) { + self.functions = functions; + } + + pub fn classes(&self) -> &HashMap { + &self.classes + } + + pub fn consts(&self) -> &HashMap { + &self.consts + } + + pub fn set_consts(&mut self, consts: HashMap) { + self.consts = consts; + } + + pub fn set_classes(&mut self, classes: HashMap) { + self.classes = classes; + } } pub const INT: &str = "int"; diff --git a/src/base.rs b/src/base.rs index 6fe177f1..2d627d15 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,2 +1,3 @@ pub mod ctrc; +pub mod dll; pub mod utils; diff --git a/src/base/dll.rs b/src/base/dll.rs new file mode 100644 index 00000000..2f0bcdb8 --- /dev/null +++ b/src/base/dll.rs @@ -0,0 +1,12 @@ +use libcore::{Module, ModuleStorage}; + +pub type GetLibFuncTy = unsafe fn() -> &'static Module; +pub type GetStorageFuncTy = unsafe fn() -> &'static ModuleStorage; + +pub fn load_module_storage(lib: &libloading::Library) -> (&'static Module, &'static ModuleStorage) { + let get_lib_func: libloading::Symbol = + unsafe { lib.get(libcore::GET_LIB_FUNC_NAME.as_bytes()).unwrap() }; + let get_storage_func: libloading::Symbol = + unsafe { lib.get(libcore::GET_STORAGE_FUNC_NAME.as_bytes()).unwrap() }; + unsafe { (get_lib_func(), get_storage_func()) } +} diff --git a/src/compiler.rs b/src/compiler.rs index 1f5fb5f6..402fa2ec 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -140,19 +140,20 @@ pub struct ValuePool { const_floats: Pool, name_pool: Pool, _const_big_int: Pool, - id_int: Vec, - id_float: Vec, - id_str: Vec, - id_name: Vec, + pub id_int: Vec, + pub id_float: Vec, + pub id_str: Vec, + pub id_name: Vec, } pub const INT_VAL_POOL_ZERO: usize = 0; pub const INT_VAL_POOL_ONE: usize = 1; -macro_rules! gen_add_funcs { +macro_rules! gen_getter_setter { ($($func_name:ident => ($const_pool:ident, $id_pool:ident, $type:ty)),*) => { $( - fn $func_name(&mut self, val: $type) -> usize { + paste::paste!{ + pub fn [](&mut self, val: $type) -> usize { let len_tmp = self.$const_pool.len(); let ret = *self.$const_pool.entry(val.clone()).or_insert(len_tmp); if len_tmp != self.$const_pool.len() { @@ -160,6 +161,10 @@ macro_rules! gen_add_funcs { } ret } + pub fn [](&self, val: &$type) -> Option { + self.$const_pool.get(val).copied() + } + } )* }; } @@ -174,11 +179,11 @@ impl ValuePool { ret } - gen_add_funcs!( - add_int => (const_ints, id_int, i64), - add_float => (const_floats, id_float, Float), - add_string => (const_strings, id_str, String), - add_id => (name_pool, id_name, String) + gen_getter_setter!( + int => (const_ints, id_int, i64), + float => (const_floats, id_float, Float), + string => (const_strings, id_str, String), + id => (name_pool, id_name, String) ); fn store_val_to_vm(&mut self) -> ConstPool { diff --git a/src/compiler/ast.rs b/src/compiler/ast.rs index a0a8caf1..f3bdefb9 100644 --- a/src/compiler/ast.rs +++ b/src/compiler/ast.rs @@ -1,16 +1,15 @@ mod ast_base; mod lexprocess; -use crate::compiler::token::TokenType::RightBigBrace; -use libcore::*; -use rust_i18n::t; -use std::{cell::RefCell, mem::swap, rc::Rc}; - use super::{ scope::*, token::{ConstPoolIndexTy, TokenType}, InputSource, TokenLex, }; +use crate::{base::dll::load_module_storage, compiler::token::TokenType::RightBigBrace}; +use libcore::*; +use rust_i18n::t; +use std::{cell::RefCell, mem::swap, path::PathBuf, rc::Rc}; #[derive(Default)] struct Cache { @@ -112,20 +111,28 @@ macro_rules! expr_gen { impl<'a> AstBuilder<'a> { pub fn new(mut token_lexer: TokenLex<'a>) -> Self { - let prelude = stdlib::get_stdlib().sub_modules.get("prelude").unwrap(); - for i in &prelude.functions { + let root_scope = Rc::new(RefCell::new(SymScope::new(None))); + let stdlib_dll = unsafe { + libloading::Library::new(libloading::library_filename("stdlib")) + .expect("without stdlib") + }; + let (stdlib, stdstorage) = load_module_storage(&stdlib_dll); + let prelude = stdlib.sub_modules().get("prelude").unwrap(); + for i in prelude.functions() { token_lexer.const_pool.add_id(i.0.clone()); } - for i in &prelude.classes { + for i in prelude.classes() { token_lexer.const_pool.add_id(i.0.clone()); } - let root_scope = Rc::new(RefCell::new(SymScope::new(None))); // 为root scope添加prelude let _optimize = token_lexer.compiler_data.option.optimize; root_scope .borrow_mut() - .import_prelude(&token_lexer.const_pool) + .import_native_module(prelude, stdstorage, &token_lexer.const_pool) .expect("Import prelude but failed"); + root_scope + .borrow_mut() + .add_imported_native_dll("std".to_string(), Rc::new(stdlib_dll)); let mut cache = Cache::new(); let val_pool_ref = &token_lexer.const_pool; cache.intty_id = root_scope @@ -839,38 +846,96 @@ impl<'a> AstBuilder<'a> { .get_token_checked(TokenType::StringValue)? .data .unwrap(); - let mut path = self.token_lexer.const_pool.id_str[tok].clone(); - // the standard library first - if path.starts_with("std") { + let mut path_with_dot = self.token_lexer.const_pool.id_str[tok].clone(); + let mut import_file_path = String::new(); + let mut is_dll = false; + if path_with_dot.starts_with("std") { + // std特殊对待 + import_file_path = "std".to_string(); + is_dll = true; + } else { + // 判断是dll还是普通模块 + match self.token_lexer.compiler_data.option.inputsource.clone() { + InputSource::File(now_module_path) => { + let path = PathBuf::from(path_with_dot.replace('.', "/")); + let mut now_module_path = PathBuf::from(now_module_path); + now_module_path.pop(); + now_module_path = now_module_path.join(path.clone()); + let tmp = now_module_path.clone(); + let file_name = match tmp.file_name() { + None => { + return self.try_err(istry, module_not_found(path.to_str().unwrap())) + } + Some(v) => v, + }; + let file_name_dll = libloading::library_filename(file_name); + // 优先判断dll + now_module_path.set_file_name(file_name_dll); + if now_module_path.exists() { + is_dll = true; + now_module_path + .to_str() + .unwrap() + .clone_into(&mut import_file_path); + } else { + let file_name_trc = format!("{}{}", file_name.to_str().unwrap(), ".trc"); + now_module_path.set_file_name(file_name_trc); + // now_module_path.ex + if now_module_path.exists() { + // 创建新的compiler来编译模块 + // self.self_scope.as_any().borrow_mut().import_module(); + } else { + return self.try_err(istry, module_not_found(path.to_str().unwrap())); + } + } + } + _ => { + return self.try_err( + istry, + ErrorInfo::new(t!(CANNOT_IMPORT_MODULE_WITHOUT_FILE), t!(SYMBOL_ERROR)), + ); + } + } + } + if is_dll { // 导入对象可能是模块,也有可能是函数,类等,先单独截取出来 let mut import_item_name = String::new(); loop { - let c = path.pop().unwrap(); + let c = path_with_dot.pop().unwrap(); if c == '.' { break; } import_item_name = format!("{}{}", c, import_item_name); } - let mut items = path.split('.'); + let mut items = path_with_dot.split('.'); + let dll_lib = self + .self_scope + .borrow_mut() + .get_dll(&import_file_path) + .expect("error not found dll"); + let (lib_module, lib_storage) = load_module_storage(dll_lib.as_ref()); // 删除std items.next(); - let now = match stdlib::get_stdlib().get_module(items) { + let now = match lib_module.get_module(items) { Some(d) => d, None => { return self.try_err( istry, - ErrorInfo::new(t!(SYMBOL_NOT_FOUND, "0" = path), t!(SYMBOL_ERROR)), + ErrorInfo::new(t!(SYMBOL_NOT_FOUND, "0" = path_with_dot), t!(SYMBOL_ERROR)), ); } }; - match now.sub_modules.get(&import_item_name) { + match now.sub_modules().get(&import_item_name) { None => { // 不是模块 - match now.functions.get(&import_item_name) { + match now.functions().get(&import_item_name) { None => { return self.try_err( istry, - ErrorInfo::new(t!(SYMBOL_NOT_FOUND, "0" = path), t!(SYMBOL_ERROR)), + ErrorInfo::new( + t!(SYMBOL_NOT_FOUND, "0" = path_with_dot), + t!(SYMBOL_ERROR), + ), ); } Some(func_item) => { @@ -880,7 +945,7 @@ impl<'a> AstBuilder<'a> { let func_id = self.insert_sym_with_error(token_idx)?; self.self_scope .borrow_mut() - .add_func(func_id, Rc::new(func_item.clone())); + .add_extern_func(func_id, func_item.clone()); } } } @@ -895,7 +960,7 @@ impl<'a> AstBuilder<'a> { .add_imported_module(module_sym_idx, sub_module.clone()); if let Err(e) = sub_module.borrow_mut().import_native_module( module, - stdlib::get_storage(), + lib_storage, &self.token_lexer.const_pool, ) { return self.try_err(istry, e); @@ -903,34 +968,7 @@ impl<'a> AstBuilder<'a> { } } } else { - // custom module - match self.token_lexer.compiler_data.option.inputsource.clone() { - InputSource::File(now_module_path) => { - let path = std::path::PathBuf::from(path.replace('.', "/")); - let mut now_module_path = std::path::PathBuf::from(now_module_path); - now_module_path.pop(); - // 找到想找到的文件 - now_module_path = now_module_path.join(path.clone()); - if now_module_path.exists() { - // 创建新的compiler来编译模块 - // self.self_scope.as_any().borrow_mut().import_module(); - } else { - return self.try_err( - istry, - ErrorInfo::new( - t!(MODULE_NOT_FOUND, "0" = path.to_str().unwrap()), - t!(MODULE_NOT_FOUND_ERROR), - ), - ); - } - } - _ => { - return self.try_err( - istry, - ErrorInfo::new(t!(CANNOT_IMPORT_MODULE_WITHOUT_FILE), t!(SYMBOL_ERROR)), - ); - } - } + todo!() } Ok(()) } @@ -962,7 +1000,7 @@ impl<'a> AstBuilder<'a> { } /// 生成新建变量的指令 - fn new_var(&mut self, name: ConstPoolIndexTy, varty: ScopeAllocClassId) -> AstError<()> { + fn new_var(&mut self, name: ConstPoolIndexTy, varty: ClassIdxId) -> AstError<()> { let sym_idx = self.insert_sym_with_error(name)?; let (_var_sym, var_addr) = self.self_scope diff --git a/src/compiler/ast/ast_base.rs b/src/compiler/ast/ast_base.rs index 1e56d8c1..77739c5d 100644 --- a/src/compiler/ast/ast_base.rs +++ b/src/compiler/ast/ast_base.rs @@ -1,11 +1,11 @@ use super::AstBuilder; use super::AstError; -use crate::compiler::token::ConstPoolIndexTy; use crate::compiler::token::Token; use crate::compiler::token::TokenType; +use crate::compiler::{scope::SymScope, token::ConstPoolIndexTy}; use libcore::*; use rust_i18n::t; -use std::mem::size_of; +use std::{cell::RefCell, mem::size_of, rc::Rc}; impl<'a> AstBuilder<'a> { pub fn clear_inst(&mut self) { @@ -158,10 +158,10 @@ impl<'a> AstBuilder<'a> { } pub fn import_module_sym(&mut self, lib: &Module) { - for i in &lib.functions { + for i in lib.functions() { self.token_lexer.const_pool.add_id(i.0.clone()); } - for i in &lib.classes { + for i in lib.classes() { self.token_lexer.const_pool.add_id(i.0.clone()); } } @@ -189,4 +189,8 @@ impl<'a> AstBuilder<'a> { VmStackType::Object => Opcode::EqWithoutPop, } } + + pub fn get_scope(&self) -> Rc> { + self.self_scope.clone() + } } diff --git a/src/compiler/scope.rs b/src/compiler/scope.rs index 45e0622f..68ed138a 100644 --- a/src/compiler/scope.rs +++ b/src/compiler/scope.rs @@ -45,6 +45,10 @@ impl FunctionInterface for CustomFunction { fn get_io_mut(&mut self) -> &mut IOType { &mut self.io } + + fn get_func_id(&self) -> usize { + self.custom_id + } } /// Manager of type @@ -110,7 +114,7 @@ impl ClassInterface for CustomType { } } -pub type ScopeAllocClassId = usize; +pub type ClassIdxId = usize; pub type VarIdxTy = ScopeAllocIdTy; pub type FuncIdxTy = ScopeAllocIdTy; pub type FuncBodyTy = Vec<(Token, usize)>; @@ -137,7 +141,7 @@ pub struct SymScope { // 当前作用域要分配的下一个ID,也就是当前作用域的最大id+1 scope_sym_id: ScopeAllocIdTy, // ID到class id的映射 - types: HashMap, + types: HashMap, // ID到函数的映射 funcs: HashMap>, // id到变量类型的映射 @@ -145,11 +149,12 @@ pub struct SymScope { // 由token id到模块的映射 // modules: HashMap, // 当前作用域可以分配的下一个class id - types_id: ScopeAllocClassId, + types_id: ClassIdxId, vars_id: ScopeAllocIdTy, - funcs_custom_id: ScopeAllocIdTy, + funcs_custom_id: FuncIdxTy, + funcs_extern_id: FuncIdxTy, // 用户自定义的类型储存位置 - types_custom_store: HashMap>, + types_custom_store: HashMap>, // 作用域暂时储存的函数token pub funcs_temp_store: Vec<(ScopeAllocIdTy, Vec<(Token, usize)>)>, // 计算当前需要最少多大的空间来保存变量 @@ -164,6 +169,7 @@ pub struct SymScope { pub in_class: bool, pub is_pub: bool, imported_modules: HashMap>>, + imported_native: HashMap>, } impl SymScope { @@ -176,6 +182,7 @@ impl SymScope { ret.scope_sym_id = prev_scope.borrow().scope_sym_id; ret.types_id = prev_scope.borrow().types_id; ret.funcs_custom_id = prev_scope.borrow().funcs_custom_id; + ret.funcs_extern_id = prev_scope.borrow().funcs_extern_id; } ret } @@ -233,7 +240,7 @@ impl SymScope { libstorage: &ModuleStorage, const_pool: &ValuePool, ) -> Result<(), ErrorInfo> { - let types = &stdlib.classes; + let types = stdlib.classes(); // println!("{:?}", types); let mut obj_vec = vec![]; for i in types { @@ -257,33 +264,18 @@ impl SymScope { self.insert_type(i.0, Rc::new(i.1)) .expect("type symbol conflict"); } - let funcs = &stdlib.functions; + let funcs = stdlib.functions(); for i in funcs { let idx = self.insert_sym_with_error(const_pool.name_pool[i.0], i.0)?; // 在将类型全部添加进去之后,需要重新改写函数和类的输入和输出参数 let mut fobj = i.1.clone(); self.fix_func(fobj.get_io_mut(), libstorage, const_pool); - let fobj = Rc::new(fobj); - self.add_func(idx, fobj.clone()); + self.add_extern_func(idx, fobj); } // 改写类的重载方法 Ok(()) } - /// import the prelude of stdlib - /// - /// # Errors - /// - /// This function will return an error if can insert the symbol to scope. - /// - /// # Panics - /// When submodule prelude is not here - pub fn import_prelude(&mut self, const_pool: &ValuePool) -> Result<(), ErrorInfo> { - let lib = &stdlib::get_stdlib().sub_modules["prelude"]; - self.import_native_module(lib, stdlib::get_storage(), const_pool)?; - Ok(()) - } - pub fn get_module(&self, id: ScopeAllocIdTy) -> Option>> { let t = self.imported_modules.get(&id); match t { @@ -295,7 +287,7 @@ impl SymScope { } } - pub fn get_function(&self, id: usize) -> Option> { + pub fn get_function(&self, id: ScopeAllocIdTy) -> Option> { match self.funcs.get(&id) { Some(f) => Some(f.clone()), None => match self.prev_scope { @@ -353,10 +345,22 @@ impl SymScope { } } - pub fn add_func(&mut self, id: usize, f: Rc) { + fn add_func(&mut self, id: ScopeAllocIdTy, f: Rc) { self.funcs.insert(id, f); } + pub fn add_extern_func(&mut self, id: ScopeAllocIdTy, mut f: RustFunction) { + let funcid = self.alloc_extern_func_id(); + f.buildin_id = funcid; + self.add_func(id, Rc::new(f)) + } + + pub fn alloc_extern_func_id(&mut self) -> FuncIdxTy { + let ret = self.funcs_extern_id; + self.funcs_extern_id += 1; + ret + } + /// 返回变量的索引和内存地址 pub fn add_var(&mut self, id: ScopeAllocIdTy, ty: TyIdxTy, var_sz: usize) -> (VarIdxTy, usize) { let ret_addr = self.var_sz; @@ -372,7 +376,7 @@ impl SymScope { self.var_sz } - pub fn get_type_id(&self, id: ScopeAllocIdTy) -> Option { + pub fn get_type_id(&self, id: ScopeAllocIdTy) -> Option { match self.types.get(&id) { None => match self.prev_scope { Some(ref prev_scope) => prev_scope.borrow().get_type_id(id), @@ -390,10 +394,7 @@ impl SymScope { self.vars_id } - pub fn get_class_by_class_id( - &self, - classid: ScopeAllocClassId, - ) -> Option> { + pub fn get_class_by_class_id(&self, classid: ClassIdxId) -> Option> { // 不存在的类 if classid >= self.types_id { return None; @@ -421,11 +422,7 @@ impl SymScope { Ok(ret) } - fn insert_type( - &mut self, - id: ScopeAllocClassId, - f: Rc, - ) -> Result<(), ScopeError> { + fn insert_type(&mut self, id: ClassIdxId, f: Rc) -> Result<(), ScopeError> { self.types_custom_store.insert(id, f); Ok(()) } @@ -434,16 +431,24 @@ impl SymScope { &mut self, idx: ScopeAllocIdTy, obj: Rc, - ) -> Result { + ) -> Result { let ret = self.alloc_type_id(idx)?; self.insert_type(ret, obj)?; Ok(ret) } - pub fn get_type_id_by_token(&self, ty_name: ConstPoolIndexTy) -> Option { + pub fn get_type_id_by_token(&self, ty_name: ConstPoolIndexTy) -> Option { let ty_idx_id = self.get_sym(ty_name).unwrap(); self.get_type_id(ty_idx_id) } + + pub fn add_imported_native_dll(&mut self, dll_name: String, lib: Rc) { + self.imported_native.insert(dll_name, lib); + } + + pub fn get_dll(&self, name: &str) -> Option> { + self.imported_native.get(name).map(|v| (*v).clone()) + } } #[cfg(test)] diff --git a/src/tvm.rs b/src/tvm.rs index 8522c0c3..44ed1bb8 100644 --- a/src/tvm.rs +++ b/src/tvm.rs @@ -4,9 +4,7 @@ mod function; use self::function::Frame; use crate::cfg; use libcore::*; -use libloading::Library; use rust_i18n::t; -use std::sync::OnceLock; pub struct Vm<'a> { run_context: Context, @@ -43,56 +41,10 @@ impl Context { } } -/// Load libc -fn load_libc() -> Option<&'static Library> { - static LIBC: OnceLock> = OnceLock::new(); - #[cfg(target_os = "linux")] - { - let tmp = LIBC.get_or_init(|| unsafe { - let lib: Result = Library::new(""); - match lib { - Err(_) => None, - Ok(val) => Some(val), - } - }); - match tmp { - None => None, - Some(val) => Some(val), - } - } - #[cfg(target_os = "windows")] - { - let tmp = LIBC.get_or_init(|| unsafe { - let lib: Result = libloading::Library::new("msvcrt.dll"); - match lib { - Err(_) => None, - Ok(val) => Some(val), - } - }); - match tmp { - None => None, - Some(val) => Some(&val), - } - } - #[cfg(target_os = "macos")] - { - let tmp = LIBC.get_or_init(|| unsafe { - let lib: Result = libloading::Library::new("libc.dylib"); - match lib { - Err(_) => None, - Ok(val) => Some(val), - } - }); - match tmp { - None => None, - Some(val) => Some(&val), - } - } -} - pub struct DydataWrap { frames_stack: Vec, dydata: DynaData, + imported_func: Vec, } impl DydataWrap { @@ -100,6 +52,7 @@ impl DydataWrap { Self { frames_stack: Vec::new(), dydata: DynaData::new(), + imported_func: Vec::new(), } } } diff --git a/stdlib/Cargo.toml b/stdlib/Cargo.toml index 79692884..fd5d0bf7 100644 --- a/stdlib/Cargo.toml +++ b/stdlib/Cargo.toml @@ -12,3 +12,4 @@ rust-i18n = "3" [lib] name = "stdlib" +crate-type = ["dylib"] diff --git a/stdlib/src/lib.rs b/stdlib/src/lib.rs index ca0386d2..7e012f0e 100644 --- a/stdlib/src/lib.rs +++ b/stdlib/src/lib.rs @@ -1,7 +1,8 @@ -use derive::def_module; +use collection_literals::collection; +use derive::{def_module, def_module_export, trc_class, trc_method}; pub use libcore; use libcore::libbasic::*; -use std::{collections::HashMap, sync::OnceLock}; +use std::collections::HashMap; pub mod algo; pub mod ds; @@ -11,39 +12,21 @@ pub mod sys; rust_i18n::i18n!("locales"); -def_module!( - module_name = std, - submodules = [prelude, ds, algo, math, sys] -); - -/// 导入标准库 -fn import_stdlib() -> (&'static Module, &'static ModuleStorage) { - // this is for any type - static STDLIB_STORAGE: OnceLock = OnceLock::new(); - static RETURN_VAL: OnceLock = OnceLock::new(); - let stro = STDLIB_STORAGE.get_or_init(|| { - let mut storage = ModuleStorage::new(); - // any - RustClass::new_in_storage("any", HashMap::new(), None, None, &mut storage); - RETURN_VAL.get_or_init(|| module_init(&mut storage)); - storage - }); - (RETURN_VAL.get().unwrap(), stro) -} +#[trc_class] +struct TrcAny {} -pub fn get_stdlib() -> &'static Module { - import_stdlib().0 +impl TrcAny { + fn override_export() -> HashMap { + collection_literals::hash![] + } } -pub fn get_storage() -> &'static ModuleStorage { - import_stdlib().1 -} +#[trc_method] +impl TrcAny {} -pub fn get_prelude_function(func_name: &str) -> Option<&'static RustFunction> { - get_stdlib() - .sub_modules - .get("prelude") - .unwrap() - .functions - .get(func_name) -} +def_module!( + module_name = std, + classes = [TrcAny => any] + submodules = [prelude, ds, algo, math, sys] +); +def_module_export!(); diff --git a/tests/test_compiler.rs b/tests/test_compiler.rs index 991bae8d..3b2b5619 100644 --- a/tests/test_compiler.rs +++ b/tests/test_compiler.rs @@ -1,6 +1,6 @@ use libcore::*; use std::mem::size_of; -use trc::compiler::*; +use trc::compiler::{ast::AstBuilder, *}; macro_rules! gen_test_env { ($test_code:expr, $env_name:ident) => { @@ -20,6 +20,47 @@ fn get_offset(int_nums: usize) -> usize { size_of::() * int_nums } +fn get_func_id(scope: &mut AstBuilder, name: &str) -> usize { + let idstr = scope + .token_lexer + .const_pool + .get_id(&name.to_string()) + .unwrap(); + let symid = scope + .get_scope() + .borrow() + .get_sym(idstr) + .expect("sym not found"); + scope + .get_scope() + .borrow() + .get_function(symid) + .unwrap() + .downcast_rc::() + .unwrap() + .buildin_id +} + +const SEPCIAL_FUNC_ID: usize = usize::MAX; + +fn opcode_assert_eq(expect: Vec, acual: Vec) { + for (i, j) in expect.iter().zip(acual.iter()) { + assert_eq!( + i.opcode, j.opcode, + "\nexpected:{:?}\nactual:{:?}", + expect, acual + ); + if i.opcode == Opcode::CallNative && j.operand == SEPCIAL_FUNC_ID { + continue; + } + assert_eq!( + i.operand, j.operand, + "\nexpected:{:?}\nactual:{:?}", + expect, acual + ); + } +} + #[test] fn test_assign() { gen_test_env!( @@ -30,7 +71,8 @@ fn test_assign() { t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), @@ -45,10 +87,7 @@ fn test_assign() { Inst::new(Opcode::LoadGlobalVarInt, get_offset(1)), Inst::new(Opcode::MoveInt, NO_ARG), Inst::new(Opcode::LoadInt, 4), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), + Inst::new(Opcode::CallNative, fid), ], ) } @@ -57,9 +96,9 @@ fn test_assign() { fn test_expr_easy1() { gen_test_env!(r#"(1)"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, - vec![Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE)] + vec![Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE)], ); } @@ -67,14 +106,14 @@ fn test_expr_easy1() { fn test_expr_easy2() { gen_test_env!(r#"5+~6"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::BitNotInt, NO_ARG), - Inst::new(Opcode::AddInt, NO_ARG) - ] + Inst::new(Opcode::AddInt, NO_ARG), + ], ); } @@ -82,15 +121,15 @@ fn test_expr_easy2() { fn text_expr_easy3() { gen_test_env!(r#"9-8-8"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::SubInt, NO_ARG), Inst::new(Opcode::LoadInt, 3), - Inst::new(Opcode::SubInt, NO_ARG) - ] + Inst::new(Opcode::SubInt, NO_ARG), + ], ) } @@ -98,15 +137,15 @@ fn text_expr_easy3() { fn test_expr_easy4() { gen_test_env!(r#"(8-9)*7"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::SubInt, NO_ARG), Inst::new(Opcode::LoadInt, 4), - Inst::new(Opcode::MulInt, NO_ARG) - ] + Inst::new(Opcode::MulInt, NO_ARG), + ], ) } @@ -114,7 +153,7 @@ fn test_expr_easy4() { fn test_expr() { gen_test_env!(r#"1+9-10*7**6"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), @@ -126,7 +165,7 @@ fn test_expr() { Inst::new(Opcode::PowerInt, NO_ARG), Inst::new(Opcode::MulInt, NO_ARG), Inst::new(Opcode::SubInt, NO_ARG), - ] + ], ); } @@ -134,7 +173,7 @@ fn test_expr() { fn test_expr_final() { gen_test_env!(r#"(1+-2)*3//4**(5**6)==1||7==(8&9)"#, t); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), @@ -157,7 +196,7 @@ fn test_expr_final() { Inst::new(Opcode::BitAndInt, NO_ARG), Inst::new(Opcode::EqInt, NO_ARG), Inst::new(Opcode::OrBool, NO_ARG), - ] + ], ); } @@ -170,7 +209,8 @@ print("{}", a+90)"#, t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), @@ -181,11 +221,8 @@ print("{}", a+90)"#, Inst::new(Opcode::AddInt, NO_ARG), Inst::new(Opcode::MoveInt, NO_ARG), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ONE), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - ] + Inst::new(Opcode::CallNative, fid), + ], ) } @@ -193,16 +230,14 @@ print("{}", a+90)"#, fn test_call_builtin_function() { gen_test_env!(r#"print("hello world!")"#, t); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - ] + Inst::new(Opcode::CallNative, fid), + ], ) } @@ -234,7 +269,8 @@ fn test_wrong_type3() { fn test_if_easy() { gen_test_env!(r#"if 1==1 { print("hello world") }"#, t); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 1), @@ -243,11 +279,8 @@ fn test_if_easy() { Inst::new(Opcode::JumpIfFalse, 7), Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - ] + Inst::new(Opcode::CallNative, fid), + ], ) } @@ -286,7 +319,7 @@ if a<8{ t ); t.generate_code().unwrap(); - assert_eq!( + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), @@ -305,8 +338,8 @@ if a<8{ Inst::new(Opcode::LoadInt, 5), Inst::new(Opcode::EqInt, 0), Inst::new(Opcode::JumpIfFalse, 16), - Inst::new(Opcode::Jump, 17) - ] + Inst::new(Opcode::Jump, 17), + ], ) } @@ -314,7 +347,8 @@ if a<8{ fn test_var_params() { gen_test_env!(r#"print("{}{}{}", 1, 2, 3)"#, t); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadString, 0), @@ -325,11 +359,8 @@ fn test_var_params() { Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::MoveInt, NO_ARG), Inst::new(Opcode::LoadInt, 3), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - ] + Inst::new(Opcode::CallNative, fid), + ], ) } @@ -337,7 +368,8 @@ fn test_var_params() { fn test_while_1() { gen_test_env!(r#"while 1==1 { print("hello world") }"#, t); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 1), @@ -346,12 +378,9 @@ fn test_while_1() { Inst::new(Opcode::JumpIfFalse, 8), Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - Inst::new(Opcode::Jump, 0) - ] + Inst::new(Opcode::CallNative, fid), + Inst::new(Opcode::Jump, 0), + ], ) } @@ -359,7 +388,8 @@ fn test_while_1() { fn test_for_1() { gen_test_env!(r#"for i:=0; i<10; i=i+1 { print("hello world") }"#, t); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 0), @@ -370,16 +400,13 @@ fn test_for_1() { Inst::new(Opcode::JumpIfFalse, 14), Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::LoadGlobalVarInt, get_offset(0)), Inst::new(Opcode::LoadInt, 1), Inst::new(Opcode::AddInt, NO_ARG), Inst::new(Opcode::StoreGlobalInt, get_offset(0)), - Inst::new(Opcode::Jump, 2) - ] + Inst::new(Opcode::Jump, 2), + ], ) } @@ -397,26 +424,21 @@ func f() { t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::Stop, NO_ARG), Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::PopFrame, NO_ARG), Inst::new(Opcode::LoadString, 1), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::CallCustom, 0), - Inst::new(Opcode::PopFrame, NO_ARG) - ] + Inst::new(Opcode::PopFrame, NO_ARG), + ], ) } @@ -431,19 +453,17 @@ f()"#, t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::CallCustom, 0), Inst::new(Opcode::Stop, NO_ARG), Inst::new(Opcode::LoadString, 0), Inst::new(Opcode::LoadInt, INT_VAL_POOL_ZERO), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - Inst::new(Opcode::PopFrame, NO_ARG) - ] + Inst::new(Opcode::CallNative, fid), + Inst::new(Opcode::PopFrame, NO_ARG), + ], ) } @@ -462,7 +482,8 @@ print("{}{}", a, b) t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 0), @@ -478,10 +499,7 @@ print("{}{}", a, b) Inst::new(Opcode::LoadGlobalVarInt, get_offset(1)), Inst::new(Opcode::MoveInt, NO_ARG), Inst::new(Opcode::LoadInt, 2), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Stop, NO_ARG), Inst::new(Opcode::StoreLocalInt, get_offset(0)), Inst::new(Opcode::StoreLocalInt, get_offset(1)), @@ -491,12 +509,9 @@ print("{}{}", a, b) Inst::new(Opcode::LoadLocalVarInt, get_offset(0)), Inst::new(Opcode::MoveInt, NO_ARG), Inst::new(Opcode::LoadInt, 2), - Inst::new( - Opcode::CallNative, - stdlib::get_prelude_function("print").unwrap().buildin_id - ), - Inst::new(Opcode::PopFrame, NO_ARG) - ] + Inst::new(Opcode::CallNative, fid), + Inst::new(Opcode::PopFrame, NO_ARG), + ], ) } @@ -527,7 +542,8 @@ while a<10{ t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "println"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 0), @@ -550,7 +566,7 @@ while a<10{ Inst::new(Opcode::LoadGlobalVarInt, 0), Inst::new(Opcode::MoveInt, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::LoadGlobalVarInt, 0), Inst::new(Opcode::LoadInt, 1), Inst::new(Opcode::AddInt, 0), @@ -575,14 +591,14 @@ while a<10{ Inst::new(Opcode::LoadGlobalVarInt, 8), Inst::new(Opcode::MoveInt, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::LoadGlobalVarInt, 8), Inst::new(Opcode::LoadInt, 4), Inst::new(Opcode::EqInt, 0), Inst::new(Opcode::JumpIfFalse, 51), Inst::new(Opcode::Jump, 52), Inst::new(Opcode::Jump, 28), - ] + ], ); } @@ -595,19 +611,17 @@ print("{}", math::sin(9.8)) t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "print"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadString, 1), Inst::new(Opcode::LoadFloat, 0), - Inst::new( - Opcode::CallNative, - stdlib::get_stdlib().sub_modules["math"].functions["sin"].buildin_id - ), + Inst::new(Opcode::CallNative, SEPCIAL_FUNC_ID), Inst::new(Opcode::MoveFloat, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 0), - ] + Inst::new(Opcode::CallNative, fid), + ], ); } @@ -632,7 +646,8 @@ println("out of range") t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "println"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadInt, 2), @@ -646,7 +661,7 @@ println("out of range") Inst::new(Opcode::LoadGlobalVarInt, 0), Inst::new(Opcode::MoveInt, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Jump, 32), Inst::new(Opcode::LoadInt, 3), Inst::new(Opcode::EqIntWithoutPop, 0), @@ -659,18 +674,18 @@ println("out of range") Inst::new(Opcode::LoadGlobalVarInt, 0), Inst::new(Opcode::MoveInt, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Jump, 32), Inst::new(Opcode::Jump, 28), Inst::new(Opcode::Jump, 32), Inst::new(Opcode::LoadString, 1), Inst::new(Opcode::LoadInt, 0), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Jump, 32), Inst::new(Opcode::LoadString, 2), Inst::new(Opcode::LoadInt, 0), - Inst::new(Opcode::CallNative, 1), - ] + Inst::new(Opcode::CallNative, fid), + ], ) } @@ -691,7 +706,8 @@ println("run final!") t ); t.generate_code().unwrap(); - assert_eq!( + let fid = get_func_id(&mut t, "println"); + opcode_assert_eq( t.staticdata.inst, vec![ Inst::new(Opcode::LoadString, 0), @@ -708,14 +724,14 @@ println("run final!") Inst::new(Opcode::LoadGlobalVarStr, 0), Inst::new(Opcode::MoveStr, 0), Inst::new(Opcode::LoadInt, 1), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Jump, 22), Inst::new(Opcode::Jump, 18), Inst::new(Opcode::Jump, 22), Inst::new(Opcode::LoadString, 3), Inst::new(Opcode::LoadInt, 0), - Inst::new(Opcode::CallNative, 1), + Inst::new(Opcode::CallNative, fid), Inst::new(Opcode::Jump, 22), - ] + ], ) } diff --git a/tests/test_stdlib_ffi.rs b/tests/test_stdlib_ffi.rs new file mode 100644 index 00000000..0b3030a8 --- /dev/null +++ b/tests/test_stdlib_ffi.rs @@ -0,0 +1,5 @@ +#[test] +fn test_load_library() { + let lib = unsafe { libloading::Library::new(libloading::library_filename("stdlib")).unwrap() }; + let (_module, _storage) = trc::base::dll::load_module_storage(&lib); +}