Skip to content

Commit 93b1720

Browse files
committed
feat: trait derive
1 parent 9a69da7 commit 93b1720

File tree

8 files changed

+76
-19
lines changed

8 files changed

+76
-19
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ use_statement = "use" identifier ("::" identifier)* ";" ;
168168
169169
string_literal = "\"" [^"]* "\"" ;
170170
171-
trait_def = "trait" identifier generic_type_def? "{" function_def* "}" ;
171+
trait_def = "trait" identifier generic_type_def? (":" type_add)? "{" function_def* "}" ;
172+
173+
type_add = type_name ("+" type_name)* ;
172174
173175
```

src/ast/node/implement.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ impl Node for ImplNode {
6363
.add_label(t.range(), Some(("type {}".to_string(), vec![name])))
6464
.add_to_ctx(ctx);
6565
};
66-
sttp.impls.push(trait_tp);
66+
sttp.impls
67+
.insert(trait_tp.clone().borrow().get_full_elm_name(), trait_tp);
6768
}
6869
ctx.send_if_go_to_def(self.target.range(), sttp.range, sttp.path.clone());
6970
}

src/ast/node/interface.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct TraitDefNode {
1515
pub id: Box<VarNode>,
1616
pub generics: Option<Box<GenericDefNode>>,
1717
pub methods: Vec<FuncDefNode>,
18+
pub derives: Vec<Box<TypeNodeEnum>>,
1819
}
1920

2021
impl PrintTrait for TraitDefNode {
@@ -39,8 +40,11 @@ impl Node for TraitDefNode {
3940
for g in &mut self.generics {
4041
g.emit(ctx, builder)?;
4142
}
42-
for method in &mut self.methods {
43-
method.emit(ctx, builder)?;
43+
for de in &self.derives {
44+
de.emit_highlight(ctx);
45+
}
46+
for method in &self.methods {
47+
method.emit_highlight(ctx);
4448
}
4549
Ok((None, None, TerminatorEnum::NONE))
4650
}
@@ -65,7 +69,8 @@ impl TraitDefNode {
6569
refs: Rc::new(RefCell::new(vec![])),
6670
doc: vec![],
6771
generic_map,
68-
impls: vec![],
72+
impls: FxHashMap::default(),
73+
derives: vec![],
6974
})));
7075
builder.opaque_struct_type(&ctx.plmod.get_full_name(&self.id.name));
7176
_ = ctx.add_type(self.id.name.clone(), stu, self.id.range);
@@ -90,6 +95,10 @@ impl TraitDefNode {
9095
);
9196
}
9297
}
98+
let mut derives = vec![];
99+
for de in &self.derives {
100+
derives.push(de.get_type(ctx, builder)?);
101+
}
93102
// type hash
94103
order_fields.push(Field {
95104
index: i,
@@ -125,6 +134,7 @@ impl TraitDefNode {
125134
range: field.range,
126135
refs: Rc::new(RefCell::new(vec![])),
127136
};
137+
field.get_type(ctx, builder)?;
128138

129139
ctx.set_if_refs(f.refs.clone(), field.id.range);
130140
fields.insert(id.name.to_string(), f.clone());
@@ -143,6 +153,7 @@ impl TraitDefNode {
143153
if let PLType::TRAIT(st) = &mut *pltype.borrow_mut() {
144154
st.fields = fields;
145155
st.ordered_fields = newf;
156+
st.derives = derives;
146157
// st.doc = self.doc.clone();
147158
}
148159
ctx.set_if_refs_tp(pltype.clone(), self.id.range);

src/ast/node/mod.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ impl<'a, 'ctx> Ctx<'a> {
243243
let expect = expect.unwrap();
244244
let range = node.range();
245245
let pri: Result<PrimaryNode, _> = (*node.clone()).try_into();
246+
// basic type implicit cast
246247
if let Ok(pri) = pri {
247248
let num: Result<NumNode, _> = (*pri.value.clone()).try_into();
248249
if let Ok(numnode) = num {
@@ -333,16 +334,7 @@ impl<'a, 'ctx> Ctx<'a> {
333334
// struct to trait
334335
(PLType::TRAIT(t), PLType::STRUCT(st)) => {
335336
let handle = builder.alloc("tmp_traitv", &expect.borrow(), self);
336-
if st
337-
.impls
338-
.iter()
339-
.find(|i| {
340-
let ty1: &PLType = &i.borrow();
341-
let ty2: &PLType = &expect.borrow();
342-
ty1 == ty2
343-
})
344-
.is_none()
345-
{
337+
if !st.implements_trait(t) {
346338
return Err(mismatch_err!(
347339
self,
348340
range,

src/ast/node/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ impl StructDefNode {
408408
refs: Rc::new(RefCell::new(vec![])),
409409
doc: vec![],
410410
generic_map,
411-
impls: vec![],
411+
impls: FxHashMap::default(),
412+
derives: vec![],
412413
})));
413414
builder.opaque_struct_type(&ctx.plmod.get_full_name(&self.id.name));
414415
_ = ctx.add_type(self.id.name.clone(), stu, self.id.range);

src/ast/pltype.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,10 +632,27 @@ pub struct STType {
632632
pub refs: Rc<RefCell<Vec<Location>>>,
633633
pub doc: Vec<Box<NodeEnum>>,
634634
pub generic_map: IndexMap<String, Rc<RefCell<PLType>>>,
635-
pub impls: Vec<Rc<RefCell<PLType>>>,
635+
pub impls: FxHashMap<String, Rc<RefCell<PLType>>>,
636+
pub derives: Vec<Rc<RefCell<PLType>>>,
636637
}
637638

638639
impl STType {
640+
pub fn implements(&self, tp: &PLType) -> bool {
641+
self.impls.get(&tp.get_full_elm_name()).is_some()
642+
}
643+
pub fn implements_trait(&self, tp: &STType) -> bool {
644+
let re = self.impls.get(&tp.get_st_full_name()).is_some();
645+
if !re {
646+
return re;
647+
}
648+
for de in &tp.derives {
649+
let re = self.implements(&de.borrow());
650+
if !re {
651+
return re;
652+
}
653+
}
654+
true
655+
}
639656
pub fn get_type_code(&self) -> u64 {
640657
let full_name = self.get_st_full_name();
641658
get_hash_code(full_name)

src/nomparser/types.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
},
1313
};
1414
use internal_macro::{test_parser, test_parser_error};
15+
use nom::sequence::preceded;
1516
use nom::{
1617
branch::alt,
1718
bytes::complete::tag,
@@ -156,12 +157,19 @@ pub fn trait_def(input: Span) -> IResult<Span, Box<TraitDefNode>> {
156157
tag_token_word(TokenType::TRAIT),
157158
identifier,
158159
opt(generic_type_def),
160+
opt(preceded(tag_token_symbol(TokenType::COLON), type_add)),
159161
del_newline_or_space!(tag_token_symbol(TokenType::LBRACE)),
160162
many0(del_newline_or_space!(function_def)),
161163
del_newline_or_space!(tag_token_symbol(TokenType::RBRACE)),
162164
)),
163-
|(_, id, generics, _, defs, (_, rr))| {
165+
|(_, id, generics, derives, _, defs, (_, rr))| {
164166
let range = id.range().start.to(rr.end);
167+
let mut de = vec![];
168+
if let Some(derives) = derives {
169+
for d in derives {
170+
de.push(d);
171+
}
172+
}
165173
Ok::<_, Error>(Box::new(TraitDefNode {
166174
id,
167175
generics,
@@ -173,7 +181,25 @@ pub fn trait_def(input: Span) -> IResult<Span, Box<TraitDefNode>> {
173181
})
174182
.collect(),
175183
range,
184+
derives: de,
176185
}))
177186
},
178187
)(input)
179188
}
189+
190+
/// ```enbf
191+
/// type_add = type_name ("+" type_name)* ;
192+
/// ```
193+
#[test_parser("a+b+c")]
194+
#[test_parser("a")]
195+
#[test_parser(
196+
"a + b
197+
+
198+
c"
199+
)]
200+
fn type_add(input: Span) -> IResult<Span, Vec<Box<TypeNodeEnum>>> {
201+
separated_list1(
202+
del_newline_or_space!(tag_token_symbol(TokenType::PLUS)),
203+
type_name,
204+
)(input)
205+
}

test/main.pi

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ impl TestTrait for mod1::Mod1 {
152152
return i;
153153
}
154154

155+
}
156+
impl TestTrait2 for mod1::Mod1 {
157+
155158
}
156159

157160
fn test_trait() void {
@@ -381,11 +384,15 @@ fn main() i64 {
381384
test_trait();
382385
return 0;
383386
}
384-
trait TestTrait {
387+
trait TestTrait:TestTrait2 {
385388
fn name() void;
386389
fn test_ret(i:i64) i64;
387390
}
388391

392+
trait TestTrait2 {
393+
394+
}
395+
389396
fn test_many_params(a: i64, b: i64, c: i64, d: i64) void {
390397
return;
391398
}

0 commit comments

Comments
 (0)