From e0dd22884b92f21963645638b70018275628061f Mon Sep 17 00:00:00 2001 From: NeverRaR <44917563+NeverRaR@users.noreply.github.com> Date: Fri, 20 Oct 2023 10:56:10 +0800 Subject: [PATCH] feat : namer for new architecture of semantic model (#762) * feat : namer for new architecture of semantic model Signed-off-by: never * feat: namer add symbol_db Signed-off-by: never --------- Signed-off-by: never --- kclvm/Cargo.lock | 20 + kclvm/ast/Cargo.toml | 9 +- kclvm/ast/src/ast.rs | 34 +- kclvm/parser/src/parser/expr.rs | 3 + kclvm/parser/src/parser/mod.rs | 1 + kclvm/parser/src/parser/stmt.rs | 1 + kclvm/sema/Cargo.toml | 18 +- kclvm/sema/src/core/global_state.rs | 29 ++ kclvm/sema/src/core/mod.rs | 3 + kclvm/sema/src/core/package.rs | 89 ++++ kclvm/sema/src/core/symbol.rs | 488 ++++++++++++++++++ kclvm/sema/src/lib.rs | 2 + kclvm/sema/src/namer/mod.rs | 156 ++++++ kclvm/sema/src/namer/node.rs | 341 ++++++++++++ .../sema/src/namer/test_data/import_test/a.k | 4 + .../sema/src/namer/test_data/import_test/b.k | 1 + .../sema/src/namer/test_data/import_test/c.k | 2 + .../sema/src/namer/test_data/import_test/d.k | 2 + .../sema/src/namer/test_data/import_test/e.k | 2 + .../sema/src/namer/test_data/import_test/f.k | 2 + kclvm/sema/src/namer/test_data/kcl.mod | 0 kclvm/sema/src/namer/test_data/pkg/pkg.k | 5 + .../sema/src/namer/test_data/schema_symbols.k | 32 ++ 23 files changed, 1230 insertions(+), 14 deletions(-) create mode 100644 kclvm/sema/src/core/global_state.rs create mode 100644 kclvm/sema/src/core/mod.rs create mode 100644 kclvm/sema/src/core/package.rs create mode 100644 kclvm/sema/src/core/symbol.rs create mode 100644 kclvm/sema/src/namer/mod.rs create mode 100644 kclvm/sema/src/namer/node.rs create mode 100644 kclvm/sema/src/namer/test_data/import_test/a.k create mode 100644 kclvm/sema/src/namer/test_data/import_test/b.k create mode 100644 kclvm/sema/src/namer/test_data/import_test/c.k create mode 100644 kclvm/sema/src/namer/test_data/import_test/d.k create mode 100644 kclvm/sema/src/namer/test_data/import_test/e.k create mode 100644 kclvm/sema/src/namer/test_data/import_test/f.k create mode 100644 kclvm/sema/src/namer/test_data/kcl.mod create mode 100644 kclvm/sema/src/namer/test_data/pkg/pkg.k create mode 100644 kclvm/sema/src/namer/test_data/schema_symbols.k diff --git a/kclvm/Cargo.lock b/kclvm/Cargo.lock index 4e0ac7247..d69def23e 100644 --- a/kclvm/Cargo.lock +++ b/kclvm/Cargo.lock @@ -1057,6 +1057,15 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +[[package]] +name = "generational-arena" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877e94aff08e743b651baaea359664321055749b398adff8740a7399af7796e7" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1502,6 +1511,7 @@ dependencies = [ "kclvm-span", "serde", "serde_json", + "uuid", ] [[package]] @@ -1756,6 +1766,7 @@ dependencies = [ "compiler_base_span 0.0.2", "criterion 0.3.6", "fancy-regex", + "generational-arena", "indexmap 1.9.3", "kclvm-ast", "kclvm-ast-pretty", @@ -3883,6 +3894,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "getrandom", +] + [[package]] name = "vergen" version = "8.2.4" diff --git a/kclvm/ast/Cargo.toml b/kclvm/ast/Cargo.toml index d5d2342af..9d9a844ad 100644 --- a/kclvm/ast/Cargo.toml +++ b/kclvm/ast/Cargo.toml @@ -6,12 +6,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -compiler_base_span = {path = "../../compiler_base/span", version = "0.0.2"} +uuid = { version = "1.4.1", features = ["v4"] } +compiler_base_span = { path = "../../compiler_base/span", version = "0.0.2" } serde = { version = "1", features = ["derive"] } serde_json = "1.0" -kclvm-span = {path = "../span"} -kclvm-error = {path = "../error"} +kclvm-span = { path = "../span" } +kclvm-error = { path = "../error" } [dev-dependencies] -kclvm-parser = {path = "../parser"} +kclvm-parser = { path = "../parser" } diff --git a/kclvm/ast/src/ast.rs b/kclvm/ast/src/ast.rs index 663879f17..1372d774d 100644 --- a/kclvm/ast/src/ast.rs +++ b/kclvm/ast/src/ast.rs @@ -39,6 +39,8 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use compiler_base_span::{Loc, Span}; +use std::fmt::Debug; +use uuid; use super::token; use crate::{node_ref, pos::ContainsPos}; @@ -79,12 +81,22 @@ impl Into for Pos { } } +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub struct AstIndex(uuid::Uuid); + +impl Default for AstIndex { + fn default() -> Self { + Self(uuid::Uuid::new_v4()) + } +} /// Node is the file, line and column number information /// that all AST nodes need to contain. /// In fact, column and end_column are the counts of character, /// For example, `\t` is counted as 1 character, so it is recorded as 1 here, but generally col is 4. -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +#[derive(Serialize, Deserialize, Clone, PartialEq)] pub struct Node { + #[serde(skip_serializing, skip_deserializing, default)] + pub id: AstIndex, pub node: T, pub filename: String, pub line: u64, @@ -93,6 +105,19 @@ pub struct Node { pub end_column: u64, } +impl Debug for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Node") + .field("node", &self.node) + .field("filename", &self.filename) + .field("line", &self.line) + .field("column", &self.column) + .field("end_line", &self.end_line) + .field("end_column", &self.end_column) + .finish() + } +} + impl Node { pub fn new( node: T, @@ -103,6 +128,7 @@ impl Node { end_column: u64, ) -> Self { Self { + id: AstIndex::default(), node, filename, line, @@ -114,6 +140,7 @@ impl Node { pub fn dummy_node(node: T) -> Self { Self { + id: AstIndex::default(), node, filename: "".to_string(), line: 1, @@ -125,6 +152,7 @@ impl Node { pub fn node(node: T, (lo, hi): (Loc, Loc)) -> Self { Self { + id: AstIndex::default(), node, filename: format!("{}", lo.file.name.prefer_remapped()), line: lo.line as u64, @@ -136,6 +164,7 @@ impl Node { pub fn node_with_pos(node: T, pos: PosTuple) -> Self { Self { + id: AstIndex::default(), node, filename: pos.0.clone(), line: pos.1, @@ -178,6 +207,7 @@ impl TryInto> for Node { fn try_into(self) -> Result, Self::Error> { match self.node { Expr::Identifier(ident) => Ok(Node { + id: self.id, node: ident, filename: self.filename, line: self.line, @@ -194,6 +224,7 @@ impl Node { /// Into a missing identifier. pub fn into_missing_identifier(&self) -> Node { Node { + id: self.id.clone(), node: Identifier { names: vec![], pkgpath: String::new(), @@ -214,6 +245,7 @@ impl TryInto> for Node { fn try_into(self) -> Result, Self::Error> { match self.node { Expr::Schema(schema_expr) => Ok(Node { + id: self.id, node: schema_expr, filename: self.filename, line: self.line, diff --git a/kclvm/parser/src/parser/expr.rs b/kclvm/parser/src/parser/expr.rs index 1f059460b..1ef1726fd 100644 --- a/kclvm/parser/src/parser/expr.rs +++ b/kclvm/parser/src/parser/expr.rs @@ -1171,6 +1171,7 @@ impl<'a> Parser<'a> { x.node.orelse = if_item.orelse; let t = Node { + id: AstIndex::default(), node: Expr::ListIfItem(x.node), filename: x.filename, line: x.line, @@ -1607,6 +1608,7 @@ impl<'a> Parser<'a> { x.node.orelse = if_entry.node.orelse; let t = Node { + id: AstIndex::default(), node: Expr::ConfigIfEntry(x.node), filename: x.filename, line: x.line, @@ -1646,6 +1648,7 @@ impl<'a> Parser<'a> { let mut body = { let node = Node { + id: AstIndex::default(), node: Expr::NameConstantLit(NameConstantLit { value: NameConstant::None, // ignore }), diff --git a/kclvm/parser/src/parser/mod.rs b/kclvm/parser/src/parser/mod.rs index 4e24d8f6f..f4cb65cc6 100644 --- a/kclvm/parser/src/parser/mod.rs +++ b/kclvm/parser/src/parser/mod.rs @@ -189,6 +189,7 @@ impl<'a> Parser<'a> { let filename: String = format!("{}", lo.file.name.prefer_remapped()); let node = kclvm_ast::ast::Node { + id: kclvm_ast::ast::AstIndex::default(), node: Comment { text: x.as_str().to_string(), }, diff --git a/kclvm/parser/src/parser/stmt.rs b/kclvm/parser/src/parser/stmt.rs index dfd4c33b7..0d12544df 100644 --- a/kclvm/parser/src/parser/stmt.rs +++ b/kclvm/parser/src/parser/stmt.rs @@ -1021,6 +1021,7 @@ impl<'a> Parser<'a> { index_signature: body_index_signature, name: Box::new(Node { + id: AstIndex::default(), node: "".to_string(), filename: "".to_string(), line: 0, diff --git a/kclvm/sema/Cargo.toml b/kclvm/sema/Cargo.toml index 117dff6f6..d5fdfd996 100644 --- a/kclvm/sema/Cargo.toml +++ b/kclvm/sema/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +generational-arena = "0.2.9" phf = { version = "0.9", features = ["macros"] } ahash = "0.7.2" indexmap = "1.0" @@ -20,22 +21,21 @@ regex = "1.7.0" lazy_static = "1.4.0" pcre2 = "*" -kclvm-ast = {path = "../ast"} -kclvm-ast-pretty = {path = "../ast_pretty"} -kclvm-runtime = {path = "../runtime"} -kclvm-error = {path = "../error"} -kclvm-span = {path = "../span"} -compiler_base_span = {path = "../../compiler_base/span", version = "0.0.2"} -compiler_base_session = {path = "../../compiler_base/session"} +kclvm-ast = { path = "../ast" } +kclvm-ast-pretty = { path = "../ast_pretty" } +kclvm-runtime = { path = "../runtime" } +kclvm-error = { path = "../error" } +kclvm-span = { path = "../span" } +compiler_base_span = { path = "../../compiler_base/span", version = "0.0.2" } +compiler_base_session = { path = "../../compiler_base/session" } compiler_base_macros = "0.0.1" compiler_base_error = {path = "../../compiler_base/error"} suggestions = "0.1.1" [dev-dependencies] -kclvm-parser = {path = "../parser"} +kclvm-parser = { path = "../parser" } criterion = "0.3" [[bench]] name = "my_benchmark" harness = false - diff --git a/kclvm/sema/src/core/global_state.rs b/kclvm/sema/src/core/global_state.rs new file mode 100644 index 000000000..d1741b71d --- /dev/null +++ b/kclvm/sema/src/core/global_state.rs @@ -0,0 +1,29 @@ +use super::{package::PackageDB, symbol::KCLSymbolData}; + +#[derive(Default, Debug)] +pub struct GlobalState { + symbols: KCLSymbolData, + packages: PackageDB, +} + +impl GlobalState { + pub fn get_symbols(&self) -> &KCLSymbolData { + &self.symbols + } + + pub fn get_symbols_mut(&mut self) -> &mut KCLSymbolData { + &mut self.symbols + } + + pub fn get_packages(&self) -> &PackageDB { + &self.packages + } + + pub fn get_packages_mut(&mut self) -> &mut PackageDB { + &mut self.packages + } + + pub fn resolve_symbols(&mut self) { + self.symbols.replace_unresolved_symbol(&self.packages) + } +} diff --git a/kclvm/sema/src/core/mod.rs b/kclvm/sema/src/core/mod.rs new file mode 100644 index 000000000..c6518d459 --- /dev/null +++ b/kclvm/sema/src/core/mod.rs @@ -0,0 +1,3 @@ +pub mod global_state; +pub mod package; +pub mod symbol; diff --git a/kclvm/sema/src/core/package.rs b/kclvm/sema/src/core/package.rs new file mode 100644 index 000000000..84bc0a3c8 --- /dev/null +++ b/kclvm/sema/src/core/package.rs @@ -0,0 +1,89 @@ +use indexmap::IndexMap; + +#[derive(Default, Debug)] +pub struct PackageDB { + pub(crate) package_info: IndexMap, +} + +impl PackageDB { + pub fn add_package(&mut self, info: PackageInfo) { + self.package_info + .insert(info.fully_qualified_name.clone(), info); + } + + pub fn remove_package_info(&mut self, name: &str) { + self.package_info.remove(name); + } + + pub fn get_package_info(&self, name: &str) -> Option<&PackageInfo> { + self.package_info.get(name) + } + + pub fn get_package_info_mut(&mut self, name: &str) -> Option<&mut PackageInfo> { + self.package_info.get_mut(name) + } +} +#[derive(Debug)] +pub struct PackageInfo { + pub(crate) fully_qualified_name: String, + pub(crate) modules: IndexMap, + pub(crate) imports: IndexMap, +} + +impl PackageInfo { + pub fn new(fully_qualified_name: String) -> Self { + Self { + fully_qualified_name, + modules: IndexMap::default(), + imports: IndexMap::default(), + } + } + + pub fn add_import_info(&mut self, info: ImportInfo) { + self.imports.insert(info.fully_qualified_name.clone(), info); + } + + pub fn remove_import_info(&mut self, name: &str) { + self.imports.remove(name); + } + + pub fn get_import_info(&self, name: &str) -> Option<&ImportInfo> { + self.imports.get(name) + } + + pub fn add_module_info(&mut self, info: ModuleInfo) { + self.modules.insert(info.filename.clone(), info); + } + + pub fn remove_module_info(&mut self, name: &str) { + self.modules.remove(name); + } + + pub fn get_module_info(&self, name: &str) -> Option<&ModuleInfo> { + self.modules.get(name) + } +} +#[derive(Debug)] +pub struct ImportInfo { + pub(crate) unqualified_name: String, + pub(crate) fully_qualified_name: String, +} + +impl ImportInfo { + pub fn new(unqualified_name: String, fully_qualified_name: String) -> Self { + Self { + unqualified_name, + fully_qualified_name, + } + } +} +#[derive(Debug)] +pub struct ModuleInfo { + pub(crate) filename: String, +} + +impl ModuleInfo { + pub fn new(filename: String) -> Self { + Self { filename } + } +} diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs new file mode 100644 index 000000000..2368a8070 --- /dev/null +++ b/kclvm/sema/src/core/symbol.rs @@ -0,0 +1,488 @@ +use std::rc::Rc; + +use generational_arena::Arena; +use indexmap::IndexMap; + +use kclvm_error::Position; + +use super::package::{PackageDB, PackageInfo}; +use crate::ty::Type; +use kclvm_ast::ast::AstIndex; + +#[derive(Default, Debug)] +pub struct KCLSymbolData { + pub(crate) values: Arena, + pub(crate) packages: Arena, + pub(crate) attributes: Arena, + pub(crate) schemas: Arena, + pub(crate) type_aliases: Arena, + pub(crate) unresolved: Arena, + pub(crate) rules: Arena, + + pub(crate) symbols_info: SymbolDB, +} + +#[derive(Default, Debug)] +pub struct SymbolDB { + pub(crate) fully_qualified_name_map: IndexMap, + pub(crate) ast_id_map: IndexMap, + pub(crate) symbol_ty_map: IndexMap>, +} + +impl KCLSymbolData { + pub fn get_symbol_by_ast_index(&self, id: &AstIndex) -> Option { + self.symbols_info.ast_id_map.get(id).cloned() + } + + pub fn get_symbol_by_fully_qualified_name(&self, fqn: &str) -> Option { + self.symbols_info.fully_qualified_name_map.get(fqn).cloned() + } + + pub fn get_fully_qualified_name(&self, symbol_ref: SymbolRef) -> Option { + match symbol_ref.get_kind() { + SymbolKind::Schema => { + let schema_symbol = self.schemas.get(symbol_ref.get_id())?; + let owner_name = self.get_fully_qualified_name(schema_symbol.owner.clone())?; + Some(owner_name + "." + &schema_symbol.name) + } + SymbolKind::Attribute => { + let attribute_symbol = self.attributes.get(symbol_ref.get_id())?; + let owner_name = self.get_fully_qualified_name(attribute_symbol.owner)?; + Some(owner_name + "." + &attribute_symbol.name) + } + SymbolKind::TypeAlias => { + let type_symbol = self.type_aliases.get(symbol_ref.get_id())?; + let owner_name = self.get_fully_qualified_name(type_symbol.owner)?; + Some(owner_name + "." + &type_symbol.name) + } + SymbolKind::Rule => { + let rule_symbol = self.rules.get(symbol_ref.get_id())?; + let owner_name = self.get_fully_qualified_name(rule_symbol.owner)?; + Some(owner_name + "." + &rule_symbol.name) + } + SymbolKind::Value => { + let value_symbol = self.values.get(symbol_ref.get_id())?; + let owner_name = self.get_fully_qualified_name(value_symbol.owner)?; + Some(owner_name + "." + &value_symbol.name) + } + SymbolKind::Package => { + Some(self.packages.get(symbol_ref.get_id()).unwrap().name.clone()) + } + SymbolKind::Unresolved => None, + } + } + + pub fn build_fully_qualified_name_map(&mut self) { + for (id, _) in self.packages.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Package, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.schemas.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Schema, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.type_aliases.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::TypeAlias, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.attributes.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Attribute, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.rules.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Rule, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + + for (id, _) in self.values.iter() { + let symbol_ref = SymbolRef { + id, + kind: SymbolKind::Value, + }; + self.symbols_info.fully_qualified_name_map.insert( + self.get_fully_qualified_name(symbol_ref).unwrap(), + symbol_ref, + ); + } + } + + fn resolve_symbol(&mut self, symbol_ref: SymbolRef, package_info: &PackageInfo) -> SymbolRef { + if matches!(symbol_ref.get_kind(), SymbolKind::Unresolved) { + let unresolved_symbol = self.unresolved.get_mut(symbol_ref.get_id()).unwrap(); + let target_symbol = self + .symbols_info + .fully_qualified_name_map + .get(&unresolved_symbol.get_fully_qualified_name(package_info)); + + match target_symbol { + Some(target_symbol) => { + unresolved_symbol.def = Some(*target_symbol); + *target_symbol + } + None => symbol_ref, + } + } else { + symbol_ref + } + } + + pub fn replace_unresolved_symbol(&mut self, package_db: &PackageDB) { + let mut schema_refs = vec![]; + for (id, _) in self.schemas.iter() { + schema_refs.push(id) + } + for schema_ref in schema_refs { + let pkg_path = self + .get_fully_qualified_name(self.schemas.get(schema_ref).unwrap().owner) + .unwrap(); + let package_info = package_db.get_package_info(&pkg_path).unwrap(); + + let parent_schema = self.schemas.get(schema_ref).unwrap().parent_schema.clone(); + self.schemas.get_mut(schema_ref).unwrap().parent_schema = + parent_schema.map(|symbol_ref| self.resolve_symbol(symbol_ref, package_info)); + + let mut mixins = self.schemas.get(schema_ref).unwrap().mixins.clone(); + + for mixin_index in 0..mixins.len() { + let mixin = mixins.get_mut(mixin_index).unwrap(); + *mixin = self.resolve_symbol(mixin.clone(), package_info) + } + self.schemas.get_mut(schema_ref).unwrap().mixins = mixins; + } + } + + pub fn alloc_package_symbol(&mut self, pkg: PackageSymbol) -> SymbolRef { + let symbol_id = self.packages.insert(pkg); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Package, + }; + self.packages.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_schema_symbol(&mut self, schema: SchemaSymbol, ast_id: &AstIndex) -> SymbolRef { + let symbol_id = self.schemas.insert(schema); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Schema, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.schemas.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_unresolved_symbol( + &mut self, + unresolved: UnresolvedSymbol, + ast_id: &AstIndex, + ) -> SymbolRef { + let symbol_id = self.unresolved.insert(unresolved); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Unresolved, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.unresolved.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_type_alias_symbol( + &mut self, + alias: TypeAliasSymbol, + ast_id: &AstIndex, + ) -> SymbolRef { + let symbol_id = self.type_aliases.insert(alias); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::TypeAlias, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.type_aliases.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_rule_symbol(&mut self, rule: RuleSymbol, ast_id: &AstIndex) -> SymbolRef { + let symbol_id = self.rules.insert(rule); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Rule, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.rules.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_attribute_symbol( + &mut self, + attribute: AttributeSymbol, + ast_id: &AstIndex, + ) -> SymbolRef { + let symbol_id = self.attributes.insert(attribute); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Attribute, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.attributes.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } + + pub fn alloc_value_symbol(&mut self, value: ValueSymbol, ast_id: &AstIndex) -> SymbolRef { + let symbol_id = self.values.insert(value); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Value, + }; + self.symbols_info + .ast_id_map + .insert(ast_id.clone(), symbol_ref); + self.values.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + symbol_ref + } +} +#[allow(unused)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum SymbolKind { + Schema, + Attribute, + Value, + Package, + TypeAlias, + Unresolved, + Rule, +} +#[allow(unused)] +#[derive(Debug, Clone, Copy)] +pub struct SymbolRef { + id: generational_arena::Index, + kind: SymbolKind, +} + +impl SymbolRef { + pub fn get_kind(&self) -> SymbolKind { + self.kind + } + + pub fn get_id(&self) -> generational_arena::Index { + self.id + } +} +#[allow(unused)] +#[derive(Debug)] +pub struct SchemaSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, + + pub(crate) parent_schema: Option, + pub(crate) mixins: Vec, + pub(crate) attributes: IndexMap, +} + +impl SchemaSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + parent_schema: None, + mixins: Vec::default(), + attributes: IndexMap::default(), + } + } +} + +#[allow(unused)] +#[derive(Debug)] +pub struct ValueSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, +} + +impl ValueSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + } + } +} + +#[allow(unused)] +#[derive(Debug)] +pub struct AttributeSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, +} + +impl AttributeSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + } + } +} +#[allow(unused)] +#[derive(Debug)] +pub struct PackageSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) members: IndexMap, + pub(crate) start: Position, + pub(crate) end: Position, +} + +impl PackageSymbol { + pub fn new(name: String, start: Position, end: Position) -> Self { + Self { + id: None, + name, + start, + end, + members: IndexMap::default(), + } + } +} +#[allow(unused)] +#[derive(Debug)] +pub struct TypeAliasSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, +} + +impl TypeAliasSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + } + } +} +#[allow(unused)] +#[derive(Debug)] +pub struct RuleSymbol { + pub(crate) id: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, +} + +impl RuleSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + name, + start, + end, + owner, + } + } +} +#[allow(unused)] +#[derive(Debug)] +pub struct UnresolvedSymbol { + pub(crate) id: Option, + pub(crate) def: Option, + pub(crate) name: String, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) owner: SymbolRef, +} + +impl UnresolvedSymbol { + pub fn new(name: String, start: Position, end: Position, owner: SymbolRef) -> Self { + Self { + id: None, + def: None, + name, + start, + end, + owner, + } + } + + pub fn get_fully_qualified_name(&self, package_info: &PackageInfo) -> String { + let names: Vec<_> = self.name.split('.').collect(); + let pkg_path = if names.len() == 1 { + kclvm_ast::MAIN_PKG.to_string() + } else { + let pkg_alias = names.first().unwrap(); + let import_info = package_info.get_import_info(*pkg_alias); + match import_info { + Some(info) => info.fully_qualified_name.clone(), + None => kclvm_ast::MAIN_PKG.to_string(), + } + }; + + pkg_path + "." + names.last().unwrap() + } +} diff --git a/kclvm/sema/src/lib.rs b/kclvm/sema/src/lib.rs index 9a90ffecf..aa015ce9c 100644 --- a/kclvm/sema/src/lib.rs +++ b/kclvm/sema/src/lib.rs @@ -1,7 +1,9 @@ pub mod builtin; +pub mod core; pub mod eval; pub mod info; pub mod lint; +pub mod namer; pub mod plugin; pub mod pre_process; pub mod resolver; diff --git a/kclvm/sema/src/namer/mod.rs b/kclvm/sema/src/namer/mod.rs new file mode 100644 index 000000000..52cdd7e65 --- /dev/null +++ b/kclvm/sema/src/namer/mod.rs @@ -0,0 +1,156 @@ +use crate::core::global_state::GlobalState; +use crate::core::package::PackageInfo; +use crate::core::symbol::{PackageSymbol, SymbolRef}; +use kclvm_ast::ast::Program; +use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_error::Position; +mod node; + +pub struct Namer<'ctx> { + gs: GlobalState, + ctx: NamerContext<'ctx>, +} + +struct NamerContext<'ctx> { + pub program: &'ctx Program, + pub current_package_info: Option, + pub owner_symbols: Vec, +} + +impl<'ctx> Namer<'ctx> { + fn new(program: &'ctx Program, gs: GlobalState) -> Self { + Self { + ctx: NamerContext { + program, + current_package_info: None, + owner_symbols: Vec::default(), + }, + gs, + } + } + + // serial namer pass + pub fn find_symbols(program: &'ctx Program, gs: GlobalState) -> GlobalState { + let mut namer = Self::new(program, gs); + + for (name, modules) in namer.ctx.program.pkgs.iter() { + { + if modules.is_empty() { + continue; + } + + let pkg_pos = Position { + filename: modules.last().unwrap().filename.clone(), + line: 1, + column: None, + }; + + let pkg_symbol = PackageSymbol::new(name.clone(), pkg_pos.clone(), pkg_pos); + let symbol_ref = namer.gs.get_symbols_mut().alloc_package_symbol(pkg_symbol); + namer.ctx.owner_symbols.push(symbol_ref); + + namer.ctx.current_package_info = Some(PackageInfo::new(name.to_string())); + } + + for module in modules.iter() { + namer.walk_module(module); + } + + namer.ctx.owner_symbols.pop(); + namer + .gs + .get_packages_mut() + .add_package(namer.ctx.current_package_info.take().unwrap()) + } + + namer.define_symbols(); + + namer.gs + } + + pub fn define_symbols(&mut self) { + self.gs.get_symbols_mut().build_fully_qualified_name_map(); + + self.gs.resolve_symbols() + } +} + +#[cfg(test)] +mod tests { + use super::Namer; + use crate::core::global_state::GlobalState; + use crate::core::symbol::SymbolKind; + use kclvm_parser::ParseSession; + use kclvm_parser::{load_program, parse_program}; + use std::sync::Arc; + + #[test] + fn test_find_symbols() { + let sess = Arc::new(ParseSession::default()); + let program = load_program( + sess.clone(), + &["./src/namer/test_data/schema_symbols.k"], + None, + ) + .unwrap(); + let gs = GlobalState::default(); + let gs = Namer::find_symbols(&program, gs); + + let symbols = gs.get_symbols(); + + let excepts_symbols = vec![ + ("import_test.a", SymbolKind::Package), + ("import_test.b", SymbolKind::Package), + ("import_test.c", SymbolKind::Package), + ("import_test.d", SymbolKind::Package), + ("import_test.e", SymbolKind::Package), + ("import_test.f", SymbolKind::Package), + ("__main__", SymbolKind::Package), + ("pkg", SymbolKind::Package), + ("import_test.f.UnionType", SymbolKind::Schema), + ("import_test.a.Person", SymbolKind::Schema), + ("import_test.c.TestOfMixin", SymbolKind::Schema), + ("import_test.d.Parent", SymbolKind::Schema), + ("import_test.e.UnionType", SymbolKind::Schema), + ("pkg.Name", SymbolKind::Schema), + ("pkg.Person", SymbolKind::Schema), + ("__main__.Main", SymbolKind::Schema), + ("import_test.f.UnionType.b", SymbolKind::Attribute), + ("import_test.a.Person.name", SymbolKind::Attribute), + ("import_test.a.Person.age", SymbolKind::Attribute), + ("pkg.Name.name", SymbolKind::Attribute), + ("pkg.Person.name", SymbolKind::Attribute), + ("import_test.c.TestOfMixin.age", SymbolKind::Attribute), + ("import_test.d.Parent.age1", SymbolKind::Attribute), + ("import_test.e.UnionType.a", SymbolKind::Attribute), + ("__main__.Main.name", SymbolKind::Attribute), + ("__main__.Main.age", SymbolKind::Attribute), + ("__main__.Main.person", SymbolKind::Attribute), + ("__main__.Main.list_union_type", SymbolKind::Attribute), + ("__main__.Main.dict_union_type", SymbolKind::Attribute), + ("__main__.p", SymbolKind::Value), + ("__main__.person", SymbolKind::Value), + ("import_test.a._a", SymbolKind::Value), + ("import_test.b._b", SymbolKind::Value), + ]; + + assert_eq!( + symbols.symbols_info.fully_qualified_name_map.len(), + excepts_symbols.len() + ); + + for (fqn, kind) in excepts_symbols { + assert!(symbols + .symbols_info + .fully_qualified_name_map + .contains_key(fqn)); + assert_eq!( + symbols + .get_symbol_by_fully_qualified_name(fqn) + .unwrap() + .get_kind(), + kind + ); + } + } +} diff --git a/kclvm/sema/src/namer/node.rs b/kclvm/sema/src/namer/node.rs new file mode 100644 index 000000000..bfc92e239 --- /dev/null +++ b/kclvm/sema/src/namer/node.rs @@ -0,0 +1,341 @@ +use crate::core::package::{ImportInfo, ModuleInfo}; +use crate::core::symbol::{ + AttributeSymbol, RuleSymbol, SchemaSymbol, SymbolKind, SymbolRef, TypeAliasSymbol, + UnresolvedSymbol, ValueSymbol, +}; + +use super::Namer; +use kclvm_ast::ast; +use kclvm_ast::pos::GetPos; +use kclvm_ast::walker::MutSelfTypedResultWalker; +use kclvm_error::diagnostic::Range; + +impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> { + type Result = Option>; + fn walk_module(&mut self, module: &'ctx ast::Module) -> Self::Result { + let owner = *self.ctx.owner_symbols.last().unwrap(); + for stmt_node in module.body.iter() { + let symbol_refs = self.walk_stmt(&stmt_node.node); + + if let Some(symbol_refs) = symbol_refs { + for symbol_ref in symbol_refs { + let full_name = self + .gs + .get_symbols() + .get_fully_qualified_name(symbol_ref) + .unwrap(); + let name = full_name.split(".").last().unwrap().to_string(); + self.gs + .get_symbols_mut() + .packages + .get_mut(owner.get_id()) + .unwrap() + .members + .insert(name, symbol_ref); + } + } + } + self.ctx + .current_package_info + .as_mut() + .unwrap() + .add_module_info(ModuleInfo::new(module.filename.clone())); + + None + } + + fn walk_expr_stmt(&mut self, _expr_stmt: &'ctx ast::ExprStmt) -> Self::Result { + None + } + + fn walk_unification_stmt( + &mut self, + unification_stmt: &'ctx ast::UnificationStmt, + ) -> Self::Result { + let (start_pos, end_pos): Range = unification_stmt.target.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new( + unification_stmt.target.node.get_name(), + start_pos, + end_pos, + owner, + ), + &unification_stmt.target.id, + ); + + Some(vec![value_ref]) + } + + fn walk_type_alias_stmt(&mut self, type_alias_stmt: &'ctx ast::TypeAliasStmt) -> Self::Result { + let (start_pos, end_pos): Range = type_alias_stmt.type_name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let type_alias_ref = self.gs.get_symbols_mut().alloc_type_alias_symbol( + TypeAliasSymbol::new( + type_alias_stmt.type_name.node.get_name(), + start_pos, + end_pos, + owner, + ), + &type_alias_stmt.type_name.id, + ); + Some(vec![type_alias_ref]) + } + + fn walk_assign_stmt(&mut self, assign_stmt: &'ctx ast::AssignStmt) -> Self::Result { + let mut value_symbols = vec![]; + for target in assign_stmt.targets.iter() { + let (start_pos, end_pos): Range = target.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let value_ref = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(target.node.get_name(), start_pos, end_pos, owner), + &target.id, + ); + value_symbols.push(value_ref) + } + Some(value_symbols) + } + + fn walk_aug_assign_stmt(&mut self, _aug_assign_stmt: &'ctx ast::AugAssignStmt) -> Self::Result { + None + } + + fn walk_assert_stmt(&mut self, _assert_stmt: &'ctx ast::AssertStmt) -> Self::Result { + None + } + + fn walk_if_stmt(&mut self, _if_stmt: &'ctx ast::IfStmt) -> Self::Result { + None + } + + fn walk_import_stmt(&mut self, import_stmt: &'ctx ast::ImportStmt) -> Self::Result { + self.ctx + .current_package_info + .as_mut() + .unwrap() + .add_import_info(ImportInfo::new( + import_stmt.name.clone(), + import_stmt.path.clone(), + )); + + None + } + + fn walk_schema_stmt(&mut self, schema_stmt: &'ctx ast::SchemaStmt) -> Self::Result { + let (start_pos, end_pos): Range = schema_stmt.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap(); + let shcema_ref = self.gs.get_symbols_mut().alloc_schema_symbol( + SchemaSymbol::new(schema_stmt.name.node.clone(), start_pos, end_pos, *owner), + &schema_stmt.name.id, + ); + self.ctx.owner_symbols.push(shcema_ref); + + self.gs + .get_symbols_mut() + .schemas + .get_mut(shcema_ref.get_id()) + .unwrap() + .parent_schema = schema_stmt.parent_name.as_ref().map(|name| { + let (start_pos, end_pos) = name.get_span_pos(); + self.gs.get_symbols_mut().alloc_unresolved_symbol( + UnresolvedSymbol::new(name.node.get_name(), start_pos, end_pos, shcema_ref), + &name.id, + ) + }); + + for mixin in schema_stmt.mixins.iter() { + let (start_pos, end_pos) = schema_stmt.name.get_span_pos(); + let mixin_ref = self.gs.get_symbols_mut().alloc_unresolved_symbol( + UnresolvedSymbol::new(mixin.node.get_name(), start_pos, end_pos, shcema_ref), + &mixin.id, + ); + self.gs + .get_symbols_mut() + .schemas + .get_mut(shcema_ref.get_id()) + .unwrap() + .mixins + .push(mixin_ref); + } + + for stmt in schema_stmt.body.iter() { + let symbol_refs = self.walk_stmt(&stmt.node); + if let Some(symbol_refs) = symbol_refs { + for symbol_ref in symbol_refs { + if matches!(&symbol_ref.get_kind(), SymbolKind::Attribute) { + let full_attribute_name = self + .gs + .get_symbols() + .get_fully_qualified_name(symbol_ref) + .unwrap(); + let attribute_name = + full_attribute_name.split(".").last().unwrap().to_string(); + let schema_symbol = self + .gs + .get_symbols_mut() + .schemas + .get_mut(shcema_ref.get_id()) + .unwrap(); + + schema_symbol.attributes.insert(attribute_name, symbol_ref); + } + } + } + } + self.ctx.owner_symbols.pop(); + Some(vec![shcema_ref]) + } + + fn walk_rule_stmt(&mut self, rule_stmt: &'ctx ast::RuleStmt) -> Self::Result { + let (start_pos, end_pos): Range = rule_stmt.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let attribute_ref = self.gs.get_symbols_mut().alloc_rule_symbol( + RuleSymbol::new(rule_stmt.name.node.clone(), start_pos, end_pos, owner), + &rule_stmt.name.id, + ); + Some(vec![attribute_ref]) + } + + fn walk_quant_expr(&mut self, _quant_expr: &'ctx ast::QuantExpr) -> Self::Result { + None + } + + fn walk_schema_attr(&mut self, schema_attr: &'ctx ast::SchemaAttr) -> Self::Result { + let (start_pos, end_pos): Range = schema_attr.name.get_span_pos(); + let owner = self.ctx.owner_symbols.last().unwrap().clone(); + let attribute_ref = self.gs.get_symbols_mut().alloc_attribute_symbol( + AttributeSymbol::new(schema_attr.name.node.clone(), start_pos, end_pos, owner), + &schema_attr.name.id, + ); + Some(vec![attribute_ref]) + } + + /// if else -> sup([body, orelse]) + fn walk_if_expr(&mut self, _if_expr: &'ctx ast::IfExpr) -> Self::Result { + None + } + + fn walk_unary_expr(&mut self, _unary_expr: &'ctx ast::UnaryExpr) -> Self::Result { + None + } + + fn walk_binary_expr(&mut self, _binary_expr: &'ctx ast::BinaryExpr) -> Self::Result { + None + } + + fn walk_selector_expr(&mut self, _selector_expr: &'ctx ast::SelectorExpr) -> Self::Result { + None + } + + fn walk_call_expr(&mut self, _call_expr: &'ctx ast::CallExpr) -> Self::Result { + None + } + + fn walk_subscript(&mut self, _subscript: &'ctx ast::Subscript) -> Self::Result { + None + } + + fn walk_paren_expr(&mut self, _paren_expr: &'ctx ast::ParenExpr) -> Self::Result { + None + } + + fn walk_list_expr(&mut self, _list_expr: &'ctx ast::ListExpr) -> Self::Result { + None + } + + fn walk_list_comp(&mut self, _list_comp: &'ctx ast::ListComp) -> Self::Result { + None + } + + fn walk_dict_comp(&mut self, _dict_comp: &'ctx ast::DictComp) -> Self::Result { + None + } + + fn walk_list_if_item_expr( + &mut self, + _list_if_item_expr: &'ctx ast::ListIfItemExpr, + ) -> Self::Result { + None + } + + fn walk_starred_expr(&mut self, _starred_expr: &'ctx ast::StarredExpr) -> Self::Result { + None + } + + fn walk_config_if_entry_expr( + &mut self, + _config_if_entry_expr: &'ctx ast::ConfigIfEntryExpr, + ) -> Self::Result { + None + } + + fn walk_comp_clause(&mut self, _comp_clause: &'ctx ast::CompClause) -> Self::Result { + None + } + + fn walk_schema_expr(&mut self, _schema_expr: &'ctx ast::SchemaExpr) -> Self::Result { + None + } + + fn walk_config_expr(&mut self, _config_expr: &'ctx ast::ConfigExpr) -> Self::Result { + None + } + + fn walk_check_expr(&mut self, _check_expr: &'ctx ast::CheckExpr) -> Self::Result { + None + } + + fn walk_lambda_expr(&mut self, _lambda_expr: &'ctx ast::LambdaExpr) -> Self::Result { + None + } + + fn walk_keyword(&mut self, _keyword: &'ctx ast::Keyword) -> Self::Result { + None + } + + fn walk_arguments(&mut self, _arguments: &'ctx ast::Arguments) -> Self::Result { + None + } + + fn walk_compare(&mut self, _compare: &'ctx ast::Compare) -> Self::Result { + None + } + + fn walk_identifier(&mut self, _identifier: &'ctx ast::Identifier) -> Self::Result { + None + } + + fn walk_number_lit(&mut self, _number_lit: &'ctx ast::NumberLit) -> Self::Result { + None + } + + fn walk_string_lit(&mut self, _string_lit: &'ctx ast::StringLit) -> Self::Result { + None + } + + fn walk_name_constant_lit( + &mut self, + _name_constant_lit: &'ctx ast::NameConstantLit, + ) -> Self::Result { + None + } + + fn walk_joined_string(&mut self, _joined_string: &'ctx ast::JoinedString) -> Self::Result { + None + } + + fn walk_formatted_value( + &mut self, + _formatted_value: &'ctx ast::FormattedValue, + ) -> Self::Result { + None + } + + fn walk_comment(&mut self, _comment: &'ctx ast::Comment) -> Self::Result { + None + } + + fn walk_missing_expr(&mut self, _missing_expr: &'ctx ast::MissingExpr) -> Self::Result { + None + } +} diff --git a/kclvm/sema/src/namer/test_data/import_test/a.k b/kclvm/sema/src/namer/test_data/import_test/a.k new file mode 100644 index 000000000..8b6a81409 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/a.k @@ -0,0 +1,4 @@ +_a = 1 +schema Person: + name: str + age: int diff --git a/kclvm/sema/src/namer/test_data/import_test/b.k b/kclvm/sema/src/namer/test_data/import_test/b.k new file mode 100644 index 000000000..79fa8ccc7 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/b.k @@ -0,0 +1 @@ +_b = 1 diff --git a/kclvm/sema/src/namer/test_data/import_test/c.k b/kclvm/sema/src/namer/test_data/import_test/c.k new file mode 100644 index 000000000..f4832d10f --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/c.k @@ -0,0 +1,2 @@ +schema TestOfMixin: + age?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/d.k b/kclvm/sema/src/namer/test_data/import_test/d.k new file mode 100644 index 000000000..78dcd8b21 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/d.k @@ -0,0 +1,2 @@ +schema Parent: + age1?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/e.k b/kclvm/sema/src/namer/test_data/import_test/e.k new file mode 100644 index 000000000..98fabf8f4 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/e.k @@ -0,0 +1,2 @@ +schema UnionType: + a?: int diff --git a/kclvm/sema/src/namer/test_data/import_test/f.k b/kclvm/sema/src/namer/test_data/import_test/f.k new file mode 100644 index 000000000..65a0fa043 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/import_test/f.k @@ -0,0 +1,2 @@ +schema UnionType: + b?: int diff --git a/kclvm/sema/src/namer/test_data/kcl.mod b/kclvm/sema/src/namer/test_data/kcl.mod new file mode 100644 index 000000000..e69de29bb diff --git a/kclvm/sema/src/namer/test_data/pkg/pkg.k b/kclvm/sema/src/namer/test_data/pkg/pkg.k new file mode 100644 index 000000000..f8c946eff --- /dev/null +++ b/kclvm/sema/src/namer/test_data/pkg/pkg.k @@ -0,0 +1,5 @@ +schema Name: + name?: str + +schema Person: + name: Name = Name {name = "Alice"} diff --git a/kclvm/sema/src/namer/test_data/schema_symbols.k b/kclvm/sema/src/namer/test_data/schema_symbols.k new file mode 100644 index 000000000..5452a4a94 --- /dev/null +++ b/kclvm/sema/src/namer/test_data/schema_symbols.k @@ -0,0 +1,32 @@ +import import_test.a +import import_test.b +import import_test.c +import import_test.d +import import_test.e +import import_test.f as g +import pkg +import regex + +schema Main(d.Parent): + mixin [c.TestOfMixin] + name?: str + age?: int = 18 + person?: a.Person + list_union_type: [e.UnionType|int] + dict_union_type: {g.UnionType|int:float} + + check: + regex.match(name, r"[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*") if name + +if a._a > 1: + _c = 1 +elif a._a == 1: + _c = 2 +else: + _c = 3 + +p = Main{ + age = b._b +} + +person = pkg.Person {}