diff --git a/VERSION b/VERSION index 35864a97f..46cc97e6b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.7 \ No newline at end of file +0.9.0-alpha.1 \ No newline at end of file diff --git a/kclvm/compiler/src/codegen/error.rs b/kclvm/compiler/src/codegen/error.rs index 4aa51b47d..dcf2b2406 100644 --- a/kclvm/compiler/src/codegen/error.rs +++ b/kclvm/compiler/src/codegen/error.rs @@ -3,11 +3,12 @@ use std::error; use std::fmt::{self, Debug}; -pub const VALUE_TYPE_NOT_FOUND_MSG: &str = "Type is not found"; -pub const CONTEXT_VAR_NOT_FOUND_MSG: &str = "Context variable is not found"; -pub const FUNCTION_RETURN_VALUE_NOT_FOUND_MSG: &str = "Function return value is not found"; -pub const COMPILE_ERROR_MSG: &str = "Compile error"; +pub const VALUE_TYPE_NOT_FOUND_MSG: &str = "Internal error, value type is not found"; +pub const CONTEXT_VAR_NOT_FOUND_MSG: &str = "Internal error, context variable is not found"; pub const INTERNAL_ERROR_MSG: &str = "Internal error, please report a bug to us"; +pub const FUNCTION_RETURN_VALUE_NOT_FOUND_MSG: &str = + "Internal error, function return value is not found"; +pub const COMPILE_ERROR_MSG: &str = "Compile error"; pub const CODE_GEN_ERROR_MSG: &str = "Code gen error"; pub const INVALID_OPERATOR_MSG: &str = "Invalid operator"; pub const INVALID_JOINED_STR_MSG: &str = "Invalid AST JoinedString value"; diff --git a/kclvm/compiler/src/codegen/llvm/context.rs b/kclvm/compiler/src/codegen/llvm/context.rs index 1f4459454..f1a60bac4 100644 --- a/kclvm/compiler/src/codegen/llvm/context.rs +++ b/kclvm/compiler/src/codegen/llvm/context.rs @@ -1311,8 +1311,10 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let tpe = self.value_ptr_type().into_pointer_type(); let void_type = self.context.void_type(); let context_ptr_type = self.context_ptr_type(); - let fn_type = tpe.fn_type(&[context_ptr_type.into()], false); - let void_fn_type = void_type.fn_type(&[context_ptr_type.into()], false); + let scope_ptr_type = self.scope_ptr_type(); + let fn_type = tpe.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false); + let void_fn_type = + void_type.fn_type(&[context_ptr_type.into(), scope_ptr_type.into()], false); let has_main_pkg = self.program.pkgs.contains_key(MAIN_PKG_PATH); let function = if self.no_link { let mut modules = self.modules.borrow_mut(); @@ -1756,6 +1758,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let variables = last.variables.borrow(); if let Some(var) = variables.get(&name.to_string()) { self.builder.build_store(*var, value); + if save_scope { + self.build_void_call( + &ApiFunc::kclvm_scope_set.name(), + &[ + self.current_runtime_ctx_ptr(), + self.current_scope_ptr(), + self.native_global_string(¤t_pkgpath, "").into(), + self.native_global_string(name, "").into(), + value, + ], + ); + } existed = true; } } @@ -1766,6 +1780,18 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { let var_name = format!("${}.${}", pkgpath_without_prefix!(pkgpath), name); let pointer = self.new_global_kcl_value_ptr(&var_name); self.builder.build_store(pointer, value); + if save_scope { + self.build_void_call( + &ApiFunc::kclvm_scope_set.name(), + &[ + self.current_runtime_ctx_ptr(), + self.current_scope_ptr(), + self.native_global_string(¤t_pkgpath, "").into(), + self.native_global_string(name, "").into(), + value, + ], + ); + } if !variables.contains_key(name) { variables.insert(name.to_string(), pointer); } @@ -1993,7 +2019,41 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { } } } else { - self.builder.build_load(*var, name) + // Not a local schema attribute or a global type. + let key = format!("{}.{name}", pkgpath_without_prefix!(pkgpath)); + let is_in_lambda = self.is_in_lambda(); + if !is_in_schema + && !is_in_lambda + && index <= GLOBAL_LEVEL + && !self.local_vars.borrow().contains(name) + && self.setter_keys.borrow().contains(&key) + { + let target = self + .target_vars + .borrow_mut() + .last() + .expect(kcl_error::INTERNAL_ERROR_MSG) + .clone(); + self.build_call( + &ApiFunc::kclvm_scope_get.name(), + &[ + // Runtime context ptr + self.current_runtime_ctx_ptr(), + // Scope ptr + self.current_scope_ptr(), + // Package path + self.native_global_string(&pkgpath, "").into(), + // Attribute name + self.native_global_string(name, "").into(), + // Target + self.native_global_string(&target, "").into(), + // Default + self.builder.build_load(*var, name), + ], + ) + } else { + self.builder.build_load(*var, name) + } }; result = Ok(value); break; diff --git a/kclvm/compiler/src/codegen/llvm/module.rs b/kclvm/compiler/src/codegen/llvm/module.rs index a0f100339..6a8146ac0 100644 --- a/kclvm/compiler/src/codegen/llvm/module.rs +++ b/kclvm/compiler/src/codegen/llvm/module.rs @@ -38,7 +38,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { }; } // Pre define global variables with setter functions. - // self.predefine_global_setters(module); + self.predefine_global_setters(module); } pub fn predefine_global_types(&self, name: &str) { @@ -59,7 +59,7 @@ impl<'ctx> LLVMCodeGenContext<'ctx> { /// Predefine all global variables. pub fn predefine_global_setters(&self, module: &'ctx ast::Module) { - // New a function block to the global setter constrcution process. + // New a function block to the global setter construction process. let global_setter_block = self.append_block(""); self.br(global_setter_block); self.builder.position_at_end(global_setter_block); diff --git a/kclvm/compiler/src/codegen/llvm/node.rs b/kclvm/compiler/src/codegen/llvm/node.rs index 108379ddc..de2f1d2c9 100644 --- a/kclvm/compiler/src/codegen/llvm/node.rs +++ b/kclvm/compiler/src/codegen/llvm/node.rs @@ -317,7 +317,10 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { PKG_INIT_FUNCTION_SUFFIX ); let tpe = self.context.void_type(); - let fn_type = tpe.fn_type(&[self.context_ptr_type().into()], false); + let fn_type = tpe.fn_type( + &[self.context_ptr_type().into(), self.scope_ptr_type().into()], + false, + ); let function = module.add_function( // Function name &module_name, @@ -367,10 +370,14 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { ); } let tpe = self.context.void_type(); - let fn_type = tpe.fn_type(&[self.context_ptr_type().into()], false); + let fn_type = tpe.fn_type( + &[self.context_ptr_type().into(), self.scope_ptr_type().into()], + false, + ); module.add_function(&name, fn_type, Some(Linkage::External)) }; let ctx = self.current_runtime_ctx_ptr(); + let scope = self.current_scope_ptr(); let pkgpath_value = self.native_global_string_value(&name); let is_imported = self .build_call( @@ -389,7 +396,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.builder .build_conditional_branch(is_not_imported, then_block, else_block); self.builder.position_at_end(then_block); - self.builder.build_call(function, &[ctx.into()], ""); + self.builder + .build_call(function, &[ctx.into(), scope.into()], ""); self.br(else_block); self.builder.position_at_end(else_block); } diff --git a/kclvm/error/src/lib.rs b/kclvm/error/src/lib.rs index a45797b2d..ce25667d0 100644 --- a/kclvm/error/src/lib.rs +++ b/kclvm/error/src/lib.rs @@ -460,7 +460,13 @@ impl SessionDiagnostic for Diagnostic { match Session::new_with_file_and_code(&msg.range.0.filename, None) { Ok(sess) => { let source = sess.sm.lookup_source_file(new_byte_pos(0)); - let line = source.get_line((msg.range.0.line - 1) as usize); + let line = source.get_line( + (if msg.range.0.line >= 1 { + msg.range.0.line - 1 + } else { + 0 + }) as usize, + ); match line.as_ref() { Some(content) => { let length = content.chars().count(); diff --git a/kclvm/runtime/src/_kcl_run.rs b/kclvm/runtime/src/_kcl_run.rs index 6c20449e1..a9ab2cbb0 100644 --- a/kclvm/runtime/src/_kcl_run.rs +++ b/kclvm/runtime/src/_kcl_run.rs @@ -103,6 +103,7 @@ pub unsafe extern "C" fn _kcl_run( ) -> kclvm_size_t { // Init runtime context with options let ctx = Box::new(new_ctx_with_opts(opts, &c2str_vec(path_selector))).into_raw(); + let scope = kclvm_scope_new(); let option_keys = std::slice::from_raw_parts(option_keys, option_len as usize); let option_values = std::slice::from_raw_parts(option_values, option_len as usize); for i in 0..(option_len as usize) { @@ -130,9 +131,7 @@ 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)); + let result = std::panic::catch_unwind(|| _kcl_run_in_closure(ctx, scope, kclvm_main_ptr)); std::panic::set_hook(prev_hook); KCL_RUNTIME_PANIC_RECORD.with(|record| { let record = record.borrow(); @@ -162,20 +161,26 @@ pub unsafe extern "C" fn _kcl_run( copy_str_to(&json_panic_info, err_buffer, err_buffer_len); // Delete the context kclvm_context_delete(ctx); + // Delete the scope + kclvm_scope_delete(scope); result.is_err() as kclvm_size_t } unsafe fn _kcl_run_in_closure( ctx: *mut Context, + scope: *mut LazyEvalScope, kclvm_main_ptr: u64, // main.k => kclvm_main ) { let kclvm_main = (&kclvm_main_ptr as *const u64) as *const () - as *const extern "C" fn(ctx: *mut kclvm_context_t) -> *mut kclvm_value_ref_t; + as *const extern "C" fn( + ctx: *mut kclvm_context_t, + scope: *mut kclvm_eval_scope_t, + ) -> *mut kclvm_value_ref_t; unsafe { if kclvm_main.is_null() { panic!("kcl program main function not found"); } - (*kclvm_main)(ctx); + (*kclvm_main)(ctx, scope); } } diff --git a/kclvm/runtime/src/_kclvm.bc b/kclvm/runtime/src/_kclvm.bc index 69a8306c6..6752000fd 100644 Binary files a/kclvm/runtime/src/_kclvm.bc and b/kclvm/runtime/src/_kclvm.bc differ diff --git a/kclvm/runtime/src/_kclvm.h b/kclvm/runtime/src/_kclvm.h index 1d98196f9..312e8db22 100644 --- a/kclvm/runtime/src/_kclvm.h +++ b/kclvm/runtime/src/_kclvm.h @@ -488,7 +488,7 @@ kclvm_value_ref_t* kclvm_schema_value_new(kclvm_context_t* ctx, kclvm_value_ref_ void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter); -void kclvm_scope_free(kclvm_eval_scope_t* scope); +void kclvm_scope_delete(kclvm_eval_scope_t* scope); kclvm_value_ref_t* kclvm_scope_get(kclvm_context_t* ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, char* target, kclvm_value_ref_t* default); diff --git a/kclvm/runtime/src/_kclvm.ll b/kclvm/runtime/src/_kclvm.ll index 60e53d0f0..35e2ee88a 100644 --- a/kclvm/runtime/src/_kclvm.ll +++ b/kclvm/runtime/src/_kclvm.ll @@ -436,7 +436,7 @@ declare %kclvm_value_ref_t* @kclvm_schema_value_new(%kclvm_context_t* %ctx, %kcl declare void @kclvm_scope_add_setter(%kclvm_context_t* %_ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i64* %setter); -declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope); +declare void @kclvm_scope_delete(%kclvm_eval_scope_t* %scope); declare %kclvm_value_ref_t* @kclvm_scope_get(%kclvm_context_t* %ctx, %kclvm_eval_scope_t* %scope, i8* %pkg, i8* %name, i8* %target, %kclvm_value_ref_t* %default); diff --git a/kclvm/runtime/src/_kclvm.rs b/kclvm/runtime/src/_kclvm.rs index e0412e10f..e3f1a7849 100644 --- a/kclvm/runtime/src/_kclvm.rs +++ b/kclvm/runtime/src/_kclvm.rs @@ -229,7 +229,7 @@ pub enum ApiFunc { kclvm_schema_value_check, kclvm_schema_value_new, kclvm_scope_add_setter, - kclvm_scope_free, + kclvm_scope_delete, kclvm_scope_get, kclvm_scope_new, kclvm_scope_set, diff --git a/kclvm/runtime/src/_kclvm_addr.rs b/kclvm/runtime/src/_kclvm_addr.rs index c9b9efe5b..cf79c027e 100644 --- a/kclvm/runtime/src/_kclvm_addr.rs +++ b/kclvm/runtime/src/_kclvm_addr.rs @@ -244,7 +244,7 @@ pub fn _kclvm_get_fn_ptr_by_name(name: &str) -> u64 { "kclvm_schema_value_check" => crate::kclvm_schema_value_check as *const () as u64, "kclvm_schema_value_new" => crate::kclvm_schema_value_new as *const () as u64, "kclvm_scope_add_setter" => crate::kclvm_scope_add_setter as *const () as u64, - "kclvm_scope_free" => crate::kclvm_scope_free as *const () as u64, + "kclvm_scope_delete" => crate::kclvm_scope_delete as *const () as u64, "kclvm_scope_get" => crate::kclvm_scope_get as *const () as u64, "kclvm_scope_new" => crate::kclvm_scope_new as *const () as u64, "kclvm_scope_set" => crate::kclvm_scope_set as *const () as u64, diff --git a/kclvm/runtime/src/_kclvm_api_spec.rs b/kclvm/runtime/src/_kclvm_api_spec.rs index 5662ccb94..15da4b435 100644 --- a/kclvm/runtime/src/_kclvm_api_spec.rs +++ b/kclvm/runtime/src/_kclvm_api_spec.rs @@ -38,9 +38,9 @@ // api-spec(c): kclvm_eval_scope_t* kclvm_scope_new(); // api-spec(llvm): declare %kclvm_eval_scope_t* @kclvm_scope_new(); -// api-spec: kclvm_scope_free -// api-spec(c): void kclvm_scope_free(kclvm_eval_scope_t* scope); -// api-spec(llvm): declare void @kclvm_scope_free(%kclvm_eval_scope_t* %scope); +// api-spec: kclvm_scope_delete +// api-spec(c): void kclvm_scope_delete(kclvm_eval_scope_t* scope); +// api-spec(llvm): declare void @kclvm_scope_delete(%kclvm_eval_scope_t* %scope); // api-spec: kclvm_scope_add_setter // api-spec(c): void kclvm_scope_add_setter(kclvm_context_t* _ctx, kclvm_eval_scope_t* scope, char* pkg, char* name, uint64_t* setter); diff --git a/kclvm/runtime/src/_kclvm_main_win.c b/kclvm/runtime/src/_kclvm_main_win.c deleted file mode 100644 index 4e6473fdb..000000000 --- a/kclvm/runtime/src/_kclvm_main_win.c +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright The KCL Authors. All rights reserved. - -extern void* kclvm_main(void* ctx); - -extern void kclvm_debug_hello(); -extern void kclvm_debug_print(const char* s); - -__declspec(dllexport) void* kclvm_main_win(void* ctx) { - return kclvm_main(ctx); -} - -__declspec(dllexport) void kclvm_debug_hello_win() { - kclvm_debug_hello(); -} - -__declspec(dllexport) void kclvm_debug_print_win(const char* s) { - kclvm_debug_print(s); -} diff --git a/kclvm/runtime/src/context/api.rs b/kclvm/runtime/src/context/api.rs index 2b3253c4c..aaeb77687 100644 --- a/kclvm/runtime/src/context/api.rs +++ b/kclvm/runtime/src/context/api.rs @@ -148,7 +148,7 @@ pub unsafe extern "C" fn kclvm_scope_new() -> *mut kclvm_eval_scope_t { #[no_mangle] #[runtime_fn] -pub unsafe extern "C" fn kclvm_scope_free(scope: *mut kclvm_eval_scope_t) { +pub unsafe extern "C" fn kclvm_scope_delete(scope: *mut kclvm_eval_scope_t) { drop(Box::from_raw(scope)); } diff --git a/test/grammar/schema/irrelevant_order/simple_10/main.k b/test/grammar/schema/irrelevant_order/simple_10/main.k new file mode 100644 index 000000000..0e59f687f --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_10/main.k @@ -0,0 +1,15 @@ +schema Data: + name: str + version?: str + +data1 = Data { + name = data2.name +} + +data2 = Data { + name = "1" + version = version +} + +# Global version +version = "v0.1.0" diff --git a/test/grammar/schema/irrelevant_order/simple_10/stdout.golden b/test/grammar/schema/irrelevant_order/simple_10/stdout.golden new file mode 100644 index 000000000..70d941e06 --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_10/stdout.golden @@ -0,0 +1,6 @@ +data1: + name: '1' +data2: + name: '1' + version: v0.1.0 +version: v0.1.0 diff --git a/test/grammar/schema/irrelevant_order/simple_7/main.k b/test/grammar/schema/irrelevant_order/simple_7/main.k new file mode 100644 index 000000000..c090b2995 --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_7/main.k @@ -0,0 +1,2 @@ +b = a +a = 1 diff --git a/test/grammar/schema/irrelevant_order/simple_7/stdout.golden b/test/grammar/schema/irrelevant_order/simple_7/stdout.golden new file mode 100644 index 000000000..1bcc2448b --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_7/stdout.golden @@ -0,0 +1,2 @@ +b: 1 +a: 1 diff --git a/test/grammar/schema/irrelevant_order/simple_8/main.k b/test/grammar/schema/irrelevant_order/simple_8/main.k new file mode 100644 index 000000000..e7dc4200f --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_8/main.k @@ -0,0 +1,3 @@ +b = a + c +a = 1 +c = a + 1 diff --git a/test/grammar/schema/irrelevant_order/simple_8/stdout.golden b/test/grammar/schema/irrelevant_order/simple_8/stdout.golden new file mode 100644 index 000000000..2befd0fca --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_8/stdout.golden @@ -0,0 +1,3 @@ +b: 3 +a: 1 +c: 2 diff --git a/test/grammar/schema/irrelevant_order/simple_9/kcl.mod b/test/grammar/schema/irrelevant_order/simple_9/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/test/grammar/schema/irrelevant_order/simple_9/main.k b/test/grammar/schema/irrelevant_order/simple_9/main.k new file mode 100644 index 000000000..af2d1b5a0 --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_9/main.k @@ -0,0 +1,3 @@ +import pkg + +output = pkg.output diff --git a/test/grammar/schema/irrelevant_order/simple_9/pkg/base.k b/test/grammar/schema/irrelevant_order/simple_9/pkg/base.k new file mode 100644 index 000000000..17f5d750f --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_9/pkg/base.k @@ -0,0 +1,4 @@ +schema MyApp: + name: str + versions: {str:str} + version = versions[name] diff --git a/test/grammar/schema/irrelevant_order/simple_9/pkg/input.k b/test/grammar/schema/irrelevant_order/simple_9/pkg/input.k new file mode 100644 index 000000000..d5b3ec80d --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_9/pkg/input.k @@ -0,0 +1,5 @@ +output = MyApp{ + name = name + versions = my_versions +} +name = "my_app" diff --git a/test/grammar/schema/irrelevant_order/simple_9/pkg/versions.k b/test/grammar/schema/irrelevant_order/simple_9/pkg/versions.k new file mode 100644 index 000000000..f65fa4fdf --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_9/pkg/versions.k @@ -0,0 +1,3 @@ +my_versions = { + "my-app": "1.0.0" +} \ No newline at end of file diff --git a/test/grammar/schema/irrelevant_order/simple_9/stdout.golden b/test/grammar/schema/irrelevant_order/simple_9/stdout.golden new file mode 100644 index 000000000..56277907c --- /dev/null +++ b/test/grammar/schema/irrelevant_order/simple_9/stdout.golden @@ -0,0 +1,4 @@ +output: + name: my_app + versions: + my-app: 1.0.0