diff --git a/internal_macro/src/node_macro/src/lib.rs b/internal_macro/src/node_macro/src/lib.rs index c8f6cd27c..9ae731cbb 100644 --- a/internal_macro/src/node_macro/src/lib.rs +++ b/internal_macro/src/node_macro/src/lib.rs @@ -1,6 +1,50 @@ use proc_macro::TokenStream; use quote::quote; use syn::{parse_macro_input, DeriveInput}; +/// node is a macro to embed new fields, add some macros and implement +/// crate::ast::node::FmtTrait and crate::ast::node::RangeTrait +/// traits for the structure. +/// currently, it supports arguemnts as 'comment' and 'copy': +/// +/// The node without any argument embeds a new field 'range' into a structure +/// ```rust +/// #[node] +/// pub struct demo { +/// pub filed: i32, +/// pub field2: String, +/// } +/// ``` +/// The embedded structure looks like: +/// ```rust +/// #[derive(Clone, PartialEq, Eq, derivative::Derivative)] +/// #[derivative(Debug)] +/// pub struct demo { +/// pub filed: i32, +/// pub field2: String, +/// pub range: crate::ast::range::Range, +/// } +/// ``` +/// +/// If we pass the argument `comment`: +/// ```rust +/// #[node(comment)] +/// pub struct demo { +/// pub filed: i32, +/// pub field2: String, +/// } +/// ``` +/// +/// The embedded structure looks like: +/// ```rust +/// #[derive(Clone, PartialEq, Eq, derivative::Derivative)] +/// #[derivative(Debug)] +/// pub struct demo { +/// pub filed: i32, +/// pub field2: String, +/// pub comments: Vec>>, +/// pub range: crate::ast::range::Range, +/// } +/// ``` #[proc_macro_attribute] pub fn node(args: TokenStream, input: TokenStream) -> TokenStream { let mut ast = parse_macro_input!(input as DeriveInput); diff --git a/src/ast/fmt.rs b/src/ast/fmt.rs index 5c5926c6d..a43046760 100644 --- a/src/ast/fmt.rs +++ b/src/ast/fmt.rs @@ -144,9 +144,9 @@ impl FmtBuilder { pub fn parse_use_node(&mut self, node: &UseNode) { self.token("use"); self.space(); - for (i, id) in node.ids.iter().enumerate() { + for (i, id) in node.namespace.iter().enumerate() { id.format(self); - if i != node.ids.len() - 1 { + if i != node.namespace.len() - 1 { self.dbcolon(); } } @@ -158,9 +158,9 @@ impl FmtBuilder { self.enter(); } pub fn parse_extern_id_node(&mut self, node: &ExternIdNode) { - for (i, id) in node.ns.iter().enumerate() { + for (i, id) in node.namespace.iter().enumerate() { id.format(self); - if i != node.ns.len() { + if i != node.namespace.len() { self.dbcolon(); } } @@ -192,7 +192,7 @@ impl FmtBuilder { } } pub fn parse_struct_def_node(&mut self, node: &StructDefNode) { - for c in node.pre_comments.iter() { + for c in node.docs.iter() { c.format(self); } self.prefix(); @@ -303,12 +303,12 @@ impl FmtBuilder { self.token("let"); self.space(); node.var.format(self); - if let Some(tp) = &node.tp { + if let Some(tp) = &node.variable_type { self.colon(); self.space(); tp.format(self); } - if let Some(exp) = &node.exp { + if let Some(exp) = &node.value_expression { self.space(); self.equal(); self.space(); @@ -350,7 +350,7 @@ impl FmtBuilder { } } pub fn parse_ret_node(&mut self, node: &RetNode) { - if let Some((t, _)) = node.yiel { + if let Some((t, _)) = node.yield_identifier { self.token(t.get_str()); self.space(); } @@ -713,7 +713,7 @@ impl FmtBuilder { self.r_paren(); } pub fn parse_trait_bound_node(&mut self, node: &TraitBoundNode) { - node.generic.format(self); + node.identifier.format(self); if let Some(impl_trait) = &node.impl_trait { impl_trait.format(self); } @@ -756,7 +756,7 @@ impl FmtBuilder { self.space(); self.token("as"); self.space(); - node.ty.format(self); + node.target_type.format(self); if let Some((t, _)) = node.tail { if t == TokenType::QUESTION { self.token("?"); @@ -770,7 +770,7 @@ impl FmtBuilder { self.space(); self.token("is"); self.space(); - node.ty.format(self); + node.target_type.format(self); } pub fn parse_tuple_init_node(&mut self, node: &TupleInitNode) { self.l_paren(); @@ -788,7 +788,7 @@ impl FmtBuilder { } pub fn parse_tuple_type_node(&mut self, node: &TupleTypeNode) { self.l_paren(); - for (i, ty) in node.tps.iter().enumerate() { + for (i, ty) in node.types.iter().enumerate() { if i > 0 { self.comma(); self.space(); @@ -844,7 +844,7 @@ impl FmtBuilder { pub fn parse_global_const_node(&mut self, node: &GlobalConstNode) { self.token("const"); self.space(); - node.var.format(self); + node.constant.format(self); self.semicolon(); // 顶层节点加空格 self.enter(); diff --git a/src/ast/node/cast.rs b/src/ast/node/cast.rs index 0e722685c..4011217d5 100644 --- a/src/ast/node/cast.rs +++ b/src/ast/node/cast.rs @@ -25,8 +25,14 @@ use crate::ast::node::RangeTrait; #[node] pub struct AsNode { + /// expr is the expression which calculates a value as output pub expr: Box, - pub ty: Box, + + /// target_type refers the desired type for the expr + pub target_type: Box, + + /// tail is the question or exclaimation mark following an 'as' statement + /// it will be None if no marks exist pub tail: Option<(TokenType, Range)>, } @@ -37,10 +43,10 @@ impl Node for AsNode { builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { let re = self.expr.emit(ctx, builder); - self.ty.emit_highlight(ctx); + self.target_type.emit_highlight(ctx); let v = re?.get_value(); let v = v.unwrap(); - let target_tp = self.ty.get_type(ctx, builder, true)?; + let target_tp = self.target_type.get_type(ctx, builder, true)?; let (val, target_tp) = ctx.force_cast_safe( v.get_value(), &v.get_ty().borrow(), @@ -58,7 +64,7 @@ impl PrintTrait for AsNode { tab(tabs, line.clone(), end); println!("AsNode"); self.expr.print(tabs + 1, false, line.clone()); - self.ty.print(tabs + 1, true, line.clone()); + self.target_type.print(tabs + 1, true, line.clone()); } } @@ -88,14 +94,14 @@ impl<'a, 'ctx> Ctx<'a> { } (PLType::Union(union), target_ty) => { if node.tail.is_none() { - let pos = node.ty.range().end; + let pos = node.target_type.range().end; let end_range = Range { start: pos, end: pos, }; return Err(node.range.new_err(ErrorCode::INVALID_DIRECT_UNION_CAST) .add_label(node.expr.range(), self.get_file(), format_label!("type of the expression is `{}`", &union.name)) - .add_label(node.ty.range(), self.get_file(), format_label!("target type is `{}`", target_ty.get_name())) + .add_label(node.target_type.range(), self.get_file(), format_label!("target type is `{}`", target_ty.get_name())) .add_label(end_range, self.get_file(), format_label!("add `{}` or `{}` to make it legal", "?", "!")) .add_help("cast a union to its member type directly is not allowed, use `?` or `!` after the cast expression") .add_to_ctx(self)); @@ -124,7 +130,7 @@ impl<'a, 'ctx> Ctx<'a> { format_label!("type of the expression is `{}`", &union.name), ) .add_label( - node.ty.range(), + node.target_type.range(), self.get_file(), format_label!("target type is `{}`", target_ty.get_name()), ) @@ -137,14 +143,14 @@ impl<'a, 'ctx> Ctx<'a> { } (PLType::Trait(t), target_ty) => { if node.tail.is_none() { - let pos = node.ty.range().end; + let pos = node.target_type.range().end; let end_range = Range { start: pos, end: pos, }; return Err(node.range.new_err(ErrorCode::INVALID_DIRECT_TRAIT_CAST) .add_label(node.expr.range(), self.get_file(), format_label!("type of the expression is `{}`", &t.name)) - .add_label(node.ty.range(), self.get_file(), format_label!("target type is `{}`", target_ty.get_name())) + .add_label(node.target_type.range(), self.get_file(), format_label!("target type is `{}`", target_ty.get_name())) .add_label(end_range, self.get_file(), format_label!("add `{}` or `{}` to make it legal", "?", "!")) .add_help("cast a trait to specific type directly is not allowed, use `?` or `!` after the cast expression") .add_to_ctx(self)); @@ -161,7 +167,7 @@ impl<'a, 'ctx> Ctx<'a> { .up_cast( target_ty.clone(), Arc::new(RefCell::new(ty.clone())), - node.ty.range(), + node.target_type.range(), node.expr.range(), val, builder, @@ -175,7 +181,7 @@ impl<'a, 'ctx> Ctx<'a> { format_label!("type of the expression is `{}`", ty.get_name()), ) .add_label( - node.ty.range(), + node.target_type.range(), self.get_file(), format_label!("target type is `{}`", target_ty.borrow().get_name()), ) @@ -486,8 +492,10 @@ pub fn get_option_type<'a, 'b>( #[node] pub struct IsNode { + /// expr is the expression which calculates a value as output pub expr: Box, - pub ty: Box, + /// target_type refers the desired type for the expr + pub target_type: Box, } impl Node for IsNode { @@ -497,9 +505,9 @@ impl Node for IsNode { builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { let re = self.expr.emit(ctx, builder); - self.ty.emit_highlight(ctx); + self.target_type.emit_highlight(ctx); let v = re?.get_value().unwrap(); - let target_tp = self.ty.get_type(ctx, builder, true)?; + let target_tp = self.target_type.get_type(ctx, builder, true)?; let val = v.get_value(); let binding = v.get_ty(); let tp = &*binding.borrow(); @@ -528,7 +536,7 @@ impl Node for IsNode { .to_result() } else { Err(self - .ty + .target_type .range() .new_err(ErrorCode::UNION_DOES_NOT_CONTAIN_TYPE) .add_to_ctx(ctx)) @@ -570,6 +578,6 @@ impl PrintTrait for IsNode { tab(tabs, line.clone(), end); println!("IsNode"); self.expr.print(tabs + 1, false, line.clone()); - self.ty.print(tabs + 1, true, line.clone()); + self.target_type.print(tabs + 1, true, line.clone()); } } diff --git a/src/ast/node/control.rs b/src/ast/node/control.rs index 5e5a3be0b..5edf34d62 100644 --- a/src/ast/node/control.rs +++ b/src/ast/node/control.rs @@ -7,9 +7,16 @@ use crate::ast::pltype::PriType; use internal_macro::node; #[node(comment)] +/// IfNode is consisted by a 'if' clause and a 'else' clause. +/// the 'else' clause is allowed to embed another IfNode pub struct IfNode { + /// condition is the bool expression for the if keyword + /// there is no type check in the AST stage, but we did check it when lowering ast pub cond: Box, + /// then is the logic to be executed if the cond is true pub then: Box, + /// els stands for the left part of the condition clause + /// it might be another IfNode or a statement pub els: Option>, } @@ -159,6 +166,20 @@ impl Node for WhileNode { } #[node(comment)] +/// ForNode is consisted by four parts: pre,cond, opt and body in the format of `for pre;cond;opt body`. +/// +/// The pre and opt are optional, but the semi-colons are compulsory. +/// +/// For example: +/// ```pi +/// for let i = 0; i < 5; i = i + 1{ +/// // ^pre ^cond ^opt +/// +/// println!(i) +/// // ^body +/// } +/// +/// ``` pub struct ForNode { pub pre: Option>, pub cond: Box, diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 9abd4bb42..1097dfd02 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -452,14 +452,21 @@ fn handle_ret<'a, 'b>( } #[node] pub struct FuncDefNode { + /// id is the function identifier pub id: Box, + /// paralist is the parameter lists pub paralist: Vec>, + /// ret is the return type of the function pub ret: Box, + /// docs is the documentation of the structure started with `///` pub doc: Vec>, + /// pre_comments is the comments above a structure pub pre_comments: Vec>, - pub declare: bool, + /// is_declaration_only refers whether this function is a declaration only, which means it has no body + pub is_declaration_only: bool, pub generics: Option>, pub body: Option, + /// modifier indicates whether the trait is decorated by a keyword `pub` pub modifier: Option<(TokenType, Range)>, pub generics_size: usize, // the size of generics except the generics from impl node pub trait_bounds: Option>>, @@ -531,7 +538,7 @@ impl TypeNode for FuncDefNode { param_names: param_name, range: self.id.range(), doc: self.doc.clone(), - llvmname: if self.declare { + llvmname: if self.is_declaration_only { if self.id.name.starts_with('|') { return Err(self .range @@ -562,7 +569,7 @@ impl TypeNode for FuncDefNode { node: Some(Box::new(self.clone())), body_range: self.range, in_trait: self.in_trait_def, - is_declare: self.declare, + is_declare: self.is_declaration_only, }; if self.generics.is_none() { builder.get_or_insert_fn_handle(&fnvalue, child); diff --git a/src/ast/node/global.rs b/src/ast/node/global.rs index 23a080834..6516a27b7 100644 --- a/src/ast/node/global.rs +++ b/src/ast/node/global.rs @@ -10,7 +10,7 @@ use lsp_types::SemanticTokenType; #[node] pub struct GlobalConstNode { - pub var: Box, + pub constant: Box, } impl PrintTrait for GlobalConstNode { @@ -18,7 +18,7 @@ impl PrintTrait for GlobalConstNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("GlobalConstNode"); - self.var.print(tabs + 1, true, line.clone()); + self.constant.print(tabs + 1, true, line.clone()); } } @@ -28,15 +28,15 @@ impl Node for GlobalConstNode { ctx: &'b mut Ctx<'a>, builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { - ctx.push_semantic_token(self.var.id.range, SemanticTokenType::VARIABLE, 0); - ctx.push_semantic_token(self.var.typenode.range(), SemanticTokenType::TYPE, 0); - let pltype = self.var.typenode.get_type(ctx, builder, true)?; - let globalptr = builder.global_const(&self.var.id.name, &pltype.borrow(), ctx); + ctx.push_semantic_token(self.constant.id.range, SemanticTokenType::VARIABLE, 0); + ctx.push_semantic_token(self.constant.typenode.range(), SemanticTokenType::TYPE, 0); + let pltype = self.constant.typenode.get_type(ctx, builder, true)?; + let globalptr = builder.global_const(&self.constant.id.name, &pltype.borrow(), ctx); ctx.add_symbol( - self.var.id.name.clone(), + self.constant.id.name.clone(), globalptr, pltype, - self.var.range, + self.constant.range, true, true, )?; @@ -45,8 +45,12 @@ impl Node for GlobalConstNode { } #[node] +/// GlobalNode stands for the code starts with `var` keyword pub struct GlobalNode { + /// var is the variable defined by `var` keyword pub var: VarNode, + + /// exp is the value of the variable pub exp: Box, } diff --git a/src/ast/node/implement.rs b/src/ast/node/implement.rs index e645d18c4..670f6be4a 100644 --- a/src/ast/node/implement.rs +++ b/src/ast/node/implement.rs @@ -10,9 +10,34 @@ use rustc_hash::FxHashSet; #[node(comment)] pub struct ImplNode { + /// generics stands for the available generics types in the implementation scope, + /// which could be accessed by all methods in the block, even it might have no generic types. + /// for example, the generics in the following implementation is the `T` after keyword impl. + /// ```rust + /// struct A { t: T } + /// trait Demo{ + /// fn a(self, t:T); + /// fn b(self,t:T, f:F); + /// } + /// impl Demo for A { + /// fn a(self,t:T) { + /// todo!() + /// } + /// fn b(self,t:T, f:F) { + /// todo!() + /// } + /// } + /// ``` + /// All methods and structures inside the block could access the generic type T. Method `b` could access it without declaring T. pub generics: Option>, + + /// target is the structure which implements the methods in impl_trait pub target: Box, + + /// methods holds the definitions of the implemented methods pub methods: Vec>, + + /// impl_trait is the trait to implement for the target structure pub impl_trait: Option<(Box, (TokenType, Range))>, } diff --git a/src/ast/node/interface.rs b/src/ast/node/interface.rs index f3d68612b..791475b11 100644 --- a/src/ast/node/interface.rs +++ b/src/ast/node/interface.rs @@ -42,7 +42,8 @@ impl MultiTraitNode { } #[node] pub struct TraitBoundNode { - pub generic: Box, + pub identifier: Box, + /// impl_trait is the trait identifier bound to pub impl_trait: Option>, } impl TraitBoundNode { @@ -51,12 +52,16 @@ impl TraitBoundNode { ctx: &mut Ctx<'_>, generic_map: &IndexMap>>, ) -> Result<(), PLDiag> { - if !generic_map.contains_key(&self.generic.name) { - return Err(ctx.add_diag(self.generic.range().new_err(ErrorCode::GENERIC_NOT_FOUND))); + if !generic_map.contains_key(&self.identifier.name) { + return Err(ctx.add_diag( + self.identifier + .range() + .new_err(ErrorCode::GENERIC_NOT_FOUND), + )); } if let Some(impl_trait) = &self.impl_trait { // let trait_pltype = impl_trait.get_types(ctx, builder)?; - let generic_type = generic_map.get(&self.generic.name).unwrap(); + let generic_type = generic_map.get(&self.identifier.name).unwrap(); if let PLType::Generic(generic_type) = &mut *generic_type.borrow_mut() { if generic_type.trait_impl.is_some() { return Err( @@ -71,7 +76,7 @@ impl TraitBoundNode { Ok(()) } pub fn emit_highlight(&self, ctx: &mut Ctx) { - ctx.push_semantic_token(self.generic.range, SemanticTokenType::TYPE, 0); + ctx.push_semantic_token(self.identifier.range, SemanticTokenType::TYPE, 0); if let Some(impl_trait) = &self.impl_trait { impl_trait.emit_highlight(ctx); } @@ -79,9 +84,13 @@ impl TraitBoundNode { } #[node] pub struct TraitDefNode { + /// id is the identifier of the trait pub id: Box, + /// methods is all methods defined by a trait pub methods: Vec, + /// derives is the trait derived by the current trait, multiple traits derivation are allowed pub derives: MultiTraitNode, + /// modifier indicates whether the trait is decorated by a keyword `pub` pub modifier: Option<(TokenType, Range)>, pub generics: Option>, } diff --git a/src/ast/node/macro_nodes.rs b/src/ast/node/macro_nodes.rs index dc2f5611a..b0b1e2147 100644 --- a/src/ast/node/macro_nodes.rs +++ b/src/ast/node/macro_nodes.rs @@ -239,7 +239,7 @@ impl Node for MacroCallNode { ) -> NodeResult { match &*self.callee { NodeEnum::ExternIdNode(ex_node) => { - for ns in &ex_node.ns { + for ns in &ex_node.namespace { ctx.push_semantic_token(ns.range(), SemanticTokenType::NAMESPACE, 0); } ctx.push_semantic_token(ex_node.id.range(), SemanticTokenType::MACRO, 0); diff --git a/src/ast/node/operator.rs b/src/ast/node/operator.rs index 49b7f0926..05acb4442 100644 --- a/src/ast/node/operator.rs +++ b/src/ast/node/operator.rs @@ -82,8 +82,10 @@ impl Node for UnaryOpNode { #[node] pub struct BinOpNode { + /// left holds the left part of the binary operation of the first binary operator in an expression pub left: Box, pub op: (TokenType, Range), + /// right holds the right part of the binary operation of the first binary operator in an expression pub right: Box, } diff --git a/src/ast/node/pkg.rs b/src/ast/node/pkg.rs index cda0ef46c..1def570e9 100644 --- a/src/ast/node/pkg.rs +++ b/src/ast/node/pkg.rs @@ -21,19 +21,25 @@ use super::PrintTrait; use super::{primary::VarNode, Node, NodeResult}; #[node] pub struct UseNode { - pub ids: Vec>, - /// 是否完整 - /// use a::b 完整 - /// use a::b:: 不完整 - pub complete: bool, - pub singlecolon: bool, + /// namespace imported by use keyword + pub namespace: Vec>, + + /// whether the pub modifier exists pub modifier: Option<(TokenType, Range)>, + + /// whether import all symbols in the namespace pub all_import: bool, + + /// complete is used for error toleration during parsing + /// for example, 'use a::b' is completed, but 'use a::b::' is incompleted + pub complete: bool, + /// singlecolon is used for error toleration during parsing + pub singlecolon: bool, } impl UseNode { pub(crate) fn get_last_id(&self) -> Option { - self.ids.last().map(|x| x.as_ref().name.clone()) + self.namespace.last().map(|x| x.as_ref().name.clone()) } } @@ -42,8 +48,8 @@ impl PrintTrait for UseNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("UseNode"); - let mut i = self.ids.len(); - for id in &self.ids { + let mut i = self.namespace.len(); + for id in &self.namespace { i -= 1; id.print(tabs + 1, i == 0, line.clone()); } @@ -60,8 +66,8 @@ impl Node for UseNode { let mut path = PathBuf::from(""); #[cfg(not(target_arch = "wasm32"))] let mut path = PathBuf::from(&ctx.config.root); - let head = self.ids[0].get_name(ctx); - if !self.ids.is_empty() { + let head = self.namespace[0].get_name(ctx); + if !self.namespace.is_empty() { // head is project name or deps name let dep = ctx.config.deps.as_ref().and_then(|x| x.get(&head)); if head == ctx.config.project || dep.is_some() { @@ -69,20 +75,20 @@ impl Node for UseNode { if let Some(dep) = dep { path = path.join(&dep.path); } - for i in 1..self.ids.len() { - path = path.join(self.ids[i].get_name(ctx)); + for i in 1..self.namespace.len() { + path = path.join(self.namespace[i].get_name(ctx)); } } } - if self.ids.len() > 1 { - for (i, v) in self.ids.iter().enumerate() { - if i == self.ids.len() - 1 { + if self.namespace.len() > 1 { + for (i, v) in self.namespace.iter().enumerate() { + if i == self.namespace.len() - 1 { break; } ctx.push_semantic_token(v.range, SemanticTokenType::NAMESPACE, 0); } } else { - for v in self.ids.iter() { + for v in self.namespace.iter() { ctx.push_semantic_token(v.range, SemanticTokenType::NAMESPACE, 0); } } @@ -92,7 +98,7 @@ impl Node for UseNode { .is_some() { ctx.push_semantic_token( - self.ids.last().unwrap().range, + self.namespace.last().unwrap().range, SemanticTokenType::NAMESPACE, 0, ); @@ -106,7 +112,7 @@ impl Node for UseNode { } path = path.parent().unwrap().to_path_buf(); } - if self.ids.len() > 1 { + if self.namespace.len() > 1 { ctx.if_completion(self.range, || { if self.singlecolon { return vec![]; @@ -120,7 +126,7 @@ impl Node for UseNode { }); let mod_id = path.file_name().unwrap().to_str().unwrap(); if let Some(m) = ctx.plmod.submods.get(mod_id) { - let n = self.ids.last().unwrap(); + let n = self.namespace.last().unwrap(); if let Ok(tp) = m.get_type(&n.name, n.range, ctx) { let t = match &*tp.borrow() { PLType::Fn(_) => SemanticTokenType::FUNCTION, @@ -159,8 +165,8 @@ impl Node for UseNode { } ctx.add_diag(self.range.new_err(ErrorCode::UNRESOLVED_MODULE)); } - if self.ids.len() > 1 { - let last = self.ids.last().unwrap(); + if self.namespace.len() > 1 { + let last = self.namespace.last().unwrap(); ctx.push_semantic_token(last.range, SemanticTokenType::NAMESPACE, 0); if let Some(m) = ctx.plmod.submods.get(&last.name) { ctx.send_if_go_to_def(last.range, Default::default(), m.path.to_owned()); @@ -171,7 +177,7 @@ impl Node for UseNode { return vec![]; } let mut completions = get_ns_path_completions(path.to_str().unwrap()); - if self.ids.len() < 2 && self.complete { + if self.namespace.len() < 2 && self.complete { completions.clear(); if let Some(deps) = &ctx.config.deps { for dep in deps.keys() { @@ -203,9 +209,16 @@ impl Node for UseNode { /// TODO: 区分该节点与ExternTypeName节点,该节点不生成类型,只生成函数与变量/常量 #[node] pub struct ExternIdNode { - pub ns: Vec>, + /// namespace refers to the namespace of an identifier + /// it might be empty + pub namespace: Vec>, + + /// id is the identifier pub id: Box, + + /// complete is used for error toleration during parsing pub complete: bool, + /// singlecolon is used for error toleration during parsing pub singlecolon: bool, } @@ -214,7 +227,7 @@ impl PrintTrait for ExternIdNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("ExternIdNode"); - for id in &self.ns { + for id in &self.namespace { id.print(tabs + 1, false, line.clone()); } self.id.print(tabs + 1, true, line.clone()); @@ -227,7 +240,7 @@ impl Node for ExternIdNode { ctx: &'b mut Ctx<'a>, builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { - if self.ns.is_empty() { + if self.namespace.is_empty() { if self.complete { // 如果该节点只有一个id,且完整,那么就是一个普通的包内符号,直接调用idnode return self.id.emit(ctx, builder); @@ -247,14 +260,15 @@ impl Node for ExternIdNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::COMPLETION))); } else { ctx.if_completion(self.range, || { - ctx.get_completions_in_ns(&self.ns[0].get_name(ctx)) + ctx.get_completions_in_ns(&self.namespace[0].get_name(ctx)) }); } - for id in &self.ns { + for id in &self.namespace { ctx.push_semantic_token(id.range, SemanticTokenType::NAMESPACE, 0); } let mut plmod = &ctx.plmod; plmod = self.solve_mod(plmod, ctx)?; + if let Some(symbol) = plmod.get_global_symbol(&self.id.get_name(ctx)) { ctx.push_semantic_token(self.id.range, SemanticTokenType::VARIABLE, 0); let pltype = symbol.tp.clone(); @@ -286,7 +300,7 @@ impl Node for ExternIdNode { } impl ExternIdNode { pub fn get_type(&self, ctx: &Ctx) -> NodeResult { - if self.ns.is_empty() { + if self.namespace.is_empty() { if self.complete { // 如果该节点只有一个id,且完整,那么就是一个普通的包内符号,直接调用idnode return self.id.get_type(ctx); @@ -305,11 +319,11 @@ impl ExternIdNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::COMPLETION))); } else { ctx.if_completion(self.range, || { - ctx.get_completions_in_ns(&self.ns[0].get_name(ctx)) + ctx.get_completions_in_ns(&self.namespace[0].get_name(ctx)) }); } let mut plmod = &ctx.plmod; - for ns in self.ns.iter() { + for ns in self.namespace.iter() { let re = plmod.submods.get(&ns.get_name(ctx)); if let Some(re) = re { plmod = re; @@ -333,7 +347,7 @@ impl ExternIdNode { } pub fn get_macro(&self, ctx: &Ctx) -> Result, PLDiag> { - if self.ns.is_empty() { + if self.namespace.is_empty() { // 如果该节点只有一个id,且完整,那么就是一个普通的包内符号,直接调用idnode if let Some(m) = ctx.get_macro(&self.id.get_name(ctx)) { return Ok(m); @@ -341,7 +355,7 @@ impl ExternIdNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::MACRO_NOT_FOUND))); } let mut plmod = &ctx.plmod; - for ns in self.ns.iter() { + for ns in self.namespace.iter() { let re = plmod.submods.get(&ns.get_name(ctx)); if let Some(re) = re { plmod = re; @@ -363,7 +377,7 @@ impl ExternIdNode { mut plmod: &'b crate::ast::plmod::Mod, ctx: &Ctx, ) -> Result<&'b crate::ast::plmod::Mod, PLDiag> { - for ns in self.ns.iter() { + for ns in self.namespace.iter() { let re = plmod.submods.get(&ns.get_name(ctx)); if let Some(re) = re { plmod = re; diff --git a/src/ast/node/primary.rs b/src/ast/node/primary.rs index 9ea12fee8..757365fb8 100644 --- a/src/ast/node/primary.rs +++ b/src/ast/node/primary.rs @@ -104,6 +104,7 @@ impl Node for NumNode { #[node] pub struct VarNode { + /// identifier name of a symbol, which could be either a variable or a type pub name: String, pub id: Option, } diff --git a/src/ast/node/program.rs b/src/ast/node/program.rs index 04c51178a..5e51f280b 100644 --- a/src/ast/node/program.rs +++ b/src/ast/node/program.rs @@ -131,7 +131,7 @@ fn new_var(name: &str) -> Box { } fn new_use(ns: &[&str]) -> Box { Box::new(NodeEnum::UseNode(UseNode { - ids: ns.iter().map(|a| new_var(a)).collect(), + namespace: ns.iter().map(|a| new_var(a)).collect(), range: Default::default(), complete: true, singlecolon: false, diff --git a/src/ast/node/ret.rs b/src/ast/node/ret.rs index 76758722f..d08d3726b 100644 --- a/src/ast/node/ret.rs +++ b/src/ast/node/ret.rs @@ -10,8 +10,11 @@ use internal_macro::node; #[node(comment)] pub struct RetNode { + /// the value returned by the keyword `return` pub value: Option>, - pub yiel: Option<(TokenType, Range)>, + + /// yield_identifier refers whether the keyword 'yield' exists and the range of it + pub yield_identifier: Option<(TokenType, Range)>, } impl PrintTrait for RetNode { @@ -32,7 +35,7 @@ impl Node for RetNode { builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { let ret_pltype = ctx.rettp.as_ref().unwrap().clone(); - if self.yiel.is_some() { + if self.yield_identifier.is_some() { let ret_node = self.value.as_mut().unwrap(); let v = ret_node.emit(ctx, builder)?.get_value().unwrap(); if ctx.generator_data.is_none() { diff --git a/src/ast/node/statement.rs b/src/ast/node/statement.rs index db974832f..5538023bd 100644 --- a/src/ast/node/statement.rs +++ b/src/ast/node/statement.rs @@ -14,11 +14,18 @@ use indexmap::IndexMap; use internal_macro::node; use internal_macro::range; use lsp_types::SemanticTokenType; + #[node(comment)] +/// DefNode stands for a let statement to define a new variable +/// pub struct DefNode { + /// var is the definition of a variable pub var: Box, - pub tp: Option>, - pub exp: Option>, + /// variable_type is the type provided during defining the variable + pub variable_type: Option>, + + /// value_expression is the value of the var + pub value_expression: Option>, } #[range] @@ -89,15 +96,17 @@ impl PrintTrait for DefNode { tab(tabs, line.clone(), end); println!("DefNode"); self.var.print(tabs + 1, false, line.clone()); - if let Some(tp) = &self.tp { + if let Some(tp) = &self.variable_type { tp.print(tabs + 1, true, line.clone()); - } else if let Some(e) = self.exp.as_ref() { + } else if let Some(e) = self.value_expression.as_ref() { e.print(tabs + 1, true, line.clone()); } } } #[derive(Debug, Clone, PartialEq, Eq)] +/// DefVar stands for the variables defined by `let` keyword +/// it might be a single variable, a deconstructed tuple, or a deconstructed structure. pub enum DefVar { Identifier(VarNode), TupleDeconstruct(TupleDeconstructNode), @@ -170,7 +179,7 @@ impl Node for DefNode { ) -> NodeResult { ctx.push_semantic_token(self.var.range(), SemanticTokenType::VARIABLE, 0); let mut pltype = None; - if self.tp.is_none() { + if self.variable_type.is_none() { let mut tp = Arc::new(RefCell::new(PLType::Unknown)); if let DefVar::Identifier(i) = &*self.var { if let Some(id) = i.id { @@ -182,17 +191,17 @@ impl Node for DefNode { pltype = Some(tp); } let mut expv = None; - if let Some(tp) = &self.tp { + if let Some(tp) = &self.variable_type { tp.emit_highlight(ctx); let pltp = tp.get_type(ctx, builder, true)?; pltype = Some(pltp); } - if self.exp.is_some() + if self.value_expression.is_some() && matches!(pltype.clone(), Some(tp) if matches!(&*tp.borrow(), PLType::Unknown)) { pltype = None; } - if let Some(exp) = &mut self.exp { + if let Some(exp) = &mut self.value_expression { let re = if let Some(expect) = pltype.clone() { ctx.emit_with_expectation(exp, expect, self.var.range(), builder) } else { @@ -220,7 +229,7 @@ impl Node for DefNode { } else { re.get_value() }; - if self.tp.is_none() && pltype.is_none() { + if self.variable_type.is_none() && pltype.is_none() { pltype = Some(tp); } expv = Some(v); @@ -228,7 +237,7 @@ impl Node for DefNode { } } let pltype = pltype.unwrap_or(unknown_arc()); - if self.tp.is_none() { + if self.variable_type.is_none() { ctx.push_type_hints(self.var.range(), pltype.clone()); } let mut gm = IndexMap::new(); @@ -246,7 +255,7 @@ impl Node for DefNode { ctx.protect_generic_context(&gm, |ctx| { handle_deconstruct( self.range(), - self.exp.as_ref().map(|e| e.range()), + self.value_expression.as_ref().map(|e| e.range()), builder, pltype.clone(), ctx, @@ -480,7 +489,9 @@ fn handle_deconstruct<'a, 'b>( } #[node] pub struct AssignNode { + /// var is the variable to be assigned at the left pub var: AssignVar, + /// exp is the value to assign the var pub exp: Box, } @@ -601,7 +612,10 @@ impl Node for EmptyNode { } #[node] +/// StatementsNode stands for several statements pub struct StatementsNode { + /// statements is a vector of all statements under a statement block + /// the order is same of the code, from top to bottom pub statements: Vec>, } diff --git a/src/ast/node/tuple.rs b/src/ast/node/tuple.rs index 727e0487f..03a6f83f9 100644 --- a/src/ast/node/tuple.rs +++ b/src/ast/node/tuple.rs @@ -19,6 +19,7 @@ use super::{Node, NodeEnum, PrintTrait, TypeNode, TypeNodeEnum}; #[node] pub struct TupleInitNode { + // exprs holds the expressions inside a tuple separated by comma `,` pub exprs: Vec>, } @@ -120,7 +121,8 @@ impl PrintTrait for TupleInitNode { #[node] pub struct TupleTypeNode { - pub tps: Vec>, + /// types hold all types in a tuple with order from left to right + pub types: Vec>, } impl TypeNode for TupleTypeNode { @@ -134,7 +136,7 @@ impl TypeNode for TupleTypeNode { let mut field_tps = vec![]; let mut err = None; let mut name = String::new(); - for (i, tp) in self.tps.iter().enumerate() { + for (i, tp) in self.types.iter().enumerate() { let tp = tp.get_type(ctx, builder, gen_code); match tp { Ok(tp) => { @@ -171,7 +173,7 @@ impl TypeNode for TupleTypeNode { } fn emit_highlight(&self, ctx: &mut crate::ast::ctx::Ctx) { - for tp in &self.tps { + for tp in &self.types { tp.emit_highlight(ctx); } } @@ -197,8 +199,8 @@ impl PrintTrait for TupleTypeNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("TupleTypeNode"); - for (i, tp) in self.tps.iter().enumerate() { - tp.print(tabs + 1, i == self.tps.len() - 1, line.clone()); + for (i, tp) in self.types.iter().enumerate() { + tp.print(tabs + 1, i == self.types.len() - 1, line.clone()); } } } diff --git a/src/ast/node/types.rs b/src/ast/node/types.rs index b40f6868c..af4442475 100644 --- a/src/ast/node/types.rs +++ b/src/ast/node/types.rs @@ -30,6 +30,7 @@ use lsp_types::SemanticTokenType; #[node] pub struct TypeNameNode { + /// id is the identifier of a type pub id: Option, pub generic_params: Option>, /// # generic_infer @@ -57,7 +58,7 @@ impl TypeNameNode { id: None, }), range: Default::default(), - ns: vec![], + namespace: vec![], complete: true, singlecolon: false, }; @@ -182,7 +183,7 @@ impl PrintTrait for TypeNameNode { impl TypeNode for TypeNameNode { fn emit_highlight(&self, ctx: &mut Ctx) { if let Some(id) = &self.id { - for ns in id.ns.iter() { + for ns in id.namespace.iter() { ctx.push_semantic_token(ns.range, SemanticTokenType::NAMESPACE, 0); } ctx.push_semantic_token(id.id.range, SemanticTokenType::TYPE, 0); @@ -299,6 +300,7 @@ impl TypeNode for TypeNameNode { #[node] pub struct ArrayTypeNameNode { + /// id is the identifier of a type pub id: Box, } @@ -353,6 +355,8 @@ impl TypeNode for ArrayTypeNameNode { #[node] pub struct PointerTypeNode { + /// elm is the element type pointed by a pointer, it de-reference one layer only. + /// the elm might be a pointer as well, for example, the element of **i8 is *i8. pub elm: Box, } @@ -400,7 +404,10 @@ impl TypeNode for PointerTypeNode { #[node] pub struct TypedIdentifierNode { + // identifier of a typed identifier node pub id: VarNode, + + // typenode is the type of id pub typenode: Box, pub doc: Option, } @@ -421,11 +428,22 @@ impl TypedIdentifierNode { #[node] pub struct StructDefNode { + /// docs is the documentation of the structure started with `///` + pub docs: Vec>, + + /// pre_comments is the comments above a structure pub pre_comments: Vec>, - pub doc: Vec>, + + /// id is the identifier of the structure pub id: Box, + + /// fields is all fields of a structure, the order follows the code order from top to bottom pub fields: Vec, + + /// generics stands for the generics arguments in the structure pub generics: Option>, + + /// modifier indicates whether the trait is decorated by a keyword `pub` pub modifier: Option<(TokenType, Range)>, } #[derive(Clone, PartialEq, Eq, Debug)] @@ -442,7 +460,7 @@ impl PrintTrait for StructDefNode { println!("StructDefNode"); tab(tabs + 1, line.clone(), false); println!("id: {}", self.id.name); - for c in self.pre_comments.iter() { + for c in self.docs.iter() { c.print(tabs + 1, false, line.clone()); } let mut i = self.fields.len(); @@ -459,7 +477,7 @@ impl Node for StructDefNode { ctx: &'b mut Ctx<'a>, _builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { - ctx.emit_comment_highlight(&self.pre_comments); + ctx.emit_comment_highlight(&self.docs); ctx.push_semantic_token(self.id.range, SemanticTokenType::STRUCT, 0); if let Some(generics) = &mut self.generics { generics.emit_highlight(ctx); @@ -522,7 +540,7 @@ impl StructDefNode { // 自引用检查 if let TypeNodeEnum::Basic(b) = &*id.typenode { if let Some(id) = &b.id { - if id.ns.is_empty() { + if id.namespace.is_empty() { // 只有本包内类型可能自引用 let v = ctx.self_ref_map.entry(id.id.name.clone()).or_default(); v.insert((self.id.name.clone(), self.id.range())); @@ -568,12 +586,12 @@ impl StructDefNode { ctx.plmod.types = clone_map; if let PLType::Struct(st) = &mut *pltype.borrow_mut() { st.fields = fields.clone(); - st.doc = self.doc.clone(); + st.doc = self.pre_comments.clone(); if let Some(stpltype) = ctx.linked_tp_tbl.remove(&pltype.tp.as_ptr()) { for st in stpltype { if let PLType::Struct(st) = &mut *st.borrow_mut() { st.fields = fields.clone(); - st.doc = self.doc.clone(); + st.doc = self.pre_comments.clone(); } } } @@ -591,7 +609,7 @@ impl StructDefNode { } ctx.set_if_refs_tp(pltype.tp.clone(), self.id.range); ctx.add_doc_symbols(pltype.tp.clone()); - ctx.save_if_comment_doc_hover(self.range, Some(self.doc.clone())); + ctx.save_if_comment_doc_hover(self.range, Some(self.pre_comments.clone())); Ok(()) }) } @@ -627,7 +645,10 @@ impl Node for StructInitFieldNode { #[node] pub struct StructInitNode { + /// typename is the structure type to initialize pub typename: Box, + // fields is all provided fields with values to initialize a structure + // the order is the code order from left to right, from top to bottom pub fields: Vec>, // TODO: comment db and salsa comment struct } @@ -849,6 +870,7 @@ impl Node for ArrayInitNode { #[node] pub struct GenericDefNode { pub generics: Vec>, + /// generics_size is the number in a generic list pub generics_size: usize, } @@ -860,7 +882,7 @@ impl PrintTrait for GenericDefNode { let mut i = self.generics.len(); for g in &self.generics { i -= 1; - g.generic.print(tabs + 1, i == 0, line.clone()); + g.identifier.print(tabs + 1, i == 0, line.clone()); } } } @@ -893,8 +915,8 @@ impl GenericDefNode { pub fn gen_generic_type(&self, ctx: &Ctx) -> IndexMap>> { let mut res = IndexMap::default(); for g in self.generics.iter() { - let range = g.generic.range; - let name = g.generic.name.clone(); + let range = g.identifier.range; + let name = g.identifier.name.clone(); let gentype = GenericType { name: name.clone(), range, diff --git a/src/ast/node/union.rs b/src/ast/node/union.rs index 0c93e1090..6130c6b8e 100644 --- a/src/ast/node/union.rs +++ b/src/ast/node/union.rs @@ -18,9 +18,12 @@ use super::{ #[node] pub struct UnionDefNode { + /// modifier indicates whether the trait is decorated by a keyword `pub` pub modifier: Option<(TokenType, Range)>, + /// name is the name of union pub name: VarNode, pub generics: Option>, + /// sum_types is the types supported in a union pub sum_types: Vec>, } diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 0d55acd63..bdbc2b5b3 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -375,7 +375,7 @@ impl PriType { fn new_typename_node(name: &str, range: Range, ns: &[String]) -> Box { Box::new(TypeNodeEnum::Basic(TypeNameNode { id: Some(ExternIdNode { - ns: ns + namespace: ns .iter() .map(|s| { Box::new(VarNode { @@ -539,7 +539,7 @@ impl PLType { PLType::Struct(st) => { if st.is_tuple { Box::new(TypeNodeEnum::Tuple(TupleTypeNode { - tps: st + types: st .fields .iter() .map(|v| v.1.typenode.clone()) diff --git a/src/inference/mod.rs b/src/inference/mod.rs index fe15da5e8..a1f359315 100644 --- a/src/inference/mod.rs +++ b/src/inference/mod.rs @@ -520,10 +520,10 @@ impl<'ctx> InferenceCtx<'ctx> { match node { NodeEnum::Def(d) => { let mut ty = unknown(); - if let Some(exp) = &mut d.exp { + if let Some(exp) = &mut d.value_expression { ty = self.inference(&mut *exp, ctx, builder); } - if let Some(tp) = &d.tp { + if let Some(tp) = &d.variable_type { let new_ty = SymbolType::PLType( tp.get_type(ctx, builder, true).unwrap_or(unknown_arc()), ); @@ -567,10 +567,7 @@ impl<'ctx> InferenceCtx<'ctx> { } }, NodeEnum::ExternIdNode(ex) => { - if ex.ns.is_empty() { - // if ex.id.name=="yuyudsyfsui" { - // eprintln!("111"); - // } + if ex.namespace.is_empty() { if let Some(t) = self.get_symbol(&ex.id.name) { let id = self.new_key(); ex.id.id = Some(id); @@ -615,7 +612,10 @@ impl<'ctx> InferenceCtx<'ctx> { } NodeEnum::AsNode(a) => { if a.tail.is_none() || a.tail.unwrap().0 == TokenType::NOT { - let tp = a.ty.get_type(ctx, builder, true).unwrap_or(unknown_arc()); + let tp = a + .target_type + .get_type(ctx, builder, true) + .unwrap_or(unknown_arc()); return SymbolType::PLType(tp); } } @@ -831,7 +831,7 @@ impl<'ctx> InferenceCtx<'ctx> { } NodeEnum::Ret(r) => { let ret = self.get_symbol("@ret"); - if r.yiel.is_some() { + if r.yield_identifier.is_some() { return unknown(); } if let Some(ret) = ret { @@ -1364,7 +1364,7 @@ impl Inferable for TypeNodeEnum { generic_params: None, .. } => { - if i.ns.is_empty() && generic_map.contains_key(&i.id.name) { + if i.namespace.is_empty() && generic_map.contains_key(&i.id.name) { return Some(SymbolType::Var(*generic_map.get(&i.id.name).unwrap())); } } @@ -1416,7 +1416,7 @@ impl Inferable for TypeNodeEnum { } TypeNodeEnum::Tuple(t) => { let mut tys = vec![]; - for ty in &t.tps { + for ty in &t.types { let ty = ty .solve_in_infer_generic_ctx(ctx, builder, infer_ctx, generic_map) .unwrap_or(SymbolType::PLType(unknown_arc())); diff --git a/src/nomparser/array.rs b/src/nomparser/array.rs index 24b063a8e..ff2b14721 100644 --- a/src/nomparser/array.rs +++ b/src/nomparser/array.rs @@ -17,8 +17,8 @@ use crate::{ use super::*; #[test_parser("[1,2,3]")] -#[test_parser("[test*test2;]")] -#[test_parser("[test*test2;2,3,4]")] +#[test_parser("[i8*capicity;]")] +#[test_parser("[i32*expected_capicity*2;2,3,4]")] #[test_parser( "[ 1, @@ -44,6 +44,7 @@ pub fn array_init(input: Span) -> IResult> { ), tag_token_symbol(TokenType::RBRACKET), )), + // lb and rb are used to mark the boundaries of an arry. |((_, lb), tp, exps, (_, rb))| { let range = lb.start.to(rb.end); res_enum(ArrayInitNode { exps, range, tp }.into()) @@ -52,6 +53,7 @@ pub fn array_init(input: Span) -> IResult> { } #[test_parser("[123]")] +#[test_parser("[index]")] pub fn array_element_op(input: Span) -> IResult>)> { delspace(map_res( tuple(( diff --git a/src/nomparser/cast.rs b/src/nomparser/cast.rs index 4558e6c44..b8a8cddbc 100644 --- a/src/nomparser/cast.rs +++ b/src/nomparser/cast.rs @@ -31,7 +31,6 @@ use super::*; "(2.3+10-800*9).add(100)[0] as i128 as f32" )] -#[test_parser("(2.3+10-800*9).add(100)[0]")] pub fn as_exp(input: Span) -> IResult> { map_res( tuple(( @@ -50,22 +49,24 @@ pub fn as_exp(input: Span) -> IResult> { |(exp, casts, tail, is)| { let mut exp = exp; let start = exp.range().start; - for (_, ty) in casts { - let end = ty.range().end; - let range = start.to(end); + + // wrap the previous expression into a new 'as' expression + for (_, target_type) in casts { + let range = start.to(target_type.range().end); + exp = Box::new(NodeEnum::AsNode(AsNode { expr: exp, - ty, + target_type, range, tail, })); } - if let Some((_, ty)) = is { - let end = ty.range().end; - let range = start.to(end); + + if let Some((_, target_type)) = is { + let range = start.to(target_type.range().end); exp = Box::new(NodeEnum::IsNode(IsNode { expr: exp, - ty, + target_type, range, })); } diff --git a/src/nomparser/error.rs b/src/nomparser/error.rs index 4401545f8..4b832b44a 100644 --- a/src/nomparser/error.rs +++ b/src/nomparser/error.rs @@ -47,7 +47,6 @@ pub fn except<'a, E: ParseError> + FromExternalError, std::fmt } } let msg = msg.to_string(); - // let end = sp.take_split(sp.len()).0; let node = Box::new( ErrorNode { msg, diff --git a/src/nomparser/function.rs b/src/nomparser/function.rs index 681f37daf..a69823baa 100644 --- a/src/nomparser/function.rs +++ b/src/nomparser/function.rs @@ -99,7 +99,7 @@ pub fn function_def(input: Span) -> IResult> { doc, g, (modifier, (_, start)), - id, + function_identifier, generics, _, paras, @@ -120,14 +120,14 @@ pub fn function_def(input: Span) -> IResult> { } } let node = FuncDefNode { - id, + id: function_identifier, paralist: paras, ret, trait_bounds, range, doc: docs, pre_comments: precoms, - declare: body.is_none(), + is_declaration_only: body.is_none(), generics_size: generics.as_ref().map_or(0, |g| g.generics.len()), generics, body, diff --git a/src/nomparser/helper.rs b/src/nomparser/helper.rs index a1e0d1d2e..71535ee52 100644 --- a/src/nomparser/helper.rs +++ b/src/nomparser/helper.rs @@ -142,11 +142,12 @@ pub fn res_box(i: Box) -> Result, ()> { } pub fn create_bin((mut left, rights): PLBin) -> Result, ()> { - for ((op, orange), right) in rights { + for ((op, op_range), right) in rights { let range = left.range().start.to(right.range().end); + left = Box::new( BinOpNode { - op: (op, orange), + op: (op, op_range), left, right, range, diff --git a/src/nomparser/identifier.rs b/src/nomparser/identifier.rs index 7354cfa71..318b54131 100644 --- a/src/nomparser/identifier.rs +++ b/src/nomparser/identifier.rs @@ -44,8 +44,9 @@ pub fn extern_identifier(input: Span) -> IResult> { opt(tag_token_symbol(TokenType::DOUBLE_COLON)), // 容忍未写完的语句 opt(tag_token_symbol(TokenType::COLON)), // 容忍未写完的语句 )), - |(mut ns, opt, opt2)| { - let id = ns.pop().unwrap(); + |(mut identifier_with_namespace, opt, opt2)| { + let id = identifier_with_namespace.pop().unwrap(); + let mut range = id.range(); if let Some(opt) = opt { range = range.start.to(opt.1.end); @@ -55,7 +56,8 @@ pub fn extern_identifier(input: Span) -> IResult> { } res_enum( ExternIdNode { - ns, + // after poping, only namespaces are left + namespace: identifier_with_namespace, id, range, complete: opt.is_none() && opt2.is_none(), diff --git a/src/nomparser/implement.rs b/src/nomparser/implement.rs index 145bbbe22..da38ab3a8 100644 --- a/src/nomparser/implement.rs +++ b/src/nomparser/implement.rs @@ -74,10 +74,10 @@ pub fn impl_def(input: Span) -> IResult> { many0(comment), del_newline_or_space!(tag_token_symbol(TokenType::RBRACE)), )), - |(_, generics, o, tp, (_, start), func_def, comment0, (_, end))| { + |(_, generics, impl_trait, structure, (_, start), func_def, comment0, (_, end))| { res_box(Box::new(TopLevel::ImplDef(ImplNode { range: start.start.to(end.end), - target: tp, + target: structure, generics, methods: func_def .iter() @@ -90,7 +90,7 @@ pub fn impl_def(input: Span) -> IResult> { }) .collect(), comments: vec![comment0], - impl_trait: o, + impl_trait, }))) }, )(input) diff --git a/src/nomparser/pkg.rs b/src/nomparser/pkg.rs index d5b3725cf..1c32dd416 100644 --- a/src/nomparser/pkg.rs +++ b/src/nomparser/pkg.rs @@ -28,6 +28,7 @@ pub fn use_statement(input: Span) -> IResult> { tag_token_symbol(TokenType::DOUBLE_COLON), tag_token_symbol(TokenType::MUL), )), + // the options are used for error toleration opt(tag_token_symbol(TokenType::DOUBLE_COLON)), opt(tag_token_symbol(TokenType::COLON)), ))), @@ -48,7 +49,7 @@ pub fn use_statement(input: Span) -> IResult> { range = range.start.to(opt2.1.end); } res_enum(NodeEnum::UseNode(UseNode { - ids: ns, + namespace: ns, range, complete: opt.is_none() && opt2.is_none(), singlecolon: opt2.is_some(), diff --git a/src/nomparser/statement.rs b/src/nomparser/statement.rs index 19dcabc18..4ed8abd98 100644 --- a/src/nomparser/statement.rs +++ b/src/nomparser/statement.rs @@ -97,7 +97,9 @@ pub fn new_variable(input: Span) -> IResult> { tuple(( tag_token_word(TokenType::LET), deconstruct, + // the type of a variable is optional because of type inference opt(pair(tag_token_symbol(TokenType::COLON), type_name)), + // the value of a variable opt(pair(tag_token_symbol(TokenType::ASSIGN), general_exp)), )), |((_, start), var, tp, v)| { @@ -109,13 +111,13 @@ pub fn new_variable(input: Span) -> IResult> { end = v.as_ref().unwrap().1.range().end; } let range = start.start.to(end); - let tp = tp.map(|(_, tp)| tp); - let exp = v.map(|(_, exp)| exp); + let variable_type = tp.map(|(_, tp)| tp); + let value_expression = v.map(|(_, exp)| exp); res_enum( DefNode { var, - tp, - exp, + variable_type, + value_expression, range, comments: vec![], } @@ -220,9 +222,6 @@ pub fn assignment(input: Span) -> IResult> { #[test_parser_error("returntrue;")] #[test_parser_error("return1 + 2;")] #[test_parser_error("return a = 2;")] -// ``` -// return_statement = "return" logic_exp newline ; -// ``` fn return_statement(input: Span) -> IResult> { delspace(map_res( tuple(( @@ -232,7 +231,7 @@ fn return_statement(input: Span) -> IResult> { tag_token_symbol(TokenType::SEMI), opt(delspace(comment)), )), - |(y, (_, range), value, (_, r2), optcomment)| { + |(y, (_, range), returned_value, (_, r2), optcomment)| { let comments = if let Some(com) = optcomment { vec![vec![com]] } else { @@ -244,10 +243,10 @@ fn return_statement(input: Span) -> IResult> { } res_enum( RetNode { - value, + value: returned_value, range, comments, - yiel: y, + yield_identifier: y, } .into(), ) @@ -288,7 +287,7 @@ pub fn global_const(input: Span) -> IResult> { res_enum( GlobalConstNode { range: var.range(), - var, + constant: var, } .into(), ) diff --git a/src/nomparser/structure.rs b/src/nomparser/structure.rs index 3bbc256f9..4bc4adda8 100644 --- a/src/nomparser/structure.rs +++ b/src/nomparser/structure.rs @@ -88,8 +88,8 @@ pub fn struct_def(input: Span) -> IResult> { } } Ok::<_, ()>(Box::new(TopLevel::StructDef(StructDefNode { + docs, pre_comments: precoms, - doc: docs, id, fields: fieldlist, range, diff --git a/src/nomparser/types.rs b/src/nomparser/types.rs index 2dbf11aec..e926426d3 100644 --- a/src/nomparser/types.rs +++ b/src/nomparser/types.rs @@ -198,14 +198,14 @@ pub fn trait_bound(input: Span) -> IResult> { identifier, opt(preceded(tag_token_symbol(TokenType::COLON), multi_trait)), )), - |(generic, impl_trait)| { + |(ident, impl_trait)| { let range = if let Some(impl_trait) = &impl_trait { - generic.range.start.to(impl_trait.range().end) + ident.range.start.to(impl_trait.range().end) } else { - generic.range + ident.range }; res_box(Box::new(TraitBoundNode { - generic, + identifier: ident, impl_trait, range, })) @@ -240,10 +240,10 @@ fn tuple_type(input: Span) -> IResult> { )), tag_token_symbol(TokenType::RPAREN), )), - |((_, rs), types, (_, re))| { + |((_, rs), tps, (_, re))| { let range = rs.start.to(re.end); - let tps = types.unwrap_or_default(); - let node = Box::new(TypeNodeEnum::Tuple(TupleTypeNode { tps, range })); + let types = tps.unwrap_or_default(); + let node = Box::new(TypeNodeEnum::Tuple(TupleTypeNode { types, range })); res_box(node) }, )(input) diff --git a/src/utils/read_config.rs b/src/utils/read_config.rs index b477d77c5..3bafb2936 100644 --- a/src/utils/read_config.rs +++ b/src/utils/read_config.rs @@ -80,11 +80,11 @@ impl ConfigWrapper { // 加载依赖包的路径 if let Some(cm) = &self.config(db).deps { // 如果use的是依赖包 - if let Some(dep) = cm.get(&u.ids[0].name) { + if let Some(dep) = cm.get(&u.namespace[0].name) { path = path.join(&dep.path); } } - for p in u.ids[1..].iter() { + for p in u.namespace[1..].iter() { path = path.join(p.name.clone()); } path = path.with_extension("pi");