From 7a1e5676c5116153afbd751650d42e69d427edbf Mon Sep 17 00:00:00 2001 From: peefy Date: Mon, 6 May 2024 21:15:02 +0800 Subject: [PATCH] feat: top level variable back reference infra Signed-off-by: peefy --- kclvm/Cargo.lock | 1 + kclvm/compiler/src/codegen/llvm/context.rs | 33 ++- kclvm/compiler/src/codegen/llvm/module.rs | 215 ++++++++++++++++++- kclvm/compiler/src/codegen/llvm/node.rs | 1 + kclvm/compiler/src/codegen/mod.rs | 2 + kclvm/compiler/src/codegen/traits/builder.rs | 2 + kclvm/compiler/src/codegen/traits/type.rs | 13 +- kclvm/compiler/src/codegen/traits/value.rs | 2 + kclvm/compiler/src/value/schema.rs | 1 + kclvm/evaluator/src/node.rs | 8 +- kclvm/runner/src/linker.rs | 1 + kclvm/runner/src/runner.rs | 26 +-- kclvm/runtime/Cargo.toml | 2 +- kclvm/runtime/src/_kcl_run.rs | 9 +- kclvm/runtime/src/stdlib/plugin.rs | 44 ++-- kclvm/src/lib.rs | 16 +- kclvm/tools/src/vet/tests.rs | 17 +- 17 files changed, 330 insertions(+), 63 deletions(-) diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index e44e924f7..211770763 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -1813,6 +1813,7 @@ dependencies = [ "indexmap 1.9.3", "itertools", "kclvm_runtime_internal_macros", + "lazy_static", "libc", "md5", "num-integer", diff --git a/kclvm/compiler/src/codegen/llvm/context.rs b/kclvm/compiler/src/codegen/llvm/context.rs index 08da56390..1f4459454 100644 --- a/kclvm/compiler/src/codegen/llvm/context.rs +++ b/kclvm/compiler/src/codegen/llvm/context.rs @@ -85,6 +85,7 @@ pub struct LLVMCodeGenContext<'ctx> { pub program: &'ctx ast::Program, pub functions: RefCell>>>, pub imported: RefCell>, + pub setter_keys: RefCell>, pub schema_stack: RefCell>, pub lambda_stack: RefCell>, pub schema_expr_stack: RefCell>, @@ -365,6 +366,20 @@ impl<'ctx> BuilderMethods for LLVMCodeGenContext<'ctx> { self.module.add_function(name, fn_ty, None) } } + + /// Add a setter function named `name`. + fn add_setter_function(&self, name: &str) -> Self::Function { + let fn_ty = self.setter_func_type(); + if self.no_link { + let pkgpath = self.current_pkgpath(); + let msg = format!("pkgpath {} is not found", pkgpath); + let modules = self.modules.borrow_mut(); + let module = modules.get(&pkgpath).expect(&msg).borrow_mut(); + module.inner.add_function(name, fn_ty, None) + } else { + self.module.add_function(name, fn_ty, None) + } + } } /* Value methods */ @@ -604,6 +619,16 @@ impl<'ctx> ValueMethods for LLVMCodeGenContext<'ctx> { .get_first_param() .expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG) } + /// Get the global evaluation scope pointer. + fn current_scope_ptr(&self) -> Self::Value { + self.builder + .get_insert_block() + .unwrap() + .get_parent() + .unwrap() + .get_nth_param(1) + .expect(kcl_error::CONTEXT_VAR_NOT_FOUND_MSG) + } } impl<'ctx> ValueCalculationMethods for LLVMCodeGenContext<'ctx> { @@ -1255,6 +1280,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { functions: RefCell::new(vec![]), imported: RefCell::new(HashSet::new()), local_vars: RefCell::new(HashSet::new()), + setter_keys: RefCell::new(HashSet::new()), schema_stack: RefCell::new(vec![]), // 1 denotes the top global main function lambda and 0 denotes the builtin scope. // Any user-defined lambda scope greater than 1. @@ -1714,7 +1740,12 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } /// Append a variable or update the existed variable - pub fn add_or_update_global_variable(&self, name: &str, value: BasicValueEnum<'ctx>) { + pub fn add_or_update_global_variable( + &self, + name: &str, + value: BasicValueEnum<'ctx>, + save_scope: bool, + ) { // Find argument name in the scope let current_pkgpath = self.current_pkgpath(); let mut pkg_scopes = self.pkg_scopes.borrow_mut(); diff --git a/kclvm/compiler/src/codegen/llvm/module.rs b/kclvm/compiler/src/codegen/llvm/module.rs index 21c3bf9c0..a0f100339 100644 --- a/kclvm/compiler/src/codegen/llvm/module.rs +++ b/kclvm/compiler/src/codegen/llvm/module.rs @@ -1,11 +1,17 @@ // Copyright The KCL Authors. All rights reserved. +use indexmap::IndexMap; +use inkwell::values::FunctionValue; +use inkwell::AddressSpace; use kclvm_ast::ast; use kclvm_ast::walker::TypedResultWalker; +use kclvm_runtime::ApiFunc; +use kclvm_sema::pkgpath_without_prefix; -use super::context::LLVMCodeGenContext; -use crate::codegen::error as kcl_error; -use crate::codegen::traits::ValueMethods; +use super::context::{BacktrackMeta, LLVMCodeGenContext}; +use crate::codegen::traits::{BuilderMethods, ProgramCodeGen, ValueMethods}; +use crate::codegen::{error as kcl_error, ENTRY_NAME}; +use crate::value; use std::str; impl<'ctx> LLVMCodeGenContext<'ctx> { @@ -31,6 +37,8 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { _ => {} }; } + // Pre define global variables with setter functions. + // self.predefine_global_setters(module); } pub fn predefine_global_types(&self, name: &str) { @@ -49,13 +57,81 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.emit_global_vars(&module.body); } + /// Predefine all global variables. + pub fn predefine_global_setters(&self, module: &'ctx ast::Module) { + // New a function block to the global setter constrcution process. + let global_setter_block = self.append_block(""); + self.br(global_setter_block); + self.builder.position_at_end(global_setter_block); + let mut place_holder_map: IndexMap>> = IndexMap::new(); + let mut body_map: IndexMap>> = IndexMap::new(); + let pkgpath = &self.current_pkgpath(); + // Setter function name format: "$set..$" + self.emit_global_setters( + &module.body, + &pkgpath, + false, + &mut place_holder_map, + &mut body_map, + &mut vec![], + ); + // Build global attribute backtrack functions. + { + for (k, functions) in &place_holder_map { + if k == kclvm_runtime::CAL_MAP_INDEX_SIGNATURE { + continue; + } + let stmt_list = body_map.get(k).expect(kcl_error::INTERNAL_ERROR_MSG); + let mut if_level = 0; + for (attr_func, stmt) in functions.iter().zip(stmt_list) { + let function = *attr_func; + let name = function + .get_name() + .to_str() + .expect(kcl_error::INTERNAL_ERROR_MSG); + // Get attribute function from the module. + let function = self.lookup_function(name); + self.push_function(function); + let attr_block = self.append_block(ENTRY_NAME); + self.builder.position_at_end(attr_block); + // Backtrack meta begin + if matches!(&stmt.node, ast::Stmt::If(..)) { + if_level += 1; + *self.backtrack_meta.borrow_mut() = Some(BacktrackMeta { + target: k.clone(), + level: if_level, + count: 0, + stop: false, + }); + } else { + if_level = 0; + } + let result = self.walk_stmt(stmt).expect(kcl_error::COMPILE_ERROR_MSG); + // Backtrack meta end + if matches!(&stmt.node, ast::Stmt::If(..)) { + *self.backtrack_meta.borrow_mut() = None + } + // Build return + self.builder.build_return(Some(&result)); + // Position at global main function block + self.builder.position_at_end(global_setter_block); + self.pop_function(); + } + } + } + } + fn emit_global_vars(&self, body: &'ctx [Box>]) { for stmt in body { match &stmt.node { ast::Stmt::Unification(unification_stmt) => { let names = &unification_stmt.target.node.names; if names.len() == 1 { - self.add_or_update_global_variable(&names[0].node, self.undefined_value()); + self.add_or_update_global_variable( + &names[0].node, + self.undefined_value(), + false, + ); } } ast::Stmt::Assign(assign_stmt) => { @@ -65,6 +141,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.add_or_update_global_variable( &names[0].node, self.undefined_value(), + false, ); } } @@ -122,4 +199,134 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } } } + + /// Emit setter functions for global variables. + pub(crate) fn emit_global_setters( + &self, + body: &'ctx [Box>], + pkgpath: &str, + is_in_if: bool, + place_holder_map: &mut IndexMap>>, + body_map: &mut IndexMap>>, + in_if_names: &mut Vec, + ) { + let add_stmt = + |name: &str, + stmt: &'ctx ast::Node, + place_holder_map: &mut IndexMap>>, + body_map: &mut IndexMap>>| { + // The function form e.g., $set.__main__.a(&Context, &LazyScope, &ValueRef, &ValueRef) + let var_key = format!("{}.{name}", pkgpath_without_prefix!(pkgpath)); + let function = + self.add_setter_function(&format!("{}.{}", value::GLOBAL_SETTER, var_key)); + let lambda_fn_ptr = self.builder.build_bitcast( + function.as_global_value().as_pointer_value(), + self.context.i64_type().ptr_type(AddressSpace::default()), + "", + ); + if !place_holder_map.contains_key(name) { + place_holder_map.insert(name.to_string(), vec![]); + } + let name_vec = place_holder_map + .get_mut(name) + .expect(kcl_error::INTERNAL_ERROR_MSG); + name_vec.push(function); + self.build_void_call( + &ApiFunc::kclvm_scope_add_setter.name(), + &[ + self.current_runtime_ctx_ptr(), + self.current_scope_ptr(), + self.native_global_string(pkgpath, "").into(), + self.native_global_string(name, "").into(), + lambda_fn_ptr, + ], + ); + let key = format!("{}.{name}", pkgpath_without_prefix!(pkgpath)); + self.setter_keys.borrow_mut().insert(key); + if !body_map.contains_key(name) { + body_map.insert(name.to_string(), vec![]); + } + let body_vec = body_map.get_mut(name).expect(kcl_error::INTERNAL_ERROR_MSG); + body_vec.push(stmt); + }; + for stmt in body { + match &stmt.node { + ast::Stmt::Unification(unification_stmt) => { + let name = &unification_stmt.target.node.names[0].node; + if is_in_if { + in_if_names.push(name.to_string()); + } else { + add_stmt(name, stmt, place_holder_map, body_map); + } + } + ast::Stmt::Assign(assign_stmt) => { + for target in &assign_stmt.targets { + let name = &target.node.names[0].node; + if is_in_if { + in_if_names.push(name.to_string()); + } else { + add_stmt(name, stmt, place_holder_map, body_map); + } + } + } + ast::Stmt::AugAssign(aug_assign_stmt) => { + let target = &aug_assign_stmt.target; + let name = &target.node.names[0].node; + if is_in_if { + in_if_names.push(name.to_string()); + } else { + add_stmt(name, stmt, place_holder_map, body_map); + } + } + ast::Stmt::If(if_stmt) => { + let mut names: Vec = vec![]; + self.emit_global_setters( + &if_stmt.body, + pkgpath, + true, + place_holder_map, + body_map, + &mut names, + ); + if is_in_if { + for name in &names { + in_if_names.push(name.to_string()); + } + } else { + for name in &names { + add_stmt(name, stmt, place_holder_map, body_map); + } + names.clear(); + } + self.emit_global_setters( + &if_stmt.orelse, + pkgpath, + true, + place_holder_map, + body_map, + &mut names, + ); + if is_in_if { + for name in &names { + in_if_names.push(name.to_string()); + } + } else { + for name in &names { + add_stmt(name, stmt, place_holder_map, body_map); + } + names.clear(); + } + } + ast::Stmt::SchemaAttr(schema_attr) => { + let name = schema_attr.name.node.as_str(); + if is_in_if { + in_if_names.push(name.to_string()); + } else { + add_stmt(name, stmt, place_holder_map, body_map); + } + } + _ => {} + } + } + } } diff --git a/kclvm/compiler/src/codegen/llvm/node.rs b/kclvm/compiler/src/codegen/llvm/node.rs index ae8535056..108379ddc 100644 --- a/kclvm/compiler/src/codegen/llvm/node.rs +++ b/kclvm/compiler/src/codegen/llvm/node.rs @@ -2402,6 +2402,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { self.add_or_update_global_variable( name, right_value.expect(kcl_error::INTERNAL_ERROR_MSG), + true, ); // Lambda local variables. } else if self.is_in_lambda() { diff --git a/kclvm/compiler/src/codegen/mod.rs b/kclvm/compiler/src/codegen/mod.rs index 10af7b51c..6b9bebac2 100644 --- a/kclvm/compiler/src/codegen/mod.rs +++ b/kclvm/compiler/src/codegen/mod.rs @@ -17,6 +17,8 @@ pub const ENTRY_NAME: &str = "entry"; pub const VALUE_TYPE_NAME: &str = "kclvm_value_ref_t"; /// The kclvm runtime context type name. pub const CONTEXT_TYPE_NAME: &str = "kclvm_context_t"; +/// The kclvm runtime evaluation type name. +pub const SCOPE_TYPE_NAME: &str = "kclvm_eval_scope_t"; /// Package init function name suffix pub const PKG_INIT_FUNCTION_SUFFIX: &str = "init"; /// Global level diff --git a/kclvm/compiler/src/codegen/traits/builder.rs b/kclvm/compiler/src/codegen/traits/builder.rs index 22120d794..dac7577cb 100644 --- a/kclvm/compiler/src/codegen/traits/builder.rs +++ b/kclvm/compiler/src/codegen/traits/builder.rs @@ -82,4 +82,6 @@ pub trait BuilderMethods: BackendTypes { fn lookup_function(&self, name: &str) -> Self::Function; /// Add a function named `name`. fn add_function(&self, name: &str) -> Self::Function; + /// Add a setter function named `name`. + fn add_setter_function(&self, name: &str) -> Self::Function; } diff --git a/kclvm/compiler/src/codegen/traits/type.rs b/kclvm/compiler/src/codegen/traits/type.rs index 01f5d1eee..a43fd1594 100644 --- a/kclvm/compiler/src/codegen/traits/type.rs +++ b/kclvm/compiler/src/codegen/traits/type.rs @@ -1,7 +1,7 @@ //! Copyright The KCL Authors. All rights reserved. use crate::codegen::abi::AddressSpace; -use crate::codegen::{CONTEXT_TYPE_NAME, VALUE_TYPE_NAME}; +use crate::codegen::{CONTEXT_TYPE_NAME, SCOPE_TYPE_NAME, VALUE_TYPE_NAME}; use super::BackendTypes; @@ -53,6 +53,10 @@ pub trait DerivedTypeMethods: BaseTypeMethods { fn context_ptr_type(&self) -> Self::Type { self.ptr_type_to(self.get_intrinsic_type(CONTEXT_TYPE_NAME)) } + /// Get the context pointer type. + fn scope_ptr_type(&self) -> Self::Type { + self.ptr_type_to(self.get_intrinsic_type(SCOPE_TYPE_NAME)) + } /// Get the function type. fn function_type(&self) -> Self::FunctionLet { let value_ptr_type = self.value_ptr_type(); @@ -62,6 +66,13 @@ pub trait DerivedTypeMethods: BaseTypeMethods { value_ptr_type, ) } + /// Get the setter function type. + fn setter_func_type(&self) -> Self::FunctionLet { + let context_ptr_type = self.context_ptr_type(); + let scope_ptr_type = self.scope_ptr_type(); + let value_ptr_type = self.value_ptr_type(); + self.function_let(&[context_ptr_type, scope_ptr_type], value_ptr_type) + } } /// TypeCodeGen defines all type APIs. diff --git a/kclvm/compiler/src/codegen/traits/value.rs b/kclvm/compiler/src/codegen/traits/value.rs index 476ce5a66..ac4e05509 100644 --- a/kclvm/compiler/src/codegen/traits/value.rs +++ b/kclvm/compiler/src/codegen/traits/value.rs @@ -43,6 +43,8 @@ pub trait ValueMethods: BackendTypes { fn global_value_ptr(&self, name: &str) -> Self::Value; /// Get current runtime context pointer. fn current_runtime_ctx_ptr(&self) -> Self::Value; + /// Get the global evaluation scope pointer. + fn current_scope_ptr(&self) -> Self::Value; } /// DerivedValueCalculationMethods defines all value base calculation APIs. diff --git a/kclvm/compiler/src/value/schema.rs b/kclvm/compiler/src/value/schema.rs index 019a121cc..2984672f4 100644 --- a/kclvm/compiler/src/value/schema.rs +++ b/kclvm/compiler/src/value/schema.rs @@ -23,6 +23,7 @@ pub const SCHEMA_VARIABLE_LIST: &[&str] = &[ ]; pub const BACKTRACK_LEVEL_MAP: &str = "$backtrack_level_map"; pub const BACKTRACK_CACHE: &str = "$backtrack_cache"; +pub const GLOBAL_SETTER: &str = "$set"; /// KCL schema type pub struct SchemaType { diff --git a/kclvm/evaluator/src/node.rs b/kclvm/evaluator/src/node.rs index 267daa745..5ff871a6f 100644 --- a/kclvm/evaluator/src/node.rs +++ b/kclvm/evaluator/src/node.rs @@ -14,7 +14,7 @@ use kclvm_runtime::{ schema_assert, schema_runtime_type, ConfigEntryOperationKind, DecoratorValue, RuntimeErrorType, UnionOptions, ValueRef, PKG_PATH_PREFIX, }; -use kclvm_sema::{builtin, plugin}; +use kclvm_sema::{builtin, pkgpath_without_prefix, plugin}; use crate::error::INTERNAL_ERROR_MSG; use crate::func::{func_body, FunctionCaller, FunctionEvalContext}; @@ -1148,7 +1148,11 @@ impl<'ctx> Evaluator<'ctx> { .clone() }; if let Proxy::Global(index) = &frame.proxy { - if let Some(module_list) = self.program.pkgs.get(&frame.pkgpath) { + if let Some(module_list) = self + .program + .pkgs + .get(&pkgpath_without_prefix!(frame.pkgpath)) + { if let Some(module) = module_list.get(*index) { if let Some(stmt) = module.body.get(setter.stmt) { self.push_backtrack_meta(setter); diff --git a/kclvm/runner/src/linker.rs b/kclvm/runner/src/linker.rs index 036ddfd8d..81d1b661b 100644 --- a/kclvm/runner/src/linker.rs +++ b/kclvm/runner/src/linker.rs @@ -96,6 +96,7 @@ impl Command { } /// Add args for cc on unix os. + #[cfg(not(target_os = "windows"))] pub(crate) fn unix_args( &self, libs: &[String], diff --git a/kclvm/runner/src/runner.rs b/kclvm/runner/src/runner.rs index fec8581c4..f06fc28d9 100644 --- a/kclvm/runner/src/runner.rs +++ b/kclvm/runner/src/runner.rs @@ -313,10 +313,10 @@ impl LibRunner { let kclvm_plugin_init: libloading::Symbol< unsafe extern "C" fn( fn_ptr: extern "C" fn( - method: *const i8, - args_json: *const i8, - kwargs_json: *const i8, - ) -> *const i8, + method: *const c_char, + args_json: *const c_char, + kwargs_json: *const c_char, + ) -> *const c_char, ), > = lib.get(b"kclvm_plugin_init")?; @@ -324,15 +324,15 @@ impl LibRunner { let plugin_method_ptr = plugin_method_ptr; let plugin_method_ptr = (plugin_method_ptr as *const u64) as *const () as *const extern "C" fn( - method: *const i8, - args: *const i8, - kwargs: *const i8, - ) -> *const i8; + method: *const c_char, + args: *const c_char, + kwargs: *const c_char, + ) -> *const c_char; let plugin_method: extern "C" fn( - method: *const i8, - args: *const i8, - kwargs: *const i8, - ) -> *const i8 = std::mem::transmute(plugin_method_ptr); + method: *const c_char, + args: *const c_char, + kwargs: *const c_char, + ) -> *const c_char = std::mem::transmute(plugin_method_ptr); // register plugin agent kclvm_plugin_init(plugin_method); @@ -506,7 +506,7 @@ impl FastRunner { #[cfg(not(target_arch = "wasm32"))] unsafe { let plugin_method: extern "C" fn( - method: *const i8, + method: *const c_char, args: *const c_char, kwargs: *const c_char, ) -> *const c_char = std::mem::transmute(self.opts.plugin_agent_ptr); diff --git a/kclvm/runtime/Cargo.toml b/kclvm/runtime/Cargo.toml index d1c02f8c6..8780fdb41 100644 --- a/kclvm/runtime/Cargo.toml +++ b/kclvm/runtime/Cargo.toml @@ -8,7 +8,7 @@ kclvm_runtime_internal_macros = { path = "./internal_macros" } serde_json = {package = "serde_json", version = "= 1.0.115"} serde = { version = "1", features = ["derive"] } serde_yaml = {path = "../third-party/serde_yaml"} - +lazy_static = "1.4.0" generational-arena = "0.2.9" base64 = "0.13.0" libc = "0.2.112" diff --git a/kclvm/runtime/src/_kcl_run.rs b/kclvm/runtime/src/_kcl_run.rs index be9cf26c3..6c20449e1 100644 --- a/kclvm/runtime/src/_kcl_run.rs +++ b/kclvm/runtime/src/_kcl_run.rs @@ -5,9 +5,14 @@ use std::os::raw::c_char; use crate::*; +use self::eval::LazyEvalScope; + #[allow(dead_code, non_camel_case_types)] type kclvm_context_t = Context; +#[allow(dead_code, non_camel_case_types)] +type kclvm_eval_scope_t = LazyEvalScope; + #[allow(dead_code, non_camel_case_types)] type kclvm_kind_t = Kind; @@ -79,6 +84,7 @@ fn new_ctx_with_opts(opts: FFIRunOptions, path_selector: &[String]) -> Context { #[no_mangle] #[runtime_fn] +#[allow(clippy::too_many_arguments)] pub unsafe extern "C" fn _kcl_run( kclvm_main_ptr: u64, // main.k => kclvm_main option_len: kclvm_size_t, @@ -124,6 +130,8 @@ pub unsafe extern "C" fn _kcl_run( } }) })); + // let scope = Box::into_raw(Box::new(LazyEvalScope::default())); + // let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, scope, kclvm_main_ptr)); let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, kclvm_main_ptr)); std::panic::set_hook(prev_hook); KCL_RUNTIME_PANIC_RECORD.with(|record| { @@ -157,7 +165,6 @@ pub unsafe extern "C" fn _kcl_run( result.is_err() as kclvm_size_t } -#[allow(clippy::too_many_arguments)] unsafe fn _kcl_run_in_closure( ctx: *mut Context, kclvm_main_ptr: u64, // main.k => kclvm_main diff --git a/kclvm/runtime/src/stdlib/plugin.rs b/kclvm/runtime/src/stdlib/plugin.rs index 5e70586bb..dc96b1814 100644 --- a/kclvm/runtime/src/stdlib/plugin.rs +++ b/kclvm/runtime/src/stdlib/plugin.rs @@ -4,23 +4,33 @@ use crate::*; +use lazy_static::lazy_static; use std::os::raw::c_char; +use std::sync::Mutex; -#[allow(non_upper_case_globals)] -static mut _plugin_handler_fn_ptr: u64 = 0; +lazy_static! { + static ref PLUGIN_HANDLER_FN_PTR: Mutex< + Option< + extern "C" fn( + method: *const c_char, + args_json: *const c_char, + kwargs_json: *const c_char, + ) -> *const c_char, + >, + > = Mutex::new(None); +} #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_plugin_init( fn_ptr: extern "C" fn( - method: *const i8, + method: *const c_char, args_json: *const c_char, kwargs_json: *const c_char, ) -> *const c_char, ) { - unsafe { - _plugin_handler_fn_ptr = fn_ptr as usize as u64; - } + let mut fn_ptr_guard = PLUGIN_HANDLER_FN_PTR.lock().unwrap(); + *fn_ptr_guard = Some(fn_ptr); } // import kcl_plugin.hello @@ -69,19 +79,11 @@ pub extern "C" fn kclvm_plugin_invoke_json( args: *const c_char, kwargs: *const c_char, ) -> *const c_char { - unsafe { - if _plugin_handler_fn_ptr == 0 { - panic!("plugin is nil, should call kclvm_plugin_init at first"); - } - - let ptr = (&_plugin_handler_fn_ptr as *const u64) as *const () - as *const extern "C" fn( - method: *const c_char, - args: *const c_char, - kwargs: *const c_char, - ) -> *const c_char; - - (*ptr)(method, args, kwargs) + let fn_ptr_guard = PLUGIN_HANDLER_FN_PTR.lock().unwrap(); + if let Some(fn_ptr) = *fn_ptr_guard { + fn_ptr(method, args, kwargs) + } else { + panic!("plugin handler is nil, should call kclvm_plugin_init at first"); } } @@ -89,7 +91,7 @@ pub extern "C" fn kclvm_plugin_invoke_json( #[no_mangle] #[runtime_fn] pub extern "C" fn kclvm_plugin_invoke_json( - method: *const i8, + method: *const c_char, args: *const c_char, kwargs: *const c_char, ) -> *const c_char { @@ -101,7 +103,7 @@ pub extern "C" fn kclvm_plugin_invoke_json( #[cfg(target_arch = "wasm32")] extern "C" { pub fn kclvm_plugin_invoke_json_wasm( - method: *const i8, + method: *const c_char, args: *const c_char, kwargs: *const c_char, ) -> *const c_char; diff --git a/kclvm/src/lib.rs b/kclvm/src/lib.rs index 4fd07cffc..186b05b68 100644 --- a/kclvm/src/lib.rs +++ b/kclvm/src/lib.rs @@ -14,7 +14,10 @@ use std::sync::Arc; /// /// args is a ExecProgramArgs JSON string. #[no_mangle] -pub unsafe extern "C" fn kclvm_cli_run(args: *const c_char, plugin_agent: *const i8) -> *const i8 { +pub unsafe extern "C" fn kclvm_cli_run( + args: *const c_char, + plugin_agent: *const c_char, +) -> *const c_char { let prev_hook = std::panic::take_hook(); // disable print panic info @@ -29,14 +32,14 @@ pub unsafe extern "C" fn kclvm_cli_run(args: *const c_char, plugin_agent: *const let c_string = std::ffi::CString::new(result.as_str()).expect("CString::new failed"); let ptr = c_string.into_raw(); - ptr as *const i8 + ptr as *const c_char } Err(result) => { let result = format!("ERROR:{result}"); let c_string = std::ffi::CString::new(result.as_str()).expect("CString::new failed"); let ptr = c_string.into_raw(); - ptr as *const i8 + ptr as *const c_char } }, Err(err) => { @@ -44,13 +47,16 @@ pub unsafe extern "C" fn kclvm_cli_run(args: *const c_char, plugin_agent: *const let result = format!("ERROR:{err_message:}"); let c_string = std::ffi::CString::new(result.as_str()).expect("CString::new failed"); let ptr = c_string.into_raw(); - ptr as *const i8 + ptr as *const c_char } } } /// KCL CLI run function CAPI. -fn kclvm_cli_run_unsafe(args: *const c_char, plugin_agent: *const i8) -> Result { +fn kclvm_cli_run_unsafe( + args: *const c_char, + plugin_agent: *const c_char, +) -> Result { let mut args = ExecProgramArgs::from_str(unsafe { std::ffi::CStr::from_ptr(args) }.to_str().unwrap()); args.plugin_agent = plugin_agent as u64; diff --git a/kclvm/tools/src/vet/tests.rs b/kclvm/tools/src/vet/tests.rs index b250847fd..ca7d3b3b4 100644 --- a/kclvm/tools/src/vet/tests.rs +++ b/kclvm/tools/src/vet/tests.rs @@ -3,8 +3,6 @@ use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; use crate::util::loader::LoaderKind; -#[cfg(target_os = "windows")] -use kclvm_runtime::PanicInfo; const CARGO_DIR: &str = env!("CARGO_MANIFEST_DIR"); pub(crate) fn rel_path() -> String { @@ -56,14 +54,6 @@ fn construct_full_path(path: &str) -> Result { .to_string()) } -#[cfg(target_os = "windows")] -pub(crate) fn path_to_windows(panic_info: &mut PanicInfo) { - panic_info.rust_file = panic_info.rust_file.replace("/", "\\"); - panic_info.kcl_pkgpath = panic_info.kcl_pkgpath.replace("/", "\\"); - panic_info.kcl_file = panic_info.kcl_file.replace("/", "\\"); - panic_info.kcl_config_meta_file = panic_info.kcl_config_meta_file.replace("/", "\\"); -} - mod test_expr_builder { use regex::Regex; @@ -77,7 +67,9 @@ mod test_expr_builder { }, }, }; - use std::{fs, panic, path::Path}; + use std::panic; + #[cfg(not(target_os = "windows"))] + use std::{fs, path::Path}; #[test] #[cfg(not(target_os = "windows"))] @@ -335,9 +327,6 @@ mod test_validater { use super::{construct_full_path, LOADER_KIND}; - #[cfg(target_os = "windows")] - use super::path_to_windows; - const KCL_TEST_CASES: &[&str] = &["test.k", "simple.k", "list.k", "plain_value.k", "complex.k"]; const VALIDATED_FILE_TYPE: &[&str] = &["json", "yaml"];