diff --git a/kclvm/evaluator/src/ty.rs b/kclvm/evaluator/src/ty.rs index 3b1de2b76..6136ced8a 100644 --- a/kclvm/evaluator/src/ty.rs +++ b/kclvm/evaluator/src/ty.rs @@ -17,7 +17,8 @@ pub fn resolve_schema(s: &Evaluator, schema: &ValueRef, keys: &[String]) -> Valu let schema_type_name = schema_runtime_type(&schema_value.name, &schema_value.pkgpath); if let Some(index) = s.schemas.borrow().get(&schema_type_name) { let keys = keys.iter().map(|v| v.as_str()).collect(); - let config_value = schema.dict_get_entries(keys); + let config_value = + schema.dict_get_entries_with_op(keys, &ConfigEntryOperationKind::Override); let config_meta = { let ctx = s.runtime_ctx.borrow(); schema_config_meta( diff --git a/kclvm/evaluator/src/union.rs b/kclvm/evaluator/src/union.rs index c17d90f41..9a2a5a16d 100644 --- a/kclvm/evaluator/src/union.rs +++ b/kclvm/evaluator/src/union.rs @@ -121,7 +121,7 @@ fn do_union( } }; - //union schema vars + // whether to union schema vars and resolve it and do the check of schema let mut union_schema = false; let mut pkgpath: String = "".to_string(); let mut name: String = "".to_string(); diff --git a/kclvm/runtime/src/value/val_dict.rs b/kclvm/runtime/src/value/val_dict.rs index 6cc06f278..3145d7728 100644 --- a/kclvm/runtime/src/value/val_dict.rs +++ b/kclvm/runtime/src/value/val_dict.rs @@ -236,6 +236,49 @@ impl ValueRef { } } + /// Dict get entries e.g., {k1: v1, k2, v2}.get_entries([k1, k2]) == {k1: v1, k1: v2} + pub fn dict_get_entries_with_op( + &self, + keys: Vec<&str>, + op: &ConfigEntryOperationKind, + ) -> ValueRef { + match &*self.rc.borrow() { + Value::dict_value(ref dict) => { + let mut d = ValueRef::dict(None); + for key in keys { + if dict.values.contains_key(key) { + let value = dict.values.get(key).unwrap(); + let index = dict.insert_indexs.get(key).unwrap_or(&-1); + d.dict_update_entry(key, value, op, index); + } + } + d.set_potential_schema_type(&dict.potential_schema.clone().unwrap_or_default()); + d + } + Value::schema_value(ref schema) => { + let mut d = ValueRef::dict(None); + for key in keys { + if schema.config.values.contains_key(key) { + let value = schema.config.values.get(key).unwrap(); + let index = schema.config.insert_indexs.get(key).unwrap_or(&-1); + d.dict_update_entry(key, value, op, index); + } + } + d.set_potential_schema_type( + &schema + .config + .potential_schema + .as_ref() + .map(|v| v.to_string()) + .unwrap_or_default(), + ); + d + } + // Panic + _ => panic!("invalid config value in dict_get_entries"), + } + } + /// Update dict value without attribute operator check, only update pub fn dict_update(&mut self, v: &ValueRef) { let mut binding = self.rc.borrow_mut(); diff --git a/kclvm/runtime/src/value/val_type.rs b/kclvm/runtime/src/value/val_type.rs index aeb701add..abd3fe56a 100644 --- a/kclvm/runtime/src/value/val_type.rs +++ b/kclvm/runtime/src/value/val_type.rs @@ -84,7 +84,7 @@ pub fn resolve_schema(ctx: &mut Context, schema: &ValueRef, keys: &[String]) -> let schema_type = schema_type.func.as_function(); let schema_fn_ptr = schema_type.fn_ptr; let keys = keys.iter().map(|v| v.as_str()).collect(); - let config = schema.dict_get_entries(keys); + let config = schema.dict_get_entries_with_op(keys, &ConfigEntryOperationKind::Override); let config_new = config.clone(); let config_meta = schema_config_meta( &ctx.panic_info.kcl_file, diff --git a/test/grammar/schema/config_op/insert/insert_5/main.k b/test/grammar/schema/config_op/insert/insert_5/main.k new file mode 100644 index 000000000..3d63d1800 --- /dev/null +++ b/test/grammar/schema/config_op/insert/insert_5/main.k @@ -0,0 +1,9 @@ +schema x: + m: [str] = ["hello"] + +s = x { +} + +t = s | { + m += ["world"] +} diff --git a/test/grammar/schema/config_op/insert/insert_5/stdout.golden b/test/grammar/schema/config_op/insert/insert_5/stdout.golden new file mode 100644 index 000000000..e1a8ce78b --- /dev/null +++ b/test/grammar/schema/config_op/insert/insert_5/stdout.golden @@ -0,0 +1,7 @@ +s: + m: + - hello +t: + m: + - hello + - world diff --git a/test/grammar/schema/config_op/insert/insert_6/main.k b/test/grammar/schema/config_op/insert/insert_6/main.k new file mode 100644 index 000000000..9a713ba8f --- /dev/null +++ b/test/grammar/schema/config_op/insert/insert_6/main.k @@ -0,0 +1,14 @@ +schema x: + m: [str] = ["hello"] + nn = m + +s = x { +} + +t = s | { + m += ["world"] +} | { + m = ["world"] +} | { + m += ["hello"] +} \ No newline at end of file diff --git a/test/grammar/schema/config_op/insert/insert_6/stdout.golden b/test/grammar/schema/config_op/insert/insert_6/stdout.golden new file mode 100644 index 000000000..deb2dde05 --- /dev/null +++ b/test/grammar/schema/config_op/insert/insert_6/stdout.golden @@ -0,0 +1,12 @@ +s: + m: + - hello + nn: + - hello +t: + m: + - world + - hello + nn: + - world + - hello