Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions internal_macro/src/node_macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<Vec<Box<crate::ast::node::NodeEnum>>>,
/// 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);
Expand Down
26 changes: 13 additions & 13 deletions src/ast/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
Expand All @@ -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();
}
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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("?");
Expand All @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
40 changes: 24 additions & 16 deletions src/ast/node/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeEnum>,
pub ty: Box<TypeNodeEnum>,

/// target_type refers the desired type for the expr
pub target_type: Box<TypeNodeEnum>,

/// tail is the question or exclaimation mark following an 'as' statement
/// it will be None if no marks exist
pub tail: Option<(TokenType, Range)>,
}

Expand All @@ -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(),
Expand All @@ -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());
}
}

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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()),
)
Expand All @@ -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));
Expand All @@ -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,
Expand All @@ -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()),
)
Expand Down Expand Up @@ -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<NodeEnum>,
pub ty: Box<TypeNodeEnum>,
/// target_type refers the desired type for the expr
pub target_type: Box<TypeNodeEnum>,
}

impl Node for IsNode {
Expand All @@ -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();
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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());
}
}
21 changes: 21 additions & 0 deletions src/ast/node/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeEnum>,
/// then is the logic to be executed if the cond is true
pub then: Box<StatementsNode>,
/// els stands for the left part of the condition clause
/// it might be another IfNode or a statement
pub els: Option<Box<NodeEnum>>,
}

Expand Down Expand Up @@ -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<Box<NodeEnum>>,
pub cond: Box<NodeEnum>,
Expand Down
13 changes: 10 additions & 3 deletions src/ast/node/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,14 +452,21 @@ fn handle_ret<'a, 'b>(
}
#[node]
pub struct FuncDefNode {
/// id is the function identifier
pub id: Box<VarNode>,
/// paralist is the parameter lists
pub paralist: Vec<Box<TypedIdentifierNode>>,
/// ret is the return type of the function
pub ret: Box<TypeNodeEnum>,
/// docs is the documentation of the structure started with `///`
pub doc: Vec<Box<NodeEnum>>,
/// pre_comments is the comments above a structure
pub pre_comments: Vec<Box<NodeEnum>>,
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<Box<GenericDefNode>>,
pub body: Option<StatementsNode>,
/// 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<Vec<Box<TraitBoundNode>>>,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
Loading