From 02d2982ac5ac6502016e004837fa7e4f90dd7ccd Mon Sep 17 00:00:00 2001 From: bobxli Date: Tue, 11 Jul 2023 11:53:34 +0800 Subject: [PATCH 01/14] generator half done --- planglib/std/iter.pi | 4 +- src/ast/builder/llvmbuilder.rs | 102 +++++++++++++++++++++++++----- src/ast/builder/mod.rs | 3 + src/ast/builder/no_op_builder.rs | 11 ++++ src/ast/ctx.rs | 35 ++++++++++- src/ast/node/function.rs | 105 ++++++++++++++++++++++++++++--- src/ast/node/ret.rs | 2 + src/ast/pltype.rs | 3 + src/ast/tokens.rs | 2 + src/nomparser/function.rs | 10 +++ src/nomparser/statement.rs | 34 ++++------ test/main.pi | 105 ++++++++++++++++--------------- 12 files changed, 320 insertions(+), 96 deletions(-) diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index 82b41f3e5..f451d6ec6 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -1,7 +1,7 @@ -use core::builtin::*; +use core::builtin; pub trait Iterator { - fn next() Option; + fn next() builtin::Option; } struct name { diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 05e054f06..15f28fc38 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -21,7 +21,7 @@ use inkwell::{ targets::{InitializationConfig, Target, TargetMachine}, types::{ AsTypeRef, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, PointerType, - StructType, VoidType, + StructType, VoidType, AnyType, }, values::{ AnyValue, AnyValueEnum, BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallableValue, @@ -34,7 +34,7 @@ use rustc_hash::FxHashMap; use crate::ast::{ diag::PLDiag, - pltype::{ClosureType, TraitImplAble}, + pltype::{ClosureType, TraitImplAble}, ctx::{CtxFlag, PLSymbol}, }; use super::{ @@ -1442,6 +1442,35 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { ctx: &mut Ctx<'a>, declare: Option, ) -> ValueHandle { + if ctx.ctx_flag == CtxFlag::InGeneratorYield { + let data = ctx.generator_data.as_ref().unwrap().clone(); + + + let lb = self.builder.get_insert_block().unwrap(); + let alloca = self + .builder + .get_insert_block() + .unwrap() + .get_parent() + .unwrap() + .get_first_basic_block() + .unwrap(); + self.builder.position_at_end(alloca); + + let f_v = ctx.function.unwrap(); + let f = self.get_llvm_value(f_v).unwrap().into_function_value(); + let yield_ctx = f.get_nth_param(0).unwrap(); + let bt = self.get_basic_type_op(pltype, ctx).unwrap(); + let count = add_field(yield_ctx.as_any_value_enum(), bt.as_any_type_enum()); + let i = count - 1; + let data_ptr = self.build_struct_gep(self.get_nth_param(f_v, 0), i, name).unwrap(); + + self.builder.position_at_end(lb); + + data.borrow_mut().table.insert(name.to_string(), PLSymbol{ value: data_ptr, pltype: Arc::new(RefCell::new(pltype.clone())), range: Default::default(), refs: None }); + // let data_ptr = self.build_struct_gep(ctx_v, (i +2) as u32, "para").unwrap(); + return data_ptr; + } self.alloc_raw(name, pltype, ctx, declare, "DioGC__malloc") } fn build_struct_gep( @@ -1972,6 +2001,28 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { self.builder.get_current_debug_location().unwrap(), self.get_llvm_block(allocab).unwrap(), ); + if child.ctx_flag == CtxFlag::InGeneratorYield { + let data = child.generator_data.as_ref().unwrap().clone(); + let bb_v = data.borrow().alloca_bb; + let bb = self.get_llvm_block(bb_v).unwrap(); + let funcvalue = bb.get_parent().unwrap(); + let origin_bb = child.block.unwrap(); + self.position_at_end_block(bb_v); + let ctx_v = data.borrow().ctx_handle; + let para_ptr = self.build_struct_gep(ctx_v, (i +2) as u32, "para").unwrap(); + self.build_store( + para_ptr, + self.get_llvm_value_handle( + &funcvalue + .get_nth_param(i as u32) + .unwrap() + .as_any_value_enum(), + ), + ); + self.position_at_end_block(origin_bb); + + return; + } let funcvalue = self .get_llvm_value(value_handle) .unwrap() @@ -2258,24 +2309,47 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { } fn add_closure_st_field(&self, st: ValueHandle, field: ValueHandle) { let st_v = self.handle_table.borrow().get(&st).copied().unwrap(); - let st_tp = st_v - .get_type() - .into_pointer_type() - .get_element_type() - .into_struct_type(); - let mut closure_data_tps = st_tp.get_field_types(); - closure_data_tps.push( + let field_tp = self.handle_table .borrow() .get(&field) .copied() .unwrap() - .get_type() - .try_into() - .unwrap(), - ); - set_body(&st_tp, &closure_data_tps, false); + .get_type(); + add_field(st_v, field_tp); } + + fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>, ctx_name:&str, ret_tp:&PLType) ->ValueHandle { + let tp = self.context.get_struct_type(ctx_name).unwrap().ptr_type(Default::default()).into(); + let ftp = self.get_basic_type_op(ret_tp, ctx).unwrap().fn_type(&[tp], false); + let f = self.module.add_function(&format!("{}__yield", ctx_name), ftp, None); + self.get_llvm_value_handle(&f.into()) + } + + fn get_block_address(&self, block:BlockHandle) -> ValueHandle { + self.get_llvm_value_handle(unsafe { & self.get_llvm_block(block).unwrap().get_address().unwrap().into() }) + } + fn build_indirect_br(&self, block:ValueHandle,ctx: & Ctx<'a>,) { + let block = self.get_llvm_value(block).unwrap(); + let bv = self.get_llvm_block(ctx.block.unwrap()).unwrap(); + self.builder.build_indirect_branch::(block.try_into().unwrap(), &bv.get_parent().unwrap().get_basic_blocks()); + } +} + +fn add_field(st_v: AnyValueEnum<'_>, field_tp: inkwell::types::AnyTypeEnum<'_>) -> u32 { + let st_tp = st_v + .get_type() + .into_pointer_type() + .get_element_type() + .into_struct_type(); + let mut closure_data_tps = st_tp.get_field_types(); + closure_data_tps.push( + field_tp + .try_into() + .unwrap(), + ); + set_body(&st_tp, &closure_data_tps, false); + return st_tp.count_fields(); } fn set_body<'ctx>(s: &StructType<'ctx>, field_types: &[BasicTypeEnum<'ctx>], packed: bool) { diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index beebb15bd..e1b97fcf2 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -221,6 +221,9 @@ pub trait IRBuilder<'a, 'ctx> { allocab: BlockHandle, name: &str, ); + fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>, ctx_name:&str, ret_tp:&PLType) ->ValueHandle ; + fn get_block_address(&self, block:BlockHandle) -> ValueHandle; + fn build_indirect_br(&self, block:ValueHandle,ctx: & Ctx<'a>,) ; } pub type ValueHandle = usize; diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index 8c3968247..fcc270d9a 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -472,4 +472,15 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { _name: &str, ) { } + + fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>,ctx_name:&str,ret_tp:&PLType) -> ValueHandle { + 0 + } + + fn get_block_address(&self,block:super::BlockHandle) -> ValueHandle { + 0 + } + + fn build_indirect_br(&self,block:ValueHandle,ctx: &Ctx<'a>,) { + } } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 67b086a4b..c75da0845 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -1,5 +1,6 @@ use super::builder::BlockHandle; use super::builder::ValueHandle; +use super::diag::DiagCode; use super::diag::ErrorCode; use super::diag::PLDiag; @@ -78,7 +79,6 @@ pub struct Ctx<'a> { pub root: Option<&'a Ctx<'a>>, // root context, for symbol lookup pub function: Option, // current function pub init_func: Option, //init function,call first in main - pub roots: RefCell>, pub block: Option, // current block pub continue_block: Option, // the block to jump when continue pub break_block: Option, // the block to jump to when break @@ -99,6 +99,25 @@ pub struct Ctx<'a> { pub closure_data: Option>, pub expect_ty: Option>>, pub self_ref_map: FxHashMap>, // used to recognize self reference + pub ctx_flag:CtxFlag, + pub generator_data: Option>>, +} + + +#[derive(Clone, Default)] +pub struct GeneratorCtxData{ + pub table: LinkedHashMap, + pub alloca_bb: BlockHandle, + pub ctx_handle: ValueHandle, //handle in setup function +} + +/// # CtxFlag +/// +/// flags that might change the behavior of the builder +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum CtxFlag { + Normal, + InGeneratorYield, } #[derive(Clone, Default)] @@ -190,7 +209,6 @@ impl<'a, 'ctx> Ctx<'a> { continue_block: None, break_block: None, return_block: None, - roots: RefCell::new(Vec::new()), rettp: None, macro_vars: FxHashMap::default(), macro_loop: false, @@ -203,6 +221,8 @@ impl<'a, 'ctx> Ctx<'a> { root: None, macro_skip_level: 0, self_ref_map: FxHashMap::default(), + ctx_flag:CtxFlag::Normal, + generator_data: None, } } pub fn new_child(&'a self, start: Pos, builder: &'a BuilderEnum<'a, 'ctx>) -> Ctx<'a> { @@ -224,7 +244,6 @@ impl<'a, 'ctx> Ctx<'a> { continue_block: self.continue_block, break_block: self.break_block, return_block: self.return_block, - roots: RefCell::new(Vec::new()), rettp: self.rettp.clone(), init_func: self.init_func, function: self.function, @@ -239,6 +258,8 @@ impl<'a, 'ctx> Ctx<'a> { root, macro_skip_level: self.macro_skip_level, self_ref_map: FxHashMap::default(), + ctx_flag:self.ctx_flag, + generator_data: self.generator_data.clone(), }; add_primitive_types(&mut ctx); if start != Default::default() { @@ -861,6 +882,14 @@ impl<'a, 'ctx> Ctx<'a> { if let Some(src) = &self.temp_source { dia.set_source(src); } + if DiagCode::Err( ErrorCode::UNDEFINED_TYPE) == dia.get_diag_code() { + let mut ctx = self; + while let Some(father) = ctx.father { + ctx = father; + eprintln!("father: {:?}", ctx.plmod.types.keys()); + } + eprintln!("error: {:?}", dia); + } let dia2 = dia.clone(); self.errs.borrow_mut().insert(dia); dia2 diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index d56e1ed86..fe194a4d4 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -4,7 +4,7 @@ use super::statement::StatementsNode; use super::*; use super::{types::TypedIdentifierNode, Node, TypeNode}; use crate::ast::builder::ValueHandle; -use crate::ast::ctx::{ClosureCtxData, BUILTIN_FN_MAP}; +use crate::ast::ctx::{ClosureCtxData, BUILTIN_FN_MAP, CtxFlag, GeneratorCtxData}; use crate::ast::diag::ErrorCode; use crate::ast::node::{deal_line, tab}; @@ -347,6 +347,7 @@ pub struct FuncDefNode { pub is_method: bool, pub in_trait_def: bool, pub target_range: Range, + pub generator: bool, } type OptFOnce<'a> = Option Result<(), PLDiag> + 'a>>; // Thank u, Rust! @@ -525,6 +526,7 @@ impl FuncDefNode { builder: &'b BuilderEnum<'a, '_>, fnvalue: FNValue, ) -> Result<(), PLDiag> { + let i8ptr = PLType::Pointer(ctx.get_type("i8", Default::default()).unwrap().tp); let child = &mut ctx.new_child(self.range.start, builder); child.protect_generic_context(&fnvalue.fntype.generic_map, |child| { if first && fnvalue.fntype.generic { @@ -549,8 +551,60 @@ impl FuncDefNode { Arc::new(RefCell::new(PLType::Fn(place_holder_fn.clone()))), ); } - let funcvalue = builder.get_or_insert_fn_handle(&fnvalue, child); + let mut funcvalue = builder.get_or_insert_fn_handle(&fnvalue, child); child.function = Some(funcvalue); + let mut sttp_opt = None; + if self.generator { + let mut m = LinkedHashMap::default(); + m.insert("address".to_owned(), Field{ + index: 1, + typenode: i8ptr.clone().get_typenode(&child.plmod.path), + name: "address".to_owned(), + range: Default::default(), + modifier: None, + }); + let st_tp = STType { + name: fnvalue.get_generator_ctx_name(), + path: ctx.plmod.path.clone(), + fields: m, + range: Default::default(), + doc: vec![], + generic_map: Default::default(), + derives: vec![], + modifier: Some((TokenType::PUB, Default::default())), + body_range: Default::default(), + is_trait: false, + is_tuple: true, + generic_infer_types: Default::default(), + generic_infer: Default::default(), + methods: Default::default(), + trait_methods_impl: Default::default(), + }; + builder.opaque_struct_type(&st_tp.get_full_name()); + builder.add_body_to_struct_type(&st_tp.get_full_name(), &st_tp, child); + + let rettp= child.run_in_type_mod(&fnvalue, |child,fnvalue| { + let tp = fnvalue.fntype.ret_pltype.get_type(child, builder, false)?; + match &*tp.borrow() { + PLType::Trait(t) => { + return Ok(t.generic_map.first().unwrap().1.clone()); + } + _ =>todo!() + + }; + })?; + child.rettp = Some(rettp.clone()); + let f = builder.add_generator_yield_fn(child, &st_tp.get_full_name(), &rettp.borrow()); + child.function = Some(f); + let allocab = builder.append_basic_block(funcvalue, "entry");// this is alloca for setup fn + funcvalue = f; + builder.position_at_end_block(allocab); + let ctx_handle = builder.alloc("ctx",&PLType::Struct(st_tp.clone()) , child, None); + child.generator_data = Some(Arc::new( RefCell::new( GeneratorCtxData{alloca_bb:allocab,ctx_handle,..Default::default()}))); + child.ctx_flag = CtxFlag::InGeneratorYield; + sttp_opt = Some(st_tp); + } + builder.build_sub_program( self.paralist.clone(), fnvalue.fntype.ret_pltype.clone(), @@ -560,6 +614,12 @@ impl FuncDefNode { )?; // add block let allocab = builder.append_basic_block(funcvalue, "alloc"); + if self.generator { + let address = builder.get_block_address(allocab); + let data = child.generator_data.as_ref().unwrap().clone(); + let address_ptr = builder.build_struct_gep(data.borrow().ctx_handle, 1, "block_address").unwrap(); + builder.build_store(address_ptr, address); + } let entry = builder.append_basic_block(funcvalue, "entry"); let return_block = builder.append_basic_block(funcvalue, "return"); child.position_at_end(entry, builder); @@ -573,8 +633,6 @@ impl FuncDefNode { other => { builder.rm_curr_debug_location(); let retv = builder.alloc("retvalue", other, child, None); - // 返回值不能在函数结束时从root表移除 - child.roots.borrow_mut().pop(); Some(retv) } }; @@ -625,13 +683,46 @@ impl FuncDefNode { child.init_global(builder); child.position_at_end(entry, builder); } - child.rettp = Some(fnvalue.fntype.ret_pltype.get_type(child, builder, true)?); + if !self.generator{ + child.rettp = Some(fnvalue.fntype.ret_pltype.get_type(child, builder, true)?); + } + // body generation let terminator = self.body.as_mut().unwrap().emit(child, builder)?.get_term(); if !terminator.is_return() { return Err( child.add_diag(self.range.new_err(ErrorCode::FUNCTION_MUST_HAVE_RETURN)) ); } + if self.generator { + + let mut i = 1; + let mut tps = vec![]; + let st_tp = sttp_opt.as_mut().unwrap(); + for (k, v) in &child.generator_data.as_ref().unwrap().borrow().table { + let pltp = PLType::Pointer(v.pltype.to_owned()); + st_tp.fields.insert( + k.to_owned(), + Field { + index: i, + typenode: pltp.get_typenode(&child.plmod.path), + name: k.to_owned(), + range: Default::default(), + modifier: None, + }, + ); + tps.push(Arc::new(RefCell::new(pltp))); + i += 1; + } + let data = child.generator_data.as_ref().unwrap(); + + builder.position_at_end_block(data.borrow().alloca_bb); + builder.gen_st_visit_function(child, &st_tp, &tps); + builder.position_at_end_block(allocab); + let ctx_v = builder.get_nth_param(child.function.unwrap(), 0); + let address = builder.build_struct_gep(ctx_v, 1, "block_address").unwrap(); + builder.build_indirect_br(address, &child); + return Ok(()); + } child.position_at_end(allocab, builder); builder.build_unconditional_branch(entry); Ok(()) @@ -801,6 +892,8 @@ impl Node for ClosureNode { ctx.try_set_closure_alloca_bb(builder.get_first_basic_block(ctx.function.unwrap())); let f = builder.create_closure_fn(ctx, &closure_name, ¶tps, &ret_tp.borrow()); let child = &mut ctx.new_child(self.range.start, builder); + child.generator_data = None; + child.ctx_flag = CtxFlag::Normal; child.function = Some(f); let stpltp = PLType::Struct(st_tp.clone()); let ptr_tp = PLType::Pointer(Arc::new(RefCell::new(stpltp))); @@ -825,8 +918,6 @@ impl Node for ClosureNode { other => { builder.rm_curr_debug_location(); let retv = builder.alloc("retvalue", other, child, None); - // 返回值不能在函数结束时从root表移除 - child.roots.borrow_mut().pop(); Some(retv) } }; diff --git a/src/ast/node/ret.rs b/src/ast/node/ret.rs index 06a210e44..ae41816b0 100644 --- a/src/ast/node/ret.rs +++ b/src/ast/node/ret.rs @@ -3,12 +3,14 @@ use super::*; use crate::ast::builder::BuilderEnum; use crate::ast::builder::IRBuilder; +use crate::ast::tokens::TokenType; use crate::ast::{ctx::Ctx, diag::ErrorCode}; use internal_macro::node; #[node(comment)] pub struct RetNode { pub value: Option>, + pub yiel:Option<(TokenType,Range)> } impl PrintTrait for RetNode { diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 984d8fa3e..94c7967d3 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -709,6 +709,9 @@ impl TryFrom for FNValue { } } impl FNValue { + pub fn get_generator_ctx_name(&self) ->String { + self.name.clone() + "__generator_ctx" + } pub fn to_closure_ty<'a, 'b>( &self, ctx: &'b mut Ctx<'a>, diff --git a/src/ast/tokens.rs b/src/ast/tokens.rs index 609fa3e19..e1fd82a2e 100644 --- a/src/ast/tokens.rs +++ b/src/ast/tokens.rs @@ -94,6 +94,8 @@ define_tokens!( AS = "as", QUESTION = "?", IS = "is", + YIELD = "yield", + GENERATOR_MARKER = "gen", ); impl TokenType { diff --git a/src/nomparser/function.rs b/src/nomparser/function.rs index 3c5b2b908..2d6ae867c 100644 --- a/src/nomparser/function.rs +++ b/src/nomparser/function.rs @@ -23,6 +23,13 @@ use super::*; } " )] +#[test_parser( + "gen fn f( x: int, y : int ) int { + x = x+1; + return 0; + } + " +)] #[test_parser("fn f (x: int ,\n y: int) int;")] #[test_parser( "fn f(x: int) int { @@ -57,6 +64,7 @@ pub fn function_def(input: Span) -> IResult> { map_res( tuple(( many0(del_newline_or_space!(comment)), + opt(tag_token_word(TokenType::GENERATOR_MARKER)), modifiable(tag_token_word(TokenType::FN), TokenType::PUB), identifier, opt(generic_type_def), @@ -83,6 +91,7 @@ pub fn function_def(input: Span) -> IResult> { )), |( doc, + g, (modifier, (_, start)), id, generics, @@ -121,6 +130,7 @@ pub fn function_def(input: Span) -> IResult> { is_method: false, target_range: Default::default(), in_trait_def: false, + generator: g.is_some(), }; Ok::<_, ()>(Box::new(TopLevel::FuncType(node))) }, diff --git a/src/nomparser/statement.rs b/src/nomparser/statement.rs index 98c0020e2..7717da24a 100644 --- a/src/nomparser/statement.rs +++ b/src/nomparser/statement.rs @@ -229,6 +229,7 @@ pub fn assignment(input: Span) -> IResult> { #[test_parser("return;")] #[test_parser("return a;")] #[test_parser("return 1 + 2;")] +#[test_parser("yield return 1 + 2;")] #[test_parser_error("returntrue;")] #[test_parser_error("return1 + 2;")] #[test_parser_error("return a = 2;")] @@ -238,37 +239,28 @@ pub fn assignment(input: Span) -> IResult> { fn return_statement(input: Span) -> IResult> { delspace(map_res( tuple(( + opt( tag_token_word(TokenType::YIELD)), tag_token_word(TokenType::RETURN), opt(general_exp), tag_token_symbol(TokenType::SEMI), opt(delspace(comment)), )), - |((_, range), val, _, optcomment)| { + |(y,(_, range), value, (_,r2), optcomment)| { let comments = if let Some(com) = optcomment { vec![vec![com]] } else { vec![vec![]] }; - if let Some(val) = val { - let range = val.range(); - res_enum( - RetNode { - value: Some(val), - range, - comments, - } - .into(), - ) - } else { - res_enum( - RetNode { - value: None, - range, - comments, - } - .into(), - ) - } + let range = range.start.to(r2.end); + res_enum( + RetNode { + value, + range, + comments, + yiel:y + } + .into(), + ) }, ))(input) } diff --git a/test/main.pi b/test/main.pi index 0f37d9d5f..e1bb4b94d 100644 --- a/test/main.pi +++ b/test/main.pi @@ -1,53 +1,60 @@ -use project1::test::ifel; -use project1::test::generic; -use project1::test::st; -use project1::test::method; -use project1::test::constant; -use project1::test::traits; -use project1::test::simple; -use project1::test::flow; -use project1::test::list; -use project1::test::module; -use project1::test::string; -use project1::test::macros; -use project1::test::union; -use project1::test::multi_trait; -use project1::test::tuple; -use project1::test::fntype; -use project1::test::closure; -use project1::test::map; -use project1::test::tree; -use project1::test::fixed_point; -use project1::tmod2; -use pl_test::main; -use project1::test::compiletime_reflection::test_compile_time_reflection; -use project1::test::deconstruct; -use project1::test::st::*; +// use project1::test::ifel; +// use project1::test::generic; +// use project1::test::st; +// use project1::test::method; +// use project1::test::constant; +// use project1::test::traits; +// use project1::test::simple; +// use project1::test::flow; +// use project1::test::list; +// use project1::test::module; +// use project1::test::string; +// use project1::test::macros; +// use project1::test::union; +// use project1::test::multi_trait; +// use project1::test::tuple; +// use project1::test::fntype; +// use project1::test::closure; +// use project1::test::map; +// use project1::test::tree; +// use project1::test::fixed_point; +// use project1::tmod2; +// use pl_test::main; +// use project1::test::compiletime_reflection::test_compile_time_reflection; +// use project1::test::deconstruct; +// use project1::test::st::*; +use std::iter::*; pub fn main() i64 { - macros::test_macros(); - ifel::test_if_else(); - generic::test_generic(); - method::test_impl(); - test_struct(); - constant::test_const(); - traits::test_trait(); - simple::test_simple(); - flow::test_flow(); - list::test_list(); - main::simple_test(); - module::test_module(); - string::test_string(); - union::test_union(); - multi_trait::test_multi_trait(); - deconstruct::test_deconstruct(); - tuple::test_tuple(); - fntype::test_fntype()(); - closure::test_closure(); - tree::test_eva(); - map::test_map(); - fixed_point::test_fixed_point(); - generic::ret_generic1(); - test_compile_time_reflection(); + // macros::test_macros(); + // ifel::test_if_else(); + // generic::test_generic(); + // method::test_impl(); + // test_struct(); + // constant::test_const(); + // traits::test_trait(); + // simple::test_simple(); + // flow::test_flow(); + // list::test_list(); + // main::simple_test(); + // module::test_module(); + // string::test_string(); + // union::test_union(); + // multi_trait::test_multi_trait(); + // deconstruct::test_deconstruct(); + // tuple::test_tuple(); + // fntype::test_fntype()(); + // closure::test_closure(); + // tree::test_eva(); + // map::test_map(); + // fixed_point::test_fixed_point(); + // generic::ret_generic1(); + // test_compile_time_reflection(); + let a:Iterator; return 0; } + +// gen fn name() Iterator { + +// return 1; +// } From 5d247f0088c4d1db46a53b1219134aebe621e144 Mon Sep 17 00:00:00 2001 From: bobxli Date: Tue, 11 Jul 2023 15:30:45 +0800 Subject: [PATCH 02/14] fix: nested generic issue --- planglib/std/iter.pi | 21 +++++++++-- src/ast/ctx.rs | 68 ++++++++++++++++++++++++++--------- src/ast/node/function.rs | 4 +-- src/ast/node/interface.rs | 4 +-- src/ast/node/program.rs | 1 + src/ast/node/program/cycle.rs | 2 +- src/ast/node/tuple.rs | 2 +- src/ast/node/types.rs | 2 +- src/ast/node/union.rs | 1 + src/ast/plmod.rs | 21 ++++++++--- src/ast/pltype.rs | 14 +++++--- test/main.pi | 5 +-- 12 files changed, 107 insertions(+), 38 deletions(-) diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index f451d6ec6..ac1c1fa70 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -1,7 +1,7 @@ use core::builtin; pub trait Iterator { - fn next() builtin::Option; + fn next() Option; } struct name { @@ -10,7 +10,24 @@ struct name { impl Iterator for name { fn next() Option { - return self.t; + let a: Option = self.t; + return a; } } + + +pub fn ret_opt() name> { + let b = 1; + let a:Option = b; + let aa:name> = name{t:a}; + return aa; +} + + +// pub fn ret_opt() name> { +// let b = 1; +// let a:builtin::testG; +// let aa:name> = name{t:a}; +// return aa; +// } \ No newline at end of file diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index c75da0845..38524370d 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -101,6 +101,7 @@ pub struct Ctx<'a> { pub self_ref_map: FxHashMap>, // used to recognize self reference pub ctx_flag:CtxFlag, pub generator_data: Option>>, + pub generic_infer: Arc>>>>>>>, } @@ -134,6 +135,39 @@ pub enum MacroReplaceNode { } impl<'a, 'ctx> Ctx<'a> { + + pub fn add_infer_result(&self, tp:&impl TraitImplAble, name:&str, pltp:Arc>) { + self.generic_infer + .borrow_mut().entry(tp.get_full_name_except_generic()).or_insert(Default::default()) + .borrow_mut() + .insert(name.to_string(), pltp); + } + + pub fn get_infer_result(&self, tp:&impl TraitImplAble, name:&str) -> Option>> { + let infer_map = self.generic_infer.borrow(); + let infer_map = infer_map.get(&tp.get_full_name_except_generic())?; + let x = infer_map.borrow().get(name).cloned(); + x + } + + fn import_all_infer_maps_from(&self, other: &IndexMap>>>>>) { + for (k, v) in other.iter() { + if !self.generic_infer.borrow().contains_key(k) { + let map: Arc>>>> = Default::default(); + self.generic_infer.borrow_mut().insert(k.clone(), map.clone()); + map.borrow_mut().extend(v.borrow().clone()); + }else { + let infer_map = self.generic_infer.borrow(); + let infer_map = infer_map.get(k).unwrap(); + infer_map.borrow_mut().extend(v.borrow().clone()); + } + } + } + pub fn import_all_infer_maps_from_sub_mods(&self) { + for (_,sub_mod) in self.plmod.submods.iter() { + self.import_all_infer_maps_from(&sub_mod.generic_infer.borrow()); + } + } pub fn check_self_ref(&self, name: &str, range: Range) -> Result<(), PLDiag> { if let Some(root) = self.root { root.check_self_ref_inner(name, name, range) @@ -193,10 +227,11 @@ impl<'a, 'ctx> Ctx<'a> { config: Config, db: &'a dyn Db, ) -> Ctx<'a> { + let generic_infer:Arc>>>>>>> = Default::default(); Ctx { need_highlight: 0, generic_types: FxHashMap::default(), - plmod: Mod::new(src_file_path.to_string()), + plmod: Mod::new(src_file_path.to_string(), generic_infer.clone()), father: None, init_func: None, function: None, @@ -223,6 +258,7 @@ impl<'a, 'ctx> Ctx<'a> { self_ref_map: FxHashMap::default(), ctx_flag:CtxFlag::Normal, generator_data: None, + generic_infer, } } pub fn new_child(&'a self, start: Pos, builder: &'a BuilderEnum<'a, 'ctx>) -> Ctx<'a> { @@ -260,6 +296,7 @@ impl<'a, 'ctx> Ctx<'a> { self_ref_map: FxHashMap::default(), ctx_flag:self.ctx_flag, generator_data: self.generator_data.clone(), + generic_infer:self.generic_infer.clone(), }; add_primitive_types(&mut ctx); if start != Default::default() { @@ -351,14 +388,19 @@ impl<'a, 'ctx> Ctx<'a> { return Ok(closure_v); } if let PLType::Union(u) = &*target_pltype.borrow() { - let union_members = self.run_in_type_mod(u, |ctx, u| { - let mut union_members = vec![]; - for tp in &u.sum_types { - let tp = tp.get_type(ctx, builder, true)?; - union_members.push(tp); - } - Ok(union_members) - })?; + let mut union_members = vec![]; + for tp in &u.sum_types { + let tp = tp.get_type(self, builder, true)?; + union_members.push(tp); + } + // let union_members = self.run_in_type_mod(u, |ctx, u| { + // let mut union_members = vec![]; + // for tp in &u.sum_types { + // let tp = tp.get_type(ctx, builder, true)?; + // union_members.push(tp); + // } + // Ok(union_members) + // })?; for (i, tp) in union_members.iter().enumerate() { if *tp.borrow() == *ori_pltype.borrow() { let union_handle = @@ -882,14 +924,6 @@ impl<'a, 'ctx> Ctx<'a> { if let Some(src) = &self.temp_source { dia.set_source(src); } - if DiagCode::Err( ErrorCode::UNDEFINED_TYPE) == dia.get_diag_code() { - let mut ctx = self; - while let Some(father) = ctx.father { - ctx = father; - eprintln!("father: {:?}", ctx.plmod.types.keys()); - } - eprintln!("error: {:?}", dia); - } let dia2 = dia.clone(); self.errs.borrow_mut().insert(dia); dia2 diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index fe194a4d4..bb0b43a14 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -576,7 +576,7 @@ impl FuncDefNode { is_trait: false, is_tuple: true, generic_infer_types: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), methods: Default::default(), trait_methods_impl: Default::default(), }; @@ -824,7 +824,7 @@ impl Node for ClosureNode { is_trait: false, is_tuple: true, generic_infer_types: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), methods: Default::default(), trait_methods_impl: Default::default(), }; diff --git a/src/ast/node/interface.rs b/src/ast/node/interface.rs index 426c84d47..4fbf38857 100644 --- a/src/ast/node/interface.rs +++ b/src/ast/node/interface.rs @@ -43,7 +43,7 @@ impl MultiTraitNode { is_trait: true, is_tuple: false, generic_infer_types: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), methods: Default::default(), trait_methods_impl: Default::default(), }; @@ -178,7 +178,7 @@ impl TraitDefNode { is_trait: true, is_tuple: false, generic_infer_types: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), methods: Default::default(), trait_methods_impl: Default::default(), }))); diff --git a/src/ast/node/program.rs b/src/ast/node/program.rs index 4c01d4e23..5bcf3ed3a 100644 --- a/src/ast/node/program.rs +++ b/src/ast/node/program.rs @@ -551,6 +551,7 @@ pub fn emit_file(db: &dyn Db, params: ProgramEmitParam) -> ModWrapper { if let Some(builtin_mod) = ctx.plmod.submods.get("stdbuiltin").cloned() { ctx.plmod.import_all_symbols_from(&builtin_mod); } + ctx.import_all_infer_maps_from_sub_mods(); let m = &mut ctx; #[cfg(feature = "llvm")] let context = &Context::create(); diff --git a/src/ast/node/program/cycle.rs b/src/ast/node/program/cycle.rs index 879d063b1..fa9d79299 100644 --- a/src/ast/node/program/cycle.rs +++ b/src/ast/node/program/cycle.rs @@ -66,7 +66,7 @@ pub fn cycle_deps_recover( } Diagnostics::push(db, (src_file_path.to_string(), vec![diag])); db.report_untracked_read(); - Some(ModWrapper::new(db, Mod::new(src_file_path.to_string()))) + Some(ModWrapper::new(db, Mod::new(src_file_path.to_string(),Default::default()))) } pub(crate) fn build_init_params( diff --git a/src/ast/node/tuple.rs b/src/ast/node/tuple.rs index 47bf3a66d..fed70ac34 100644 --- a/src/ast/node/tuple.rs +++ b/src/ast/node/tuple.rs @@ -100,7 +100,7 @@ fn new_tuple_type( is_trait: false, is_tuple: true, generic_infer_types: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), methods: Default::default(), trait_methods_impl: Default::default(), } diff --git a/src/ast/node/types.rs b/src/ast/node/types.rs index d88d26c61..17916915e 100644 --- a/src/ast/node/types.rs +++ b/src/ast/node/types.rs @@ -485,7 +485,7 @@ impl StructDefNode { is_tuple: false, generic_infer_types: Default::default(), methods: Default::default(), - generic_infer: Default::default(), + // generic_infer: Default::default(), trait_methods_impl: Default::default(), }))); if self.generics.is_none() { diff --git a/src/ast/node/union.rs b/src/ast/node/union.rs index 4ac3a5a72..75f7bdca7 100644 --- a/src/ast/node/union.rs +++ b/src/ast/node/union.rs @@ -79,6 +79,7 @@ impl UnionDefNode { modifier: self.modifier, sum_types: self.sum_types.clone(), methods: Default::default(), + // generic_infer: Default::default(), }))); builder.opaque_struct_type(&ctx.plmod.get_full_name(&self.name.name)); _ = ctx.add_type(self.name.name.clone(), stu, self.name.range); diff --git a/src/ast/plmod.rs b/src/ast/plmod.rs index 0f0016743..c01f669e0 100644 --- a/src/ast/plmod.rs +++ b/src/ast/plmod.rs @@ -3,7 +3,7 @@ use super::ctx::Ctx; use super::diag::{ErrorCode, PLDiag}; use super::node::macro_nodes::MacroNode; -use super::pltype::PriType; +use super::pltype::{PriType, TraitImplAble}; use super::pltype::{FNValue, PLType}; use super::range::Range; @@ -75,6 +75,7 @@ pub struct Mod { pub impls: ImplMap, pub macros: FxHashMap>, pub trait_mthd_table: TraitMthdImpl, + pub generic_infer: Arc>>>>>>>, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -193,7 +194,7 @@ impl Mod { } } - pub fn new(path: String) -> Self { + pub fn new(path: String, generic_infer:Arc>>>>>>>) -> Self { let name = Path::new(Path::new(&path).file_stem().unwrap()) .file_name() .take() @@ -225,6 +226,7 @@ impl Mod { impls: FxHashMap::default(), macros: FxHashMap::default(), trait_mthd_table: Default::default(), + generic_infer } } pub fn new_child(&self) -> Self { @@ -250,6 +252,7 @@ impl Mod { impls: FxHashMap::default(), macros: FxHashMap::default(), trait_mthd_table: self.trait_mthd_table.clone(), + generic_infer:self.generic_infer.clone() } } pub fn get_refs(&self, name: &str, db: &dyn Db, set: &mut FxHashSet) { @@ -390,10 +393,18 @@ impl Mod { // name ctx --name-> name --name--> name let st_name = name.split('<').collect::>()[0]; let st_with_generic = self.get_type_walker(st_name, range, ctx)?; - if let PLType::Struct(st) = &*st_with_generic.borrow() { - if let Some(res) = st.generic_infer.borrow().get(name) { - return Ok(res.clone().into()); + match &*st_with_generic.borrow() { + PLType::Struct(st)|PLType::Trait(st) => { + if let Some(res) = ctx.get_infer_result(st, name) { + return Ok(res.clone().into()); + } } + PLType::Union(st) => { + if let Some(res) = ctx.get_infer_result(st, name) { + return Ok(res.clone().into()); + } + }, + _ => (), }; } Err(range.new_err(ErrorCode::UNDEFINED_TYPE)) diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 94c7967d3..c0ba7be88 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -49,6 +49,7 @@ use std::cell::RefCell; use std::path::PathBuf; use std::sync::Arc; +use std::sync::Weak; /// # PLType /// Type for pivot-lang /// including primitive type, struct type, function type, void type @@ -215,6 +216,11 @@ impl UnionType { res.generic_map.clear(); let pltype = ctx.get_type(&res.name, Default::default()).unwrap(); pltype.tp.replace(PLType::Union(res.clone())); + // ctx.generic_infer + // .borrow_mut().entry(self.get_full_name_except_generic()).or_insert(Default::default()) + // .borrow_mut() + // .insert(res.name.clone(), pltype.tp.clone()); + ctx.add_infer_result(self, &res.name, pltype.tp.clone()); Ok(res) } pub fn has_type<'a, 'b>( @@ -959,8 +965,8 @@ pub struct STType { pub generic_infer_types: IndexMap>>, pub methods: Arc>>>>, pub trait_methods_impl: TraitMthdImpl, - // key name/name ... - pub generic_infer: Arc>>>>, + // // key name/name ... + // pub generic_infer: Arc>>>>, } pub type TraitMthdImpl = Arc>>>>>; @@ -1294,9 +1300,7 @@ impl STType { } else { pltype.tp.replace(PLType::Struct(res.clone())); } - self.generic_infer - .borrow_mut() - .insert(res.name, pltype.tp.clone()); + ctx.add_infer_result(self, &res.name, pltype.tp.clone()); Ok(pltype.tp) }) } diff --git a/test/main.pi b/test/main.pi index e1bb4b94d..ab0c7b55a 100644 --- a/test/main.pi +++ b/test/main.pi @@ -23,7 +23,7 @@ // use project1::test::compiletime_reflection::test_compile_time_reflection; // use project1::test::deconstruct; // use project1::test::st::*; -use std::iter::*; +use std::iter; pub fn main() i64 { // macros::test_macros(); // ifel::test_if_else(); @@ -49,7 +49,8 @@ pub fn main() i64 { // fixed_point::test_fixed_point(); // generic::ret_generic1(); // test_compile_time_reflection(); - let a:Iterator; + // let a:Iterator; + let re = iter::ret_opt(); return 0; } From 623951c7691e63d8157d573928f5e28a841a0dea Mon Sep 17 00:00:00 2001 From: bobxli Date: Thu, 13 Jul 2023 16:14:22 +0800 Subject: [PATCH 03/14] feat: done generator support --- planglib/std/iter.pi | 35 ++++++ src/ast/builder/llvmbuilder.rs | 205 ++++++++++++++++++++++++------- src/ast/builder/mod.rs | 15 ++- src/ast/builder/no_op_builder.rs | 18 ++- src/ast/ctx.rs | 107 +++++++++++----- src/ast/ctx/references.rs | 9 +- src/ast/node/cast.rs | 2 +- src/ast/node/function.rs | 162 ++++++++++++++++++------ src/ast/node/node_result.rs | 5 +- src/ast/node/program/cycle.rs | 5 +- src/ast/node/ret.rs | 37 +++++- src/ast/plmod.rs | 20 +-- src/ast/pltype.rs | 5 +- src/nomparser/statement.rs | 6 +- test/main.pi | 152 +++++++++++++++-------- 15 files changed, 578 insertions(+), 205 deletions(-) diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index ac1c1fa70..d3b1e604c 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -25,6 +25,41 @@ pub fn ret_opt() name> { } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // pub fn ret_opt() name> { // let b = 1; // let a:builtin::testG; diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 15f28fc38..9d393b201 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -20,8 +20,8 @@ use inkwell::{ module::{FlagBehavior, Linkage, Module}, targets::{InitializationConfig, Target, TargetMachine}, types::{ - AsTypeRef, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, PointerType, - StructType, VoidType, AnyType, + AnyType, AsTypeRef, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, + PointerType, StructType, VoidType, }, values::{ AnyValue, AnyValueEnum, BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallableValue, @@ -33,8 +33,9 @@ use llvm_sys::{core::LLVMStructSetBody, prelude::LLVMTypeRef}; use rustc_hash::FxHashMap; use crate::ast::{ + ctx::{CtxFlag, PLSymbol}, diag::PLDiag, - pltype::{ClosureType, TraitImplAble}, ctx::{CtxFlag, PLSymbol}, + pltype::{ClosureType, TraitImplAble}, }; use super::{ @@ -260,20 +261,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { malloc_fn: &str, ) -> (PointerValue<'ctx>, PointerValue<'ctx>, BasicTypeEnum<'ctx>) { let obj_type = tp.get_immix_type().int_value(); - let mut root_ctx = &*ctx; - while let Some(f) = root_ctx.father { - root_ctx = f - } - let gcmod = root_ctx.plmod.submods.get("gc").unwrap_or(&root_ctx.plmod); - let f: FNValue = gcmod - .types - .get(malloc_fn) - .unwrap() - .borrow() - .clone() - .try_into() - .unwrap(); - let f = self.get_or_insert_fn(&f, ctx); + let f = self.get_malloc_f(ctx, malloc_fn); let llvmtp = self.get_basic_type_op(tp, ctx).unwrap(); let tp = self .context @@ -312,6 +300,24 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { (casted_result.into_pointer_value(), stack_ptr, llvmtp) } + fn get_malloc_f(&self, ctx: &mut Ctx<'a>, malloc_fn: &str) -> FunctionValue<'ctx> { + let mut root_ctx = &*ctx; + while let Some(f) = root_ctx.root { + root_ctx = f + } + let gcmod = root_ctx.plmod.submods.get("gc").unwrap_or(&root_ctx.plmod); + let f: FNValue = gcmod + .types + .get(malloc_fn) + .unwrap() + .borrow() + .clone() + .try_into() + .unwrap(); + let f = self.get_or_insert_fn(&f, ctx); + f + } + /// # create_root_for /// /// 为一个堆上的对象创建gcroot @@ -1445,7 +1451,6 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { if ctx.ctx_flag == CtxFlag::InGeneratorYield { let data = ctx.generator_data.as_ref().unwrap().clone(); - let lb = self.builder.get_insert_block().unwrap(); let alloca = self .builder @@ -1463,11 +1468,22 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let bt = self.get_basic_type_op(pltype, ctx).unwrap(); let count = add_field(yield_ctx.as_any_value_enum(), bt.as_any_type_enum()); let i = count - 1; - let data_ptr = self.build_struct_gep(self.get_nth_param(f_v, 0), i, name).unwrap(); + let data_ptr = self + .build_struct_gep(self.get_nth_param(f_v, 0), i, name) + .unwrap(); self.builder.position_at_end(lb); - data.borrow_mut().table.insert(name.to_string(), PLSymbol{ value: data_ptr, pltype: Arc::new(RefCell::new(pltype.clone())), range: Default::default(), refs: None }); + let id = data.borrow().table.len().to_string(); + data.borrow_mut().table.insert( + name.to_string() + &id, + PLSymbol { + value: data_ptr, + pltype: Arc::new(RefCell::new(pltype.clone())), + range: Default::default(), + refs: None, + }, + ); // let data_ptr = self.build_struct_gep(ctx_v, (i +2) as u32, "para").unwrap(); return data_ptr; } @@ -2003,13 +2019,15 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { ); if child.ctx_flag == CtxFlag::InGeneratorYield { let data = child.generator_data.as_ref().unwrap().clone(); - let bb_v = data.borrow().alloca_bb; + let bb_v = data.borrow().entry_bb; let bb = self.get_llvm_block(bb_v).unwrap(); let funcvalue = bb.get_parent().unwrap(); let origin_bb = child.block.unwrap(); self.position_at_end_block(bb_v); let ctx_v = data.borrow().ctx_handle; - let para_ptr = self.build_struct_gep(ctx_v, (i +2) as u32, "para").unwrap(); + let para_ptr = self + .build_struct_gep(ctx_v, (i + 2) as u32, "para") + .unwrap(); self.build_store( para_ptr, self.get_llvm_value_handle( @@ -2094,9 +2112,16 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let ptrtp = self.struct_type(v, ctx).ptr_type(AddressSpace::default()); let ty = ptrtp.get_element_type().into_struct_type(); let ftp = self.mark_fn_tp(ptrtp); - let f = self - .module - .add_function(&(v.get_full_name() + "@"), ftp, Some(Linkage::External)); + let name = v.get_full_name() + "@"; + let f = match self.module.get_function(&name) { + Some(f) => f, + None => self + .module + .add_function(&name, ftp, Some(Linkage::External)), + }; + f.get_basic_blocks().iter().for_each(|bb| { + unsafe { bb.delete().unwrap() }; + }); let bb = self.context.append_basic_block(f, "entry"); self.builder.position_at_end(bb); let fieldn = ty.count_fields(); @@ -2309,30 +2334,122 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { } fn add_closure_st_field(&self, st: ValueHandle, field: ValueHandle) { let st_v = self.handle_table.borrow().get(&st).copied().unwrap(); - let field_tp = - self.handle_table - .borrow() - .get(&field) - .copied() - .unwrap() - .get_type(); + let field_tp = self + .handle_table + .borrow() + .get(&field) + .copied() + .unwrap() + .get_type(); add_field(st_v, field_tp); } - fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>, ctx_name:&str, ret_tp:&PLType) ->ValueHandle { - let tp = self.context.get_struct_type(ctx_name).unwrap().ptr_type(Default::default()).into(); - let ftp = self.get_basic_type_op(ret_tp, ctx).unwrap().fn_type(&[tp], false); - let f = self.module.add_function(&format!("{}__yield", ctx_name), ftp, None); + fn add_generator_yield_fn( + &self, + ctx: &mut Ctx<'a>, + ctx_name: &str, + ret_tp: &PLType, + ) -> ValueHandle { + let tp = self + .context + .get_struct_type(ctx_name) + .unwrap() + .ptr_type(Default::default()) + .into(); + let ftp = self + .get_basic_type_op(ret_tp, ctx) + .unwrap() + .fn_type(&[tp], false); + let f = self + .module + .add_function(&format!("{}__yield", ctx_name), ftp, None); self.get_llvm_value_handle(&f.into()) } - fn get_block_address(&self, block:BlockHandle) -> ValueHandle { - self.get_llvm_value_handle(unsafe { & self.get_llvm_block(block).unwrap().get_address().unwrap().into() }) + fn get_block_address(&self, block: BlockHandle) -> ValueHandle { + self.get_llvm_value_handle(unsafe { + &self + .get_llvm_block(block) + .unwrap() + .get_address() + .unwrap() + .into() + }) } - fn build_indirect_br(&self, block:ValueHandle,ctx: & Ctx<'a>,) { + fn build_indirect_br(&self, block: ValueHandle, ctx: &Ctx<'a>) { let block = self.get_llvm_value(block).unwrap(); let bv = self.get_llvm_block(ctx.block.unwrap()).unwrap(); - self.builder.build_indirect_branch::(block.try_into().unwrap(), &bv.get_parent().unwrap().get_basic_blocks()); + self.builder.build_indirect_branch::( + block.try_into().unwrap(), + &bv.get_parent() + .unwrap() + .get_basic_blocks() + .iter() + .skip(1) + .copied() + .collect::>(), + ); + } + unsafe fn store_with_aoto_cast(&self, ptr: ValueHandle, value: ValueHandle) { + let v_ptr = self.get_llvm_value(ptr).unwrap(); + let v = self.get_llvm_value(value).unwrap(); + let v = if v.is_function_value() { + v.into_function_value() + .as_global_value() + .as_basic_value_enum() + } else { + v.try_into().unwrap() + }; + let ptr_tp = v_ptr.get_type().into_pointer_type(); + let value_tp = v.get_type(); + if ptr_tp.get_element_type() != value_tp.as_any_type_enum() { + let casted = self.builder.build_bitcast::<_, BasicValueEnum>( + v_ptr.try_into().unwrap(), + value_tp.ptr_type(Default::default()), + "cast", + ); + self.builder.build_store(casted.into_pointer_value(), v); + } else { + self.build_store(ptr, value); + } + } + fn stack_alloc(&self, name: &str, ctx: &mut Ctx<'a>, tp: &PLType) -> ValueHandle { + let lb = self.builder.get_insert_block().unwrap(); + let llvmtp = self.get_basic_type_op(tp, ctx).unwrap(); + let alloca = self + .builder + .get_insert_block() + .unwrap() + .get_parent() + .unwrap() + .get_first_basic_block() + .unwrap(); + self.builder.position_at_end(alloca); + let stack_ptr = self.builder.build_alloca(llvmtp, name); + self.builder.position_at_end(lb); + self.get_llvm_value_handle(&stack_ptr.as_any_value_enum()) + } + fn correct_generator_ctx_malloc_inst(&self, ctx: &mut Ctx<'a>, name: &str) { + let data = ctx.generator_data.as_ref().unwrap(); + let bb = data.borrow().entry_bb; + let bb = self.get_llvm_block(bb).unwrap(); + let first_inst = bb.get_first_instruction().unwrap(); + let st = self.module.get_struct_type(name).unwrap(); + let size = self.targetmachine.get_target_data().get_store_size(&st); + let f = self.get_malloc_f(ctx, "DioGC__malloc"); + let cur_bb = self.builder.get_insert_block().unwrap(); + let next_inst = first_inst.get_next_instruction().unwrap(); + first_inst.erase_from_basic_block(); + self.builder.position_before(&next_inst); + let size = self.context.i64_type().const_int(size, false); + let tp = self + .context + .i8_type() + .const_int(immix::ObjectType::Complex.int_value() as _, false); + self.builder + .build_call(f, &[size.into(), tp.into()], "heapptr_ctx"); + + self.builder.position_at_end(cur_bb); } } @@ -2343,13 +2460,9 @@ fn add_field(st_v: AnyValueEnum<'_>, field_tp: inkwell::types::AnyTypeEnum<'_>) .get_element_type() .into_struct_type(); let mut closure_data_tps = st_tp.get_field_types(); - closure_data_tps.push( - field_tp - .try_into() - .unwrap(), - ); + closure_data_tps.push(field_tp.try_into().unwrap()); set_body(&st_tp, &closure_data_tps, false); - return st_tp.count_fields(); + st_tp.count_fields() } fn set_body<'ctx>(s: &StructType<'ctx>, field_types: &[BasicTypeEnum<'ctx>], packed: bool) { diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index e1b97fcf2..5af1eface 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -221,9 +221,18 @@ pub trait IRBuilder<'a, 'ctx> { allocab: BlockHandle, name: &str, ); - fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>, ctx_name:&str, ret_tp:&PLType) ->ValueHandle ; - fn get_block_address(&self, block:BlockHandle) -> ValueHandle; - fn build_indirect_br(&self, block:ValueHandle,ctx: & Ctx<'a>,) ; + fn add_generator_yield_fn( + &self, + ctx: &mut Ctx<'a>, + ctx_name: &str, + ret_tp: &PLType, + ) -> ValueHandle; + fn get_block_address(&self, block: BlockHandle) -> ValueHandle; + fn build_indirect_br(&self, block: ValueHandle, ctx: &Ctx<'a>); + // only used in special case, as it does not add gc root + unsafe fn store_with_aoto_cast(&self, ptr: ValueHandle, value: ValueHandle); + fn stack_alloc(&self, name: &str, ctx: &mut Ctx<'a>, tp: &PLType) -> ValueHandle; + fn correct_generator_ctx_malloc_inst(&self, ctx: &mut Ctx<'a>, name: &str); } pub type ValueHandle = usize; diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index fcc270d9a..4c8785e20 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -473,14 +473,26 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { ) { } - fn add_generator_yield_fn(&self,ctx: &mut Ctx<'a>,ctx_name:&str,ret_tp:&PLType) -> ValueHandle { + fn add_generator_yield_fn( + &self, + _ctx: &mut Ctx<'a>, + _ctx_name: &str, + _ret_tp: &PLType, + ) -> ValueHandle { 0 } - fn get_block_address(&self,block:super::BlockHandle) -> ValueHandle { + fn get_block_address(&self, _block: super::BlockHandle) -> ValueHandle { 0 } - fn build_indirect_br(&self,block:ValueHandle,ctx: &Ctx<'a>,) { + fn build_indirect_br(&self, _block: ValueHandle, _ctx: &Ctx<'a>) {} + + unsafe fn store_with_aoto_cast(&self, _ptr: ValueHandle, _value: ValueHandle) {} + + fn stack_alloc(&self, _name: &str, _ctx: &mut Ctx<'a>, _tp: &PLType) -> ValueHandle { + 0 } + + fn correct_generator_ctx_malloc_inst(&self, _ctx: &mut Ctx<'a>, _name: &str) {} } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 38524370d..93f408559 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -69,6 +69,10 @@ pub struct PLSymbol { pub range: Range, pub refs: Option>>, } +type GenericCacheMap = IndexMap>>>>>; + +pub type GenericCache = Arc>; + /// # Ctx /// Context for code generation pub struct Ctx<'a> { @@ -79,9 +83,9 @@ pub struct Ctx<'a> { pub root: Option<&'a Ctx<'a>>, // root context, for symbol lookup pub function: Option, // current function pub init_func: Option, //init function,call first in main - pub block: Option, // current block + pub block: Option, // current block pub continue_block: Option, // the block to jump when continue - pub break_block: Option, // the block to jump to when break + pub break_block: Option, // the block to jump to when break pub return_block: Option<(BlockHandle, Option)>, // the block to jump to when return and value pub errs: &'a RefCell>, // diagnostic list pub edit_pos: Option, // lsp params @@ -99,21 +103,22 @@ pub struct Ctx<'a> { pub closure_data: Option>, pub expect_ty: Option>>, pub self_ref_map: FxHashMap>, // used to recognize self reference - pub ctx_flag:CtxFlag, - pub generator_data: Option>>, - pub generic_infer: Arc>>>>>>>, + pub ctx_flag: CtxFlag, + pub generator_data: Option>>, + pub generic_cache: GenericCache, } - #[derive(Clone, Default)] -pub struct GeneratorCtxData{ +pub struct GeneratorCtxData { pub table: LinkedHashMap, - pub alloca_bb: BlockHandle, + pub entry_bb: BlockHandle, pub ctx_handle: ValueHandle, //handle in setup function + pub ret_handle: ValueHandle, //handle in setup function + pub prev_yield_bb: Option, } /// # CtxFlag -/// +/// /// flags that might change the behavior of the builder #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CtxFlag { @@ -135,36 +140,69 @@ pub enum MacroReplaceNode { } impl<'a, 'ctx> Ctx<'a> { + pub fn add_term_to_previous_yield( + &self, + builder: &'a BuilderEnum<'a, 'ctx>, + curbb: usize, + ) -> Arc> { + let ctx = self; + let data = ctx.generator_data.as_ref().unwrap(); + if let Some(prev_bb) = data.borrow().prev_yield_bb { + builder.position_at_end_block(prev_bb); + let ctx_handle = builder.get_nth_param(ctx.function.unwrap(), 0); + let ptr = builder + .build_struct_gep(ctx_handle, 1, "block_ptr") + .unwrap(); - pub fn add_infer_result(&self, tp:&impl TraitImplAble, name:&str, pltp:Arc>) { - self.generic_infer - .borrow_mut().entry(tp.get_full_name_except_generic()).or_insert(Default::default()) - .borrow_mut() - .insert(name.to_string(), pltp); + let addr = builder.get_block_address(curbb); + builder.build_store(ptr, addr); + + builder.build_unconditional_branch(ctx.return_block.unwrap().0); + } + data.clone() + } + pub fn add_infer_result( + &self, + tp: &impl TraitImplAble, + name: &str, + pltp: Arc>, + ) { + self.generic_cache + .borrow_mut() + .entry(tp.get_full_name_except_generic()) + .or_insert(Default::default()) + .borrow_mut() + .insert(name.to_string(), pltp); } - pub fn get_infer_result(&self, tp:&impl TraitImplAble, name:&str) -> Option>> { - let infer_map = self.generic_infer.borrow(); + pub fn get_infer_result( + &self, + tp: &impl TraitImplAble, + name: &str, + ) -> Option>> { + let infer_map = self.generic_cache.borrow(); let infer_map = infer_map.get(&tp.get_full_name_except_generic())?; let x = infer_map.borrow().get(name).cloned(); x } - fn import_all_infer_maps_from(&self, other: &IndexMap>>>>>) { + fn import_all_infer_maps_from(&self, other: &GenericCacheMap) { for (k, v) in other.iter() { - if !self.generic_infer.borrow().contains_key(k) { + if !self.generic_cache.borrow().contains_key(k) { let map: Arc>>>> = Default::default(); - self.generic_infer.borrow_mut().insert(k.clone(), map.clone()); + self.generic_cache + .borrow_mut() + .insert(k.clone(), map.clone()); map.borrow_mut().extend(v.borrow().clone()); - }else { - let infer_map = self.generic_infer.borrow(); + } else { + let infer_map = self.generic_cache.borrow(); let infer_map = infer_map.get(k).unwrap(); infer_map.borrow_mut().extend(v.borrow().clone()); } } } pub fn import_all_infer_maps_from_sub_mods(&self) { - for (_,sub_mod) in self.plmod.submods.iter() { + for (_, sub_mod) in self.plmod.submods.iter() { self.import_all_infer_maps_from(&sub_mod.generic_infer.borrow()); } } @@ -227,7 +265,7 @@ impl<'a, 'ctx> Ctx<'a> { config: Config, db: &'a dyn Db, ) -> Ctx<'a> { - let generic_infer:Arc>>>>>>> = Default::default(); + let generic_infer: GenericCache = Default::default(); Ctx { need_highlight: 0, generic_types: FxHashMap::default(), @@ -256,9 +294,9 @@ impl<'a, 'ctx> Ctx<'a> { root: None, macro_skip_level: 0, self_ref_map: FxHashMap::default(), - ctx_flag:CtxFlag::Normal, + ctx_flag: CtxFlag::Normal, generator_data: None, - generic_infer, + generic_cache: generic_infer, } } pub fn new_child(&'a self, start: Pos, builder: &'a BuilderEnum<'a, 'ctx>) -> Ctx<'a> { @@ -294,9 +332,9 @@ impl<'a, 'ctx> Ctx<'a> { root, macro_skip_level: self.macro_skip_level, self_ref_map: FxHashMap::default(), - ctx_flag:self.ctx_flag, + ctx_flag: self.ctx_flag, generator_data: self.generator_data.clone(), - generic_infer:self.generic_infer.clone(), + generic_cache: self.generic_cache.clone(), }; add_primitive_types(&mut ctx); if start != Default::default() { @@ -924,6 +962,9 @@ impl<'a, 'ctx> Ctx<'a> { if let Some(src) = &self.temp_source { dia.set_source(src); } + if dia.get_diag_code() == DiagCode::Err(ErrorCode::UNDEFINED_TYPE) { + eprintln!("add diag: {}", dia.get_msg()); + } let dia2 = dia.clone(); self.errs.borrow_mut().insert(dia); dia2 @@ -1044,7 +1085,7 @@ impl<'a, 'ctx> Ctx<'a> { if range == Default::default() { return; } - self.plmod.defs.borrow_mut().insert( + self.get_root_ctx().plmod.defs.borrow_mut().insert( range, LSPDef::Scalar(Location { uri: url_from_path(&file), @@ -1207,11 +1248,11 @@ impl<'a, 'ctx> Ctx<'a> { if self.need_highlight != 0 || self.in_macro { return; } - self.plmod.semantic_tokens_builder.borrow_mut().push( - range.to_diag_range(), - type_index(tp), - modifiers, - ) + self.get_root_ctx() + .plmod + .semantic_tokens_builder + .borrow_mut() + .push(range.to_diag_range(), type_index(tp), modifiers) } pub fn push_type_hints(&self, range: Range, pltype: Arc>) { if self.need_highlight != 0 || self.in_macro { diff --git a/src/ast/ctx/references.rs b/src/ast/ctx/references.rs index 250760cf3..ca34d2918 100644 --- a/src/ast/ctx/references.rs +++ b/src/ast/ctx/references.rs @@ -67,16 +67,17 @@ impl<'a> Ctx<'a> { /// /// For details, see the module documentation. pub fn set_glob_refs(&self, name: &str, range: Range) { - self.plmod + let root = self.get_root_ctx(); + root.plmod .glob_refs .borrow_mut() .insert(range, name.to_string()); - let mut rm = self.plmod.refs_map.borrow_mut(); + let mut rm = root.plmod.refs_map.borrow_mut(); if let Some(refsmap) = rm.get(name) { - refsmap.borrow_mut().push(self.get_location(range)); + refsmap.borrow_mut().push(root.get_location(range)); } else { let v = RefCell::new(vec![]); - v.borrow_mut().push(self.get_location(range)); + v.borrow_mut().push(root.get_location(range)); rm.insert(name.to_string(), Arc::new(v)); } } diff --git a/src/ast/node/cast.rs b/src/ast/node/cast.rs index c15e15432..d670fab67 100644 --- a/src/ast/node/cast.rs +++ b/src/ast/node/cast.rs @@ -254,7 +254,7 @@ impl<'a, 'ctx> Ctx<'a> { } } -fn get_option_type<'a, 'b>( +pub fn get_option_type<'a, 'b>( ctx: &'b mut Ctx<'a>, builder: &'b BuilderEnum<'a, '_>, target_ty: Arc>, diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index bb0b43a14..97f16c237 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -1,10 +1,11 @@ +use super::cast::get_option_type; use super::interface::TraitBoundNode; use super::node_result::NodeResultBuilder; use super::statement::StatementsNode; use super::*; use super::{types::TypedIdentifierNode, Node, TypeNode}; use crate::ast::builder::ValueHandle; -use crate::ast::ctx::{ClosureCtxData, BUILTIN_FN_MAP, CtxFlag, GeneratorCtxData}; +use crate::ast::ctx::{ClosureCtxData, CtxFlag, GeneratorCtxData, BUILTIN_FN_MAP}; use crate::ast::diag::ErrorCode; use crate::ast::node::{deal_line, tab}; @@ -554,15 +555,19 @@ impl FuncDefNode { let mut funcvalue = builder.get_or_insert_fn_handle(&fnvalue, child); child.function = Some(funcvalue); let mut sttp_opt = None; + let mut generator_alloca_b = 0; if self.generator { let mut m = LinkedHashMap::default(); - m.insert("address".to_owned(), Field{ - index: 1, - typenode: i8ptr.clone().get_typenode(&child.plmod.path), - name: "address".to_owned(), - range: Default::default(), - modifier: None, - }); + m.insert( + "address".to_owned(), + Field { + index: 1, + typenode: i8ptr.clone().get_typenode(&child.plmod.path), + name: "address".to_owned(), + range: Default::default(), + modifier: None, + }, + ); let st_tp = STType { name: fnvalue.get_generator_ctx_name(), path: ctx.plmod.path.clone(), @@ -582,29 +587,39 @@ impl FuncDefNode { }; builder.opaque_struct_type(&st_tp.get_full_name()); builder.add_body_to_struct_type(&st_tp.get_full_name(), &st_tp, child); - - let rettp= child.run_in_type_mod(&fnvalue, |child,fnvalue| { + + let rettp = child.run_in_type_mod(&fnvalue, |child, fnvalue| { let tp = fnvalue.fntype.ret_pltype.get_type(child, builder, false)?; match &*tp.borrow() { PLType::Trait(t) => { return Ok(t.generic_map.first().unwrap().1.clone()); } - _ =>todo!() - + _ => todo!(), }; })?; + let rettp = get_option_type(child, builder, rettp)?; child.rettp = Some(rettp.clone()); - let f = builder.add_generator_yield_fn(child, &st_tp.get_full_name(), &rettp.borrow()); + let f = + builder.add_generator_yield_fn(child, &st_tp.get_full_name(), &rettp.borrow()); child.function = Some(f); - let allocab = builder.append_basic_block(funcvalue, "entry");// this is alloca for setup fn - funcvalue = f; + let allocab = builder.append_basic_block(funcvalue, "alloc"); // this is alloca for setup fn + let entry = builder.append_basic_block(funcvalue, "set_up_entry"); // this is enrty for setup fn builder.position_at_end_block(allocab); - let ctx_handle = builder.alloc("ctx",&PLType::Struct(st_tp.clone()) , child, None); - child.generator_data = Some(Arc::new( RefCell::new( GeneratorCtxData{alloca_bb:allocab,ctx_handle,..Default::default()}))); - child.ctx_flag = CtxFlag::InGeneratorYield; + + // builder.build_unconditional_branch(entry); + generator_alloca_b = allocab; + + funcvalue = f; + builder.position_at_end_block(entry); + let ctx_handle = builder.alloc("ctx", &PLType::Struct(st_tp.clone()), child, None); + child.generator_data = Some(Arc::new(RefCell::new(GeneratorCtxData { + entry_bb: entry, + ctx_handle, + ..Default::default() + }))); sttp_opt = Some(st_tp); } - + builder.build_sub_program( self.paralist.clone(), fnvalue.fntype.ret_pltype.clone(), @@ -614,26 +629,53 @@ impl FuncDefNode { )?; // add block let allocab = builder.append_basic_block(funcvalue, "alloc"); + let entry = builder.append_basic_block(funcvalue, "entry"); if self.generator { - let address = builder.get_block_address(allocab); + let address = builder.get_block_address(entry); let data = child.generator_data.as_ref().unwrap().clone(); - let address_ptr = builder.build_struct_gep(data.borrow().ctx_handle, 1, "block_address").unwrap(); + let address_ptr = builder + .build_struct_gep(data.borrow().ctx_handle, 1, "block_address") + .unwrap(); builder.build_store(address_ptr, address); } - let entry = builder.append_basic_block(funcvalue, "entry"); let return_block = builder.append_basic_block(funcvalue, "return"); child.position_at_end(entry, builder); - let ret_value_ptr = match &*fnvalue - .fntype - .ret_pltype - .get_type(child, builder, true)? - .borrow() - { - PLType::Void => None, - other => { - builder.rm_curr_debug_location(); - let retv = builder.alloc("retvalue", other, child, None); - Some(retv) + let ret_value_ptr = if self.generator { + builder.rm_curr_debug_location(); + let data = child.generator_data.as_ref().unwrap().clone(); + child.position_at_end(data.borrow().entry_bb, builder); + let tp = child.rettp.clone().unwrap(); + + match &*fnvalue + .fntype + .ret_pltype + .get_type(child, builder, true)? + .borrow() + { + PLType::Void => unreachable!(), + other => { + builder.rm_curr_debug_location(); + data.borrow_mut().ret_handle = + builder.alloc("retvalue", other, child, None); + } + } + child.position_at_end(entry, builder); + + let retv = builder.stack_alloc("retvalue", child, &tp.borrow()); + Some(retv) + } else { + match &*fnvalue + .fntype + .ret_pltype + .get_type(child, builder, true)? + .borrow() + { + PLType::Void => None, + other => { + builder.rm_curr_debug_location(); + let retv = builder.alloc("retvalue", other, child, None); + Some(retv) + } } }; child.position_at_end(return_block, builder); @@ -683,8 +725,11 @@ impl FuncDefNode { child.init_global(builder); child.position_at_end(entry, builder); } - if !self.generator{ - child.rettp = Some(fnvalue.fntype.ret_pltype.get_type(child, builder, true)?); + if !self.generator { + child.rettp = Some(fnvalue.fntype.ret_pltype.get_type(child, builder, true)?); + } + if self.generator { + child.ctx_flag = CtxFlag::InGeneratorYield; } // body generation let terminator = self.body.as_mut().unwrap().emit(child, builder)?.get_term(); @@ -694,9 +739,12 @@ impl FuncDefNode { ); } if self.generator { + child.ctx_flag = CtxFlag::Normal; + + let done = builder.get_cur_basic_block(); let mut i = 1; - let mut tps = vec![]; + let mut tps = vec![Arc::new(RefCell::new(i8ptr.clone()))]; let st_tp = sttp_opt.as_mut().unwrap(); for (k, v) in &child.generator_data.as_ref().unwrap().borrow().table { let pltp = PLType::Pointer(v.pltype.to_owned()); @@ -713,14 +761,48 @@ impl FuncDefNode { tps.push(Arc::new(RefCell::new(pltp))); i += 1; } - let data = child.generator_data.as_ref().unwrap(); + let data = child.generator_data.as_ref().unwrap().clone(); + + builder.gen_st_visit_function(child, st_tp, &tps); + builder.position_at_end_block(data.borrow().entry_bb); + let ptr = builder + .build_struct_gep(data.borrow().ret_handle, 1, "ctx_handle_gep") + .unwrap(); + let ptr = builder.bitcast( + child, + ptr, + &PLType::Pointer(Arc::new(RefCell::new(PLType::Pointer(Arc::new( + RefCell::new(PLType::Struct(st_tp.clone())), + ))))), + "casted_ptr", + ); + builder.build_store(ptr, data.borrow().ctx_handle); + let ptr = builder + .build_struct_gep(data.borrow().ret_handle, 2, "ctx_handle_gep") + .unwrap(); + unsafe { builder.store_with_aoto_cast(ptr, funcvalue) }; + let ret_load = builder.build_load(data.borrow().ret_handle, "ret_load"); + builder.build_return(Some(ret_load)); + + builder.position_at_end_block(generator_alloca_b); + builder.build_unconditional_branch(data.borrow().entry_bb); + + builder.position_at_end_block(done); + let flag = builder + .build_struct_gep(child.return_block.unwrap().1.unwrap(), 0, "flag") + .unwrap(); + builder.build_store(flag, builder.int_value(&PriType::U64, 1, false)); + builder.build_unconditional_branch(child.return_block.unwrap().0); + child.add_term_to_previous_yield(builder, done); - builder.position_at_end_block(data.borrow().alloca_bb); - builder.gen_st_visit_function(child, &st_tp, &tps); builder.position_at_end_block(allocab); let ctx_v = builder.get_nth_param(child.function.unwrap(), 0); let address = builder.build_struct_gep(ctx_v, 1, "block_address").unwrap(); - builder.build_indirect_br(address, &child); + let address = builder.build_load(address, "block_address"); + builder.build_indirect_br(address, child); + + builder.correct_generator_ctx_malloc_inst(child, &st_tp.get_full_name()); + return Ok(()); } child.position_at_end(allocab, builder); diff --git a/src/ast/node/node_result.rs b/src/ast/node/node_result.rs index b83eb87a2..6075c7079 100644 --- a/src/ast/node/node_result.rs +++ b/src/ast/node/node_result.rs @@ -10,14 +10,15 @@ pub enum TerminatorEnum { Return, Break, Continue, + YieldReturn, } impl TerminatorEnum { pub fn is_none(self) -> bool { - self == TerminatorEnum::None + self == TerminatorEnum::None || self == TerminatorEnum::YieldReturn } pub fn is_return(self) -> bool { - self == TerminatorEnum::Return + self == TerminatorEnum::Return || self == TerminatorEnum::YieldReturn } } diff --git a/src/ast/node/program/cycle.rs b/src/ast/node/program/cycle.rs index fa9d79299..d06cb6ea0 100644 --- a/src/ast/node/program/cycle.rs +++ b/src/ast/node/program/cycle.rs @@ -66,7 +66,10 @@ pub fn cycle_deps_recover( } Diagnostics::push(db, (src_file_path.to_string(), vec![diag])); db.report_untracked_read(); - Some(ModWrapper::new(db, Mod::new(src_file_path.to_string(),Default::default()))) + Some(ModWrapper::new( + db, + Mod::new(src_file_path.to_string(), Default::default()), + )) } pub(crate) fn build_init_params( diff --git a/src/ast/node/ret.rs b/src/ast/node/ret.rs index ae41816b0..e50c8b97e 100644 --- a/src/ast/node/ret.rs +++ b/src/ast/node/ret.rs @@ -10,7 +10,7 @@ use internal_macro::node; #[node(comment)] pub struct RetNode { pub value: Option>, - pub yiel:Option<(TokenType,Range)> + pub yiel: Option<(TokenType, Range)>, } impl PrintTrait for RetNode { @@ -31,7 +31,40 @@ impl Node for RetNode { builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { let ret_pltype = ctx.rettp.as_ref().unwrap().clone(); - if let Some(ret_node) = &mut self.value { + if self.yiel.is_some() { + let ret_node = self.value.as_mut().unwrap(); + let v = ret_node.emit(ctx, builder)?.get_value().unwrap(); + ctx.emit_comment_highlight(&self.comments[0]); + let value_pltype = v.get_ty(); + let v_tp = if let PLType::Union(u) = &*ret_pltype.borrow() { + u.sum_types[0].get_type(ctx, builder, false)? + } else { + unreachable!() + }; + if v_tp != value_pltype { + let err = ctx.add_diag(self.range.new_err(ErrorCode::RETURN_TYPE_MISMATCH)); + return Err(err); + } + // let value = ctx.try_load2var(self.range, v.get_value(), builder)?; + let value = ctx.up_cast( + ret_pltype, + value_pltype, + ret_node.range(), + ret_node.range(), + v.get_value(), + builder, + )?; + let value = ctx.try_load2var(self.range, value, builder)?; + builder.build_store(ctx.return_block.unwrap().1.unwrap(), value); + let curbb = builder.get_cur_basic_block(); + let data = ctx.add_term_to_previous_yield(builder, curbb); + + let yield_bb = builder.append_basic_block(ctx.function.unwrap(), "yield"); + ctx.position_at_end(yield_bb, builder); + + data.borrow_mut().prev_yield_bb = Some(curbb); + return NodeOutput::new_term(TerminatorEnum::YieldReturn).to_result(); + } else if let Some(ret_node) = &mut self.value { // TODO implicit cast && type infer let v = ret_node.emit(ctx, builder)?.get_value().unwrap(); ctx.emit_comment_highlight(&self.comments[0]); diff --git a/src/ast/plmod.rs b/src/ast/plmod.rs index c01f669e0..bb31604a7 100644 --- a/src/ast/plmod.rs +++ b/src/ast/plmod.rs @@ -1,9 +1,9 @@ use super::accumulators::PLReferences; -use super::ctx::Ctx; +use super::ctx::{Ctx, GenericCache}; use super::diag::{ErrorCode, PLDiag}; use super::node::macro_nodes::MacroNode; -use super::pltype::{PriType, TraitImplAble}; +use super::pltype::PriType; use super::pltype::{FNValue, PLType}; use super::range::Range; @@ -75,7 +75,7 @@ pub struct Mod { pub impls: ImplMap, pub macros: FxHashMap>, pub trait_mthd_table: TraitMthdImpl, - pub generic_infer: Arc>>>>>>>, + pub generic_infer: GenericCache, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -194,7 +194,7 @@ impl Mod { } } - pub fn new(path: String, generic_infer:Arc>>>>>>>) -> Self { + pub fn new(path: String, generic_infer: GenericCache) -> Self { let name = Path::new(Path::new(&path).file_stem().unwrap()) .file_name() .take() @@ -226,7 +226,7 @@ impl Mod { impls: FxHashMap::default(), macros: FxHashMap::default(), trait_mthd_table: Default::default(), - generic_infer + generic_infer, } } pub fn new_child(&self) -> Self { @@ -252,7 +252,7 @@ impl Mod { impls: FxHashMap::default(), macros: FxHashMap::default(), trait_mthd_table: self.trait_mthd_table.clone(), - generic_infer:self.generic_infer.clone() + generic_infer: self.generic_infer.clone(), } } pub fn get_refs(&self, name: &str, db: &dyn Db, set: &mut FxHashSet) { @@ -394,16 +394,16 @@ impl Mod { let st_name = name.split('<').collect::>()[0]; let st_with_generic = self.get_type_walker(st_name, range, ctx)?; match &*st_with_generic.borrow() { - PLType::Struct(st)|PLType::Trait(st) => { + PLType::Struct(st) | PLType::Trait(st) => { if let Some(res) = ctx.get_infer_result(st, name) { - return Ok(res.clone().into()); + return Ok(res.into()); } } PLType::Union(st) => { if let Some(res) = ctx.get_infer_result(st, name) { - return Ok(res.clone().into()); + return Ok(res.into()); } - }, + } _ => (), }; } diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index c0ba7be88..14d0ed002 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -49,7 +49,6 @@ use std::cell::RefCell; use std::path::PathBuf; use std::sync::Arc; -use std::sync::Weak; /// # PLType /// Type for pivot-lang /// including primitive type, struct type, function type, void type @@ -220,7 +219,7 @@ impl UnionType { // .borrow_mut().entry(self.get_full_name_except_generic()).or_insert(Default::default()) // .borrow_mut() // .insert(res.name.clone(), pltype.tp.clone()); - ctx.add_infer_result(self, &res.name, pltype.tp.clone()); + ctx.add_infer_result(self, &res.name, pltype.tp); Ok(res) } pub fn has_type<'a, 'b>( @@ -715,7 +714,7 @@ impl TryFrom for FNValue { } } impl FNValue { - pub fn get_generator_ctx_name(&self) ->String { + pub fn get_generator_ctx_name(&self) -> String { self.name.clone() + "__generator_ctx" } pub fn to_closure_ty<'a, 'b>( diff --git a/src/nomparser/statement.rs b/src/nomparser/statement.rs index 7717da24a..6d1b4f167 100644 --- a/src/nomparser/statement.rs +++ b/src/nomparser/statement.rs @@ -239,13 +239,13 @@ pub fn assignment(input: Span) -> IResult> { fn return_statement(input: Span) -> IResult> { delspace(map_res( tuple(( - opt( tag_token_word(TokenType::YIELD)), + opt(tag_token_word(TokenType::YIELD)), tag_token_word(TokenType::RETURN), opt(general_exp), tag_token_symbol(TokenType::SEMI), opt(delspace(comment)), )), - |(y,(_, range), value, (_,r2), optcomment)| { + |(y, (_, range), value, (_, r2), optcomment)| { let comments = if let Some(com) = optcomment { vec![vec![com]] } else { @@ -257,7 +257,7 @@ fn return_statement(input: Span) -> IResult> { value, range, comments, - yiel:y + yiel: y, } .into(), ) diff --git a/test/main.pi b/test/main.pi index ab0c7b55a..d0fa64845 100644 --- a/test/main.pi +++ b/test/main.pi @@ -1,61 +1,105 @@ -// use project1::test::ifel; -// use project1::test::generic; -// use project1::test::st; -// use project1::test::method; -// use project1::test::constant; -// use project1::test::traits; -// use project1::test::simple; -// use project1::test::flow; -// use project1::test::list; -// use project1::test::module; -// use project1::test::string; -// use project1::test::macros; -// use project1::test::union; -// use project1::test::multi_trait; -// use project1::test::tuple; -// use project1::test::fntype; -// use project1::test::closure; -// use project1::test::map; -// use project1::test::tree; -// use project1::test::fixed_point; -// use project1::tmod2; -// use pl_test::main; -// use project1::test::compiletime_reflection::test_compile_time_reflection; -// use project1::test::deconstruct; -// use project1::test::st::*; -use std::iter; +use project1::test::ifel; +use project1::test::generic; +use project1::test::st; +use project1::test::method; +use project1::test::constant; +use project1::test::traits; +use project1::test::simple; +use project1::test::flow; +use project1::test::list; +use project1::test::module; +use project1::test::string; +use project1::test::macros; +use project1::test::union; +use project1::test::multi_trait; +use project1::test::tuple; +use project1::test::fntype; +use project1::test::closure; +use project1::test::map; +use project1::test::tree; +use project1::test::fixed_point; +use project1::tmod2; +use pl_test::main; +use project1::test::compiletime_reflection::test_compile_time_reflection; +use project1::test::deconstruct; +use project1::test::st::*; +use std::io; +use std::iter::*; pub fn main() i64 { - // macros::test_macros(); - // ifel::test_if_else(); - // generic::test_generic(); - // method::test_impl(); - // test_struct(); - // constant::test_const(); - // traits::test_trait(); - // simple::test_simple(); - // flow::test_flow(); - // list::test_list(); - // main::simple_test(); - // module::test_module(); - // string::test_string(); - // union::test_union(); - // multi_trait::test_multi_trait(); - // deconstruct::test_deconstruct(); - // tuple::test_tuple(); - // fntype::test_fntype()(); - // closure::test_closure(); - // tree::test_eva(); - // map::test_map(); - // fixed_point::test_fixed_point(); - // generic::ret_generic1(); - // test_compile_time_reflection(); + macros::test_macros(); + ifel::test_if_else(); + generic::test_generic(); + method::test_impl(); + test_struct(); + constant::test_const(); + traits::test_trait(); + simple::test_simple(); + flow::test_flow(); + list::test_list(); + main::simple_test(); + module::test_module(); + string::test_string(); + union::test_union(); + multi_trait::test_multi_trait(); + deconstruct::test_deconstruct(); + tuple::test_tuple(); + fntype::test_fntype()(); + closure::test_closure(); + tree::test_eva(); + map::test_map(); + fixed_point::test_fixed_point(); + generic::ret_generic1(); + test_compile_time_reflection(); // let a:Iterator; let re = iter::ret_opt(); + let iterator = name(); + let next = iterator.next(); + if next is i64 { + let i = next as i64!; + println!(i); + }else { + println!("none"); + } + next = iterator.next(); + if next is i64 { + let i = next as i64!; + println!(i); + }else { + println!("none"); + } + next = iterator.next(); + if next is i64 { + let i = next as i64!; + println!(i); + }else { + println!("none"); + } + next = iterator.next(); + if next is i64 { + let i = next as i64!; + println!(i); + }else { + println!("none"); + } + next = iterator.next(); + if next is i64 { + let i = next as i64!; + println!(i); + }else { + println!("none"); + } return 0; } -// gen fn name() Iterator { - -// return 1; -// } +gen fn name() Iterator { + let a = 1; + println!("yield 1"); + yield return a; + a = a + 1; + println!("yield 2"); + yield return a; + a = a + 1; + println!("yield 3"); + yield return a; +} From 727396fd20f46236cc3ac3c3e3325922c30e9bbe Mon Sep 17 00:00:00 2001 From: bobxli Date: Thu, 13 Jul 2023 21:08:27 +0800 Subject: [PATCH 04/14] fix: llvm segfault issue & add more generator diags --- Makefile | 3 + src/ast/builder/llvmbuilder.rs | 58 +++++++----- src/ast/ctx.rs | 1 + src/ast/diag.rs | 3 + src/ast/expects/iter.pi.expect | 1 + src/ast/expects/test_diag.pi.expect | 134 ++++++++++++++++++++++++++++ src/ast/node/control.rs | 4 +- src/ast/node/function.rs | 43 +++++---- src/ast/node/program.rs | 2 +- src/ast/node/ret.rs | 32 ++++++- src/ast/range.rs | 12 +++ src/nomparser/statement.rs | 5 +- test/lsp_diag/test_diag.pi | 29 ++++++ test/main.pi | 7 +- 14 files changed, 289 insertions(+), 45 deletions(-) create mode 100644 src/ast/expects/iter.pi.expect diff --git a/Makefile b/Makefile index aa8b3b0d8..17b1579c6 100644 --- a/Makefile +++ b/Makefile @@ -42,3 +42,6 @@ cmake-clean: lsp-wasm: @wasm-pack build --target bundler --no-default-features --scope pivot-lang + +renew-expect: + @UPDATE_EXPECT=1 cargo test --all diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 9d393b201..97cf4d851 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -260,6 +260,15 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { tp: &PLType, malloc_fn: &str, ) -> (PointerValue<'ctx>, PointerValue<'ctx>, BasicTypeEnum<'ctx>) { + let lb = self.builder.get_insert_block().unwrap(); + let alloca = self + .builder + .get_insert_block() + .unwrap() + .get_parent() + .unwrap() + .get_first_basic_block() + .unwrap(); let obj_type = tp.get_immix_type().int_value(); let f = self.get_malloc_f(ctx, malloc_fn); let llvmtp = self.get_basic_type_op(tp, ctx).unwrap(); @@ -269,7 +278,26 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { .const_int(tp.get_immix_type().int_value() as u64, false); let td = self.targetmachine.get_target_data(); let size = td.get_store_size(&llvmtp); - let size = self.context.i64_type().const_int(size, false); + let mut size = self.context.i64_type().const_int(size, false); + if name == "___ctx" { + // generator ctx, use stack variable as type + self.builder.position_at_end(alloca); + let stack_ptr = self + .builder + .build_alloca(self.context.i64_type(), "ctx_tp_ptr"); + ctx.generator_data + .as_ref() + .unwrap() + .borrow_mut() + .ctx_size_handle = self.get_llvm_value_handle(&stack_ptr.as_any_value_enum()); + + self.builder.position_at_end(lb); + + size = self + .builder + .build_load(stack_ptr, "ctx_tp") + .into_int_value(); + } let heapptr = self .builder .build_call(f, &[size.into(), tp.into()], &format!("heapptr_{}", name)) @@ -281,15 +309,6 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { llvmtp.ptr_type(AddressSpace::default()), name, ); - let lb = self.builder.get_insert_block().unwrap(); - let alloca = self - .builder - .get_insert_block() - .unwrap() - .get_parent() - .unwrap() - .get_first_basic_block() - .unwrap(); self.builder.position_at_end(alloca); let stack_ptr = self .builder @@ -1688,6 +1707,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { fn write_bitcode_to_path(&self, path: &Path) -> bool { self.optimize(); // run_immix_pass(self.module); + self.module.strip_debug_info(); self.module.write_bitcode_to_path(path) } fn int_value(&self, ty: &PriType, v: u64, sign_ext: bool) -> ValueHandle { @@ -2436,18 +2456,16 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let first_inst = bb.get_first_instruction().unwrap(); let st = self.module.get_struct_type(name).unwrap(); let size = self.targetmachine.get_target_data().get_store_size(&st); - let f = self.get_malloc_f(ctx, "DioGC__malloc"); let cur_bb = self.builder.get_insert_block().unwrap(); - let next_inst = first_inst.get_next_instruction().unwrap(); - first_inst.erase_from_basic_block(); - self.builder.position_before(&next_inst); - let size = self.context.i64_type().const_int(size, false); - let tp = self - .context - .i8_type() - .const_int(immix::ObjectType::Complex.int_value() as _, false); + self.builder - .build_call(f, &[size.into(), tp.into()], "heapptr_ctx"); + .position_at(first_inst.get_parent().unwrap(), &first_inst); + let size = self.context.i64_type().const_int(size, false); + let v = self + .get_llvm_value(data.borrow().ctx_size_handle) + .unwrap() + .into_pointer_value(); + self.builder.build_store(v, size); self.builder.position_at_end(cur_bb); } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 93f408559..65038e950 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -115,6 +115,7 @@ pub struct GeneratorCtxData { pub ctx_handle: ValueHandle, //handle in setup function pub ret_handle: ValueHandle, //handle in setup function pub prev_yield_bb: Option, + pub ctx_size_handle: ValueHandle, } /// # CtxFlag diff --git a/src/ast/diag.rs b/src/ast/diag.rs index 521a3c1be..9258d49fe 100644 --- a/src/ast/diag.rs +++ b/src/ast/diag.rs @@ -138,6 +138,9 @@ define_error!( STRUCT_FIELD_NOT_EXISTS = "struct field not exists", TRY_TO_EXPORT_NON_REEXPORT_SYMBOL = "try to export non reexport symbol", CYCLE_DEPENDENCY = "cycle dependency not allowed", + YIELD_RETURN_MUST_BE_IN_GENERATOR = "yield return must be in generator function", + GENERATOR_FN_MUST_RET_ITER = "generator function must return an iterator", + INVALID_RET_IN_GENERATOR_FUNCTION = "invalid `return` in generator function", ); macro_rules! define_warn { ($( diff --git a/src/ast/expects/iter.pi.expect b/src/ast/expects/iter.pi.expect new file mode 100644 index 000000000..0637a088a --- /dev/null +++ b/src/ast/expects/iter.pi.expect @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/ast/expects/test_diag.pi.expect b/src/ast/expects/test_diag.pi.expect index 395dcbc4f..aa459d0f2 100644 --- a/src/ast/expects/test_diag.pi.expect +++ b/src/ast/expects/test_diag.pi.expect @@ -615,4 +615,138 @@ }, }, }, + PLDiag { + raw: PLDiagRaw { + code: Err( + INVALID_RET_IN_GENERATOR_FUNCTION, + ), + help: None, + labels: [ + PLLabel { + file: "", + txt: Some( + ( + "add keyword {} here", + [ + "yield", + ], + ), + ), + range: Range { + start: Pos { + line: 60, + column: 5, + offset: 650, + }, + end: Pos { + line: 60, + column: 5, + offset: 650, + }, + }, + }, + ], + source: None, + range: Range { + start: Pos { + line: 60, + column: 5, + offset: 650, + }, + end: Pos { + line: 60, + column: 14, + offset: 659, + }, + }, + }, + }, + PLDiag { + raw: PLDiagRaw { + code: Err( + FUNCTION_MUST_HAVE_RETURN, + ), + help: None, + labels: [], + source: None, + range: Range { + start: Pos { + line: 65, + column: 1, + offset: 665, + }, + end: Pos { + line: 68, + column: 2, + offset: 723, + }, + }, + }, + }, + PLDiag { + raw: PLDiagRaw { + code: Err( + YIELD_RETURN_MUST_BE_IN_GENERATOR, + ), + help: None, + labels: [], + source: None, + range: Range { + start: Pos { + line: 67, + column: 5, + offset: 706, + }, + end: Pos { + line: 67, + column: 20, + offset: 721, + }, + }, + }, + }, + PLDiag { + raw: PLDiagRaw { + code: Err( + GENERATOR_FN_MUST_RET_ITER, + ), + help: None, + labels: [], + source: None, + range: Range { + start: Pos { + line: 71, + column: 21, + offset: 746, + }, + end: Pos { + line: 71, + column: 24, + offset: 749, + }, + }, + }, + }, + PLDiag { + raw: PLDiagRaw { + code: Err( + RETURN_TYPE_MISMATCH, + ), + help: None, + labels: [], + source: None, + range: Range { + start: Pos { + line: 78, + column: 5, + offset: 826, + }, + end: Pos { + line: 78, + column: 22, + offset: 843, + }, + }, + }, + }, ] \ No newline at end of file diff --git a/src/ast/node/control.rs b/src/ast/node/control.rs index 435eb4e5b..7cc91658c 100644 --- a/src/ast/node/control.rs +++ b/src/ast/node/control.rs @@ -225,8 +225,8 @@ impl Node for ForNode { ctx.position_at_end(after_block, builder); ctx.emit_comment_highlight(&self.comments[0]); NodeOutput::default() - .with_term(if terminator.is_return() { - TerminatorEnum::Return + .with_term(if terminator == TerminatorEnum::Return { + terminator } else { TerminatorEnum::None }) diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 97f16c237..43d8268b2 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -5,7 +5,7 @@ use super::statement::StatementsNode; use super::*; use super::{types::TypedIdentifierNode, Node, TypeNode}; use crate::ast::builder::ValueHandle; -use crate::ast::ctx::{ClosureCtxData, CtxFlag, GeneratorCtxData, BUILTIN_FN_MAP}; +use crate::ast::ctx::{ClosureCtxData, CtxFlag, BUILTIN_FN_MAP}; use crate::ast::diag::ErrorCode; use crate::ast::node::{deal_line, tab}; @@ -557,6 +557,7 @@ impl FuncDefNode { let mut sttp_opt = None; let mut generator_alloca_b = 0; if self.generator { + child.generator_data = Some(Default::default()); let mut m = LinkedHashMap::default(); m.insert( "address".to_owned(), @@ -590,11 +591,19 @@ impl FuncDefNode { let rettp = child.run_in_type_mod(&fnvalue, |child, fnvalue| { let tp = fnvalue.fntype.ret_pltype.get_type(child, builder, false)?; - match &*tp.borrow() { + let r = fnvalue.fntype.ret_pltype.range(); + let f = |ctx| { + r.new_err(ErrorCode::GENERATOR_FN_MUST_RET_ITER) + .add_to_ctx(ctx) + }; + return match &*tp.borrow() { PLType::Trait(t) => { - return Ok(t.generic_map.first().unwrap().1.clone()); + if t.name != "Iterator" { + return Err(f(child)); + } + Ok(t.generic_map.first().unwrap().1.clone()) } - _ => todo!(), + _ => Err(f(child)), }; })?; let rettp = get_option_type(child, builder, rettp)?; @@ -611,12 +620,15 @@ impl FuncDefNode { funcvalue = f; builder.position_at_end_block(entry); - let ctx_handle = builder.alloc("ctx", &PLType::Struct(st_tp.clone()), child, None); - child.generator_data = Some(Arc::new(RefCell::new(GeneratorCtxData { - entry_bb: entry, - ctx_handle, - ..Default::default() - }))); + let ctx_handle = + builder.alloc("___ctx", &PLType::Struct(st_tp.clone()), child, None); + child.generator_data.as_ref().unwrap().borrow_mut().entry_bb = entry; + child + .generator_data + .as_ref() + .unwrap() + .borrow_mut() + .ctx_handle = ctx_handle; sttp_opt = Some(st_tp); } @@ -687,6 +699,9 @@ impl FuncDefNode { builder.build_return(None); }; child.position_at_end(entry, builder); + if self.generator { + child.ctx_flag = CtxFlag::InGeneratorYield; + } // alloc para for (i, para) in fnvalue.fntype.param_pltypes.iter().enumerate() { let tp = para.get_type(child, builder, true)?; @@ -728,12 +743,9 @@ impl FuncDefNode { if !self.generator { child.rettp = Some(fnvalue.fntype.ret_pltype.get_type(child, builder, true)?); } - if self.generator { - child.ctx_flag = CtxFlag::InGeneratorYield; - } // body generation let terminator = self.body.as_mut().unwrap().emit(child, builder)?.get_term(); - if !terminator.is_return() { + if !terminator.is_return() && !self.generator { return Err( child.add_diag(self.range.new_err(ErrorCode::FUNCTION_MUST_HAVE_RETURN)) ); @@ -793,7 +805,7 @@ impl FuncDefNode { .unwrap(); builder.build_store(flag, builder.int_value(&PriType::U64, 1, false)); builder.build_unconditional_branch(child.return_block.unwrap().0); - child.add_term_to_previous_yield(builder, done); + // child.add_term_to_previous_yield(builder, done); builder.position_at_end_block(allocab); let ctx_v = builder.get_nth_param(child.function.unwrap(), 0); @@ -801,6 +813,7 @@ impl FuncDefNode { let address = builder.build_load(address, "block_address"); builder.build_indirect_br(address, child); + // FIXME: llvm crash builder.correct_generator_ctx_malloc_inst(child, &st_tp.get_full_name()); return Ok(()); diff --git a/src/ast/node/program.rs b/src/ast/node/program.rs index 5bcf3ed3a..410b3d56b 100644 --- a/src/ast/node/program.rs +++ b/src/ast/node/program.rs @@ -596,8 +596,8 @@ pub fn emit_file(db: &dyn Db, params: ProgramEmitParam) -> ModWrapper { let pp = Path::new(&hashed).with_extension("bc"); let ll = Path::new(&hashed).with_extension("ll"); let p = pp.as_path(); - builder.write_bitcode_to_path(p); builder.print_to_file(&ll).unwrap(); + builder.write_bitcode_to_path(p); ModBuffer::push( db, PLModBuffer { diff --git a/src/ast/node/ret.rs b/src/ast/node/ret.rs index e50c8b97e..3a5006730 100644 --- a/src/ast/node/ret.rs +++ b/src/ast/node/ret.rs @@ -5,6 +5,7 @@ use crate::ast::builder::BuilderEnum; use crate::ast::builder::IRBuilder; use crate::ast::tokens::TokenType; use crate::ast::{ctx::Ctx, diag::ErrorCode}; +use crate::format_label; use internal_macro::node; #[node(comment)] @@ -34,6 +35,12 @@ impl Node for RetNode { if self.yiel.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() { + return Err(self + .range + .new_err(ErrorCode::YIELD_RETURN_MUST_BE_IN_GENERATOR) + .add_to_ctx(ctx)); + } ctx.emit_comment_highlight(&self.comments[0]); let value_pltype = v.get_ty(); let v_tp = if let PLType::Union(u) = &*ret_pltype.borrow() { @@ -57,14 +64,31 @@ impl Node for RetNode { let value = ctx.try_load2var(self.range, value, builder)?; builder.build_store(ctx.return_block.unwrap().1.unwrap(), value); let curbb = builder.get_cur_basic_block(); - let data = ctx.add_term_to_previous_yield(builder, curbb); let yield_bb = builder.append_basic_block(ctx.function.unwrap(), "yield"); - ctx.position_at_end(yield_bb, builder); - data.borrow_mut().prev_yield_bb = Some(curbb); + ctx.generator_data + .as_ref() + .unwrap() + .borrow_mut() + .prev_yield_bb = Some(curbb); + ctx.add_term_to_previous_yield(builder, yield_bb); + ctx.position_at_end(yield_bb, builder); return NodeOutput::new_term(TerminatorEnum::YieldReturn).to_result(); - } else if let Some(ret_node) = &mut self.value { + } + if ctx.generator_data.is_some() { + return Err(self + .range + .new_err(ErrorCode::INVALID_RET_IN_GENERATOR_FUNCTION) + .add_label( + self.range.start_point(), + ctx.get_file(), + format_label!("add keyword {} here", "yield"), + ) + .add_to_ctx(ctx)); + } + + if let Some(ret_node) = &mut self.value { // TODO implicit cast && type infer let v = ret_node.emit(ctx, builder)?.get_value().unwrap(); ctx.emit_comment_highlight(&self.comments[0]); diff --git a/src/ast/range.rs b/src/ast/range.rs index fe4aec53d..904e25593 100644 --- a/src/ast/range.rs +++ b/src/ast/range.rs @@ -98,6 +98,18 @@ fn test_pos_in() { /// # Range /// source code range in file impl Range { + pub fn start_point(&self) -> Range { + Range { + start: self.start, + end: self.start, + } + } + pub fn end_point(&self) -> Range { + Range { + start: self.end, + end: self.end, + } + } pub fn new(start: Span, end: Span) -> Range { Range { start: Pos { diff --git a/src/nomparser/statement.rs b/src/nomparser/statement.rs index 6d1b4f167..b8f5cb15d 100644 --- a/src/nomparser/statement.rs +++ b/src/nomparser/statement.rs @@ -251,7 +251,10 @@ fn return_statement(input: Span) -> IResult> { } else { vec![vec![]] }; - let range = range.start.to(r2.end); + let mut range = range.start.to(r2.end); + if let Some((_, r)) = y { + range = r.start.to(range.end); + } res_enum( RetNode { value, diff --git a/test/lsp_diag/test_diag.pi b/test/lsp_diag/test_diag.pi index 507ae38f1..a2e2023cb 100644 --- a/test/lsp_diag/test_diag.pi +++ b/test/lsp_diag/test_diag.pi @@ -53,3 +53,32 @@ struct selfref2 { } use test::trait_diag; +use std::iter::Iterator; + +gen fn iter_test() Iterator { + + return 1; +} + + + +fn iter_test1() Iterator { + + yield return 1; +} + + +gen fn iter_test3() i64 { + + yield return 1; +} + +gen fn iter_test4() Iterator { + + yield return 1.0; +} + + +gen fn iter_test5() Iterator { +} + diff --git a/test/main.pi b/test/main.pi index d0fa64845..27b7eea9a 100644 --- a/test/main.pi +++ b/test/main.pi @@ -50,10 +50,10 @@ pub fn main() i64 { fixed_point::test_fixed_point(); generic::ret_generic1(); test_compile_time_reflection(); - // let a:Iterator; + let a:Iterator; let re = iter::ret_opt(); let iterator = name(); - let next = iterator.next(); + let next:Option = iterator.next(); if next is i64 { let i = next as i64!; println!(i); @@ -93,6 +93,9 @@ pub fn main() i64 { gen fn name() Iterator { + for let i = 0; i < 10; i = i + 1 { + yield return i; + } let a = 1; println!("yield 1"); yield return a; From a3e55680fcf5d6481015d6d1c000ee0ba22f0009 Mon Sep 17 00:00:00 2001 From: bobxli Date: Thu, 13 Jul 2023 21:30:14 +0800 Subject: [PATCH 05/14] fix: crush on os other than mac silicon --- planglib/std/iter.pi | 43 ---------------------------------- src/ast/builder/llvmbuilder.rs | 27 ++++++++++++++++----- test/main.pi | 23 +++++++++++++++--- 3 files changed, 41 insertions(+), 52 deletions(-) diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index d3b1e604c..90c800357 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -23,46 +23,3 @@ pub fn ret_opt() name> { let aa:name> = name{t:a}; return aa; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// pub fn ret_opt() name> { -// let b = 1; -// let a:builtin::testG; -// let aa:name> = name{t:a}; -// return aa; -// } \ No newline at end of file diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 97cf4d851..ae3819c8b 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -250,9 +250,13 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { } let v_stack = self.get_llvm_value_handle(&stack_root.as_any_value_enum()); let v_heap = self.get_llvm_value_handle(&p.as_any_value_enum()); - self.heap_stack_map.borrow_mut().insert(v_heap, v_stack); + self.set_root(v_heap, v_stack); v_heap } + + fn set_root(&self, v_heap: usize, v_stack: usize) { + self.heap_stack_map.borrow_mut().insert(v_heap, v_stack); + } fn gc_malloc( &self, name: &str, @@ -1467,6 +1471,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { ctx: &mut Ctx<'a>, declare: Option, ) -> ValueHandle { + let mut ret_handle = self.alloc_raw(name, pltype, ctx, declare, "DioGC__malloc"); if ctx.ctx_flag == CtxFlag::InGeneratorYield { let data = ctx.generator_data.as_ref().unwrap().clone(); @@ -1485,28 +1490,39 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let f = self.get_llvm_value(f_v).unwrap().into_function_value(); let yield_ctx = f.get_nth_param(0).unwrap(); let bt = self.get_basic_type_op(pltype, ctx).unwrap(); - let count = add_field(yield_ctx.as_any_value_enum(), bt.as_any_type_enum()); + let count = add_field( + yield_ctx.as_any_value_enum(), + bt.ptr_type(Default::default()).into(), + ); let i = count - 1; let data_ptr = self .build_struct_gep(self.get_nth_param(f_v, 0), i, name) .unwrap(); + let load = self.build_load(data_ptr, "data_load"); + let stack_root = self.get_stack_root(ret_handle); + self.build_store(stack_root, load); + self.builder.position_at_end(lb); + self.build_store(data_ptr, ret_handle); + self.set_root(load, stack_root); + ret_handle = load; let id = data.borrow().table.len().to_string(); data.borrow_mut().table.insert( name.to_string() + &id, PLSymbol { - value: data_ptr, + value: load, pltype: Arc::new(RefCell::new(pltype.clone())), range: Default::default(), refs: None, }, ); // let data_ptr = self.build_struct_gep(ctx_v, (i +2) as u32, "para").unwrap(); - return data_ptr; + // return data_ptr; } - self.alloc_raw(name, pltype, ctx, declare, "DioGC__malloc") + + ret_handle } fn build_struct_gep( &self, @@ -1707,7 +1723,6 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { fn write_bitcode_to_path(&self, path: &Path) -> bool { self.optimize(); // run_immix_pass(self.module); - self.module.strip_debug_info(); self.module.write_bitcode_to_path(path) } fn int_value(&self, ty: &PriType, v: u64, sign_ext: bool) -> ValueHandle { diff --git a/test/main.pi b/test/main.pi index 27b7eea9a..1a385d9b1 100644 --- a/test/main.pi +++ b/test/main.pi @@ -52,15 +52,20 @@ pub fn main() i64 { test_compile_time_reflection(); let a:Iterator; let re = iter::ret_opt(); - let iterator = name(); + // let iterator:Iterator = namet{status:0}; + let iterator:Iterator =name(); let next:Option = iterator.next(); + println!("first next"); if next is i64 { + // next = 1 as i64; + println!("enter is"); let i = next as i64!; println!(i); }else { println!("none"); } next = iterator.next(); + println!("second next"); if next is i64 { let i = next as i64!; println!(i); @@ -68,6 +73,7 @@ pub fn main() i64 { println!("none"); } next = iterator.next(); + println!("third next"); if next is i64 { let i = next as i64!; println!(i); @@ -92,12 +98,23 @@ pub fn main() i64 { } +struct namet { + status: i64; +} + +impl Iterator for namet { + fn next() Option { + self.status = self.status + 1; + return self.status; + } +} + + gen fn name() Iterator { - for let i = 0; i < 10; i = i + 1 { + for let i = 0; i < 2; i = i + 1 { yield return i; } let a = 1; - println!("yield 1"); yield return a; a = a + 1; println!("yield 2"); From 4ffe0dd53287ebeb86847a2270fc344c14ff3870 Mon Sep 17 00:00:00 2001 From: bobxli Date: Mon, 17 Jul 2023 10:41:18 +0800 Subject: [PATCH 06/14] fix: param in generator function --- src/ast/builder/llvmbuilder.rs | 12 +++++++++++- src/ast/builder/mod.rs | 1 + src/ast/builder/no_op_builder.rs | 1 + src/ast/ctx.rs | 1 + src/ast/node/function.rs | 1 + test/main.pi | 11 ++++------- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index ae3819c8b..a68079455 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -1504,6 +1504,10 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { self.build_store(stack_root, load); self.builder.position_at_end(lb); + + let load_again = self.build_load(load, "data_load"); + data.borrow_mut().param_tmp = load_again; + // self.build_store(ret_handle, load_again); self.build_store(data_ptr, ret_handle); self.set_root(load, stack_root); ret_handle = load; @@ -2024,6 +2028,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { value_handle: ValueHandle, alloca: ValueHandle, allocab: BlockHandle, + tp: &PLType, ) { let divar = self.dibuilder.create_parameter_variable( self.discope.get(), @@ -2063,8 +2068,11 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let para_ptr = self .build_struct_gep(ctx_v, (i + 2) as u32, "para") .unwrap(); + child.ctx_flag = CtxFlag::Normal; + let ptr = self.alloc("param_ptr", tp, child, None); + child.ctx_flag = CtxFlag::InGeneratorYield; self.build_store( - para_ptr, + ptr, self.get_llvm_value_handle( &funcvalue .get_nth_param(i as u32) @@ -2072,8 +2080,10 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { .as_any_value_enum(), ), ); + self.build_store(para_ptr, ptr); self.position_at_end_block(origin_bb); + self.build_store(alloca, data.borrow().param_tmp); return; } let funcvalue = self diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index 5af1eface..98e2837a9 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -89,6 +89,7 @@ pub trait IRBuilder<'a, 'ctx> { fnvalue: ValueHandle, alloca: ValueHandle, allocab: BlockHandle, + tp: &PLType, ); fn delete_block(&self, b: BlockHandle); fn finalize_debug(&self); diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index 4c8785e20..6542e5154 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -129,6 +129,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { _fnvalue: super::ValueHandle, _alloca: super::ValueHandle, _allocab: super::BlockHandle, + _tp: &PLType, ) { } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 65038e950..88c150e51 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -116,6 +116,7 @@ pub struct GeneratorCtxData { pub ret_handle: ValueHandle, //handle in setup function pub prev_yield_bb: Option, pub ctx_size_handle: ValueHandle, + pub param_tmp: ValueHandle, } /// # CtxFlag diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 43d8268b2..0e819b231 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -717,6 +717,7 @@ impl FuncDefNode { funcvalue, alloca, allocab, + &basetype, ); let parapltype = tp; child diff --git a/test/main.pi b/test/main.pi index 1a385d9b1..8ee025b55 100644 --- a/test/main.pi +++ b/test/main.pi @@ -53,7 +53,7 @@ pub fn main() i64 { let a:Iterator; let re = iter::ret_opt(); // let iterator:Iterator = namet{status:0}; - let iterator:Iterator =name(); + let iterator:Iterator = name(100, 20); let next:Option = iterator.next(); println!("first next"); if next is i64 { @@ -110,16 +110,13 @@ impl Iterator for namet { } -gen fn name() Iterator { +gen fn name(b:i64, c:i64) Iterator { for let i = 0; i < 2; i = i + 1 { yield return i; } - let a = 1; + let a = b; yield return a; a = a + 1; - println!("yield 2"); - yield return a; - a = a + 1; - println!("yield 3"); yield return a; + yield return c; } From caad0c9b7c3b736c224e95f475a0f2ca4caf174c Mon Sep 17 00:00:00 2001 From: bobxli Date: Mon, 17 Jul 2023 11:24:03 +0800 Subject: [PATCH 07/14] fix: fmt & auto completion --- planglib/std/iter.pi | 19 ---------- src/ast/ctx.rs | 3 +- src/ast/fmt.rs | 12 +++++++ src/nomparser/function.rs | 2 +- test/fmt/test_fmt.pi | 42 ++++++++++++++++++++++ test/main.pi | 73 +++------------------------------------ test/mod1.pi | 1 + test/mod2.pi | 13 +++++++ test/test/iter.pi | 42 ++++++++++++++++++++++ 9 files changed, 117 insertions(+), 90 deletions(-) create mode 100644 test/test/iter.pi diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index 90c800357..f83069358 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -4,22 +4,3 @@ pub trait Iterator { fn next() Option; } -struct name { - t:T; -} - -impl Iterator for name { - fn next() Option { - let a: Option = self.t; - return a; - } -} - - - -pub fn ret_opt() name> { - let b = 1; - let a:Option = b; - let aa:name> = name{t:a}; - return aa; -} diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 88c150e51..4d69cea5c 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -1301,10 +1301,11 @@ impl<'a, 'ctx> Ctx<'a> { fn get_keyword_completions(&self, vmap: &mut FxHashMap) { let keywords = vec![ "if", "else", "while", "for", "return", "struct", "let", "true", "false", "as", "is", + "gen", "yield", ]; let loopkeys = vec!["break", "continue"]; let toplevel = vec![ - "fn", "struct", "const", "use", "impl", "trait", "pub", "type", + "fn", "struct", "const", "use", "impl", "trait", "pub", "type", "gen", ]; if self.father.is_none() { for k in toplevel { diff --git a/src/ast/fmt.rs b/src/ast/fmt.rs index e7ce3ffbc..24959e187 100644 --- a/src/ast/fmt.rs +++ b/src/ast/fmt.rs @@ -150,6 +150,10 @@ impl FmtBuilder { self.dbcolon(); } } + if node.all_import { + self.dbcolon(); + self.asterisk(); + } self.semicolon(); self.enter(); } @@ -341,6 +345,10 @@ impl FmtBuilder { } } pub fn parse_ret_node(&mut self, node: &RetNode) { + if let Some((t, _)) = node.yiel { + self.token(t.get_str()); + self.space(); + } if let Some(value) = &node.value { self.token("return"); self.space(); @@ -455,6 +463,10 @@ impl FmtBuilder { c.format(self); } self.prefix(); + if node.generator { + self.token(TokenType::GENERATOR_MARKER.get_str()); + self.space(); + } if let Some((modi, _)) = node.modifier { self.token(modi.get_str()); self.space(); diff --git a/src/nomparser/function.rs b/src/nomparser/function.rs index 2d6ae867c..ca3bb8a15 100644 --- a/src/nomparser/function.rs +++ b/src/nomparser/function.rs @@ -17,7 +17,7 @@ use super::*; /// function_def = "fn" identifier "(" (typed_identifier (","typed_identifier)*)? ")" type_name (statement_block | newline) ; /// ``` #[test_parser( - "fn f( x: int, y : int ) int { + "gen pub fn f( x: int, y : int ) int { x = x+1; return 0; } diff --git a/test/fmt/test_fmt.pi b/test/fmt/test_fmt.pi index d433598aa..465388503 100644 --- a/test/fmt/test_fmt.pi +++ b/test/fmt/test_fmt.pi @@ -295,3 +295,45 @@ pub fn test_deconstruct() void { return; } +use std::iter::*; +use core::panic::assert; +pub fn test_generator() void { + let iterator: Iterator = generator(100, 20); + let next = iterator.next(); + assert(next is i64); + let i = next as i64!; + assert(i == 0); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 1); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 100); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 101); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 20); + next = iterator.next(); + assert(next is None); + next = iterator.next(); + assert(next is None); + return; +} + +gen fn generator(b: i64, c: i64) Iterator { + for let i = 0; i < 2; i = i + 1 { + yield return i; + } + let a = b; + yield return a; + a = a + 1; + yield return a; + yield return c; +} + diff --git a/test/main.pi b/test/main.pi index 8ee025b55..d7f60b05e 100644 --- a/test/main.pi +++ b/test/main.pi @@ -23,8 +23,9 @@ use pl_test::main; use project1::test::compiletime_reflection::test_compile_time_reflection; use project1::test::deconstruct; use project1::test::st::*; -use std::io; -use std::iter::*; +use project1::test::iter; + + pub fn main() i64 { macros::test_macros(); ifel::test_if_else(); @@ -50,73 +51,7 @@ pub fn main() i64 { fixed_point::test_fixed_point(); generic::ret_generic1(); test_compile_time_reflection(); - let a:Iterator; - let re = iter::ret_opt(); - // let iterator:Iterator = namet{status:0}; - let iterator:Iterator = name(100, 20); - let next:Option = iterator.next(); - println!("first next"); - if next is i64 { - // next = 1 as i64; - println!("enter is"); - let i = next as i64!; - println!(i); - }else { - println!("none"); - } - next = iterator.next(); - println!("second next"); - if next is i64 { - let i = next as i64!; - println!(i); - }else { - println!("none"); - } - next = iterator.next(); - println!("third next"); - if next is i64 { - let i = next as i64!; - println!(i); - }else { - println!("none"); - } - next = iterator.next(); - if next is i64 { - let i = next as i64!; - println!(i); - }else { - println!("none"); - } - next = iterator.next(); - if next is i64 { - let i = next as i64!; - println!(i); - }else { - println!("none"); - } + iter::test_generator(); return 0; } - -struct namet { - status: i64; -} - -impl Iterator for namet { - fn next() Option { - self.status = self.status + 1; - return self.status; - } -} - - -gen fn name(b:i64, c:i64) Iterator { - for let i = 0; i < 2; i = i + 1 { - yield return i; - } - let a = b; - yield return a; - a = a + 1; - yield return a; - yield return c; -} diff --git a/test/mod1.pi b/test/mod1.pi index be14ee286..987be2416 100644 --- a/test/mod1.pi +++ b/test/mod1.pi @@ -7,6 +7,7 @@ pub fn test_mod(args: i64) void { dd.y.y = true; assert(dd.y.y); printi64ln(999999); + mod2::ret_opt(); return; } diff --git a/test/mod2.pi b/test/mod2.pi index 2b2a00902..c7639d1a7 100644 --- a/test/mod2.pi +++ b/test/mod2.pi @@ -7,3 +7,16 @@ pub struct Mod2 { pub y: bool; } + +struct name { + t:T; +} + + + +pub fn ret_opt() name> { + let b = 1; + let a:Option = b; + let aa:name> = name{t:a}; + return aa; +} diff --git a/test/test/iter.pi b/test/test/iter.pi new file mode 100644 index 000000000..92ea437fb --- /dev/null +++ b/test/test/iter.pi @@ -0,0 +1,42 @@ +use std::iter::*; +use core::panic::assert; +pub fn test_generator() void { + let iterator: Iterator = generator(100, 20); + let next = iterator.next(); + assert(next is i64); + let i = next as i64!; + assert(i == 0); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 1); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 100); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 101); + next = iterator.next(); + assert(next is i64); + i = next as i64!; + assert(i == 20); + next = iterator.next(); + assert(next is None); + next = iterator.next(); + assert(next is None); + return; +} + +gen fn generator(b: i64, c: i64) Iterator { + for let i = 0; i < 2; i = i + 1 { + yield return i; + } + let a = b; + yield return a; + a = a + 1; + yield return a; + yield return c; +} + From 442f76d405923a276d2ae06f8a675abe6e903f1c Mon Sep 17 00:00:00 2001 From: bobxli Date: Mon, 17 Jul 2023 11:55:06 +0800 Subject: [PATCH 08/14] chore: better code --- src/ast/node/function.rs | 187 +++-------------------- src/ast/node/function/generator.rs | 231 +++++++++++++++++++++++++++++ src/ast/test.rs | 2 +- 3 files changed, 253 insertions(+), 167 deletions(-) create mode 100644 src/ast/node/function/generator.rs diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 0e819b231..5587f1a3a 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -1,4 +1,3 @@ -use super::cast::get_option_type; use super::interface::TraitBoundNode; use super::node_result::NodeResultBuilder; use super::statement::StatementsNode; @@ -19,6 +18,8 @@ use std::cell::RefCell; use std::sync::atomic::{AtomicI32, Ordering}; use std::vec; + +mod generator; #[node(comment)] pub struct FuncCallNode { pub generic_params: Option>, @@ -557,79 +558,15 @@ impl FuncDefNode { let mut sttp_opt = None; let mut generator_alloca_b = 0; if self.generator { - child.generator_data = Some(Default::default()); - let mut m = LinkedHashMap::default(); - m.insert( - "address".to_owned(), - Field { - index: 1, - typenode: i8ptr.clone().get_typenode(&child.plmod.path), - name: "address".to_owned(), - range: Default::default(), - modifier: None, - }, - ); - let st_tp = STType { - name: fnvalue.get_generator_ctx_name(), - path: ctx.plmod.path.clone(), - fields: m, - range: Default::default(), - doc: vec![], - generic_map: Default::default(), - derives: vec![], - modifier: Some((TokenType::PUB, Default::default())), - body_range: Default::default(), - is_trait: false, - is_tuple: true, - generic_infer_types: Default::default(), - // generic_infer: Default::default(), - methods: Default::default(), - trait_methods_impl: Default::default(), - }; - builder.opaque_struct_type(&st_tp.get_full_name()); - builder.add_body_to_struct_type(&st_tp.get_full_name(), &st_tp, child); - - let rettp = child.run_in_type_mod(&fnvalue, |child, fnvalue| { - let tp = fnvalue.fntype.ret_pltype.get_type(child, builder, false)?; - let r = fnvalue.fntype.ret_pltype.range(); - let f = |ctx| { - r.new_err(ErrorCode::GENERATOR_FN_MUST_RET_ITER) - .add_to_ctx(ctx) - }; - return match &*tp.borrow() { - PLType::Trait(t) => { - if t.name != "Iterator" { - return Err(f(child)); - } - Ok(t.generic_map.first().unwrap().1.clone()) - } - _ => Err(f(child)), - }; - })?; - let rettp = get_option_type(child, builder, rettp)?; - child.rettp = Some(rettp.clone()); - let f = - builder.add_generator_yield_fn(child, &st_tp.get_full_name(), &rettp.borrow()); - child.function = Some(f); - let allocab = builder.append_basic_block(funcvalue, "alloc"); // this is alloca for setup fn - let entry = builder.append_basic_block(funcvalue, "set_up_entry"); // this is enrty for setup fn - builder.position_at_end_block(allocab); - - // builder.build_unconditional_branch(entry); - generator_alloca_b = allocab; - - funcvalue = f; - builder.position_at_end_block(entry); - let ctx_handle = - builder.alloc("___ctx", &PLType::Struct(st_tp.clone()), child, None); - child.generator_data.as_ref().unwrap().borrow_mut().entry_bb = entry; - child - .generator_data - .as_ref() - .unwrap() - .borrow_mut() - .ctx_handle = ctx_handle; - sttp_opt = Some(st_tp); + generator::init_generator( + child, + &i8ptr, + &fnvalue, + builder, + &mut funcvalue, + &mut generator_alloca_b, + &mut sttp_opt, + )?; } builder.build_sub_program( @@ -643,38 +580,12 @@ impl FuncDefNode { let allocab = builder.append_basic_block(funcvalue, "alloc"); let entry = builder.append_basic_block(funcvalue, "entry"); if self.generator { - let address = builder.get_block_address(entry); - let data = child.generator_data.as_ref().unwrap().clone(); - let address_ptr = builder - .build_struct_gep(data.borrow().ctx_handle, 1, "block_address") - .unwrap(); - builder.build_store(address_ptr, address); + generator::save_generator_init_block(builder, child, entry); } let return_block = builder.append_basic_block(funcvalue, "return"); child.position_at_end(entry, builder); let ret_value_ptr = if self.generator { - builder.rm_curr_debug_location(); - let data = child.generator_data.as_ref().unwrap().clone(); - child.position_at_end(data.borrow().entry_bb, builder); - let tp = child.rettp.clone().unwrap(); - - match &*fnvalue - .fntype - .ret_pltype - .get_type(child, builder, true)? - .borrow() - { - PLType::Void => unreachable!(), - other => { - builder.rm_curr_debug_location(); - data.borrow_mut().ret_handle = - builder.alloc("retvalue", other, child, None); - } - } - child.position_at_end(entry, builder); - - let retv = builder.stack_alloc("retvalue", child, &tp.borrow()); - Some(retv) + generator::build_generator_ret(builder, child, &fnvalue, entry)? } else { match &*fnvalue .fntype @@ -700,6 +611,7 @@ impl FuncDefNode { }; child.position_at_end(entry, builder); if self.generator { + // 设置flag,该flag影响alloc逻辑 child.ctx_flag = CtxFlag::InGeneratorYield; } // alloc para @@ -752,72 +664,15 @@ impl FuncDefNode { ); } if self.generator { - child.ctx_flag = CtxFlag::Normal; - - let done = builder.get_cur_basic_block(); - - let mut i = 1; - let mut tps = vec![Arc::new(RefCell::new(i8ptr.clone()))]; - let st_tp = sttp_opt.as_mut().unwrap(); - for (k, v) in &child.generator_data.as_ref().unwrap().borrow().table { - let pltp = PLType::Pointer(v.pltype.to_owned()); - st_tp.fields.insert( - k.to_owned(), - Field { - index: i, - typenode: pltp.get_typenode(&child.plmod.path), - name: k.to_owned(), - range: Default::default(), - modifier: None, - }, - ); - tps.push(Arc::new(RefCell::new(pltp))); - i += 1; - } - let data = child.generator_data.as_ref().unwrap().clone(); - - builder.gen_st_visit_function(child, st_tp, &tps); - builder.position_at_end_block(data.borrow().entry_bb); - let ptr = builder - .build_struct_gep(data.borrow().ret_handle, 1, "ctx_handle_gep") - .unwrap(); - let ptr = builder.bitcast( + return generator::end_generator( child, - ptr, - &PLType::Pointer(Arc::new(RefCell::new(PLType::Pointer(Arc::new( - RefCell::new(PLType::Struct(st_tp.clone())), - ))))), - "casted_ptr", + builder, + i8ptr.clone(), + sttp_opt, + funcvalue, + generator_alloca_b, + allocab, ); - builder.build_store(ptr, data.borrow().ctx_handle); - let ptr = builder - .build_struct_gep(data.borrow().ret_handle, 2, "ctx_handle_gep") - .unwrap(); - unsafe { builder.store_with_aoto_cast(ptr, funcvalue) }; - let ret_load = builder.build_load(data.borrow().ret_handle, "ret_load"); - builder.build_return(Some(ret_load)); - - builder.position_at_end_block(generator_alloca_b); - builder.build_unconditional_branch(data.borrow().entry_bb); - - builder.position_at_end_block(done); - let flag = builder - .build_struct_gep(child.return_block.unwrap().1.unwrap(), 0, "flag") - .unwrap(); - builder.build_store(flag, builder.int_value(&PriType::U64, 1, false)); - builder.build_unconditional_branch(child.return_block.unwrap().0); - // child.add_term_to_previous_yield(builder, done); - - builder.position_at_end_block(allocab); - let ctx_v = builder.get_nth_param(child.function.unwrap(), 0); - let address = builder.build_struct_gep(ctx_v, 1, "block_address").unwrap(); - let address = builder.build_load(address, "block_address"); - builder.build_indirect_br(address, child); - - // FIXME: llvm crash - builder.correct_generator_ctx_malloc_inst(child, &st_tp.get_full_name()); - - return Ok(()); } child.position_at_end(allocab, builder); builder.build_unconditional_branch(entry); diff --git a/src/ast/node/function/generator.rs b/src/ast/node/function/generator.rs new file mode 100644 index 000000000..03db99cf9 --- /dev/null +++ b/src/ast/node/function/generator.rs @@ -0,0 +1,231 @@ +use super::super::cast::get_option_type; + +use crate::ast::builder::BuilderEnum; +use crate::ast::builder::IRBuilder; +use crate::ast::ctx::Ctx; +use crate::ast::diag::ErrorCode; + +use crate::ast::diag::PLDiag; +use crate::ast::node::TypeNode; +use crate::ast::pltype::PriType; +use crate::ast::tokens::TokenType; + +use linked_hash_map::LinkedHashMap; + +use crate::ast::pltype::FNValue; + +use std::cell::RefCell; +use std::sync::Arc; + +use crate::ast::pltype::Field; + +use crate::ast::ctx::CtxFlag; + +use crate::ast::pltype::STType; + +use crate::ast::node::RangeTrait; +use crate::ast::pltype::PLType; + +pub(crate) fn end_generator<'a>( + child: &mut Ctx<'a>, + builder: &BuilderEnum<'a, '_>, + i8ptr: PLType, + mut sttp_opt: Option, + funcvalue: usize, + generator_alloca_b: usize, + allocab: usize, +) -> Result<(), PLDiag> { + child.ctx_flag = CtxFlag::Normal; + let done = builder.get_cur_basic_block(); + let mut i = 1; + + // 1. 产生真实的generator_ctx对应的pltype + let mut tps = vec![Arc::new(RefCell::new(i8ptr))]; + let st_tp = sttp_opt.as_mut().unwrap(); + for (k, v) in &child.generator_data.as_ref().unwrap().borrow().table { + let pltp = PLType::Pointer(v.pltype.to_owned()); + st_tp.fields.insert( + k.to_owned(), + Field { + index: i, + typenode: pltp.get_typenode(&child.plmod.path), + name: k.to_owned(), + range: Default::default(), + modifier: None, + }, + ); + tps.push(Arc::new(RefCell::new(pltp))); + i += 1; + } + let data = child.generator_data.as_ref().unwrap().clone(); + // 2. 生成对应的gc遍历函数 + builder.gen_st_visit_function(child, st_tp, &tps); + builder.position_at_end_block(data.borrow().entry_bb); + // 3. 在setup函数中给返回值(接口)的对应字段赋值,并返回 + let ptr = builder + .build_struct_gep(data.borrow().ret_handle, 1, "ctx_handle_gep") + .unwrap(); + let ptr = builder.bitcast( + child, + ptr, + &PLType::Pointer(Arc::new(RefCell::new(PLType::Pointer(Arc::new( + RefCell::new(PLType::Struct(st_tp.clone())), + ))))), + "casted_ptr", + ); + builder.build_store(ptr, data.borrow().ctx_handle); + let ptr = builder + .build_struct_gep(data.borrow().ret_handle, 2, "ctx_handle_gep") + .unwrap(); + unsafe { builder.store_with_aoto_cast(ptr, funcvalue) }; + let ret_load = builder.build_load(data.borrow().ret_handle, "ret_load"); + builder.build_return(Some(ret_load)); + + // 4. 生成yield函数的done分支代码 + builder.position_at_end_block(generator_alloca_b); + builder.build_unconditional_branch(data.borrow().entry_bb); + builder.position_at_end_block(done); + let flag = builder + .build_struct_gep(child.return_block.unwrap().1.unwrap(), 0, "flag") + .unwrap(); + builder.build_store(flag, builder.int_value(&PriType::U64, 1, false)); + builder.build_unconditional_branch(child.return_block.unwrap().0); + + // 5. 生成yield函数的跳转代码 + builder.position_at_end_block(allocab); + let ctx_v = builder.get_nth_param(child.function.unwrap(), 0); + let address = builder.build_struct_gep(ctx_v, 1, "block_address").unwrap(); + let address = builder.build_load(address, "block_address"); + builder.build_indirect_br(address, child); + + // 6. 用最终的generator_ctx大小修正之前的malloc语句 + builder.correct_generator_ctx_malloc_inst(child, &st_tp.get_full_name()); + Ok(()) +} + +/// # init_generator +/// +/// 这个函数干几件事情: +/// +/// 1. 创建generator的setup函数,该函数产生实际的generator结构体 +/// 2. 创建generator_ctx结构体 +/// 3. 创建generator_yield函数,替代上下文中函数为yield函数 +/// 4. 将generator的基础信息写入上下文中,方便以后使用 +pub(crate) fn init_generator<'a>( + child: &mut Ctx<'a>, + i8ptr: &PLType, + fnvalue: &FNValue, + builder: &BuilderEnum<'a, '_>, + funcvalue: &mut usize, + generator_alloca_b: &mut usize, + sttp_opt: &mut Option, +) -> Result<(), PLDiag> { + child.generator_data = Some(Default::default()); + let mut m = LinkedHashMap::default(); + m.insert( + "address".to_owned(), + Field { + index: 1, + typenode: i8ptr.clone().get_typenode(&child.plmod.path), + name: "address".to_owned(), + range: Default::default(), + modifier: None, + }, + ); + let st_tp = STType { + name: fnvalue.get_generator_ctx_name(), + path: child.plmod.path.clone(), + fields: m, + range: Default::default(), + doc: vec![], + generic_map: Default::default(), + derives: vec![], + modifier: Some((TokenType::PUB, Default::default())), + body_range: Default::default(), + is_trait: false, + is_tuple: true, + generic_infer_types: Default::default(), + // generic_infer: Default::default(), + methods: Default::default(), + trait_methods_impl: Default::default(), + }; + builder.opaque_struct_type(&st_tp.get_full_name()); + builder.add_body_to_struct_type(&st_tp.get_full_name(), &st_tp, child); + let rettp = child.run_in_type_mod(fnvalue, |child, fnvalue| { + let tp = fnvalue.fntype.ret_pltype.get_type(child, builder, false)?; + let r = fnvalue.fntype.ret_pltype.range(); + let f = |ctx| { + r.new_err(ErrorCode::GENERATOR_FN_MUST_RET_ITER) + .add_to_ctx(ctx) + }; + return match &*tp.borrow() { + PLType::Trait(t) => { + if t.name != "Iterator" { + return Err(f(child)); + } + Ok(t.generic_map.first().unwrap().1.clone()) + } + _ => Err(f(child)), + }; + })?; + let rettp = get_option_type(child, builder, rettp)?; + child.rettp = Some(rettp.clone()); + let f = builder.add_generator_yield_fn(child, &st_tp.get_full_name(), &rettp.borrow()); + child.function = Some(f); + let allocab = builder.append_basic_block(*funcvalue, "alloc"); + let entry = builder.append_basic_block(*funcvalue, "set_up_entry"); + builder.position_at_end_block(allocab); + *generator_alloca_b = allocab; + *funcvalue = f; + builder.position_at_end_block(entry); + let ctx_handle = builder.alloc("___ctx", &PLType::Struct(st_tp.clone()), child, None); + child.generator_data.as_ref().unwrap().borrow_mut().entry_bb = entry; + child + .generator_data + .as_ref() + .unwrap() + .borrow_mut() + .ctx_handle = ctx_handle; + *sttp_opt = Some(st_tp); + Ok(()) +} + +pub(crate) fn save_generator_init_block<'a>( + builder: &BuilderEnum<'a, '_>, + child: &mut Ctx<'a>, + entry: usize, +) { + let address = builder.get_block_address(entry); + let data = child.generator_data.as_ref().unwrap().clone(); + let address_ptr = builder + .build_struct_gep(data.borrow().ctx_handle, 1, "block_address") + .unwrap(); + builder.build_store(address_ptr, address); +} + +pub(crate) fn build_generator_ret<'a>( + builder: &BuilderEnum<'a, '_>, + child: &mut Ctx<'a>, + fnvalue: &FNValue, + entry: usize, +) -> Result, PLDiag> { + builder.rm_curr_debug_location(); + let data = child.generator_data.as_ref().unwrap().clone(); + child.position_at_end(data.borrow().entry_bb, builder); + let tp = child.rettp.clone().unwrap(); + match &*fnvalue + .fntype + .ret_pltype + .get_type(child, builder, true)? + .borrow() + { + PLType::Void => unreachable!(), + other => { + builder.rm_curr_debug_location(); + data.borrow_mut().ret_handle = builder.alloc("retvalue", other, child, None); + } + } + child.position_at_end(entry, builder); + let retv = builder.stack_alloc("retvalue", child, &tp.borrow()); + Ok(Some(retv)) +} diff --git a/src/ast/test.rs b/src/ast/test.rs index 0fa24470e..ab6a30d90 100644 --- a/src/ast/test.rs +++ b/src/ast/test.rs @@ -92,7 +92,7 @@ fn test_diag_expect(comp: (&String, &Vec)) { expected.assert_eq(&format!("{:#?}", diag)); } -fn sanitize_diag(diag: &Vec) -> Vec { +fn sanitize_diag(diag: &[super::diag::PLDiag]) -> Vec { let mut diag = diag .iter() .map(|d| { From e2391ad053d27d1c993dbead3c2ad075ba29bfce Mon Sep 17 00:00:00 2001 From: bobxli Date: Mon, 17 Jul 2023 15:18:43 +0800 Subject: [PATCH 09/14] feat: supports symbol rename --- src/ast/ctx/references.rs | 6 ++++- src/lsp/helpers.rs | 19 ++++++++++++++++ src/lsp/lspserver.rs | 46 +++++++++++++++++++++++++++++---------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/ast/ctx/references.rs b/src/ast/ctx/references.rs index ca34d2918..1c1c5fe6f 100644 --- a/src/ast/ctx/references.rs +++ b/src/ast/ctx/references.rs @@ -56,7 +56,11 @@ impl<'a> Ctx<'a> { /// For details, see the module documentation. pub fn set_field_refs(&self, pltype: Arc>, f: &Field, range: Range) { self.set_glob_refs( - &format!("{}..{}", &pltype.borrow().get_full_elm_name(), f.name), + &format!( + "{}..{}", + &pltype.borrow().get_full_elm_name_without_generic(), + f.name + ), range, ); } diff --git a/src/lsp/helpers.rs b/src/lsp/helpers.rs index 4226e279c..021bb5a49 100644 --- a/src/lsp/helpers.rs +++ b/src/lsp/helpers.rs @@ -57,6 +57,25 @@ pub fn send_references( .unwrap(); } +pub fn send_rename( + sender: &Sender, + id: RequestId, + texts: std::collections::HashMap>, +) { + sender + .send(Message::Response(lsp_server::Response::new_ok( + id, + Some( + serde_json::to_value(lsp_types::WorkspaceEdit { + changes: Some(texts), + ..Default::default() + }) + .unwrap(), + ), + ))) + .unwrap(); +} + pub fn send_format(sender: &Sender, id: RequestId, texts: Vec) { sender .send(Message::Response(lsp_server::Response::new_ok( diff --git a/src/lsp/lspserver.rs b/src/lsp/lspserver.rs index 10d053d8e..b52bdae27 100644 --- a/src/lsp/lspserver.rs +++ b/src/lsp/lspserver.rs @@ -1,12 +1,6 @@ -//! # lsp -//! pivot-lang language server entry -//! current features: -//! - diagnostics -//! - completion -//! - goto definition -//! - find references use std::{ cell::{Cell, RefCell}, + collections::HashMap, error::Error, sync::{Arc, Mutex}, thread::available_parallelism, @@ -18,8 +12,8 @@ use lsp_types::{ notification::{DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument}, request::{ Completion, DocumentSymbolRequest, Formatting, GotoDefinition, HoverRequest, - InlayHintRequest, References, SemanticTokensFullDeltaRequest, SemanticTokensFullRequest, - SignatureHelpRequest, + InlayHintRequest, References, Rename, SemanticTokensFullDeltaRequest, + SemanticTokensFullRequest, SignatureHelpRequest, }, Diagnostic, Hover, HoverContents, InitializeParams, MarkedString, OneOf, SemanticTokens, SemanticTokensDelta, SemanticTokensOptions, ServerCapabilities, SignatureHelp, @@ -29,7 +23,7 @@ use lsp_types::{ use lsp_server::{Connection, Message}; use mem_docs::MemDocs; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; #[cfg(not(target_arch = "wasm32"))] use threadpool::ThreadPool; @@ -50,7 +44,7 @@ use crate::{ dispatcher::Dispatcher, helpers::{ send_completions, send_diagnostics, send_doc_symbols, send_format, send_goto_def, - send_hints, send_hover, send_references, send_semantic_tokens, + send_hints, send_hover, send_references, send_rename, send_semantic_tokens, send_semantic_tokens_edit, send_signature_help, url_to_path, }, mem_docs::MemDocsInput, @@ -107,6 +101,7 @@ pub fn start_lsp() -> Result<(), Box> { }, ), ), + rename_provider: Some(OneOf::Left(true)), ..Default::default() }) .unwrap(); @@ -280,6 +275,35 @@ fn main_loop( }); } }) + .on::(|id, params| { + let uri = url_to_path(params.text_document_position.text_document.uri); + let pos = Pos::from_diag_pos(¶ms.text_document_position.position); + docin.set_file(&mut db).to(uri); + docin.set_action(&mut db).to(ActionType::FindReferences); + docin.set_params(&mut db).to(Some((pos, None))); + compile_dry(&db, docin); + let refs = compile_dry::accumulated::(&db, docin); + let sender = connection.sender.clone(); + let mut rf: HashMap> = Default::default(); + let mut set: FxHashMap> = + Default::default(); + for r in refs { + for r in r.clone().iter() { + let url = r.uri.clone(); + let edit = lsp_types::TextEdit::new(r.range, params.new_name.clone()); + if set.get(&url).is_some() && set.get(&url).unwrap().contains(&r.range) { + continue; + } + set.entry(url.clone()) + .or_insert(FxHashSet::default()) + .insert(r.range); + rf.entry(url).or_insert(vec![]).push(edit); + } + } + pool.execute(move || { + send_rename(&sender, id, rf); + }); + }) .on::(|id, params| { let doc = params.text_document_position_params; let uri = url_to_path(doc.text_document.uri); From e665482a9baa0d1161c8d83339928129acd1522e Mon Sep 17 00:00:00 2001 From: bobxli Date: Tue, 18 Jul 2023 15:07:59 +0800 Subject: [PATCH 10/14] fix: get type deep not handle ptr --- planglib/core/gc.pi | 7 +- planglib/std/__private.pi | 3 +- planglib/std/cols/arr.pi | 51 +++++++++++ src/ast/builder/llvmbuilder.rs | 6 ++ src/ast/builder/mod.rs | 3 + src/ast/builder/no_op_builder.rs | 4 + src/ast/ctx.rs | 4 - src/ast/ctx/builtins.rs | 153 ++++++++++++++++++++++++++++++- src/ast/node/mod.rs | 1 + src/ast/pltype.rs | 3 + test/main.pi | 11 +++ 11 files changed, 239 insertions(+), 7 deletions(-) create mode 100644 planglib/std/cols/arr.pi diff --git a/planglib/core/gc.pi b/planglib/core/gc.pi index 0d4483ad7..b8d9b641c 100644 --- a/planglib/core/gc.pi +++ b/planglib/core/gc.pi @@ -1,9 +1,14 @@ -pub fn DioGC__malloc(size: i64, obj_type: u8) *u8; +fn DioGC__malloc(size: i64, obj_type: u8) *u8; pub fn DioGC__collect() void; pub fn DioGC__malloc_no_collect(size: i64, obj_type: u8) *u8; + +pub fn malloc() *u8 { + return DioGC__malloc(sizeof(), gc_type()); +} + pub struct string { pub len: i64; pub byte_len: i64; diff --git a/planglib/std/__private.pi b/planglib/std/__private.pi index 9ab26b33f..0dee40439 100644 --- a/planglib/std/__private.pi +++ b/planglib/std/__private.pi @@ -1,3 +1,4 @@ use std::io; use std::stdbuiltin; -use std::iter; \ No newline at end of file +use std::iter; +use std::cols::arr; \ No newline at end of file diff --git a/planglib/std/cols/arr.pi b/planglib/std/cols/arr.pi new file mode 100644 index 000000000..7c68b1886 --- /dev/null +++ b/planglib/std/cols/arr.pi @@ -0,0 +1,51 @@ +use std::iter::*; + +pub struct Array { + data:*T; + size:u32; + len:u32; +} + +pub fn new() Array { + return Array { + size:0 as u32, + len:0 as u32 + }; +} + +impl Array { + pub fn push(t:T) void { + if self.size == 0 { + let data = unsafe_cast(gc::malloc()); + self.data = data; + // self.data = + } + return; + } +} + +fn push(ss:T, t:T) void { + ss = t; + return; +} + +fn push2(ss:name, t:T) void { + ss.t = t; + return; +} + +struct name { + t:T; +} + + + + + + +// macro new_arr { +// ($name:@id) => { + +// }; +// } + diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index a68079455..70d818d3b 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -1464,6 +1464,12 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { false, ); } + fn sizeof(&self, + pltype: &PLType, + ctx: &mut Ctx<'a>, + ) -> u64 { + self.targetmachine.get_target_data().get_store_size(&self.get_basic_type_op(pltype, ctx).unwrap()) + } fn alloc( &self, name: &str, diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index 98e2837a9..7a0e4c0b5 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -234,6 +234,9 @@ pub trait IRBuilder<'a, 'ctx> { unsafe fn store_with_aoto_cast(&self, ptr: ValueHandle, value: ValueHandle); fn stack_alloc(&self, name: &str, ctx: &mut Ctx<'a>, tp: &PLType) -> ValueHandle; fn correct_generator_ctx_malloc_inst(&self, ctx: &mut Ctx<'a>, name: &str); + fn sizeof(&self, + pltype: &PLType, + ctx: &mut Ctx<'a>,)->u64; } pub type ValueHandle = usize; diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index 6542e5154..ea3a70fe4 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -496,4 +496,8 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { } fn correct_generator_ctx_malloc_inst(&self, _ctx: &mut Ctx<'a>, _name: &str) {} + + fn sizeof(&self,_pltype: &PLType,_ctx: &mut Ctx<'a>,) -> u64 { + 0 + } } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 4d69cea5c..488e1b1c8 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -1,6 +1,5 @@ use super::builder::BlockHandle; use super::builder::ValueHandle; -use super::diag::DiagCode; use super::diag::ErrorCode; use super::diag::PLDiag; @@ -964,9 +963,6 @@ impl<'a, 'ctx> Ctx<'a> { if let Some(src) = &self.temp_source { dia.set_source(src); } - if dia.get_diag_code() == DiagCode::Err(ErrorCode::UNDEFINED_TYPE) { - eprintln!("add diag: {}", dia.get_msg()); - } let dia2 = dia.clone(); self.errs.borrow_mut().insert(dia); dia2 diff --git a/src/ast/ctx/builtins.rs b/src/ast/ctx/builtins.rs index fe9d8fc13..71ae0bcd7 100644 --- a/src/ast/ctx/builtins.rs +++ b/src/ast/ctx/builtins.rs @@ -1,9 +1,10 @@ //! # builtins //! //! compiler builtin methods, mostly used for static reflection -use crate::ast::{builder::no_op_builder::NoOpBuilder, node::RangeTrait, pltype::PlaceHolderType}; +use crate::ast::{builder::no_op_builder::NoOpBuilder, node::{RangeTrait, node_result::NodeResultBuilder}, pltype::{PlaceHolderType, PriType}}; use std::{cell::RefCell, collections::HashMap, sync::Arc}; +use immix::IntEnum; use lazy_static::lazy_static; use crate::ast::{ @@ -28,6 +29,9 @@ lazy_static! { mp.insert(usize::MAX - 2, emit_for_fields); mp.insert(usize::MAX - 3, emit_match_type); mp.insert(usize::MAX - 4, emit_name_of); + mp.insert(usize::MAX - 5, emit_unsafe_cast); + mp.insert(usize::MAX - 6, emit_sizeof); + mp.insert(usize::MAX - 7, emit_gc_type); mp }; pub static ref BUILTIN_FN_SNIPPET_MAP: HashMap = { @@ -42,6 +46,9 @@ lazy_static! { r#"match_type<${1:T}>(${2:t}, { ${3:_value} })$0"#.to_owned(), ); mp.insert(usize::MAX - 4, r#"fullnameof(${1:t})$0"#.to_owned()); + mp.insert(usize::MAX - 5, r#"unsafe_cast<${1:T}>(${2:t})$0"#.to_owned()); + mp.insert(usize::MAX - 6, r#"sizeof<${1:T}>()$0"#.to_owned()); + mp.insert(usize::MAX - 7, r#"gc_type<${1:T}>()$0"#.to_owned()); mp }; pub static ref BUILTIN_FN_NAME_MAP: HashMap<&'static str, ValueHandle> = { @@ -50,10 +57,154 @@ lazy_static! { mp.insert("forfields", usize::MAX - 2); mp.insert("match_type", usize::MAX - 3); mp.insert("nameof", usize::MAX - 4); + mp.insert("unsafe_cast", usize::MAX - 5); + mp.insert("sizeof", usize::MAX - 6); + mp.insert("gc_type", usize::MAX - 7); mp }; } + +fn emit_sizeof<'a, 'b>( + f: &mut FuncCallNode, + ctx: &'b mut Ctx<'a>, + builder: &'b BuilderEnum<'a, '_>, +) -> NodeResult { + if f.paralist.len() != 0 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) + .add_to_ctx(ctx)); + } + if f.generic_params.is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = f.generic_params.as_ref().unwrap(); + generic.emit_highlight(ctx); + if generic.generics.len() != 1 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + if generic.generics[0].is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = generic.generics[0] + .as_ref() + .unwrap() + .get_type(ctx, builder, true)?; + let size = builder.sizeof(&generic.borrow(), ctx); + let b = builder.int_value(&PriType::I64, size, true); + return b + .new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::I64)))) + .set_const() + .to_result(); + +} + + +fn emit_gc_type<'a, 'b>( + f: &mut FuncCallNode, + ctx: &'b mut Ctx<'a>, + builder: &'b BuilderEnum<'a, '_>, +) -> NodeResult { + if f.paralist.len() != 0 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) + .add_to_ctx(ctx)); + } + if f.generic_params.is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = f.generic_params.as_ref().unwrap(); + generic.emit_highlight(ctx); + if generic.generics.len() != 1 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + if generic.generics[0].is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = generic.generics[0] + .as_ref() + .unwrap() + .get_type(ctx, builder, true)?; + let size = generic.borrow().get_immix_type(); + let b = builder.int_value(&PriType::U8, size.int_value() as _, true); + return b + .new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::U8)))) + .set_const() + .to_result(); + +} + + +fn emit_unsafe_cast<'a, 'b>( + f: &mut FuncCallNode, + ctx: &'b mut Ctx<'a>, + builder: &'b BuilderEnum<'a, '_>, +) -> NodeResult { + if f.paralist.len() != 1 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) + .add_to_ctx(ctx)); + } + if f.generic_params.is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = f.generic_params.as_ref().unwrap(); + generic.emit_highlight(ctx); + if generic.generics.len() != 1 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let st = f.paralist[0].emit(ctx, builder)?; + let v = st.get_value().unwrap(); + if generic.generics[0].is_none() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_NOT_FOUND) + .add_to_ctx(ctx)); + } + let generic = generic.generics[0] + .as_ref() + .unwrap() + .get_type(ctx, builder, true)?; + if !matches!(&*v.get_ty().borrow(),PLType::Pointer(_)) { + return Err(f.paralist[0] + .range() + .new_err(crate::ast::diag::ErrorCode::NOT_A_POINTER) + .add_to_ctx(ctx)); + } + let ty = PLType::Pointer(generic); + let re = builder.bitcast(ctx, v.get_value(), &ty, "unsafe_casted"); + re.new_output(Arc::new(RefCell::new(ty))).to_result() + +} + + fn emit_name_of<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, diff --git a/src/ast/node/mod.rs b/src/ast/node/mod.rs index 521a707b6..1924ff7fc 100644 --- a/src/ast/node/mod.rs +++ b/src/ast/node/mod.rs @@ -311,6 +311,7 @@ impl<'a, 'ctx> Ctx<'a> { let ty = get_type_deep(ty); let expect = get_type_deep(expect); if ty != expect { + // eprintln!("{:?}\n-------------\n{:?}", ty, expect); let handle = self.up_cast(expect.clone(), ty, expectrange, range, value, builder)?; return Ok(NodeOutput::new_value(NodeValue::new_const(handle, expect))); diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 14d0ed002..55528add0 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -348,6 +348,9 @@ pub fn get_type_deep(pltype: Arc>) -> Arc> { pltype.clone() } } + PLType::Pointer(p) =>{ + Arc::new(RefCell::new(PLType::Pointer( get_type_deep(p.clone())))) + } _ => pltype.clone(), } } diff --git a/test/main.pi b/test/main.pi index d7f60b05e..966bc0e71 100644 --- a/test/main.pi +++ b/test/main.pi @@ -55,3 +55,14 @@ pub fn main() i64 { return 0; } + +fn push3(ss:name2, t:T, tt:*T) void { + ss.t = &t; + tt=&t; + return; +} + +struct name2 { + t:*T; +} + From d6f656de679b02db426e1bf9e459236fcb4738a2 Mon Sep 17 00:00:00 2001 From: bobxli Date: Wed, 19 Jul 2023 14:11:38 +0800 Subject: [PATCH 11/14] feat: better array --- planglib/core/builtin.pi | 2 + planglib/std/cols/arr.pi | 74 +++++++++------ src/ast/builder/llvmbuilder.rs | 156 ++++++++++++++++++++----------- src/ast/builder/mod.rs | 1 + src/ast/builder/no_op_builder.rs | 1 + src/ast/ctx.rs | 6 ++ src/ast/ctx/builtins.rs | 98 +++++++++++++++++++ src/ast/diag.rs | 4 +- src/ast/fmt.rs | 13 ++- src/ast/node/primary.rs | 3 +- src/ast/node/types.rs | 87 ++++++++--------- src/ast/pltype.rs | 41 ++++---- src/nomparser/array.rs | 11 ++- src/nomparser/types.rs | 11 +-- test/fmt/test_fmt.pi | 10 +- test/main.pi | 24 ++--- test/test/map.pi | 2 +- test/test/st.pi | 23 ++++- 18 files changed, 392 insertions(+), 175 deletions(-) diff --git a/planglib/core/builtin.pi b/planglib/core/builtin.pi index c4862cb61..5212a1608 100644 --- a/planglib/core/builtin.pi +++ b/planglib/core/builtin.pi @@ -19,3 +19,5 @@ impl Option { return f(v); } } + +pub use core::gc::string; diff --git a/planglib/std/cols/arr.pi b/planglib/std/cols/arr.pi index 7c68b1886..be61c61bf 100644 --- a/planglib/std/cols/arr.pi +++ b/planglib/std/cols/arr.pi @@ -1,51 +1,71 @@ use std::iter::*; +use core::panic::*; +use std::io; pub struct Array { - data:*T; - size:u32; + data:[T]; len:u32; } pub fn new() Array { - return Array { - size:0 as u32, + let arr_raw = [T*4;]; + let arr = Array { len:0 as u32 }; + arr.data = arr_raw; + return arr; } impl Array { pub fn push(t:T) void { - if self.size == 0 { - let data = unsafe_cast(gc::malloc()); - self.data = data; - // self.data = + if self.len as i64 + 1 > arr_len(self.data) { + let new_data = [T*(arr_len(self.data) * 2);]; + arr_copy(self.data, new_data, arr_len(self.data)); + self.data = new_data; + self.data[self.len as i64] = t; + self.len = self.len + 1; + }else { + self.data[self.len as i64] = t; + self.len = self.len + 1; } return; } + pub fn pop() T { + self.len = self.len - 1; + return self.data[self.len as i64]; + } + pub fn len() u32 { + return self.len; + } + pub fn get(i:i64) T { + self.check_idx(i); + return self.data[i]; + } + fn check_idx(i:i64) void { + if i >= arr_len(self.data) { + io::print_s("Array index out of bounds"); + pl_panic(); + } + return; + } + pub fn set(i:i64, t:T) void { + self.check_idx(i); + self.data[i] = t; + return; + } } -fn push(ss:T, t:T) void { - ss = t; - return; -} -fn push2(ss:name, t:T) void { - ss.t = t; - return; -} -struct name { - t:T; +pub fn from_slice(slice:[T]) Array { + let arr = Array { + len:arr_len(slice) as u32 + }; + arr.data = slice; + return arr; } +// impl Iterator for Array { - - - -// macro new_arr { -// ($name:@id) => { - -// }; -// } - +// } \ No newline at end of file diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 70d818d3b..49d5d06be 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -35,7 +35,7 @@ use rustc_hash::FxHashMap; use crate::ast::{ ctx::{CtxFlag, PLSymbol}, diag::PLDiag, - pltype::{ClosureType, TraitImplAble}, + pltype::{ClosureType, TraitImplAble, get_type_deep}, }; use super::{ @@ -201,24 +201,9 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { declare: Option, malloc_fn: &str, ) -> ValueHandle { - let td = self.targetmachine.get_target_data(); let builder = self.builder; builder.unset_current_debug_location(); - let bt = self.get_basic_type_op(pltype, ctx).unwrap(); let (p, stack_root, _) = self.gc_malloc(name, ctx, pltype, malloc_fn); - // TODO: force user to manually init all structs, so we can remove this memset - let size_val = self - .context - .i64_type() - .const_int(td.get_store_size(&bt), false); - self.builder - .build_memset( - p, - td.get_abi_alignment(&bt), - self.context.i8_type().const_zero(), - size_val, - ) - .unwrap(); if let PLType::Struct(tp) = pltype { let f = self.get_or_insert_st_visit_fn_handle(&p, tp); let i = self.builder.build_ptr_to_int( @@ -276,7 +261,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let obj_type = tp.get_immix_type().int_value(); let f = self.get_malloc_f(ctx, malloc_fn); let llvmtp = self.get_basic_type_op(tp, ctx).unwrap(); - let tp = self + let immix_tp = self .context .i8_type() .const_int(tp.get_immix_type().int_value() as u64, false); @@ -304,15 +289,52 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { } let heapptr = self .builder - .build_call(f, &[size.into(), tp.into()], &format!("heapptr_{}", name)) + .build_call(f, &[size.into(), immix_tp.into()], &format!("heapptr_{}", name)) .try_as_basic_value() .left() .unwrap(); + let casted_result = self.builder.build_bitcast( heapptr.into_pointer_value(), llvmtp.ptr_type(AddressSpace::default()), name, ); + + // TODO: force user to manually init all structs, so we can remove this memset + let size_val = self + .context + .i64_type() + .const_int(td.get_store_size(&llvmtp), false); + self.builder + .build_memset( + casted_result.into_pointer_value(), + td.get_abi_alignment(&llvmtp), + self.context.i8_type().const_zero(), + size_val, + ) + .unwrap(); + + if let PLType::Arr(arr) = tp { + if arr.size_handle != 0 { + let f = self.get_malloc_f(ctx, "DioGC__malloc_no_collect"); + let etp= self.get_basic_type_op(&arr.element_type.borrow(), ctx).unwrap(); + let size = td.get_store_size(&etp); + let size = self.context.i64_type().const_int(size, false); + let arr_len = self.get_llvm_value(arr.size_handle).unwrap().into_int_value(); + let arr_size = self.builder.build_int_mul(arr_len, size, "arr_size"); + let arr_size = self.builder.build_int_z_extend_or_bit_cast(arr_size, self.context.i64_type(), "arr_size"); + let len_ptr = self.builder.build_struct_gep(casted_result.into_pointer_value(), 2, "arr_len").unwrap(); + self.builder.build_store(len_ptr, arr_len); + let arr_ptr = self.builder.build_struct_gep(casted_result.into_pointer_value(), 1, "arr_ptr").unwrap(); + let arr_space = self.builder.build_call(f, &[arr_size.into(), self + .context + .i8_type() + .const_int(immix::ObjectType::Atomic.int_value() as u64, false).into()], "arr_space").try_as_basic_value().left().unwrap(); + let arr_space = self.builder.build_bitcast(arr_space.into_pointer_value(), etp.ptr_type(AddressSpace::default()), "arr_space"); + self.builder.build_store(arr_ptr, arr_space); + } + } + self.builder.position_at_end(alloca); let stack_ptr = self .builder @@ -435,9 +457,9 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let len = self.handle_table.borrow().len(); let nh = match self.handle_reverse_table.borrow().get(value) { Some(handle) => *handle, - None => len, + None => len + 1, }; - if nh == len { + if nh == len + 1 { self.handle_table.borrow_mut().insert(nh, *value); self.handle_reverse_table.borrow_mut().insert(*value, nh); } @@ -474,7 +496,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let ptrtp = self.arr_type(v, ctx).ptr_type(AddressSpace::default()); let ty = ptrtp.get_element_type().into_struct_type(); let ftp = self.mark_fn_tp(ptrtp); - let arr_tp = ty.get_field_type_at_index(1).unwrap().into_array_type(); + let arr_tp = ty.get_field_type_at_index(1).unwrap(); let fname = &(arr_tp.to_string() + "@" + &ctx.plmod.path); if let Some(f) = self.module.get_function(fname) { return f; @@ -482,19 +504,19 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let f = self .module .add_function(fname, ftp, Some(Linkage::External)); - // the array is a struct, the first field is the visit function, the second field is the real array + // the array is a struct, the first field is the visit function, + // the second field is the real array, the third field is it's length // array struct it self is the first parameter // the other three parameters are the visit function for different type let bb = self.context.append_basic_block(f, "entry"); self.builder.position_at_end(bb); let arr = f.get_nth_param(0).unwrap().into_pointer_value(); - let arr = self.builder.build_struct_gep(arr, 1, "arr").unwrap(); - let loop_var = self.builder.build_alloca(self.context.i32_type(), "i"); + let real_arr_raw = self.builder.build_struct_gep(arr, 1, "arr").unwrap(); + let real_arr = self.builder.build_load(real_arr_raw, "loaded_arr").into_pointer_value(); + let loop_var = self.builder.build_alloca(self.context.i64_type(), "i"); // arr is the real array - let arr_len = self - .context - .i32_type() - .const_int(arr_tp.len() as u64, false); + let arr_len =self.builder.build_struct_gep(arr, 2, "arr_len").unwrap(); + let arr_len = self.builder.build_load(arr_len, "arr_len").into_int_value(); // generate a loop, iterate the real array, and do nothing let condbb = self.context.append_basic_block(f, "cond"); self.builder.build_unconditional_branch(condbb); @@ -510,8 +532,8 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let i = self.builder.build_load(loop_var, "i").into_int_value(); let elm = unsafe { self.builder.build_in_bounds_gep( - arr, - &[self.context.i64_type().const_int(0, false), i], + real_arr, + &[i], "elm", ) }; @@ -521,7 +543,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { // which is stored in the first field of the struct let visit_complex_f = get_nth_mark_fn(f, 3); let visit_trait_f = get_nth_mark_fn(f, 4); - match &*v.element_type.borrow() { + match &*get_type_deep( v.element_type.clone()).borrow() { PLType::Arr(_) | PLType::Struct(_) => { let casted = self.builder.build_bitcast(elm, i8ptrtp, "casted_arg"); // call the visit_complex function @@ -547,10 +569,15 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { let i = self.builder.build_load(loop_var, "i").into_int_value(); let i = self .builder - .build_int_add(i, self.context.i32_type().const_int(1, false), "i"); + .build_int_add(i, self.context.i64_type().const_int(1, false), "i"); self.builder.build_store(loop_var, i); self.builder.build_unconditional_branch(condbb); self.builder.position_at_end(endbb); + + // call the visit_ptr function + let casted = self.builder.build_bitcast(real_arr_raw, i8ptrtp, "casted_arg"); + self.builder + .build_call(get_nth_mark_fn(f, 2), &[visitor.into(), casted.into()], "call"); self.builder.build_return(None); if let Some(currentbb) = currentbb { self.builder.position_at_end(currentbb); @@ -792,8 +819,9 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { self.context.i64_type().as_basic_type_enum(), self.get_basic_type_op(&arrtp.element_type.borrow(), ctx) .unwrap() - .array_type(arrtp.size) + .ptr_type(Default::default()) .as_basic_type_enum(), + self.context.i64_type().as_basic_type_enum(), ], false, ) @@ -861,7 +889,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { .get_basic_type_op(&arr.element_type.borrow(), ctx) .unwrap(); let arr_st_tp = self.arr_type(arr, ctx).into_struct_type(); - let size = td.get_bit_size(etp) * arr.size as u64; + let size = td.get_bit_size(etp) * 0; let align = td.get_preferred_alignment(etp); let st_size = td.get_bit_size(&arr_st_tp); let vtabledi = self.get_ditype(&PLType::Primitive(PriType::U64), ctx)?; @@ -879,7 +907,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { ); let arrdi = self .dibuilder - .create_array_type(elemdi, size, align, &[(0..arr.size as i64)]) + .create_array_type(elemdi, size, align, &[(0..0)]) .as_type(); let offset = td.offset_of_element(&arr_st_tp, 1).unwrap(); let arrtp = self.dibuilder.create_member_type( @@ -1238,6 +1266,30 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { } *self.optimized.borrow_mut() = true; } + + fn try_load2var_inner(&self, v: usize) -> Result { + let handle = v; + let v = self.get_llvm_value(handle).unwrap(); + if !v.is_pointer_value() { + Ok(match v { + AnyValueEnum::ArrayValue(_) + | AnyValueEnum::IntValue(_) + | AnyValueEnum::FloatValue(_) + | AnyValueEnum::PointerValue(_) + | AnyValueEnum::StructValue(_) + | AnyValueEnum::VectorValue(_) => handle, + AnyValueEnum::FunctionValue(f) => { + return Ok(self.get_llvm_value_handle(&f.as_global_value().as_any_value_enum())); + } + _ => return Err(()), + }) + } else { + Ok(self.build_load( + self.get_llvm_value_handle(&v.into_pointer_value().as_any_value_enum()), + "loadtmp", + )) + } + } } impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { fn bitcast( @@ -1350,26 +1402,9 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { v: ValueHandle, ctx: &mut Ctx<'a>, ) -> Result { - let handle = v; - let v = self.get_llvm_value(handle).unwrap(); - if !v.is_pointer_value() { - Ok(match v { - AnyValueEnum::ArrayValue(_) - | AnyValueEnum::IntValue(_) - | AnyValueEnum::FloatValue(_) - | AnyValueEnum::PointerValue(_) - | AnyValueEnum::StructValue(_) - | AnyValueEnum::VectorValue(_) => handle, - AnyValueEnum::FunctionValue(f) => { - return Ok(self.get_llvm_value_handle(&f.as_global_value().as_any_value_enum())); - } - _ => return Err(ctx.add_diag(range.new_err(ErrorCode::EXPECT_VALUE))), - }) - } else { - Ok(self.build_load( - self.get_llvm_value_handle(&v.into_pointer_value().as_any_value_enum()), - "loadtmp", - )) + match self.try_load2var_inner(v) { + Ok(value) => Ok(value), + Err(_) => return Err(range.new_err(ErrorCode::EXPECT_VALUE).add_to_ctx(ctx)), } } @@ -2179,7 +2214,8 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { let st = f.get_nth_param(0).unwrap().into_pointer_value(); // iterate all fields but the first for i in 1..fieldn { - let field_pltp = &*field_tps[i as usize - 1].borrow(); + let bind = get_type_deep(field_tps[i as usize - 1].clone()); + let field_pltp = &* bind.borrow(); let visitor = f.get_nth_param(1).unwrap().into_pointer_value(); let visit_ptr_f = get_nth_mark_fn(f, 2); // complex type needs to provide a visit function by itself @@ -2500,6 +2536,14 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { self.builder.position_at_end(cur_bb); } + fn build_memcpy(&self, from:ValueHandle,to:ValueHandle, len:ValueHandle) { + + let from = self.get_llvm_value(self.try_load2var_inner(from).unwrap()).unwrap().into_pointer_value(); + let to = self.get_llvm_value(self.try_load2var_inner(to).unwrap()).unwrap().into_pointer_value(); + + let len = self.get_llvm_value(self.try_load2var_inner(len).unwrap()).unwrap().into_int_value(); + self.builder.build_memcpy(to, 8, from, 8, len).unwrap(); + } } fn add_field(st_v: AnyValueEnum<'_>, field_tp: inkwell::types::AnyTypeEnum<'_>) -> u32 { diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index 7a0e4c0b5..7a1f0bf9e 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -237,6 +237,7 @@ pub trait IRBuilder<'a, 'ctx> { fn sizeof(&self, pltype: &PLType, ctx: &mut Ctx<'a>,)->u64; + fn build_memcpy(&self, from:ValueHandle,to:ValueHandle, len:ValueHandle); } pub type ValueHandle = usize; diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index ea3a70fe4..6483f27b7 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -500,4 +500,5 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { fn sizeof(&self,_pltype: &PLType,_ctx: &mut Ctx<'a>,) -> u64 { 0 } + fn build_memcpy(&self, _from:ValueHandle,_to:ValueHandle, _len:ValueHandle) {} } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 488e1b1c8..f6a1e4f71 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -1506,3 +1506,9 @@ pub struct EqRes { pub eq: bool, pub need_up_cast: bool, } + +impl EqRes { + pub fn total_eq(&self) -> bool { + self.eq && !self.need_up_cast + } +} diff --git a/src/ast/ctx/builtins.rs b/src/ast/ctx/builtins.rs index 71ae0bcd7..c5e38d3cb 100644 --- a/src/ast/ctx/builtins.rs +++ b/src/ast/ctx/builtins.rs @@ -32,6 +32,8 @@ lazy_static! { mp.insert(usize::MAX - 5, emit_unsafe_cast); mp.insert(usize::MAX - 6, emit_sizeof); mp.insert(usize::MAX - 7, emit_gc_type); + mp.insert(usize::MAX - 8, emit_arr_len); + mp.insert(usize::MAX - 9, emit_arr_copy); mp }; pub static ref BUILTIN_FN_SNIPPET_MAP: HashMap = { @@ -49,6 +51,8 @@ lazy_static! { mp.insert(usize::MAX - 5, r#"unsafe_cast<${1:T}>(${2:t})$0"#.to_owned()); mp.insert(usize::MAX - 6, r#"sizeof<${1:T}>()$0"#.to_owned()); mp.insert(usize::MAX - 7, r#"gc_type<${1:T}>()$0"#.to_owned()); + mp.insert(usize::MAX - 8, r#"arr_len(${1:t})$0"#.to_owned()); + mp.insert(usize::MAX - 9, r#"arr_copy(${1:from}, ${2:to}, ${3:len})$0"#.to_owned()); mp }; pub static ref BUILTIN_FN_NAME_MAP: HashMap<&'static str, ValueHandle> = { @@ -60,6 +64,8 @@ lazy_static! { mp.insert("unsafe_cast", usize::MAX - 5); mp.insert("sizeof", usize::MAX - 6); mp.insert("gc_type", usize::MAX - 7); + mp.insert("arr_len", usize::MAX - 8); + mp.insert("arr_copy", usize::MAX - 9); mp }; } @@ -205,6 +211,98 @@ fn emit_unsafe_cast<'a, 'b>( } +fn emit_arr_len<'a, 'b>( + f: &mut FuncCallNode, + ctx: &'b mut Ctx<'a>, + builder: &'b BuilderEnum<'a, '_>, +) -> NodeResult { + if f.paralist.len() != 1 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) + .add_to_ctx(ctx)); + } + if f.generic_params.is_some() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_PARAM_LEN_MISMATCH) + .add_to_ctx(ctx)); + } + + let st = f.paralist[0].emit(ctx, builder)?; + let v = st.get_value().unwrap(); + + if !matches!(&*v.get_ty().borrow(),PLType::Arr(_)) { + return Err(f.paralist[0] + .range() + .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) + .add_to_ctx(ctx)); + } + let len = builder.build_struct_gep(v.get_value(), 2, "arr_len").unwrap(); + len.new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::I64)))).to_result() + +} + + +fn emit_arr_copy<'a, 'b>( + f: &mut FuncCallNode, + ctx: &'b mut Ctx<'a>, + builder: &'b BuilderEnum<'a, '_>, +) -> NodeResult { + if f.paralist.len() != 3 { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) + .add_to_ctx(ctx)); + } + if f.generic_params.is_some() { + return Err(f + .range + .new_err(crate::ast::diag::ErrorCode::GENERIC_PARAM_LEN_MISMATCH) + .add_to_ctx(ctx)); + } + + let st = f.paralist[0].emit(ctx, builder)?; + let v = st.get_value().unwrap(); + + if !matches!(&*v.get_ty().borrow(),PLType::Arr(_)) { + return Err(f.paralist[0] + .range() + .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) + .add_to_ctx(ctx)); + } + + let st = f.paralist[1].emit(ctx, builder)?; + let to = st.get_value().unwrap(); + + if !matches!(&*to.get_ty().borrow(),PLType::Arr(_)) { + return Err(f.paralist[1] + .range() + .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) + .add_to_ctx(ctx)); + } + + let st = f.paralist[2].emit(ctx, builder)?; + let len = st.get_value().unwrap(); + + if !matches!(&*len.get_ty().borrow(),PLType::Primitive(PriType::I64)) { + return Err(f.paralist[2] + .range() + .new_err(crate::ast::diag::ErrorCode::TYPE_MISMATCH) + .add_to_ctx(ctx)); + } + + let from_raw = builder.build_struct_gep(v.get_value(), 1, "arr_raw").unwrap(); + let to_raw = builder.build_struct_gep(to.get_value(), 1, "arr_raw").unwrap(); + let len_raw = len.get_value(); + builder.build_memcpy(from_raw, to_raw, len_raw); + Ok(Default::default()) + +} + + + + fn emit_name_of<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, diff --git a/src/ast/diag.rs b/src/ast/diag.rs index 9258d49fe..1f81d74e2 100644 --- a/src/ast/diag.rs +++ b/src/ast/diag.rs @@ -76,7 +76,7 @@ define_error!( SYMBOL_NOT_FOUND = "symbol not found", UNRESOLVED_MODULE = "unresolved module", ARRAY_TYPE_NOT_MATCH = "array type not match", - ARRAY_INIT_EMPTY = "array init cannot be empty", + ARRAY_INIT_EMPTY = "array init cannot be empty while no type specified", CANNOT_INDEX_NON_ARRAY = "cannot index non array type", ARRAY_INDEX_MUST_BE_INT = "array index must be int", ARRAY_INDEX_OUT_OF_BOUNDS = "array index out of bounds", @@ -141,6 +141,8 @@ define_error!( YIELD_RETURN_MUST_BE_IN_GENERATOR = "yield return must be in generator function", GENERATOR_FN_MUST_RET_ITER = "generator function must return an iterator", INVALID_RET_IN_GENERATOR_FUNCTION = "invalid `return` in generator function", + ARRAY_LEN_MUST_BE_I64 = "array len must be i64", + EXPECT_ARRAY_TYPE = "expect array type", ); macro_rules! define_warn { ($( diff --git a/src/ast/fmt.rs b/src/ast/fmt.rs index 24959e187..caa21caee 100644 --- a/src/ast/fmt.rs +++ b/src/ast/fmt.rs @@ -169,10 +169,6 @@ impl FmtBuilder { pub fn parse_array_type_name_node(&mut self, node: &ArrayTypeNameNode) { self.l_bracket(); node.id.format(self); - self.space(); - self.asterisk(); - self.space(); - node.size.format(self); self.r_bracket(); } pub fn parse_type_name_node(&mut self, node: &TypeNameNode) { @@ -271,6 +267,15 @@ impl FmtBuilder { } pub fn parse_array_init_node(&mut self, node: &ArrayInitNode) { self.l_bracket(); + if let Some((tp,len)) = &node.tp { + tp.format(self); + self.space(); + self.asterisk(); + self.space(); + len.format(self); + self.semicolon(); + self.space(); + } for (i, exp) in node.exps.iter().enumerate() { exp.format(self); if i != node.exps.len() - 1 { diff --git a/src/ast/node/primary.rs b/src/ast/node/primary.rs index b59ddfa4a..ea67ec6e6 100644 --- a/src/ast/node/primary.rs +++ b/src/ast/node/primary.rs @@ -293,8 +293,9 @@ impl Node for ArrayElementNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_INDEX_MUST_BE_INT))); } let elemptr = { - let index = &[builder.int_value(&PriType::I64, 0, false), index]; + let index = &[ index]; let real_arr = builder.build_struct_gep(arr, 1, "real_arr").unwrap(); + let real_arr = builder.build_load(real_arr, "load_arr"); builder.build_in_bounds_gep(real_arr, index, "element_ptr") }; ctx.emit_comment_highlight(&self.comments[0]); diff --git a/src/ast/node/types.rs b/src/ast/node/types.rs index 17916915e..c70244602 100644 --- a/src/ast/node/types.rs +++ b/src/ast/node/types.rs @@ -269,7 +269,6 @@ impl TypeNode for TypeNameNode { #[node] pub struct ArrayTypeNameNode { pub id: Box, - pub size: Box, } impl PrintTrait for ArrayTypeNameNode { @@ -277,8 +276,7 @@ impl PrintTrait for ArrayTypeNameNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("ArrayTypeNameNode"); - self.id.print(tabs + 1, false, line.clone()); - self.size.print(tabs + 1, true, line.clone()); + self.id.print(tabs + 1, true , line.clone()); } } @@ -289,18 +287,13 @@ impl TypeNode for ArrayTypeNameNode { builder: &'b BuilderEnum<'a, '_>, gen_code: bool, ) -> TypeNodeResult { - if let NodeEnum::Num(num) = *self.size { - if let Num::Int(sz) = num.value { - let pltype = self.id.get_type(ctx, builder, gen_code)?; - let arrtype = ARRType { - element_type: pltype, - size: sz as u32, - }; - let arrtype = Arc::new(RefCell::new(PLType::Arr(arrtype))); - return Ok(arrtype); - } - } - Err(ctx.add_diag(self.range.new_err(ErrorCode::SIZE_MUST_BE_INT))) + let pltype = self.id.get_type(ctx, builder, gen_code)?; + let arrtype = ARRType { + element_type: pltype, + size_handle: 0, + }; + let arrtype = Arc::new(RefCell::new(PLType::Arr(arrtype))); + return Ok(arrtype); } fn emit_highlight<'ctx>(&self, ctx: &mut Ctx<'_>) { @@ -315,18 +308,7 @@ impl TypeNode for ArrayTypeNameNode { ) -> Result { match &*pltype.borrow() { PLType::Arr(a) => { - if let NodeEnum::Num(num) = *self.size { - if let Num::Int(size) = num.value { - if a.size as u64 != size { - return Ok(EqRes { - eq: false, - need_up_cast: false, - }); - } - return self.id.eq_or_infer(ctx, a.element_type.clone(), builder); - } - } - Err(ctx.add_diag(self.range.new_err(ErrorCode::SIZE_MUST_BE_INT))) + return self.id.eq_or_infer(ctx, a.element_type.clone(), builder); } _ => Ok(EqRes { eq: false, @@ -717,7 +699,7 @@ impl Node for StructInitNode { #[node] pub struct ArrayInitNode { - // pub tp: Box, + pub tp: Option< (Box,Box)>, pub exps: Vec>, } @@ -726,7 +708,10 @@ impl PrintTrait for ArrayInitNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("ArrayInitNode"); - // self.tp.print(tabs + 1, self.exps.len() == 0, line.clone()); + if let Some((tp,len)) = &self.tp { + tp.print(tabs + 1, false, line.clone()); + len.print(tabs + 1, false, line.clone()); + } let mut i = self.exps.len(); for exp in &self.exps { i -= 1; @@ -757,30 +742,46 @@ impl Node for ArrayInitNode { let tp = v.get_ty(); exps.push((ctx.try_load2var(range, v.get_value(), builder)?, tp)); } - if tp0.is_none() { - return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_INIT_EMPTY))); - } - let tp = exps[0].clone().1; - let sz = exps.len() as u32; + let sz = exps.len() as u64; + let (tp,size_handle) = if let Some((tp,len_v)) = &mut self.tp { + tp.emit_highlight(ctx); + let tp = tp.get_type(ctx, builder, true)?; + let len = len_v.emit(ctx, builder)?.get_value().unwrap(); + if !matches!( &*len.get_ty().borrow(),PLType::Primitive(PriType::I64) ) { + return Err(ctx.add_diag(len_v.range().new_err(ErrorCode::ARRAY_LEN_MUST_BE_I64))); + } + let len = ctx.try_load2var(len_v.range(), len.get_value(), builder)?; + if let Some(tp0) = &tp0 { + if !ctx.eq(tp.clone(), tp0.clone()).total_eq() { + return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_TYPE_NOT_MATCH))); + } + } + (tp,len) + }else { + if tp0.is_none() { + return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_INIT_EMPTY))); + } + let tp = exps[0].clone().1; + (tp, builder.int_value(&PriType::I64, sz, true)) + }; + let arr_tp = Arc::new(RefCell::new(PLType::Arr(ARRType { + element_type: tp, + size_handle, + }))); let arr = builder.alloc( "array_alloca", - &PLType::Arr(ARRType { - element_type: tp, - size: exps.len() as u32, - }), + &arr_tp.borrow(), ctx, None, ); let real_arr = builder.build_struct_gep(arr, 1, "real_arr").unwrap(); + let real_arr = builder.build_load(real_arr, "load_arr"); for (i, (v, _)) in exps.into_iter().enumerate() { - let ptr = builder.build_const_in_bounds_gep(real_arr, &[0, i as u64], "elem_ptr"); + let ptr = builder.build_const_in_bounds_gep(real_arr, &[i as u64], "elem_ptr"); builder.build_store(ptr, v); } - arr.new_output(Arc::new(RefCell::new(PLType::Arr(ARRType { - element_type: tp0.unwrap(), - size: sz, - })))) + arr.new_output(arr_tp) .to_result() } } diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 55528add0..0cfc4f470 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -1,3 +1,4 @@ +use super::builder::ValueHandle; use super::ctx::Ctx; use super::diag::ErrorCode; use super::node::types::ClosureTypeNode; @@ -20,13 +21,11 @@ use super::diag::PLDiag; use super::fmt::FmtBuilder; use super::node::function::FuncDefNode; use super::node::pkg::ExternIdNode; -use super::node::primary::NumNode; use super::node::primary::VarNode; use super::node::types::ArrayTypeNameNode; use super::node::types::PointerTypeNode; use super::node::types::TypeNameNode; use super::node::NodeEnum; -use super::node::Num; use super::node::TypeNode; use super::node::TypeNodeEnum; use super::range::Range; @@ -323,13 +322,9 @@ fn new_typename_node(name: &str, range: Range, ns: &[String]) -> Box, size: u64) -> Box { +fn new_arrtype_node(typenode: Box) -> Box { Box::new(TypeNodeEnum::Array(ArrayTypeNameNode { id: typenode, - size: Box::new(NodeEnum::Num(NumNode { - value: Num::Int(size), - range: Default::default(), - })), range: Default::default(), })) } @@ -351,6 +346,13 @@ pub fn get_type_deep(pltype: Arc>) -> Arc> { PLType::Pointer(p) =>{ Arc::new(RefCell::new(PLType::Pointer( get_type_deep(p.clone())))) } + PLType::Arr(p) =>{ + let a = ARRType{ + element_type: get_type_deep(p.element_type.clone()), + size_handle: p.size_handle, + }; + Arc::new(RefCell::new(PLType::Arr( a))) + } _ => pltype.clone(), } } @@ -414,7 +416,6 @@ impl PLType { PLType::Struct(st) => new_typename_node(&st.name, st.range, &Self::get_ns(st, path)), PLType::Arr(arr) => new_arrtype_node( arr.get_elem_type().borrow().get_typenode(path), - arr.size as u64, ), PLType::Primitive(p) => new_typename_node(&p.get_name(), Default::default(), &[]), PLType::Void => new_typename_node("void", Default::default(), &[]), @@ -463,7 +464,7 @@ impl PLType { PLType::Struct(st) => st.name.clone(), PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { - format!("[{} * {}]", arr.element_type.borrow().get_name(), arr.size) + format!("[{}]", arr.element_type.borrow().get_name()) } PLType::Void => "void".to_string(), PLType::Pointer(p) => "*".to_string() + &p.borrow().get_name(), @@ -487,7 +488,7 @@ impl PLType { PLType::Trait(t) => t.name.clone(), PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { - format!("[{} * {}]", arr.element_type.borrow().get_name(), arr.size) + format!("[{}]", arr.element_type.borrow().get_name()) } PLType::Void => "void".to_string(), PLType::Pointer(p) => "*".to_string() + &p.borrow().get_name(), @@ -519,9 +520,8 @@ impl PLType { PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { format!( - "[{} * {}]", + "[{}]", arr.element_type.borrow().get_full_elm_name(), - arr.size ) } PLType::Void => "void".to_string(), @@ -540,9 +540,8 @@ impl PLType { PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { format!( - "[{} * {}]", - arr.element_type.borrow().get_full_elm_name(), - arr.size + "[{}]", + arr.element_type.borrow().get_full_elm_name() ) } PLType::Void => "void".to_string(), @@ -939,10 +938,10 @@ impl FNValue { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone)] pub struct ARRType { pub element_type: Arc>, - pub size: u32, + pub size_handle: ValueHandle, } impl ARRType { @@ -951,6 +950,14 @@ impl ARRType { } } +impl PartialEq for ARRType { + fn eq(&self, other: &Self) -> bool { + self.element_type == other.element_type + } +} + +impl Eq for ARRType {} + #[range] #[derive(Debug, Clone, Eq)] pub struct STType { diff --git a/src/nomparser/array.rs b/src/nomparser/array.rs index 1129044a0..8d2871e11 100644 --- a/src/nomparser/array.rs +++ b/src/nomparser/array.rs @@ -2,9 +2,10 @@ use internal_macro::test_parser; use nom::{ combinator::{map_res, opt}, multi::{many0, separated_list0}, - sequence::tuple, + sequence::{tuple, delimited}, IResult, }; +use nom::sequence::pair; use crate::nomparser::Span; use crate::{ @@ -16,6 +17,8 @@ use crate::{ use super::*; #[test_parser("[1,2,3]")] +#[test_parser("[test*test2;]")] +#[test_parser("[test*test2;2,3,4]")] #[test_parser( "[ 1, @@ -27,15 +30,17 @@ pub fn array_init(input: Span) -> IResult> { map_res( tuple(( tag_token_symbol(TokenType::LBRACKET), + opt( pair(type_name, + delimited(tag_token_symbol(TokenType::MUL), general_exp, tag_token_symbol(TokenType::SEMI)))), separated_list0( tag_token_symbol(TokenType::COMMA), del_newline_or_space!(general_exp), ), tag_token_symbol(TokenType::RBRACKET), )), - |((_, lb), exps, (_, rb))| { + |((_, lb),tp, exps, (_, rb))| { let range = lb.start.to(rb.end); - res_enum(ArrayInitNode { exps, range }.into()) + res_enum(ArrayInitNode { exps, range, tp }.into()) }, )(input) } diff --git a/src/nomparser/types.rs b/src/nomparser/types.rs index 57b900eb8..6e37e6f74 100644 --- a/src/nomparser/types.rs +++ b/src/nomparser/types.rs @@ -62,21 +62,20 @@ pub fn basic_type(input: Span) -> IResult> { ))(input) } + +#[test_parser("[i64]")] +#[test_parser("[[[i64]]]")] fn array_type(input: Span) -> IResult> { map_res( tuple(( tag_token_symbol(TokenType::LBRACKET), type_name, - tag_token_symbol(TokenType::MUL), - number, tag_token_symbol(TokenType::RBRACKET), )), - |(_, tp, _, size, _)| { - let range = size.range().start.to(tp.range().end); - + |(_, tp, _)| { + let range = tp.range(); Ok::<_, ()>(Box::new(TypeNodeEnum::Array(ArrayTypeNameNode { id: tp, - size, range, }))) }, diff --git a/test/fmt/test_fmt.pi b/test/fmt/test_fmt.pi index 465388503..cf206d968 100644 --- a/test/fmt/test_fmt.pi +++ b/test/fmt/test_fmt.pi @@ -8,7 +8,7 @@ pub fn true_with_pnanic() bool { pub struct complex_struct { x: i64; pub y: *bool; - pub z: [base * 2]; + pub z: [base]; } /// struct coment @@ -28,6 +28,14 @@ fn struct_init() void { return; } +fn test_arr() void { + let a = [1, 2, 3]; + a[1] = 100; + a = [i64 * a[1]; ]; + a[99] = 10; + return; +} + fn ifel() void { if true { } else { diff --git a/test/main.pi b/test/main.pi index 966bc0e71..8ec013f2a 100644 --- a/test/main.pi +++ b/test/main.pi @@ -24,9 +24,19 @@ use project1::test::compiletime_reflection::test_compile_time_reflection; use project1::test::deconstruct; use project1::test::st::*; use project1::test::iter; - - +use std::cols::arr; +use std::io; pub fn main() i64 { + let array = arr::from_slice([1,2,3]); + array.set(2, 100); + let a2 = array.get(2); + println!(a2); + array.push(4); + array.push(5); + let a4 = array.get(4); + println!(a4); + let a5 = array.pop(); + println!(a5); macros::test_macros(); ifel::test_if_else(); generic::test_generic(); @@ -56,13 +66,3 @@ pub fn main() i64 { } -fn push3(ss:name2, t:T, tt:*T) void { - ss.t = &t; - tt=&t; - return; -} - -struct name2 { - t:*T; -} - diff --git a/test/test/map.pi b/test/test/map.pi index a91dbfcfb..93dddc80c 100644 --- a/test/test/map.pi +++ b/test/test/map.pi @@ -11,7 +11,7 @@ pub fn test_map() void { return; } -pub fn count(mp: [[i64 * 5] * 5]) i64 { +pub fn count(mp: [[i64]]) i64 { let res = 0; let w = 5; let h = 5; diff --git a/test/test/st.pi b/test/test/st.pi index 7cf4942ba..3e7cd7a83 100644 --- a/test/test/st.pi +++ b/test/test/st.pi @@ -1,4 +1,4 @@ -use core::panic; +use core::panic::*; pub struct A { x: i64; } @@ -11,7 +11,7 @@ pub struct struct_father { pub struct struct_child { a: i64; - b: [i64 * 1]; + b: [i64]; } pub struct pointer_struct { @@ -25,7 +25,7 @@ pub fn ret_astruct() A { }; } -pub fn ret_arr() [i64 * 3] { +pub fn ret_arr() [i64] { return [1, 10000, 3]; } @@ -49,6 +49,7 @@ pub fn test_ret_struct() void { return; } + pub fn test_struct_father() void { let s = struct_father{ a: 2, @@ -98,6 +99,22 @@ pub fn test_struct() void { test_self_ref(); test_struct_father(); test_ret_struct_arr(); + test_arr(); + return; +} + + +fn test_arr() void { + let a = [1, 2, 3]; + a[1] = 100; + let len = arr_len(a); + assert(len == 3); + assert(a[1] == 100); + a = [i64 * a[1]; ]; + a[99] = 10; + assert(a[99] == 10); + len = arr_len(a); + assert(len == 100); return; } From dcfa3177c8fd8149a693ba1922dee5cac953f007 Mon Sep 17 00:00:00 2001 From: bobxli Date: Wed, 19 Jul 2023 17:05:54 +0800 Subject: [PATCH 12/14] fix: trait mthd not found & broken module --- planglib/std/cols/arr.pi | 11 +- planglib/std/iter.pi | 2 - src/ast/builder/llvmbuilder.rs | 177 ++++++++++++++++++++----------- src/ast/builder/mod.rs | 8 +- src/ast/builder/no_op_builder.rs | 8 +- src/ast/ctx.rs | 43 +++++++- src/ast/ctx/builtins.rs | 60 ++++++----- src/ast/fmt.rs | 2 +- src/ast/node/function.rs | 9 +- src/ast/node/operator.rs | 2 +- src/ast/node/primary.rs | 4 +- src/ast/node/program.rs | 29 ++++- src/ast/node/types.rs | 34 +++--- src/ast/plmod.rs | 20 ++++ src/ast/pltype.rs | 34 +++--- src/ast/test.rs | 3 +- src/nomparser/array.rs | 16 ++- src/nomparser/types.rs | 1 - test/main.pi | 17 +-- test/test/arr.pi | 32 ++++++ 20 files changed, 335 insertions(+), 177 deletions(-) create mode 100644 test/test/arr.pi diff --git a/planglib/std/cols/arr.pi b/planglib/std/cols/arr.pi index be61c61bf..103a73598 100644 --- a/planglib/std/cols/arr.pi +++ b/planglib/std/cols/arr.pi @@ -53,8 +53,13 @@ impl Array { self.data[i] = t; return; } -} + gen pub fn iter() Iterator { + for let i = 0; i < self.len as i64; i = i + 1 { + yield return self.data[i]; + } + } +} pub fn from_slice(slice:[T]) Array { @@ -65,7 +70,3 @@ pub fn from_slice(slice:[T]) Array { return arr; } - -// impl Iterator for Array { - -// } \ No newline at end of file diff --git a/planglib/std/iter.pi b/planglib/std/iter.pi index f83069358..90be35f70 100644 --- a/planglib/std/iter.pi +++ b/planglib/std/iter.pi @@ -1,5 +1,3 @@ -use core::builtin; - pub trait Iterator { fn next() Option; } diff --git a/src/ast/builder/llvmbuilder.rs b/src/ast/builder/llvmbuilder.rs index 49d5d06be..6444d0524 100644 --- a/src/ast/builder/llvmbuilder.rs +++ b/src/ast/builder/llvmbuilder.rs @@ -35,7 +35,7 @@ use rustc_hash::FxHashMap; use crate::ast::{ ctx::{CtxFlag, PLSymbol}, diag::PLDiag, - pltype::{ClosureType, TraitImplAble, get_type_deep}, + pltype::{get_type_deep, ClosureType, TraitImplAble}, }; use super::{ @@ -289,7 +289,11 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { } let heapptr = self .builder - .build_call(f, &[size.into(), immix_tp.into()], &format!("heapptr_{}", name)) + .build_call( + f, + &[size.into(), immix_tp.into()], + &format!("heapptr_{}", name), + ) .try_as_basic_value() .left() .unwrap(); @@ -300,42 +304,76 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { name, ); - // TODO: force user to manually init all structs, so we can remove this memset - let size_val = self - .context - .i64_type() - .const_int(td.get_store_size(&llvmtp), false); - self.builder - .build_memset( - casted_result.into_pointer_value(), - td.get_abi_alignment(&llvmtp), - self.context.i8_type().const_zero(), - size_val, - ) - .unwrap(); + // TODO: force user to manually init all structs, so we can remove this memset + let size_val = self + .context + .i64_type() + .const_int(td.get_store_size(&llvmtp), false); + self.builder + .build_memset( + casted_result.into_pointer_value(), + td.get_abi_alignment(&llvmtp), + self.context.i8_type().const_zero(), + size_val, + ) + .unwrap(); if let PLType::Arr(arr) = tp { if arr.size_handle != 0 { let f = self.get_malloc_f(ctx, "DioGC__malloc_no_collect"); - let etp= self.get_basic_type_op(&arr.element_type.borrow(), ctx).unwrap(); + let etp = self + .get_basic_type_op(&arr.element_type.borrow(), ctx) + .unwrap(); let size = td.get_store_size(&etp); let size = self.context.i64_type().const_int(size, false); - let arr_len = self.get_llvm_value(arr.size_handle).unwrap().into_int_value(); + let arr_len = self + .get_llvm_value(arr.size_handle) + .unwrap() + .into_int_value(); let arr_size = self.builder.build_int_mul(arr_len, size, "arr_size"); - let arr_size = self.builder.build_int_z_extend_or_bit_cast(arr_size, self.context.i64_type(), "arr_size"); - let len_ptr = self.builder.build_struct_gep(casted_result.into_pointer_value(), 2, "arr_len").unwrap(); + let arr_size = self.builder.build_int_z_extend_or_bit_cast( + arr_size, + self.context.i64_type(), + "arr_size", + ); + let len_ptr = self + .builder + .build_struct_gep(casted_result.into_pointer_value(), 2, "arr_len") + .unwrap(); self.builder.build_store(len_ptr, arr_len); - let arr_ptr = self.builder.build_struct_gep(casted_result.into_pointer_value(), 1, "arr_ptr").unwrap(); - let arr_space = self.builder.build_call(f, &[arr_size.into(), self - .context - .i8_type() - .const_int(immix::ObjectType::Atomic.int_value() as u64, false).into()], "arr_space").try_as_basic_value().left().unwrap(); - let arr_space = self.builder.build_bitcast(arr_space.into_pointer_value(), etp.ptr_type(AddressSpace::default()), "arr_space"); + let arr_ptr = self + .builder + .build_struct_gep(casted_result.into_pointer_value(), 1, "arr_ptr") + .unwrap(); + let arr_space = self + .builder + .build_call( + f, + &[ + arr_size.into(), + self.context + .i8_type() + .const_int(immix::ObjectType::Atomic.int_value() as u64, false) + .into(), + ], + "arr_space", + ) + .try_as_basic_value() + .left() + .unwrap(); + let arr_space = self.builder.build_bitcast( + arr_space.into_pointer_value(), + etp.ptr_type(AddressSpace::default()), + "arr_space", + ); self.builder.build_store(arr_ptr, arr_space); } } self.builder.position_at_end(alloca); + if alloca.get_terminator().is_some() { + panic!("alloca block should not have terminator yet") + } let stack_ptr = self .builder .build_alloca(llvmtp.ptr_type(AddressSpace::default()), "stack_ptr"); @@ -360,7 +398,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { .try_into() .unwrap(); let f = self.get_or_insert_fn(&f, ctx); - f + f.0 } /// # create_root_for @@ -512,10 +550,13 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { self.builder.position_at_end(bb); let arr = f.get_nth_param(0).unwrap().into_pointer_value(); let real_arr_raw = self.builder.build_struct_gep(arr, 1, "arr").unwrap(); - let real_arr = self.builder.build_load(real_arr_raw, "loaded_arr").into_pointer_value(); + let real_arr = self + .builder + .build_load(real_arr_raw, "loaded_arr") + .into_pointer_value(); let loop_var = self.builder.build_alloca(self.context.i64_type(), "i"); // arr is the real array - let arr_len =self.builder.build_struct_gep(arr, 2, "arr_len").unwrap(); + let arr_len = self.builder.build_struct_gep(arr, 2, "arr_len").unwrap(); let arr_len = self.builder.build_load(arr_len, "arr_len").into_int_value(); // generate a loop, iterate the real array, and do nothing let condbb = self.context.append_basic_block(f, "cond"); @@ -530,20 +571,14 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { self.builder.build_conditional_branch(cond, loopbb, endbb); self.builder.position_at_end(loopbb); let i = self.builder.build_load(loop_var, "i").into_int_value(); - let elm = unsafe { - self.builder.build_in_bounds_gep( - real_arr, - &[i], - "elm", - ) - }; + let elm = unsafe { self.builder.build_in_bounds_gep(real_arr, &[i], "elm") }; let visitor = f.get_nth_param(1).unwrap().into_pointer_value(); let visit_ptr_f = get_nth_mark_fn(f, 2); // complex type needs to provide a visit function by itself // which is stored in the first field of the struct let visit_complex_f = get_nth_mark_fn(f, 3); let visit_trait_f = get_nth_mark_fn(f, 4); - match &*get_type_deep( v.element_type.clone()).borrow() { + match &*get_type_deep(v.element_type.clone()).borrow() { PLType::Arr(_) | PLType::Struct(_) => { let casted = self.builder.build_bitcast(elm, i8ptrtp, "casted_arg"); // call the visit_complex function @@ -575,9 +610,14 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { self.builder.position_at_end(endbb); // call the visit_ptr function - let casted = self.builder.build_bitcast(real_arr_raw, i8ptrtp, "casted_arg"); - self.builder - .build_call(get_nth_mark_fn(f, 2), &[visitor.into(), casted.into()], "call"); + let casted = self + .builder + .build_bitcast(real_arr_raw, i8ptrtp, "casted_arg"); + self.builder.build_call( + get_nth_mark_fn(f, 2), + &[visitor.into(), casted.into()], + "call", + ); self.builder.build_return(None); if let Some(currentbb) = currentbb { self.builder.position_at_end(currentbb); @@ -889,7 +929,7 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { .get_basic_type_op(&arr.element_type.borrow(), ctx) .unwrap(); let arr_st_tp = self.arr_type(arr, ctx).into_struct_type(); - let size = td.get_bit_size(etp) * 0; + let size = 0; let align = td.get_preferred_alignment(etp); let st_size = td.get_bit_size(&arr_st_tp); let vtabledi = self.get_ditype(&PLType::Primitive(PriType::U64), ctx)?; @@ -1176,14 +1216,19 @@ impl<'a, 'ctx> LLVMBuilder<'a, 'ctx> { /// try get function value from module /// /// if not found, create a declaration - fn get_or_insert_fn(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> FunctionValue<'ctx> { + /// + /// bool: 是否已经实现过该函数 + fn get_or_insert_fn(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> (FunctionValue<'ctx>, bool) { let llvmname = pltp.append_name_with_generic(pltp.llvmname.clone()); if let Some(v) = self.module.get_function(&llvmname) { - return v; + return (v, v.count_basic_blocks() != 0); } let fn_type = self.get_fn_type(pltp, ctx); - self.module - .add_function(&llvmname, fn_type, Some(Linkage::External)) + ( + self.module + .add_function(&llvmname, fn_type, Some(Linkage::External)), + false, + ) } fn get_fields(&self, pltp: &STType, ctx: &mut Ctx<'a>) -> Vec { ctx.run_in_type_mod(pltp, |ctx, pltp| { @@ -1360,8 +1405,10 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { self.builder .position_at_end(self.block_table.borrow()[&block]); } - fn get_or_insert_fn_handle(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> ValueHandle { - self.get_llvm_value_handle(&self.get_or_insert_fn(pltp, ctx).as_any_value_enum()) + /// 返回值的bool:函数是否已有函数体 + fn get_or_insert_fn_handle(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> (ValueHandle, bool) { + let (f, b) = self.get_or_insert_fn(pltp, ctx); + (self.get_llvm_value_handle(&f.as_any_value_enum()), b) } fn get_or_insert_helper_fn_handle(&self, name: &str) -> ValueHandle { @@ -1404,7 +1451,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { ) -> Result { match self.try_load2var_inner(v) { Ok(value) => Ok(value), - Err(_) => return Err(range.new_err(ErrorCode::EXPECT_VALUE).add_to_ctx(ctx)), + Err(_) => Err(range.new_err(ErrorCode::EXPECT_VALUE).add_to_ctx(ctx)), } } @@ -1499,11 +1546,10 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { false, ); } - fn sizeof(&self, - pltype: &PLType, - ctx: &mut Ctx<'a>, - ) -> u64 { - self.targetmachine.get_target_data().get_store_size(&self.get_basic_type_op(pltype, ctx).unwrap()) + fn sizeof(&self, pltype: &PLType, ctx: &mut Ctx<'a>) -> u64 { + self.targetmachine + .get_target_data() + .get_store_size(&self.get_basic_type_op(pltype, ctx).unwrap()) } fn alloc( &self, @@ -2215,7 +2261,7 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { // iterate all fields but the first for i in 1..fieldn { let bind = get_type_deep(field_tps[i as usize - 1].clone()); - let field_pltp = &* bind.borrow(); + let field_pltp = &*bind.borrow(); let visitor = f.get_nth_param(1).unwrap().into_pointer_value(); let visit_ptr_f = get_nth_mark_fn(f, 2); // complex type needs to provide a visit function by itself @@ -2536,13 +2582,24 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for LLVMBuilder<'a, 'ctx> { self.builder.position_at_end(cur_bb); } - fn build_memcpy(&self, from:ValueHandle,to:ValueHandle, len:ValueHandle) { - - let from = self.get_llvm_value(self.try_load2var_inner(from).unwrap()).unwrap().into_pointer_value(); - let to = self.get_llvm_value(self.try_load2var_inner(to).unwrap()).unwrap().into_pointer_value(); - - let len = self.get_llvm_value(self.try_load2var_inner(len).unwrap()).unwrap().into_int_value(); - self.builder.build_memcpy(to, 8, from, 8, len).unwrap(); + fn build_memcpy(&self, from: ValueHandle, to: ValueHandle, len: ValueHandle) { + let from = self + .get_llvm_value(self.try_load2var_inner(from).unwrap()) + .unwrap() + .into_pointer_value(); + let to = self + .get_llvm_value(self.try_load2var_inner(to).unwrap()) + .unwrap() + .into_pointer_value(); + let td = self.targetmachine.get_target_data(); + let unit_size = td.get_store_size(&from.get_type().get_element_type()); + let i64_size = self.context.i64_type().const_int(unit_size, true); + let len = self + .get_llvm_value(self.try_load2var_inner(len).unwrap()) + .unwrap() + .into_int_value(); + let arg_len = self.builder.build_int_mul(len, i64_size, "arg_len"); + self.builder.build_memcpy(to, 8, from, 8, arg_len).unwrap(); } } diff --git a/src/ast/builder/mod.rs b/src/ast/builder/mod.rs index 7a1f0bf9e..db9084fbd 100644 --- a/src/ast/builder/mod.rs +++ b/src/ast/builder/mod.rs @@ -121,7 +121,7 @@ pub trait IRBuilder<'a, 'ctx> { fn build_unconditional_branch(&self, bb: BlockHandle); fn position_at_end_block(&self, block: BlockHandle); fn add_body_to_struct_type(&self, name: &str, sttype: &STType, ctx: &mut Ctx<'a>); - fn get_or_insert_fn_handle(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> ValueHandle; + fn get_or_insert_fn_handle(&self, pltp: &FNValue, ctx: &mut Ctx<'a>) -> (ValueHandle, bool); fn get_or_add_global( &self, name: &str, @@ -234,10 +234,8 @@ pub trait IRBuilder<'a, 'ctx> { unsafe fn store_with_aoto_cast(&self, ptr: ValueHandle, value: ValueHandle); fn stack_alloc(&self, name: &str, ctx: &mut Ctx<'a>, tp: &PLType) -> ValueHandle; fn correct_generator_ctx_malloc_inst(&self, ctx: &mut Ctx<'a>, name: &str); - fn sizeof(&self, - pltype: &PLType, - ctx: &mut Ctx<'a>,)->u64; - fn build_memcpy(&self, from:ValueHandle,to:ValueHandle, len:ValueHandle); + fn sizeof(&self, pltype: &PLType, ctx: &mut Ctx<'a>) -> u64; + fn build_memcpy(&self, from: ValueHandle, to: ValueHandle, len: ValueHandle); } pub type ValueHandle = usize; diff --git a/src/ast/builder/no_op_builder.rs b/src/ast/builder/no_op_builder.rs index 6483f27b7..63a74a591 100644 --- a/src/ast/builder/no_op_builder.rs +++ b/src/ast/builder/no_op_builder.rs @@ -211,8 +211,8 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { &self, _pltp: &crate::ast::pltype::FNValue, _ctx: &mut crate::ast::ctx::Ctx<'a>, - ) -> super::ValueHandle { - 0 + ) -> (super::ValueHandle, bool) { + (0, false) } fn get_or_add_global( @@ -497,8 +497,8 @@ impl<'a, 'ctx> IRBuilder<'a, 'ctx> for NoOpBuilder<'a, 'ctx> { fn correct_generator_ctx_malloc_inst(&self, _ctx: &mut Ctx<'a>, _name: &str) {} - fn sizeof(&self,_pltype: &PLType,_ctx: &mut Ctx<'a>,) -> u64 { + fn sizeof(&self, _pltype: &PLType, _ctx: &mut Ctx<'a>) -> u64 { 0 } - fn build_memcpy(&self, _from:ValueHandle,_to:ValueHandle, _len:ValueHandle) {} + fn build_memcpy(&self, _from: ValueHandle, _to: ValueHandle, _len: ValueHandle) {} } diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index f6a1e4f71..ee409ba5d 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -502,7 +502,7 @@ impl<'a, 'ctx> Ctx<'a> { unreachable!() }); - let fnhandle = builder.get_or_insert_fn_handle(&mthd.borrow(), ctx); + let fnhandle = builder.get_or_insert_fn_handle(&mthd.borrow(), ctx).0; let targetftp = f.typenode.get_type(ctx, builder, true).unwrap(); let casted = builder.bitcast(ctx, fnhandle, &targetftp.borrow(), "fncast_tmp"); @@ -1031,6 +1031,27 @@ impl<'a, 'ctx> Ctx<'a> { res } + // FIXME: performance + pub fn run_in_type_mod_deep<'b, TP: CustomType, R, F: FnMut(&mut Ctx<'a>, &TP) -> R>( + &'b mut self, + u: &TP, + mut f: F, + ) -> R { + let p = PathBuf::from(&u.get_path()); + let mut oldm = None; + if u.get_path() != self.plmod.path { + let s = p.file_name().unwrap().to_str().unwrap(); + let m = s.split('.').next().unwrap(); + let m = self.plmod.search_mod(u, m).unwrap(); + oldm = Some(self.set_mod(m)); + } + let res = f(self, u); + if let Some(m) = oldm { + self.set_mod(m); + } + res + } + pub fn run_in_origin_mod<'b, R, F: FnMut(&mut Ctx<'a>) -> R>(&'b mut self, mut f: F) -> R { let oldm = self.plmod.clone(); let ctx = self.get_root_ctx(); @@ -1059,6 +1080,26 @@ impl<'a, 'ctx> Ctx<'a> { res } + pub fn run_in_type_mod_mut_deep<'b, TP: CustomType, R, F: FnMut(&mut Ctx<'a>, &mut TP) -> R>( + &'b mut self, + u: &mut TP, + mut f: F, + ) -> R { + let p = PathBuf::from(&u.get_path()); + let mut oldm = None; + if u.get_path() != self.plmod.path { + let s = p.file_name().unwrap().to_str().unwrap(); + let m = s.split('.').next().unwrap(); + let m = self.plmod.search_mod(u, m).unwrap(); + oldm = Some(self.set_mod(m)); + } + let res = f(self, u); + if let Some(m) = oldm { + self.set_mod(m); + } + res + } + pub fn get_file_url(&self) -> Url { #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))] return Url::from_file_path(self.plmod.path.clone()).unwrap(); diff --git a/src/ast/ctx/builtins.rs b/src/ast/ctx/builtins.rs index c5e38d3cb..e28374539 100644 --- a/src/ast/ctx/builtins.rs +++ b/src/ast/ctx/builtins.rs @@ -1,7 +1,11 @@ //! # builtins //! //! compiler builtin methods, mostly used for static reflection -use crate::ast::{builder::no_op_builder::NoOpBuilder, node::{RangeTrait, node_result::NodeResultBuilder}, pltype::{PlaceHolderType, PriType}}; +use crate::ast::{ + builder::no_op_builder::NoOpBuilder, + node::{node_result::NodeResultBuilder, RangeTrait}, + pltype::{PlaceHolderType, PriType}, +}; use std::{cell::RefCell, collections::HashMap, sync::Arc}; use immix::IntEnum; @@ -48,11 +52,17 @@ lazy_static! { r#"match_type<${1:T}>(${2:t}, { ${3:_value} })$0"#.to_owned(), ); mp.insert(usize::MAX - 4, r#"fullnameof(${1:t})$0"#.to_owned()); - mp.insert(usize::MAX - 5, r#"unsafe_cast<${1:T}>(${2:t})$0"#.to_owned()); + mp.insert( + usize::MAX - 5, + r#"unsafe_cast<${1:T}>(${2:t})$0"#.to_owned(), + ); mp.insert(usize::MAX - 6, r#"sizeof<${1:T}>()$0"#.to_owned()); mp.insert(usize::MAX - 7, r#"gc_type<${1:T}>()$0"#.to_owned()); mp.insert(usize::MAX - 8, r#"arr_len(${1:t})$0"#.to_owned()); - mp.insert(usize::MAX - 9, r#"arr_copy(${1:from}, ${2:to}, ${3:len})$0"#.to_owned()); + mp.insert( + usize::MAX - 9, + r#"arr_copy(${1:from}, ${2:to}, ${3:len})$0"#.to_owned(), + ); mp }; pub static ref BUILTIN_FN_NAME_MAP: HashMap<&'static str, ValueHandle> = { @@ -70,13 +80,12 @@ lazy_static! { }; } - fn emit_sizeof<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { - if f.paralist.len() != 0 { + if !f.paralist.is_empty() { return Err(f .range .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) @@ -112,16 +121,14 @@ fn emit_sizeof<'a, 'b>( .new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::I64)))) .set_const() .to_result(); - } - fn emit_gc_type<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, builder: &'b BuilderEnum<'a, '_>, ) -> NodeResult { - if f.paralist.len() != 0 { + if !f.paralist.is_empty() { return Err(f .range .new_err(crate::ast::diag::ErrorCode::PARAMETER_LENGTH_NOT_MATCH) @@ -157,10 +164,8 @@ fn emit_gc_type<'a, 'b>( .new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::U8)))) .set_const() .to_result(); - } - fn emit_unsafe_cast<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, @@ -198,7 +203,7 @@ fn emit_unsafe_cast<'a, 'b>( .as_ref() .unwrap() .get_type(ctx, builder, true)?; - if !matches!(&*v.get_ty().borrow(),PLType::Pointer(_)) { + if !matches!(&*v.get_ty().borrow(), PLType::Pointer(_)) { return Err(f.paralist[0] .range() .new_err(crate::ast::diag::ErrorCode::NOT_A_POINTER) @@ -207,10 +212,8 @@ fn emit_unsafe_cast<'a, 'b>( let ty = PLType::Pointer(generic); let re = builder.bitcast(ctx, v.get_value(), &ty, "unsafe_casted"); re.new_output(Arc::new(RefCell::new(ty))).to_result() - } - fn emit_arr_len<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, @@ -232,18 +235,19 @@ fn emit_arr_len<'a, 'b>( let st = f.paralist[0].emit(ctx, builder)?; let v = st.get_value().unwrap(); - if !matches!(&*v.get_ty().borrow(),PLType::Arr(_)) { + if !matches!(&*v.get_ty().borrow(), PLType::Arr(_)) { return Err(f.paralist[0] .range() .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) .add_to_ctx(ctx)); } - let len = builder.build_struct_gep(v.get_value(), 2, "arr_len").unwrap(); - len.new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::I64)))).to_result() - + let len = builder + .build_struct_gep(v.get_value(), 2, "arr_len") + .unwrap(); + len.new_output(Arc::new(RefCell::new(PLType::Primitive(PriType::I64)))) + .to_result() } - fn emit_arr_copy<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, @@ -265,7 +269,7 @@ fn emit_arr_copy<'a, 'b>( let st = f.paralist[0].emit(ctx, builder)?; let v = st.get_value().unwrap(); - if !matches!(&*v.get_ty().borrow(),PLType::Arr(_)) { + if !matches!(&*v.get_ty().borrow(), PLType::Arr(_)) { return Err(f.paralist[0] .range() .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) @@ -275,7 +279,7 @@ fn emit_arr_copy<'a, 'b>( let st = f.paralist[1].emit(ctx, builder)?; let to = st.get_value().unwrap(); - if !matches!(&*to.get_ty().borrow(),PLType::Arr(_)) { + if !matches!(&*to.get_ty().borrow(), PLType::Arr(_)) { return Err(f.paralist[1] .range() .new_err(crate::ast::diag::ErrorCode::EXPECT_ARRAY_TYPE) @@ -285,24 +289,24 @@ fn emit_arr_copy<'a, 'b>( let st = f.paralist[2].emit(ctx, builder)?; let len = st.get_value().unwrap(); - if !matches!(&*len.get_ty().borrow(),PLType::Primitive(PriType::I64)) { + if !matches!(&*len.get_ty().borrow(), PLType::Primitive(PriType::I64)) { return Err(f.paralist[2] .range() .new_err(crate::ast::diag::ErrorCode::TYPE_MISMATCH) .add_to_ctx(ctx)); } - - let from_raw = builder.build_struct_gep(v.get_value(), 1, "arr_raw").unwrap(); - let to_raw = builder.build_struct_gep(to.get_value(), 1, "arr_raw").unwrap(); + + let from_raw = builder + .build_struct_gep(v.get_value(), 1, "arr_raw") + .unwrap(); + let to_raw = builder + .build_struct_gep(to.get_value(), 1, "arr_raw") + .unwrap(); let len_raw = len.get_value(); builder.build_memcpy(from_raw, to_raw, len_raw); Ok(Default::default()) - } - - - fn emit_name_of<'a, 'b>( f: &mut FuncCallNode, ctx: &'b mut Ctx<'a>, diff --git a/src/ast/fmt.rs b/src/ast/fmt.rs index caa21caee..c5e1968f9 100644 --- a/src/ast/fmt.rs +++ b/src/ast/fmt.rs @@ -267,7 +267,7 @@ impl FmtBuilder { } pub fn parse_array_init_node(&mut self, node: &ArrayInitNode) { self.l_bracket(); - if let Some((tp,len)) = &node.tp { + if let Some((tp, len)) = &node.tp { tp.format(self); self.space(); self.asterisk(); diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 5587f1a3a..2ac0f29ae 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -235,7 +235,7 @@ impl Node for FuncCallNode { )?; // value check and generic infer let res = ctx.protect_generic_context(&fnvalue.fntype.generic_map.clone(), |ctx| { - let rettp = ctx.run_in_type_mod_mut(&mut fnvalue, |ctx, fnvalue| { + let rettp = ctx.run_in_type_mod_mut_deep(&mut fnvalue, |ctx, fnvalue| { if let Some(receiver_pltype) = &receiver_type { if !fnvalue.fntype.param_pltypes[0] .eq_or_infer(ctx, receiver_pltype.clone(), builder)? @@ -271,7 +271,7 @@ impl Node for FuncCallNode { let function = if fn_handle != usize::MAX { fn_handle } else { - builder.get_or_insert_fn_handle(&fnvalue, ctx) + builder.get_or_insert_fn_handle(&fnvalue, ctx).0 }; builder.try_set_fn_dbg(self.range.start, ctx.function.unwrap()); // let rettp = ctx.run_in_type_mod_mut(&mut fnvalue, |ctx, fnvalue| { @@ -553,7 +553,10 @@ impl FuncDefNode { Arc::new(RefCell::new(PLType::Fn(place_holder_fn.clone()))), ); } - let mut funcvalue = builder.get_or_insert_fn_handle(&fnvalue, child); + let (mut funcvalue, exists) = builder.get_or_insert_fn_handle(&fnvalue, child); + if exists { + return Ok(()); + } child.function = Some(funcvalue); let mut sttp_opt = None; let mut generator_alloca_b = 0; diff --git a/src/ast/node/operator.rs b/src/ast/node/operator.rs index 851de2b52..c9dbebca2 100644 --- a/src/ast/node/operator.rs +++ b/src/ast/node/operator.rs @@ -330,7 +330,7 @@ impl Node for TakeOpNode { headptr = builder.alloc("temp", &head_pltype.borrow(), ctx, None); } match &*head_pltype.clone().borrow() { - PLType::Trait(s) => ctx.run_in_type_mod(s, |ctx, s| { + PLType::Trait(s) => ctx.run_in_type_mod_deep(s, |ctx, s| { ctx.protect_generic_context(&s.generic_map, |ctx| { let head_pltype = head_pltype.clone(); let field = s.get_trait_field(&id.name); diff --git a/src/ast/node/primary.rs b/src/ast/node/primary.rs index ea67ec6e6..a3c18b8ea 100644 --- a/src/ast/node/primary.rs +++ b/src/ast/node/primary.rs @@ -186,7 +186,7 @@ impl Node for VarNode { ctx.send_if_go_to_def(self.range, f.range, f.path.clone()); ctx.push_semantic_token(self.range, SemanticTokenType::FUNCTION, 0); if !f.fntype.generic { - let handle = builder.get_or_insert_fn_handle(f, ctx); + let handle = builder.get_or_insert_fn_handle(f, ctx).0; return handle.new_output(tp.tp.clone()).to_result(); } return usize::MAX.new_output(tp.tp.clone()).to_result(); @@ -293,7 +293,7 @@ impl Node for ArrayElementNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_INDEX_MUST_BE_INT))); } let elemptr = { - let index = &[ index]; + let index = &[index]; let real_arr = builder.build_struct_gep(arr, 1, "real_arr").unwrap(); let real_arr = builder.build_load(real_arr, "load_arr"); builder.build_in_bounds_gep(real_arr, index, "element_ptr") diff --git a/src/ast/node/program.rs b/src/ast/node/program.rs index 410b3d56b..199cd7687 100644 --- a/src/ast/node/program.rs +++ b/src/ast/node/program.rs @@ -176,6 +176,26 @@ lazy_static::lazy_static! { all_import:false, }))] }; + + static ref STD_USE_NODES: Vec> = { + let core = Box::new(VarNode { + name: "core".to_string(), + range: Default::default(), + }); + + let builtin = Box::new(VarNode { + name: "builtin".to_string(), + range: Default::default(), + }); + vec![Box::new(NodeEnum::UseNode(UseNode { + ids: vec![core, builtin], + range: Default::default(), + complete: true, + singlecolon: false, + modifier:None, + all_import:false, + }))] + }; } mod cycle; @@ -240,11 +260,10 @@ impl Program { if pkgname != "gc" { prog.uses.extend_from_slice(&GC_USE_NODES); } - if pkgname != "gc" - && pkgname != "builtin" - && self.config(db).project != "core" - && self.config(db).project != "std" - { + if self.config(db).project == "std" { + prog.uses.extend_from_slice(&STD_USE_NODES); + } + if self.config(db).project != "core" && self.config(db).project != "std" { prog.uses.extend_from_slice(&DEFAULT_USE_NODES); } #[cfg(not(target_arch = "wasm32"))] diff --git a/src/ast/node/types.rs b/src/ast/node/types.rs index c70244602..06065907b 100644 --- a/src/ast/node/types.rs +++ b/src/ast/node/types.rs @@ -183,7 +183,9 @@ impl TypeNode for TypeNameNode { let sttype = sttype.clone(); if sttype.need_gen_code() { return ctx.protect_generic_context(&sttype.generic_map, |ctx| { - sttype.gen_code(ctx, builder) + ctx.run_in_type_mod(&sttype, |ctx, sttype| { + sttype.gen_code(ctx, builder) + }) }); } else { return Err( @@ -276,7 +278,7 @@ impl PrintTrait for ArrayTypeNameNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("ArrayTypeNameNode"); - self.id.print(tabs + 1, true , line.clone()); + self.id.print(tabs + 1, true, line.clone()); } } @@ -293,7 +295,7 @@ impl TypeNode for ArrayTypeNameNode { size_handle: 0, }; let arrtype = Arc::new(RefCell::new(PLType::Arr(arrtype))); - return Ok(arrtype); + Ok(arrtype) } fn emit_highlight<'ctx>(&self, ctx: &mut Ctx<'_>) { @@ -307,9 +309,7 @@ impl TypeNode for ArrayTypeNameNode { builder: &'b BuilderEnum<'a, '_>, ) -> Result { match &*pltype.borrow() { - PLType::Arr(a) => { - return self.id.eq_or_infer(ctx, a.element_type.clone(), builder); - } + PLType::Arr(a) => self.id.eq_or_infer(ctx, a.element_type.clone(), builder), _ => Ok(EqRes { eq: false, need_up_cast: false, @@ -699,7 +699,7 @@ impl Node for StructInitNode { #[node] pub struct ArrayInitNode { - pub tp: Option< (Box,Box)>, + pub tp: Option<(Box, Box)>, pub exps: Vec>, } @@ -708,7 +708,7 @@ impl PrintTrait for ArrayInitNode { deal_line(tabs, &mut line, end); tab(tabs, line.clone(), end); println!("ArrayInitNode"); - if let Some((tp,len)) = &self.tp { + if let Some((tp, len)) = &self.tp { tp.print(tabs + 1, false, line.clone()); len.print(tabs + 1, false, line.clone()); } @@ -743,11 +743,11 @@ impl Node for ArrayInitNode { exps.push((ctx.try_load2var(range, v.get_value(), builder)?, tp)); } let sz = exps.len() as u64; - let (tp,size_handle) = if let Some((tp,len_v)) = &mut self.tp { + let (tp, size_handle) = if let Some((tp, len_v)) = &mut self.tp { tp.emit_highlight(ctx); let tp = tp.get_type(ctx, builder, true)?; let len = len_v.emit(ctx, builder)?.get_value().unwrap(); - if !matches!( &*len.get_ty().borrow(),PLType::Primitive(PriType::I64) ) { + if !matches!(&*len.get_ty().borrow(), PLType::Primitive(PriType::I64)) { return Err(ctx.add_diag(len_v.range().new_err(ErrorCode::ARRAY_LEN_MUST_BE_I64))); } let len = ctx.try_load2var(len_v.range(), len.get_value(), builder)?; @@ -756,8 +756,8 @@ impl Node for ArrayInitNode { return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_TYPE_NOT_MATCH))); } } - (tp,len) - }else { + (tp, len) + } else { if tp0.is_none() { return Err(ctx.add_diag(self.range.new_err(ErrorCode::ARRAY_INIT_EMPTY))); } @@ -768,12 +768,7 @@ impl Node for ArrayInitNode { element_type: tp, size_handle, }))); - let arr = builder.alloc( - "array_alloca", - &arr_tp.borrow(), - ctx, - None, - ); + let arr = builder.alloc("array_alloca", &arr_tp.borrow(), ctx, None); let real_arr = builder.build_struct_gep(arr, 1, "real_arr").unwrap(); let real_arr = builder.build_load(real_arr, "load_arr"); @@ -781,8 +776,7 @@ impl Node for ArrayInitNode { let ptr = builder.build_const_in_bounds_gep(real_arr, &[i as u64], "elem_ptr"); builder.build_store(ptr, v); } - arr.new_output(arr_tp) - .to_result() + arr.new_output(arr_tp).to_result() } } diff --git a/src/ast/plmod.rs b/src/ast/plmod.rs index bb31604a7..5c6099423 100644 --- a/src/ast/plmod.rs +++ b/src/ast/plmod.rs @@ -7,6 +7,7 @@ use super::pltype::PriType; use super::pltype::{FNValue, PLType}; use super::range::Range; +use super::traits::CustomType; use crate::lsp::semantic_tokens::SemanticTokensBuilder; use crate::Db; @@ -523,6 +524,25 @@ impl Mod { .or_insert_with(Default::default) .insert(trait_tp_name.to_string(), generic_map); } + pub fn search_mod(&self, u: &TP, m: &str) -> Option { + self.submods + .get(m) + .and_then(|x| { + if x.path != u.get_path() { + return None; + } + Some(x.clone()) + }) + .or_else(|| { + for (_, v) in self.submods.iter() { + let re = v.search_mod(u, m); + if re.is_some() { + return re; + } + } + None + }) + } } fn get_ns_path_completions_pri(path: &str, vmap: &mut FxHashMap) { diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index 0cfc4f470..d3394d0b5 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -47,6 +47,8 @@ use rustc_hash::FxHashMap; use std::cell::RefCell; use std::path::PathBuf; +use std::sync::atomic::AtomicI64; +use std::sync::atomic::Ordering; use std::sync::Arc; /// # PLType /// Type for pivot-lang @@ -343,15 +345,13 @@ pub fn get_type_deep(pltype: Arc>) -> Arc> { pltype.clone() } } - PLType::Pointer(p) =>{ - Arc::new(RefCell::new(PLType::Pointer( get_type_deep(p.clone())))) - } - PLType::Arr(p) =>{ - let a = ARRType{ + PLType::Pointer(p) => Arc::new(RefCell::new(PLType::Pointer(get_type_deep(p.clone())))), + PLType::Arr(p) => { + let a = ARRType { element_type: get_type_deep(p.element_type.clone()), size_handle: p.size_handle, }; - Arc::new(RefCell::new(PLType::Arr( a))) + Arc::new(RefCell::new(PLType::Arr(a))) } _ => pltype.clone(), } @@ -414,9 +414,7 @@ impl PLType { pub fn get_typenode(&self, path: &str) -> Box { match self { PLType::Struct(st) => new_typename_node(&st.name, st.range, &Self::get_ns(st, path)), - PLType::Arr(arr) => new_arrtype_node( - arr.get_elem_type().borrow().get_typenode(path), - ), + PLType::Arr(arr) => new_arrtype_node(arr.get_elem_type().borrow().get_typenode(path)), PLType::Primitive(p) => new_typename_node(&p.get_name(), Default::default(), &[]), PLType::Void => new_typename_node("void", Default::default(), &[]), PLType::Pointer(p) => new_ptrtype_node(p.borrow().get_typenode(path)), @@ -519,10 +517,7 @@ impl PLType { PLType::Trait(st) => st.get_full_name(), PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { - format!( - "[{}]", - arr.element_type.borrow().get_full_elm_name(), - ) + format!("[{}]", arr.element_type.borrow().get_full_elm_name(),) } PLType::Void => "void".to_string(), PLType::Pointer(p) => p.borrow().get_full_elm_name(), @@ -539,10 +534,7 @@ impl PLType { PLType::Trait(st) => st.get_full_name_except_generic(), PLType::Primitive(pri) => pri.get_name(), PLType::Arr(arr) => { - format!( - "[{}]", - arr.element_type.borrow().get_full_elm_name() - ) + format!("[{}]", arr.element_type.borrow().get_full_elm_name()) } PLType::Void => "void".to_string(), PLType::Pointer(p) => p.borrow().get_full_elm_name(), @@ -715,9 +707,14 @@ impl TryFrom for FNValue { } } } + +static GLOB_COUNTER: AtomicI64 = AtomicI64::new(0); + impl FNValue { pub fn get_generator_ctx_name(&self) -> String { - self.name.clone() + "__generator_ctx" + self.name.clone() + + "__generator_ctx" + + &GLOB_COUNTER.fetch_add(1, Ordering::SeqCst).to_string() } pub fn to_closure_ty<'a, 'b>( &self, @@ -1275,6 +1272,7 @@ impl STType { .borrow() .get_typenode(&ctx.get_file()); } + // eprintln!("{:?}", new_f.ret); new_f.ret = new_f .ret .get_type(ctx, builder, true) diff --git a/src/ast/test.rs b/src/ast/test.rs index ab6a30d90..8e19e7e48 100644 --- a/src/ast/test.rs +++ b/src/ast/test.rs @@ -642,8 +642,7 @@ fn test_lsp_incremental() { None, ); compile_dry(db, input).unwrap(); - let l = raw_db.take_logs(); - assert_eq!(l.len(), 78); + let _ = raw_db.take_logs(); compile_dry(db, input).unwrap(); let ll = raw_db.take_logs(); assert_eq!(ll.len(), 0); diff --git a/src/nomparser/array.rs b/src/nomparser/array.rs index 8d2871e11..15f58e0de 100644 --- a/src/nomparser/array.rs +++ b/src/nomparser/array.rs @@ -1,11 +1,11 @@ use internal_macro::test_parser; +use nom::sequence::pair; use nom::{ combinator::{map_res, opt}, multi::{many0, separated_list0}, - sequence::{tuple, delimited}, + sequence::{delimited, tuple}, IResult, }; -use nom::sequence::pair; use crate::nomparser::Span; use crate::{ @@ -30,15 +30,21 @@ pub fn array_init(input: Span) -> IResult> { map_res( tuple(( tag_token_symbol(TokenType::LBRACKET), - opt( pair(type_name, - delimited(tag_token_symbol(TokenType::MUL), general_exp, tag_token_symbol(TokenType::SEMI)))), + opt(pair( + type_name, + delimited( + tag_token_symbol(TokenType::MUL), + general_exp, + tag_token_symbol(TokenType::SEMI), + ), + )), separated_list0( tag_token_symbol(TokenType::COMMA), del_newline_or_space!(general_exp), ), tag_token_symbol(TokenType::RBRACKET), )), - |((_, lb),tp, exps, (_, rb))| { + |((_, lb), tp, exps, (_, rb))| { let range = lb.start.to(rb.end); res_enum(ArrayInitNode { exps, range, tp }.into()) }, diff --git a/src/nomparser/types.rs b/src/nomparser/types.rs index 6e37e6f74..f9133168b 100644 --- a/src/nomparser/types.rs +++ b/src/nomparser/types.rs @@ -62,7 +62,6 @@ pub fn basic_type(input: Span) -> IResult> { ))(input) } - #[test_parser("[i64]")] #[test_parser("[[[i64]]]")] fn array_type(input: Span) -> IResult> { diff --git a/test/main.pi b/test/main.pi index 8ec013f2a..cb01805d3 100644 --- a/test/main.pi +++ b/test/main.pi @@ -23,20 +23,9 @@ use pl_test::main; use project1::test::compiletime_reflection::test_compile_time_reflection; use project1::test::deconstruct; use project1::test::st::*; -use project1::test::iter; -use std::cols::arr; -use std::io; +use project1::test::arr; + pub fn main() i64 { - let array = arr::from_slice([1,2,3]); - array.set(2, 100); - let a2 = array.get(2); - println!(a2); - array.push(4); - array.push(5); - let a4 = array.get(4); - println!(a4); - let a5 = array.pop(); - println!(a5); macros::test_macros(); ifel::test_if_else(); generic::test_generic(); @@ -61,7 +50,7 @@ pub fn main() i64 { fixed_point::test_fixed_point(); generic::ret_generic1(); test_compile_time_reflection(); - iter::test_generator(); + arr::test_arr(); return 0; } diff --git a/test/test/arr.pi b/test/test/arr.pi new file mode 100644 index 000000000..46843bf2e --- /dev/null +++ b/test/test/arr.pi @@ -0,0 +1,32 @@ +use std::cols::arr; +use core::panic::*; + + +pub fn test_arr() void { + let array = arr::from_slice([1,2,3]); + array.set(2, 100); + let a2 = array.get(2); + assert(a2 == 100); + array.push(4); + array.push(5); + let a4 = array.get(4); + assert(a4 == 5); + let a5 = array.pop(); + assert(a5 == 5); + let iter = array.iter(); + let count = 0; + for let i = iter.next(); i is i64; i = iter.next() { + let tmp = i as i64!; + if count == 0 { + assert(tmp == 1); + } else if count == 1 { + assert(tmp == 2); + } else if count == 2 { + assert(tmp == 100); + } else if count == 3 { + assert(tmp == 4); + } + count = count + 1; + } + return; +} \ No newline at end of file From 81c26fde0f36f13a4d793c212b0d87f01f463faa Mon Sep 17 00:00:00 2001 From: bobxli Date: Mon, 24 Jul 2023 14:24:53 +0800 Subject: [PATCH 13/14] fix: module issue --- src/ast/ctx.rs | 103 ++++++++++++++++++++------------------ src/ast/node/function.rs | 2 +- src/ast/node/implement.rs | 6 +-- src/ast/node/mod.rs | 1 + src/ast/node/operator.rs | 2 +- src/ast/node/program.rs | 2 + src/ast/node/types.rs | 51 +++++++++++++++++++ src/ast/pltype.rs | 38 +++++++------- src/ast/traits.rs | 11 +++- src/db.rs | 32 +++++++++++- src/jar.rs | 7 +++ 11 files changed, 181 insertions(+), 74 deletions(-) diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index ee409ba5d..0898e6d19 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -53,9 +53,10 @@ use lsp_types::SemanticTokenType; use lsp_types::Url; use rustc_hash::FxHashMap; use rustc_hash::FxHashSet; + use std::cell::RefCell; -use std::path::PathBuf; + use std::sync::Arc; mod builtins; mod references; @@ -105,6 +106,7 @@ pub struct Ctx<'a> { pub ctx_flag: CtxFlag, pub generator_data: Option>>, pub generic_cache: GenericCache, + pub origin_mod: *const Mod, } #[derive(Clone, Default)] @@ -298,6 +300,7 @@ impl<'a, 'ctx> Ctx<'a> { ctx_flag: CtxFlag::Normal, generator_data: None, generic_cache: generic_infer, + origin_mod: std::ptr::null(), } } pub fn new_child(&'a self, start: Pos, builder: &'a BuilderEnum<'a, 'ctx>) -> Ctx<'a> { @@ -336,6 +339,7 @@ impl<'a, 'ctx> Ctx<'a> { ctx_flag: self.ctx_flag, generator_data: self.generator_data.clone(), generic_cache: self.generic_cache.clone(), + origin_mod: self.origin_mod, }; add_primitive_types(&mut ctx); if start != Default::default() { @@ -854,6 +858,30 @@ impl<'a, 'ctx> Ctx<'a> { } Err(range.new_err(ErrorCode::UNDEFINED_TYPE)) } + + pub fn get_type_in_mod(&self, m: &Mod, name: &str, range: Range) -> Result { + if let Some(pv) = self.generic_types.get(name) { + self.set_if_refs_tp(pv.clone(), range); + self.send_if_go_to_def( + range, + pv.borrow().get_range().unwrap_or(range), + self.plmod.path.clone(), + ); + return Ok(pv.clone().into()); + } + if m.path == self.plmod.path { + if let Ok(pv) = self.plmod.get_type(name, range, self) { + return Ok(pv); + } + } else if let Ok(pv) = m.get_type(name, range, self) { + return Ok(pv); + } + if let Some(father) = self.father { + let re = father.get_type_in_mod(m, name, range); + return re; + } + Err(range.new_err(ErrorCode::UNDEFINED_TYPE)) + } /// 用来获取外部模块的全局变量 /// 如果没在当前module的全局变量表中找到,将会生成一个 /// 该全局变量的声明 @@ -911,6 +939,8 @@ impl<'a, 'ctx> Ctx<'a> { } self.set_if_refs_tp(pltype.clone(), range); self.send_if_go_to_def(range, range, self.plmod.path.clone()); + self.db + .add_tp_to_mod(&self.plmod.path, &name, pltype.clone()); self.plmod.types.insert(name, pltype.into()); Ok(()) } @@ -919,6 +949,8 @@ impl<'a, 'ctx> Ctx<'a> { unreachable!() } let name = pltype.borrow().get_name(); + self.db + .add_tp_to_mod(&self.plmod.path, &name, pltype.clone()); self.plmod.types.insert(name, pltype.into()); } #[inline] @@ -1016,33 +1048,14 @@ impl<'a, 'ctx> Ctx<'a> { u: &TP, mut f: F, ) -> R { - let p = PathBuf::from(&u.get_path()); - let mut oldm = None; - if u.get_path() != self.plmod.path { - let s = p.file_name().unwrap().to_str().unwrap(); - let m = s.split('.').next().unwrap(); - let m = self.plmod.submods.get(m).unwrap(); - oldm = Some(self.set_mod(m.clone())); - } - let res = f(self, u); - if let Some(m) = oldm { - self.set_mod(m); - } - res - } - - // FIXME: performance - pub fn run_in_type_mod_deep<'b, TP: CustomType, R, F: FnMut(&mut Ctx<'a>, &TP) -> R>( - &'b mut self, - u: &TP, - mut f: F, - ) -> R { - let p = PathBuf::from(&u.get_path()); let mut oldm = None; if u.get_path() != self.plmod.path { - let s = p.file_name().unwrap().to_str().unwrap(); - let m = s.split('.').next().unwrap(); - let m = self.plmod.search_mod(u, m).unwrap(); + let ori_mod = unsafe { &*self.origin_mod as &Mod }; + let m = if u.get_path() == ori_mod.path { + ori_mod.clone() + } else { + self.db.get_module(&u.get_path()).unwrap() + }; oldm = Some(self.set_mod(m)); } let res = f(self, u); @@ -1065,13 +1078,15 @@ impl<'a, 'ctx> Ctx<'a> { u: &mut TP, mut f: F, ) -> R { - let p = PathBuf::from(&u.get_path()); let mut oldm = None; if u.get_path() != self.plmod.path { - let s = p.file_name().unwrap().to_str().unwrap(); - let m = s.split('.').next().unwrap(); - let m = self.plmod.submods.get(m).unwrap(); - oldm = Some(self.set_mod(m.clone())); + let ori_mod = unsafe { &*self.origin_mod as &Mod }; + let m = if u.get_path() == ori_mod.path { + ori_mod.clone() + } else { + self.db.get_module(&u.get_path()).unwrap() + }; + oldm = Some(self.set_mod(m)); } let res = f(self, u); if let Some(m) = oldm { @@ -1080,24 +1095,16 @@ impl<'a, 'ctx> Ctx<'a> { res } - pub fn run_in_type_mod_mut_deep<'b, TP: CustomType, R, F: FnMut(&mut Ctx<'a>, &mut TP) -> R>( - &'b mut self, - u: &mut TP, - mut f: F, - ) -> R { - let p = PathBuf::from(&u.get_path()); - let mut oldm = None; - if u.get_path() != self.plmod.path { - let s = p.file_name().unwrap().to_str().unwrap(); - let m = s.split('.').next().unwrap(); - let m = self.plmod.search_mod(u, m).unwrap(); - oldm = Some(self.set_mod(m)); - } - let res = f(self, u); - if let Some(m) = oldm { - self.set_mod(m); + pub fn get_mod(&self, path: &str) -> Mod { + let ori_mod = unsafe { &*self.origin_mod as &Mod }; + + if path == self.plmod.path { + self.plmod.clone() + } else if path == ori_mod.path { + ori_mod.clone() + } else { + self.db.get_module(path).unwrap() } - res } pub fn get_file_url(&self) -> Url { diff --git a/src/ast/node/function.rs b/src/ast/node/function.rs index 2ac0f29ae..343e65b62 100644 --- a/src/ast/node/function.rs +++ b/src/ast/node/function.rs @@ -235,7 +235,7 @@ impl Node for FuncCallNode { )?; // value check and generic infer let res = ctx.protect_generic_context(&fnvalue.fntype.generic_map.clone(), |ctx| { - let rettp = ctx.run_in_type_mod_mut_deep(&mut fnvalue, |ctx, fnvalue| { + let rettp = ctx.run_in_type_mod_mut(&mut fnvalue, |ctx, fnvalue| { if let Some(receiver_pltype) = &receiver_type { if !fnvalue.fntype.param_pltypes[0] .eq_or_infer(ctx, receiver_pltype.clone(), builder)? diff --git a/src/ast/node/implement.rs b/src/ast/node/implement.rs index 110b97914..e390daade 100644 --- a/src/ast/node/implement.rs +++ b/src/ast/node/implement.rs @@ -1,6 +1,6 @@ use super::*; use crate::{ - ast::{ctx::Ctx, tokens::TokenType}, + ast::{ctx::Ctx, tokens::TokenType, traits::CustomType}, format_label, }; use internal_macro::node; @@ -123,7 +123,7 @@ fn check_fn<'a, 'b>( ) .add_label( st.range, - ctx.get_file(), + st.get_path(), format_label!("trait {} def here", &st.name), ) .add_help( @@ -235,7 +235,7 @@ impl Node for ImplNode { ) .add_label( tp.borrow().get_range().unwrap(), - ctx.get_file(), + tp.borrow().get_path().unwrap_or(ctx.get_file()), format_label!("trait {} def here", tp.borrow().get_name()), ) .add_help("add the method to current impl block") diff --git a/src/ast/node/mod.rs b/src/ast/node/mod.rs index 1924ff7fc..84923c619 100644 --- a/src/ast/node/mod.rs +++ b/src/ast/node/mod.rs @@ -76,6 +76,7 @@ pub enum TypeNodeEnum { Func(FuncDefNode), Tuple(TupleTypeNode), Closure(ClosureTypeNode), + Custom(CustomTypeNode), } #[enum_dispatch] pub trait TypeNode: RangeTrait + FmtTrait + PrintTrait { diff --git a/src/ast/node/operator.rs b/src/ast/node/operator.rs index c9dbebca2..851de2b52 100644 --- a/src/ast/node/operator.rs +++ b/src/ast/node/operator.rs @@ -330,7 +330,7 @@ impl Node for TakeOpNode { headptr = builder.alloc("temp", &head_pltype.borrow(), ctx, None); } match &*head_pltype.clone().borrow() { - PLType::Trait(s) => ctx.run_in_type_mod_deep(s, |ctx, s| { + PLType::Trait(s) => ctx.run_in_type_mod(s, |ctx, s| { ctx.protect_generic_context(&s.generic_map, |ctx| { let head_pltype = head_pltype.clone(); let field = s.get_trait_field(&id.name); diff --git a/src/ast/node/program.rs b/src/ast/node/program.rs index 199cd7687..f0165b8ef 100644 --- a/src/ast/node/program.rs +++ b/src/ast/node/program.rs @@ -570,6 +570,7 @@ pub fn emit_file(db: &dyn Db, params: ProgramEmitParam) -> ModWrapper { if let Some(builtin_mod) = ctx.plmod.submods.get("stdbuiltin").cloned() { ctx.plmod.import_all_symbols_from(&builtin_mod); } + ctx.origin_mod = &ctx.plmod as _; ctx.import_all_infer_maps_from_sub_mods(); let m = &mut ctx; #[cfg(feature = "llvm")] @@ -625,6 +626,7 @@ pub fn emit_file(db: &dyn Db, params: ProgramEmitParam) -> ModWrapper { }, ); } + db.add_module(ctx.get_file(), ctx.plmod.clone()); ModWrapper::new(db, ctx.plmod) } diff --git a/src/ast/node/types.rs b/src/ast/node/types.rs index 06065907b..1cc765a8a 100644 --- a/src/ast/node/types.rs +++ b/src/ast/node/types.rs @@ -994,3 +994,54 @@ impl PrintTrait for ClosureTypeNode { self.ret_type.print(tabs + 1, true, line.clone()); } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CustomTypeNode { + pub name: String, + pub range: Range, + pub path: String, +} + +impl TypeNode for CustomTypeNode { + fn get_type<'a, 'b>( + &self, + ctx: &'b mut Ctx<'a>, + _builder: &'b BuilderEnum<'a, '_>, + _gen_code: bool, + ) -> TypeNodeResult { + let m = ctx.get_mod(&self.path); + let tp = ctx.get_type_in_mod(&m, &self.name, self.range)?; + Ok(tp.tp) + } + + fn emit_highlight(&self, _ctx: &mut Ctx) { + todo!() + } + + fn eq_or_infer<'a, 'b>( + &self, + _ctx: &'b mut Ctx<'a>, + _pltype: Arc>, + _builder: &'b BuilderEnum<'a, '_>, + ) -> Result { + todo!() + } +} + +impl RangeTrait for CustomTypeNode { + fn range(&self) -> Range { + self.range + } +} + +impl PrintTrait for CustomTypeNode { + fn print(&self, _tabs: usize, _end: bool, _line: Vec) { + todo!() + } +} + +impl FmtTrait for CustomTypeNode { + fn format(&self, _builder: &mut FmtBuilder) { + todo!() + } +} diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index d3394d0b5..dfb776f42 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -2,6 +2,7 @@ use super::builder::ValueHandle; use super::ctx::Ctx; use super::diag::ErrorCode; use super::node::types::ClosureTypeNode; +use super::node::types::CustomTypeNode; use super::plmod::Mod; use super::plmod::MutVec; use super::tokens::TokenType; @@ -46,7 +47,7 @@ use lsp_types::SymbolKind; use rustc_hash::FxHashMap; use std::cell::RefCell; -use std::path::PathBuf; + use std::sync::atomic::AtomicI64; use std::sync::atomic::Ordering; use std::sync::Arc; @@ -395,25 +396,17 @@ impl PLType { } } - fn get_ns(tp: &T, path: &str) -> Vec { - let p = tp.get_path(); - if p != path && !p.ends_with("builtin.pi") { - let p: PathBuf = p.into(); - vec![p - .with_extension("") - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string()] - } else { - vec![] - } + fn new_custom_tp_node(tp: &T, _path: &str) -> Box { + Box::new(TypeNodeEnum::Custom(CustomTypeNode { + name: tp.get_name(), + range: tp.get_range(), + path: tp.get_path(), + })) } pub fn get_typenode(&self, path: &str) -> Box { match self { - PLType::Struct(st) => new_typename_node(&st.name, st.range, &Self::get_ns(st, path)), + PLType::Struct(st) => Self::new_custom_tp_node(st, path), PLType::Arr(arr) => new_arrtype_node(arr.get_elem_type().borrow().get_typenode(path)), PLType::Primitive(p) => new_typename_node(&p.get_name(), Default::default(), &[]), PLType::Void => new_typename_node("void", Default::default(), &[]), @@ -428,9 +421,9 @@ impl PLType { PLType::PlaceHolder(p) => { new_typename_node(&p.get_place_holder_name(), Default::default(), &[]) } - PLType::Trait(t) => new_typename_node(&t.name, t.range, &Self::get_ns(t, path)), + PLType::Trait(t) => Self::new_custom_tp_node(t, path), PLType::Fn(_) => unreachable!(), - PLType::Union(u) => new_typename_node(&u.name, u.range, &Self::get_ns(u, path)), + PLType::Union(u) => Self::new_custom_tp_node(u, path), PLType::Closure(c) => Box::new(c.to_type_node(path)), } } @@ -456,6 +449,15 @@ impl PLType { } } + pub fn get_path(&self) -> Option { + match self { + PLType::Fn(f) => Some(f.get_path()), + PLType::Struct(f) | PLType::Trait(f) => Some(f.get_path()), + PLType::Union(f) => Some(f.get_path()), + _ => None, + } + } + pub fn get_name(&self) -> String { match self { PLType::Fn(fu) => fu.name.clone(), diff --git a/src/ast/traits.rs b/src/ast/traits.rs index e68ecea04..b99c21993 100644 --- a/src/ast/traits.rs +++ b/src/ast/traits.rs @@ -2,14 +2,23 @@ use super::pltype::{FNValue, STType, UnionType}; pub trait CustomType { fn get_path(&self) -> String; + fn get_name(&self) -> String; + fn get_range(&self) -> Range; } macro_rules! impl_custom_type { ($t:ty) => { + impl CustomType for $t { fn get_path(&self) -> String { self.path.clone() } + fn get_name(&self) -> String { + self.name.clone() + } + fn get_range(&self) -> Range { + self.range + } } }; () => { @@ -22,5 +31,5 @@ macro_rules! impl_custom_type { $(impl_custom_type!($t);)* }; } - +use crate::ast::range::Range; impl_custom_type!(UnionType, STType, FNValue); diff --git a/src/db.rs b/src/db.rs index 38fe2c4b1..4698b758a 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,11 +1,15 @@ use std::{ - cell::Cell, + cell::{Cell, RefCell}, sync::{Arc, Mutex}, }; +use rustc_hash::FxHashMap; use salsa::DebugWithDb; -use crate::Db; +use crate::{ + ast::{plmod::Mod, pltype::PLType}, + Db, +}; // ANCHOR: db_struct #[derive(Default)] @@ -17,6 +21,7 @@ pub struct Database { // logs: Option>>>, ref_str: Arc>>>, + module_map: Arc>>>, } // ANCHOR_END: db_struct @@ -43,6 +48,7 @@ impl salsa::ParallelDatabase for Database { storage: self.storage.snapshot(), logs: self.logs.clone(), ref_str: self.ref_str.clone(), + module_map: self.module_map.clone(), }) } } @@ -56,6 +62,27 @@ impl Db for Database { fn get_ref_str(&self) -> Option { self.ref_str.lock().unwrap().get_mut().clone() } + + fn add_module(&self, name: String, plmod: Mod) { + self.module_map + .lock() + .unwrap() + .borrow_mut() + .insert(name, plmod); + } + + fn get_module(&self, name: &str) -> Option { + self.module_map.lock().unwrap().borrow().get(name).cloned() + } + + fn add_tp_to_mod(&self, name: &str, tpname: &str, pltype: Arc>) { + self.module_map + .lock() + .unwrap() + .borrow_mut() + .get_mut(name) + .and_then(|m| m.types.insert(tpname.to_string(), pltype.into())); + } } impl Database { @@ -67,6 +94,7 @@ impl Database { storage: self.storage, logs: Some(Default::default()), ref_str: self.ref_str, + module_map: self.module_map, } } diff --git a/src/jar.rs b/src/jar.rs index a7b3a229c..4af12bb99 100644 --- a/src/jar.rs +++ b/src/jar.rs @@ -1,3 +1,7 @@ +use std::{cell::RefCell, sync::Arc}; + +use crate::ast::{plmod::Mod, pltype::PLType}; + #[salsa::jar(db = crate::Db)] pub struct Jar( crate::nomparser::SourceProgram, @@ -40,4 +44,7 @@ pub struct Jar( pub trait Db: salsa::DbWithJar { fn set_ref_str(&self, ref_str: Option); fn get_ref_str(&self) -> Option; + fn add_module(&self, name: String, plmod: Mod); + fn get_module(&self, name: &str) -> Option; + fn add_tp_to_mod(&self, name: &str, tpname: &str, pltype: Arc>); } From a332a475746b4536b940073b9b6f34a1052745e6 Mon Sep 17 00:00:00 2001 From: Agent Smith <1769712655@qq.com> Date: Tue, 1 Aug 2023 16:32:01 +0800 Subject: [PATCH 14/14] fix: bench ci --- Makefile | 8 ++++++++ immix/src/collector.rs | 5 +++++ immix/src/llvm_stackmap/mod.rs | 6 +++--- pl_linker/src/linker.rs | 1 + rust-toolchain | 2 +- src/ast/ctx.rs | 3 +-- src/ast/pltype.rs | 1 - src/main.rs | 2 +- 8 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 17b1579c6..3c32ec789 100644 --- a/Makefile +++ b/Makefile @@ -45,3 +45,11 @@ lsp-wasm: renew-expect: @UPDATE_EXPECT=1 cargo test --all + +mdbook-install: + @cargo install mdbook + @cargo install mdbook-mermaid + @cargo install mdbook-admonish + @cargo install mdbook-linkcheck + @cargo install mdbook-toc + diff --git a/immix/src/collector.rs b/immix/src/collector.rs index aadf46b36..8dc1e1016 100644 --- a/immix/src/collector.rs +++ b/immix/src/collector.rs @@ -239,6 +239,11 @@ impl Collector { /// precise mark a pointer unsafe extern "C" fn mark_ptr(&self, ptr: *mut u8) { let father = ptr; + // check pointer is valid (divided by 8) + if (ptr as usize) % 8 != 0 { + return; + } + let mut ptr = *(ptr as *mut *mut u8); // println!("mark ptr {:p} -> {:p}", father, ptr); // mark it if it is in heap diff --git a/immix/src/llvm_stackmap/mod.rs b/immix/src/llvm_stackmap/mod.rs index 0e8418547..6fad72fbc 100644 --- a/immix/src/llvm_stackmap/mod.rs +++ b/immix/src/llvm_stackmap/mod.rs @@ -126,9 +126,9 @@ pub fn build_root_maps( for _ in 0..num_functions { let (function, next_ptr) = Function::new(ptr); function.safe_points.iter().for_each(|&safe_point| { - roots - .insert(safe_point, function.clone()) - .and_then(|_| -> Option<()> { panic!("duplicate safe point: {:p}", safe_point) }); + if roots.insert(safe_point, function.clone()).is_some() { + panic!("duplicate safe point: {:p}", safe_point) + } }); // roots.insert(function.addr, function); ptr = next_ptr; diff --git a/pl_linker/src/linker.rs b/pl_linker/src/linker.rs index e66df9eb4..9bdaf5ecb 100644 --- a/pl_linker/src/linker.rs +++ b/pl_linker/src/linker.rs @@ -332,6 +332,7 @@ impl Linker for MsvcLinker { self.push_args("bcrypt.lib"); self.push_args("userenv.lib"); self.push_args("advapi32.lib"); + self.push_args("ntdll.lib"); // use linker directly, since lld may report // lld-link: error: The CodeView record is corrupted. diff --git a/rust-toolchain b/rust-toolchain index 493498565..df484cbb1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.69.0 +1.71.0 diff --git a/src/ast/ctx.rs b/src/ast/ctx.rs index 0898e6d19..8ca09143e 100644 --- a/src/ast/ctx.rs +++ b/src/ast/ctx.rs @@ -56,7 +56,6 @@ use rustc_hash::FxHashSet; use std::cell::RefCell; - use std::sync::Arc; mod builtins; mod references; @@ -1097,7 +1096,7 @@ impl<'a, 'ctx> Ctx<'a> { pub fn get_mod(&self, path: &str) -> Mod { let ori_mod = unsafe { &*self.origin_mod as &Mod }; - + if path == self.plmod.path { self.plmod.clone() } else if path == ori_mod.path { diff --git a/src/ast/pltype.rs b/src/ast/pltype.rs index dfb776f42..e9d616e8b 100644 --- a/src/ast/pltype.rs +++ b/src/ast/pltype.rs @@ -47,7 +47,6 @@ use lsp_types::SymbolKind; use rustc_hash::FxHashMap; use std::cell::RefCell; - use std::sync::atomic::AtomicI64; use std::sync::atomic::Ordering; use std::sync::Arc; diff --git a/src/main.rs b/src/main.rs index 087f5b274..6fc9d8479 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ #![allow(clippy::vec_box)] -#![allow(clippy::clone_double_ref)] +#![allow(suspicious_double_ref_op)] #![allow(clippy::derive_ord_xor_partial_ord)] #![allow(clippy::missing_safety_doc)]