From 4888ad139dc359d4f98c6a87e65114f2dac002f8 Mon Sep 17 00:00:00 2001 From: peefy Date: Mon, 26 Feb 2024 20:30:07 +0800 Subject: [PATCH] feat: support arguments and keyword arguments union for the schema value Signed-off-by: peefy --- kclvm/compiler/src/codegen/llvm/node.rs | 6 ++++- kclvm/runner/src/runner.rs | 3 ++- kclvm/runtime/src/_kclvm.bc | Bin 13748 -> 13752 bytes kclvm/runtime/src/_kclvm.h | 10 +++---- kclvm/runtime/src/_kclvm.ll | 10 +++---- kclvm/runtime/src/_kclvm_api_spec.rs | 20 +++++++------- kclvm/runtime/src/api/kclvm.rs | 4 +++ kclvm/runtime/src/value/api.rs | 22 +++++++++++++-- kclvm/runtime/src/value/val_clone.rs | 4 +++ kclvm/runtime/src/value/val_plan.rs | 2 ++ kclvm/runtime/src/value/val_schema.rs | 25 ++++++++++++++++++ kclvm/runtime/src/value/val_type.rs | 6 ++--- kclvm/runtime/src/value/val_union.rs | 16 ++++++++++- .../union/arguments/keyword_argument_0/main.k | 10 +++++++ .../keyword_argument_0/stdout.golden | 12 +++++++++ .../union/arguments/keyword_argument_1/main.k | 10 +++++++ .../keyword_argument_1/stdout.golden | 12 +++++++++ .../union/arguments/single_argument_0/main.k | 10 +++++++ .../arguments/single_argument_0/stdout.golden | 12 +++++++++ .../union/arguments/single_argument_1/main.k | 10 +++++++ .../arguments/single_argument_1/stdout.golden | 10 +++++++ .../union/arguments/single_argument_2/main.k | 13 +++++++++ .../arguments/single_argument_2/stdout.golden | 12 +++++++++ 23 files changed, 211 insertions(+), 28 deletions(-) create mode 100644 test/grammar/schema/union/arguments/keyword_argument_0/main.k create mode 100644 test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden create mode 100644 test/grammar/schema/union/arguments/keyword_argument_1/main.k create mode 100644 test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden create mode 100644 test/grammar/schema/union/arguments/single_argument_0/main.k create mode 100644 test/grammar/schema/union/arguments/single_argument_0/stdout.golden create mode 100644 test/grammar/schema/union/arguments/single_argument_1/main.k create mode 100644 test/grammar/schema/union/arguments/single_argument_1/stdout.golden create mode 100644 test/grammar/schema/union/arguments/single_argument_2/main.k create mode 100644 test/grammar/schema/union/arguments/single_argument_2/stdout.golden diff --git a/kclvm/compiler/src/codegen/llvm/node.rs b/kclvm/compiler/src/codegen/llvm/node.rs index d4695af30..2cc5c01c2 100644 --- a/kclvm/compiler/src/codegen/llvm/node.rs +++ b/kclvm/compiler/src/codegen/llvm/node.rs @@ -583,12 +583,14 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { self.walk_decorator_with_name(&decorator.node, Some(schema_name), true) .expect(kcl_error::COMPILE_ERROR_MSG); } - // Append schema default settings + // Append schema default settings, args, kwargs and runtime type. self.build_void_call( &ApiFunc::kclvm_schema_default_settings.name(), &[ schema_value, schema_config, + args, + kwargs, self.native_global_string_value(&runtime_type), ], ); @@ -721,6 +723,8 @@ impl<'ctx> TypedResultWalker<'ctx> for LLVMCodeGenContext<'ctx> { record_instance, instance_pkgpath, attr_optional_mapping, + args, + kwargs, ], ); // Schema constructor function returns a schema diff --git a/kclvm/runner/src/runner.rs b/kclvm/runner/src/runner.rs index 0fc36f7e4..6d3ca2ec7 100644 --- a/kclvm/runner/src/runner.rs +++ b/kclvm/runner/src/runner.rs @@ -14,6 +14,7 @@ use std::ffi::OsStr; use std::os::raw::c_char; const RESULT_SIZE: usize = 2048 * 2048; +const KCL_DEBUG_ERROR_ENV_VAR: &str = "KCL_DEBUG_ERROR"; #[allow(non_camel_case_types)] pub type kclvm_char_t = c_char; @@ -407,7 +408,7 @@ impl KclLibRunner { err_message: err_buffer.to_string()?, }; // Wrap runtime JSON Panic error string into diagnostic style string. - if !result.err_message.is_empty() { + if !result.err_message.is_empty() && std::env::var(KCL_DEBUG_ERROR_ENV_VAR).is_err() { result.err_message = match Handler::default() .add_diagnostic(>::into(PanicInfo::from( result.err_message.as_str(), diff --git a/kclvm/runtime/src/_kclvm.bc b/kclvm/runtime/src/_kclvm.bc index 19da38ac9f8c66358ec75c3cd1ddb71f053414fb..39425598bdd7509bd4e913cac93c0afe03482afb 100644 GIT binary patch delta 56 zcmV-80LTBdYq)EWBmpInC2Ikiv5|NI1Q-AY29pZ{%nCFH1O^5M0s;mGv)=-t76F>G Off+6X0iLt490VE4Uk@<= delta 52 zcmV-40L%ZlYqV>SBmpFmC2Ikhv5|NI0uTU`4Fb#vECvJy1_lBGv*QAx76FR0g&8gb K0iCn790VDrqz?c9 diff --git a/kclvm/runtime/src/_kclvm.h b/kclvm/runtime/src/_kclvm.h index 551157f5b..5c0e36a59 100644 --- a/kclvm/runtime/src/_kclvm.h +++ b/kclvm/runtime/src/_kclvm.h @@ -320,7 +320,7 @@ kclvm_value_ref_t* kclvm_iterator_next_value(kclvm_iterator_t* p, kclvm_value_re kclvm_value_ref_t* kclvm_json_decode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); kclvm_value_ref_t* kclvm_json_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); @@ -450,7 +450,7 @@ void kclvm_schema_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_v void kclvm_schema_backtrack_cache(kclvm_context_t* ctx, kclvm_value_ref_t* schema, kclvm_value_ref_t* cache, kclvm_value_ref_t* cal_map, kclvm_char_t* name, kclvm_value_ref_t* runtime_type); -void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_char_t* runtime_type); +void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* runtime_type); void kclvm_schema_do_check_with_index_sign_attr(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, uint64_t* check_fn_ptr, kclvm_char_t* attr_name); @@ -630,7 +630,7 @@ void kclvm_value_remove_item(kclvm_value_ref_t* a, kclvm_value_ref_t* b); kclvm_value_ref_t* kclvm_value_schema_function(kclvm_context_t* ctx, uint64_t* fn_ptr, uint64_t* check_fn_ptr, kclvm_value_ref_t* attr_map, kclvm_char_t* tpe); -kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping); +kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); kclvm_value_ref_t* kclvm_value_slice(kclvm_context_t* ctx, kclvm_value_ref_t* x, kclvm_value_ref_t* a, kclvm_value_ref_t* b, kclvm_value_ref_t* step); @@ -664,9 +664,9 @@ kclvm_value_ref_t* kclvm_yaml_decode(kclvm_context_t* ctx, kclvm_value_ref_t* ar kclvm_value_ref_t* kclvm_yaml_decode_all(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); -kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); kclvm_value_ref_t* kclvm_yaml_encode(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); diff --git a/kclvm/runtime/src/_kclvm.ll b/kclvm/runtime/src/_kclvm.ll index 069e137c7..c9b3176f6 100644 --- a/kclvm/runtime/src/_kclvm.ll +++ b/kclvm/runtime/src/_kclvm.ll @@ -268,7 +268,7 @@ declare %kclvm_value_ref_t* @kclvm_iterator_next_value(%kclvm_iterator_t* %p, %k declare %kclvm_value_ref_t* @kclvm_json_decode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare %kclvm_value_ref_t* @kclvm_json_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); @@ -398,7 +398,7 @@ declare void @kclvm_schema_assert(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %v declare void @kclvm_schema_backtrack_cache(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema, %kclvm_value_ref_t* %cache, %kclvm_value_ref_t* %cal_map, %kclvm_char_t* %name, %kclvm_value_ref_t* %runtime_type); -declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_char_t* %runtime_type); +declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %runtime_type); declare void @kclvm_schema_do_check_with_index_sign_attr(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, i64* %check_fn_ptr, %kclvm_char_t* %attr_name); @@ -578,7 +578,7 @@ declare void @kclvm_value_remove_item(%kclvm_value_ref_t* %a, %kclvm_value_ref_t declare %kclvm_value_ref_t* @kclvm_value_schema_function(%kclvm_context_t* %ctx, i64* %fn_ptr, i64* %check_fn_ptr, %kclvm_value_ref_t* %attr_map, %kclvm_char_t* %tpe); -declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping); +declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare %kclvm_value_ref_t* @kclvm_value_slice(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %x, %kclvm_value_ref_t* %a, %kclvm_value_ref_t* %b, %kclvm_value_ref_t* %step); @@ -612,9 +612,9 @@ declare %kclvm_value_ref_t* @kclvm_yaml_decode(%kclvm_context_t* %ctx, %kclvm_va declare %kclvm_value_ref_t* @kclvm_yaml_decode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); -declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); -declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); declare %kclvm_value_ref_t* @kclvm_yaml_encode(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); diff --git a/kclvm/runtime/src/_kclvm_api_spec.rs b/kclvm/runtime/src/_kclvm_api_spec.rs index c05256cdd..67fe31408 100644 --- a/kclvm/runtime/src/_kclvm_api_spec.rs +++ b/kclvm/runtime/src/_kclvm_api_spec.rs @@ -123,8 +123,8 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_Schema(%kclvm_context_t* %ctx); // api-spec: kclvm_value_schema_with_config -// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping); +// api-spec(c): kclvm_value_ref_t* kclvm_value_schema_with_config(kclvm_context_t* ctx, kclvm_value_ref_t* schema_dict, kclvm_value_ref_t* config, kclvm_value_ref_t* config_meta, kclvm_char_t* name, kclvm_char_t* pkgpath, kclvm_value_ref_t* is_sub_schema, kclvm_value_ref_t* record_instance, kclvm_value_ref_t* instance_pkgpath, kclvm_value_ref_t* optional_mapping, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_value_schema_with_config(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %schema_dict, %kclvm_value_ref_t* %config, %kclvm_value_ref_t* %config_meta, %kclvm_char_t* %name, %kclvm_char_t* %pkgpath, %kclvm_value_ref_t* %is_sub_schema, %kclvm_value_ref_t* %record_instance, %kclvm_value_ref_t* %instance_pkgpath, %kclvm_value_ref_t* %optional_mapping, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_value_Function // api-spec(c): kclvm_value_ref_t* kclvm_value_Function(kclvm_context_t* ctx, uint64_t* fn_ptr, kclvm_value_ref_t* closure, kclvm_char_t* name, kclvm_bool_t is_external); @@ -595,8 +595,8 @@ // api-spec(llvm): declare void @kclvm_schema_optional_check(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %p); // api-spec: kclvm_schema_default_settings -// api-spec(c): void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_char_t* runtime_type); -// api-spec(llvm): declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_char_t* %runtime_type); +// api-spec(c): void kclvm_schema_default_settings(kclvm_value_ref_t* schema_value, kclvm_value_ref_t* _config_value, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs, kclvm_char_t* runtime_type); +// api-spec(llvm): declare void @kclvm_schema_default_settings(%kclvm_value_ref_t* %schema_value, %kclvm_value_ref_t* %_config_value, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs, %kclvm_char_t* %runtime_type); // api-spec: kclvm_schema_assert // api-spec(c): void kclvm_schema_assert(kclvm_context_t* ctx, kclvm_value_ref_t* value, kclvm_value_ref_t* msg, kclvm_value_ref_t* config_meta); @@ -803,8 +803,8 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_validate(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_json_dump_to_file -// api-spec(c): kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_json_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_json_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_manifests_yaml_stream // api-spec(c): void kclvm_manifests_yaml_stream(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); @@ -1163,12 +1163,12 @@ // api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_decode_all(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %_kwargs); // api-spec: kclvm_yaml_dump_to_file -// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_yaml_dump_all_to_file -// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* _ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); -// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %_ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); +// api-spec(c): kclvm_value_ref_t* kclvm_yaml_dump_all_to_file(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* kwargs); +// api-spec(llvm): declare %kclvm_value_ref_t* @kclvm_yaml_dump_all_to_file(%kclvm_context_t* %ctx, %kclvm_value_ref_t* %args, %kclvm_value_ref_t* %kwargs); // api-spec: kclvm_yaml_validate // api-spec(c): kclvm_value_ref_t* kclvm_yaml_validate(kclvm_context_t* ctx, kclvm_value_ref_t* args, kclvm_value_ref_t* _kwargs); diff --git a/kclvm/runtime/src/api/kclvm.rs b/kclvm/runtime/src/api/kclvm.rs index c22305d5d..c050b2bbd 100644 --- a/kclvm/runtime/src/api/kclvm.rs +++ b/kclvm/runtime/src/api/kclvm.rs @@ -243,6 +243,10 @@ pub struct SchemaValue { pub config_meta: ValueRef, /// This map stores which attributes of the schema are optional and which are required. pub optional_mapping: ValueRef, + /// Schema instance argument values + pub args: ValueRef, + /// Schema instance keyword argument values + pub kwargs: ValueRef, } #[derive(PartialEq, Eq, Clone, Default, Debug)] diff --git a/kclvm/runtime/src/value/api.rs b/kclvm/runtime/src/value/api.rs index 8033fd86b..bb2752b81 100644 --- a/kclvm/runtime/src/value/api.rs +++ b/kclvm/runtime/src/value/api.rs @@ -280,6 +280,8 @@ pub unsafe extern "C" fn kclvm_value_schema_with_config( record_instance: *const kclvm_value_ref_t, instance_pkgpath: *const kclvm_value_ref_t, optional_mapping: *const kclvm_value_ref_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, ) -> *mut kclvm_value_ref_t { let ctx = mut_ptr_as_ref(ctx); let schema_dict = ptr_as_ref(schema_dict); @@ -296,8 +298,17 @@ pub unsafe extern "C" fn kclvm_value_schema_with_config( let instance_pkgpath = ptr_as_ref(instance_pkgpath); let instance_pkgpath = instance_pkgpath.as_str(); let optional_mapping = ptr_as_ref(optional_mapping); - let schema = - schema_dict.dict_to_schema(name, pkgpath, &config_keys, config_meta, optional_mapping); + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); + let schema = schema_dict.dict_to_schema( + name, + pkgpath, + &config_keys, + config_meta, + optional_mapping, + Some(args.clone()), + Some(kwargs.clone()), + ); if record_instance.is_truthy() && (instance_pkgpath.is_empty() || instance_pkgpath == MAIN_PKG_PATH) { @@ -2174,6 +2185,8 @@ pub unsafe extern "C" fn kclvm_schema_instances( &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); list.list_append(&v); } @@ -2311,11 +2324,16 @@ pub unsafe extern "C" fn kclvm_schema_optional_check( pub unsafe extern "C" fn kclvm_schema_default_settings( schema_value: *mut kclvm_value_ref_t, _config_value: *const kclvm_value_ref_t, + args: *const kclvm_value_ref_t, + kwargs: *const kclvm_value_ref_t, runtime_type: *const kclvm_char_t, ) { let schema_value = mut_ptr_as_ref(schema_value); + let args = ptr_as_ref(args); + let kwargs = ptr_as_ref(kwargs); let runtime_type = c2str(runtime_type); schema_value.set_potential_schema_type(runtime_type); + schema_value.set_schema_args(args, kwargs); } #[no_mangle] diff --git a/kclvm/runtime/src/value/val_clone.rs b/kclvm/runtime/src/value/val_clone.rs index a9e867bfb..dd9865b5c 100644 --- a/kclvm/runtime/src/value/val_clone.rs +++ b/kclvm/runtime/src/value/val_clone.rs @@ -96,6 +96,10 @@ impl ValueRef { config_keys: v.config_keys.clone(), config_meta: v.config_meta.clone(), optional_mapping: v.optional_mapping.clone(), + // For KCL, args and kwargs are both immutable within the schema scope, + // so here we only need to clone the references. + args: v.args.clone(), + kwargs: v.kwargs.clone(), })))), }; } diff --git a/kclvm/runtime/src/value/val_plan.rs b/kclvm/runtime/src/value/val_plan.rs index 89066e965..6d6f3d90d 100644 --- a/kclvm/runtime/src/value/val_plan.rs +++ b/kclvm/runtime/src/value/val_plan.rs @@ -285,6 +285,8 @@ mod test_value_plan { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); schema.set_potential_schema_type(&schema_runtime_type(TEST_SCHEMA_NAME, MAIN_PKG_PATH)); schema diff --git a/kclvm/runtime/src/value/val_schema.rs b/kclvm/runtime/src/value/val_schema.rs index 07e7aee1c..3cd44c330 100644 --- a/kclvm/runtime/src/value/val_schema.rs +++ b/kclvm/runtime/src/value/val_schema.rs @@ -42,6 +42,8 @@ impl ValueRef { config_keys: &[String], config_meta: &ValueRef, optional_mapping: &ValueRef, + args: Option, + kwargs: Option, ) -> Self { if self.is_dict() { Self::from(Value::schema_value(Box::new(SchemaValue { @@ -51,6 +53,8 @@ impl ValueRef { config_keys: config_keys.to_owned(), config_meta: config_meta.clone(), optional_mapping: optional_mapping.clone(), + args: args.unwrap_or(ValueRef::list(None)), + kwargs: kwargs.unwrap_or(ValueRef::dict(None)), }))) } else if self.is_schema() { self.clone() @@ -176,6 +180,17 @@ impl ValueRef { } } + /// Set the schema instance value with arguments and keyword arguments. + pub fn set_schema_args(&mut self, args: &ValueRef, kwargs: &ValueRef) { + match &mut *self.rc.borrow_mut() { + Value::schema_value(ref mut schema) => { + schema.args = args.clone(); + schema.kwargs = kwargs.clone(); + } + _ => {} + } + } + pub fn get_potential_schema_type(&self) -> Option { match &*self.rc.borrow() { Value::dict_value(ref dict) => dict.potential_schema.clone(), @@ -276,6 +291,8 @@ mod test_value_schema { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); schema.set_potential_schema_type(&schema_runtime_type(TEST_SCHEMA_NAME, MAIN_PKG_PATH)); schema @@ -292,6 +309,8 @@ mod test_value_schema { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); assert!(schema.is_schema()); let schema = schema.dict_to_schema( @@ -300,6 +319,8 @@ mod test_value_schema { &[], &ValueRef::dict(None), &ValueRef::dict(None), + None, + None, ); assert!(schema.is_schema()); let dict = schema.schema_to_dict(); @@ -318,6 +339,8 @@ mod test_value_schema { &[], &config_meta, &optional_mapping, + None, + None, ); schema.schema_check_attr_optional(&mut ctx, true); schema.schema_check_attr_optional(&mut ctx, false); @@ -336,6 +359,8 @@ mod test_value_schema { &[], &config_meta, &optional_mapping, + None, + None, ); schema.schema_check_attr_optional(&mut ctx, true); }); diff --git a/kclvm/runtime/src/value/val_type.rs b/kclvm/runtime/src/value/val_type.rs index 2f0e4ec05..19f7098bd 100644 --- a/kclvm/runtime/src/value/val_type.rs +++ b/kclvm/runtime/src/value/val_type.rs @@ -88,7 +88,7 @@ pub fn resolve_schema(ctx: &mut Context, schema: &ValueRef, keys: &[String]) -> let value = unsafe { let schema_fn: SchemaTypeFunc = transmute_copy(&schema_fn_ptr); let cal_map = kclvm_value_Dict(ctx as *mut Context); - let list = kclvm_value_List(ctx as *mut Context); + let list = schema_value.args.clone().into_raw(ctx); // Schema function closures // is sub schema kclvm_list_append(list, ValueRef::bool(false).into_raw(ctx)); @@ -113,9 +113,9 @@ pub fn resolve_schema(ctx: &mut Context, schema: &ValueRef, keys: &[String]) -> list, ValueRef::str(&now_meta_info.kcl_pkgpath).into_raw(ctx), ); - let dict = kclvm_value_Dict(ctx as *mut Context); + let dict = schema_value.kwargs.clone().into_raw(ctx); schema_fn(ctx, list, dict); - let list = kclvm_value_List(ctx as *mut Context); + let list = schema_value.args.clone().into_raw(ctx); // Schema function closures // is sub schema kclvm_list_append(list, ValueRef::bool(true).into_raw(ctx)); diff --git a/kclvm/runtime/src/value/val_union.rs b/kclvm/runtime/src/value/val_union.rs index b10cfdba3..804ac8db3 100644 --- a/kclvm/runtime/src/value/val_union.rs +++ b/kclvm/runtime/src/value/val_union.rs @@ -155,6 +155,8 @@ impl ValueRef { let mut pkgpath: String = "".to_string(); let mut name: String = "".to_string(); let mut common_keys: Vec = vec![]; + let mut args = None; + let mut kwargs = None; let mut valid = true; match (&mut *self.rc.borrow_mut(), &*x.rc.borrow()) { (Value::list_value(obj), Value::list_value(delta)) => { @@ -193,6 +195,8 @@ impl ValueRef { common_keys = obj.config_keys.clone(); let mut other_keys: Vec = delta.values.keys().cloned().collect(); common_keys.append(&mut other_keys); + args = Some(obj.args.clone()); + kwargs = Some(obj.kwargs.clone()); union_schema = true; } (Value::schema_value(obj), Value::schema_value(delta)) => { @@ -204,6 +208,8 @@ impl ValueRef { common_keys = obj.config_keys.clone(); let mut other_keys: Vec = delta.config_keys.clone(); common_keys.append(&mut other_keys); + args = Some(delta.args.clone()); + kwargs = Some(delta.kwargs.clone()); union_schema = true; } (Value::dict_value(obj), Value::schema_value(delta)) => { @@ -214,6 +220,8 @@ impl ValueRef { common_keys = delta.config_keys.clone(); let mut other_keys: Vec = obj.values.keys().cloned().collect(); common_keys.append(&mut other_keys); + args = Some(delta.args.clone()); + kwargs = Some(delta.kwargs.clone()); union_schema = true; } _ => valid = false, @@ -229,7 +237,11 @@ impl ValueRef { return self.clone(); } if union_schema { - let result = self.clone(); + // Override schema arguments and keyword arguments. + let mut result = self.clone(); + if let (Some(args), Some(kwargs)) = (&args, &kwargs) { + result.set_schema_args(args, kwargs); + } let optional_mapping = if self.is_schema() { self.schema_optional_mapping() } else { @@ -241,6 +253,8 @@ impl ValueRef { &common_keys, &x.schema_config_meta(), &optional_mapping, + args, + kwargs, ); if opts.config_resolve { *self = resolve_schema(ctx, &schema, &common_keys); diff --git a/test/grammar/schema/union/arguments/keyword_argument_0/main.k b/test/grammar/schema/union/arguments/keyword_argument_0/main.k new file mode 100644 index 000000000..2bc3701dd --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_0/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(separator=" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden b/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_0/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/keyword_argument_1/main.k b/test/grammar/schema/union/arguments/keyword_argument_1/main.k new file mode 100644 index 000000000..601a9cd2c --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_1/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person(separator="-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden b/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/keyword_argument_1/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_0/main.k b/test/grammar/schema/union/arguments/single_argument_0/main.k new file mode 100644 index 000000000..422efd147 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_0/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/single_argument_0/stdout.golden b/test/grammar/schema/union/arguments/single_argument_0/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_0/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_1/main.k b/test/grammar/schema/union/arguments/single_argument_1/main.k new file mode 100644 index 000000000..83a0f95d6 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_1/main.k @@ -0,0 +1,10 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = {lastName = "Doe1"} + +z = x | y diff --git a/test/grammar/schema/union/arguments/single_argument_1/stdout.golden b/test/grammar/schema/union/arguments/single_argument_1/stdout.golden new file mode 100644 index 000000000..b981466f5 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_1/stdout.golden @@ -0,0 +1,10 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + lastName: Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John Doe1 diff --git a/test/grammar/schema/union/arguments/single_argument_2/main.k b/test/grammar/schema/union/arguments/single_argument_2/main.k new file mode 100644 index 000000000..b81ebc06c --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_2/main.k @@ -0,0 +1,13 @@ +schema Person[separator]: + firstName: str = "John" + lastName: str + fullName: str = firstName + separator + lastName + +x = Person(" ") {lastName = "Doe"} + +y = Person("-") {lastName = "Doe1"} + +z = Person("*") { + **x + **y +} diff --git a/test/grammar/schema/union/arguments/single_argument_2/stdout.golden b/test/grammar/schema/union/arguments/single_argument_2/stdout.golden new file mode 100644 index 000000000..3ee6d5c90 --- /dev/null +++ b/test/grammar/schema/union/arguments/single_argument_2/stdout.golden @@ -0,0 +1,12 @@ +x: + firstName: John + lastName: Doe + fullName: John Doe +y: + firstName: John + lastName: Doe1 + fullName: John-Doe1 +z: + firstName: John + lastName: Doe1 + fullName: John-Doe1