diff --git a/kclvm/evaluator/src/node.rs b/kclvm/evaluator/src/node.rs index 8d6c91424..01f8c2a7b 100644 --- a/kclvm/evaluator/src/node.rs +++ b/kclvm/evaluator/src/node.rs @@ -1208,10 +1208,22 @@ impl<'ctx> Evaluator<'ctx> { // Lambda local variables. } else if self.is_in_lambda() { let value = right_value.clone().expect(kcl_error::INTERNAL_ERROR_MSG); - // If variable exists in the scope and update it, if not, add it to the scope. - if !self.store_variable_in_current_scope(name, value.clone()) { - self.add_variable(name, self.undefined_value()); - self.store_variable(name, value); + // schema frame in the lambda + if self.is_schema_scope() { + let is_local_var = self.is_local_var(name); + let value = right_value.clone().expect(kcl_error::INTERNAL_ERROR_MSG); + match (is_local_var, is_in_schema) { + (false, true) => { + self.update_schema_or_rule_scope_value(name, Some(&value)) + } + _ => self.add_variable(name, value), + } + } else { + // If variable exists in the scope and update it, if not, add it to the scope. + if !self.store_variable_in_current_scope(name, value.clone()) { + self.add_variable(name, self.undefined_value()); + self.store_variable(name, value); + } } } else { let is_local_var = self.is_local_var(name); diff --git a/kclvm/evaluator/src/schema.rs b/kclvm/evaluator/src/schema.rs index ede41b97c..5a9ae3a7e 100644 --- a/kclvm/evaluator/src/schema.rs +++ b/kclvm/evaluator/src/schema.rs @@ -367,7 +367,7 @@ pub(crate) fn schema_body( }; let schema_name = { ctx.borrow().node.name.node.to_string() }; s.push_schema(crate::EvalContext::Schema(ctx.clone())); - s.enter_scope(); + s.enter_schema_scope(true); // Evaluate arguments and keyword arguments and store values to local variables. s.walk_arguments(&ctx.borrow().node.args, args, kwargs); // Eval schema body and record schema instances. diff --git a/kclvm/evaluator/src/scope.rs b/kclvm/evaluator/src/scope.rs index 6507816f3..de1acc450 100644 --- a/kclvm/evaluator/src/scope.rs +++ b/kclvm/evaluator/src/scope.rs @@ -24,6 +24,8 @@ pub struct Scope { pub scalars: Vec, /// schema_scalar_idx denotes whether a schema exists in the scalar list. pub schema_scalar_idx: usize, + /// is_schema denotes whether the scope is a schema. + pub is_schema: bool, /// Scope normal variables pub variables: IndexMap, /// Potential arguments in the current scope, such as schema/lambda arguments. @@ -107,16 +109,36 @@ impl<'ctx> Evaluator<'ctx> { scopes.len() - 1 } - /// Enter scope - pub(crate) fn enter_scope(&self) { + /// Get the scope level + pub(crate) fn is_schema_scope(&self) -> bool { + let current_pkgpath = self.current_pkgpath(); + let pkg_scopes = &self.pkg_scopes.borrow(); + let msg = format!("pkgpath {} is not found", current_pkgpath); + let scopes = pkg_scopes.get(¤t_pkgpath).expect(&msg); + if let Some(last_scope) = scopes.last() { + last_scope.is_schema + } else { + false + } + } + + /// Enter a schema scope + pub(crate) fn enter_schema_scope(&self, is_schema: bool) { let current_pkgpath = self.current_pkgpath(); let pkg_scopes = &mut self.pkg_scopes.borrow_mut(); let msg = format!("pkgpath {} is not found", current_pkgpath); let scopes = pkg_scopes.get_mut(¤t_pkgpath).expect(&msg); - let scope = Scope::default(); + let mut scope = Scope::default(); + scope.is_schema = is_schema; scopes.push(scope); } + /// Enter scope + #[inline] + pub(crate) fn enter_scope(&self) { + self.enter_schema_scope(false); + } + /// Leave scope pub(crate) fn leave_scope(&self) { let current_pkgpath = self.current_pkgpath(); diff --git a/test/grammar/builtins/file/append/file_append.txt b/test/grammar/builtins/file/append/file_append.txt deleted file mode 100644 index 719403733..000000000 --- a/test/grammar/builtins/file/append/file_append.txt +++ /dev/null @@ -1 +0,0 @@ -sample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample contentsample content \ No newline at end of file diff --git a/test/grammar/builtins/file/append/main.k b/test/grammar/builtins/file/append/main.k deleted file mode 100644 index 4798753ca..000000000 --- a/test/grammar/builtins/file/append/main.k +++ /dev/null @@ -1,5 +0,0 @@ -import file - -file.append("file_append.txt", "sample content") - -file.append("", "sample content without path") \ No newline at end of file diff --git a/test/grammar/builtins/file/append/stderr.golden b/test/grammar/builtins/file/append/stderr.golden deleted file mode 100644 index 7233d69b5..000000000 --- a/test/grammar/builtins/file/append/stderr.golden +++ /dev/null @@ -1,6 +0,0 @@ -error[E3M38]: EvaluationError - --> ${CWD}/main.k:5:1 - | -5 | file.append("", "sample content without path") - | Failed to open or create file '': No such file or directory (os error 2) - | \ No newline at end of file diff --git a/test/grammar/schema/optional_attr/inherit_4/main.k b/test/grammar/schema/optional_attr/inherit_4/main.k new file mode 100644 index 000000000..04ac1fef2 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_4/main.k @@ -0,0 +1,13 @@ +schema Name: + n1: str = "aa" + n2: str + +schema Sub[a: str](Name): + n2 = a + +schema Phase: + a: Sub + +a = lambda { + [[Phase{a = Sub("a")}.a]][0][0] | {} +}() diff --git a/test/grammar/schema/optional_attr/inherit_4/stdout.golden b/test/grammar/schema/optional_attr/inherit_4/stdout.golden new file mode 100644 index 000000000..654f98b45 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_4/stdout.golden @@ -0,0 +1,3 @@ +a: + n1: aa + n2: a diff --git a/test/grammar/schema/optional_attr/inherit_5/main.k b/test/grammar/schema/optional_attr/inherit_5/main.k new file mode 100644 index 000000000..e2fcc474e --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_5/main.k @@ -0,0 +1,16 @@ +schema Name: + n1: str = "aa" + n2: str + +schema Sub[a: str](Name): + n2 = a + +schema Phase: + a: Sub + +schema Schema: + f = lambda { + [[Phase{a = Sub("a")}.a]][0][0] | {} + }() + +a = Schema{} \ No newline at end of file diff --git a/test/grammar/schema/optional_attr/inherit_5/stdout.golden b/test/grammar/schema/optional_attr/inherit_5/stdout.golden new file mode 100644 index 000000000..d90f9ab82 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_5/stdout.golden @@ -0,0 +1,4 @@ +a: + f: + n1: aa + n2: a diff --git a/test/grammar/schema/optional_attr/inherit_6/main.k b/test/grammar/schema/optional_attr/inherit_6/main.k new file mode 100644 index 000000000..9f27d96cc --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_6/main.k @@ -0,0 +1,31 @@ +schema Name: + n1: str = "aa" + n2: str + +schema Sub[a: str](Name): + n2 = a + +schema Phase: + a: Sub + +schema Schema: + f0: () = lambda { + [[Phase{a = Sub("a")}.a]][0][0] + } + f1: () = lambda { + [[Phase{a = Sub("a")}.a]][0][0] | {} + } + f2: () = lambda { + s = [[Phase{a = Sub("a")}.a]][0][0] + s | {} + } + ff: () -> () = lambda { + lambda { + [[Phase{a = Sub("a")}.a]][0] | [{}] + } + } + +a = Schema().f0() +b = Schema().f1() +c = Schema().f2() +d = Schema().ff()() diff --git a/test/grammar/schema/optional_attr/inherit_6/stdout.golden b/test/grammar/schema/optional_attr/inherit_6/stdout.golden new file mode 100644 index 000000000..eaba9f398 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_6/stdout.golden @@ -0,0 +1,12 @@ +a: + n1: aa + n2: a +b: + n1: aa + n2: a +c: + n1: aa + n2: a +d: +- n1: aa + n2: a diff --git a/test/grammar/schema/optional_attr/inherit_7/main.k b/test/grammar/schema/optional_attr/inherit_7/main.k new file mode 100644 index 000000000..0c53d54a8 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_7/main.k @@ -0,0 +1,31 @@ +schema Name: + n1: str = "aa" + n2: str + +schema Sub[a: str](Name): + n2: str = a + +schema Phase: + a: Sub + +schema Schema: + f0: () = lambda { + [[Phase{a = Sub("a")}.a]][0][0] + } + f1: () = lambda { + [[Phase{a = Sub("a")}.a]][0][0] | {} + } + f2: () = lambda { + s = [[Phase{a = Sub("a")}.a]][0][0] + s | {} + } + ff: () -> () = lambda { + lambda { + [[Phase{a = Sub("a")}.a]][0] | [{}] + } + } + +a = Schema().f0() +b = Schema().f1() +c = Schema().f2() +d = Schema().ff()() diff --git a/test/grammar/schema/optional_attr/inherit_7/stdout.golden b/test/grammar/schema/optional_attr/inherit_7/stdout.golden new file mode 100644 index 000000000..eaba9f398 --- /dev/null +++ b/test/grammar/schema/optional_attr/inherit_7/stdout.golden @@ -0,0 +1,12 @@ +a: + n1: aa + n2: a +b: + n1: aa + n2: a +c: + n1: aa + n2: a +d: +- n1: aa + n2: a