diff --git a/compiler/pipec-ast/src/ast/mod.rs b/compiler/pipec-ast/src/ast/mod.rs index 6b72655..e2c4dd9 100644 --- a/compiler/pipec-ast/src/ast/mod.rs +++ b/compiler/pipec-ast/src/ast/mod.rs @@ -79,6 +79,7 @@ impl<'this> ASTGenerator<'this> { Token::PublicKeyword => self.consume_public_keyword(), Token::TypeKeyword => self.consume_type_keyword(), Token::TraitKeyword => self.consume_trait_keyword(), + Token::ImplementKeyword => self.consume_implement_keyword(), Token::AtSign => self.consume_attributes(), _v => { println!("{_v:#?}"); @@ -89,6 +90,56 @@ impl<'this> ASTGenerator<'this> { } } + #[inline] + pub(crate) fn consume_implement_keyword(&mut self) -> ASTNode { + self.advance_stream(); + let generics = self.consume_generics(); + self.consume_whitespace(); + let first = self.consume_a_path(); + let second = { + self.consume_whitespace(); + match self.peek_stream() { + Some(Token::ForKeyword) => { + self.advance_stream(); + self.consume_whitespace(); + Some(self.consume_a_path()) + } + Some(Token::LeftCurly) => None, + v => todo!("unexpected {v:#?}"), + } + }; + self.consume_whitespace(); + let block = { + self.must(Token::LeftCurly); + let mut nodes = Vec::new(); + loop { + self.consume_whitespace(); + if self.peek_stream() == &Some(Token::RightCurly) { + self.advance_stream(); + break; + } + nodes.push(self.parse_value()); + } + ASTTree::new(nodes, self.src) + }; + + if let Some(implementor) = second { + ASTNode::ImplementBlock { + generics, + traitpath: Some(first), + implementor, + block, + } + } else { + ASTNode::ImplementBlock { + generics, + traitpath: second, + implementor: first, + block, + } + } + } + #[inline] pub(crate) fn consume_trait_keyword(&mut self) -> ASTNode { self.advance_stream(); @@ -132,6 +183,7 @@ impl<'this> ASTGenerator<'this> { .parse_arena(self.loader.load(self.src), self.arena); match name { "language" => attributes.push(self.consume_language_attribute()), + "inline" => attributes.push(self.consume_inline_attribute()), _ => todo!(), } } else { @@ -141,6 +193,11 @@ impl<'this> ASTGenerator<'this> { ASTNode::Attributed(attributes, Box::new(self.parse_value())) } + #[inline] + pub(crate) fn consume_inline_attribute(&mut self) -> Attribute { + Attribute::Inline + } + #[inline] pub(crate) fn consume_language_attribute(&mut self) -> Attribute { self.must(Token::LeftParenthesis); @@ -366,13 +423,13 @@ impl<'this> ASTGenerator<'this> { self.consume_whitespace(); match self.peek_stream() { Some(Token::Ident(_)) => { - let name = self.must_ident(); - let generics = self.consume_generics(); - out.push(Trait { name, generics }); + out.push(self.consume_a_path()); self.consume_whitespace(); if self.next_is(Token::Plus) { self.advance_stream(); continue; + } else { + break; } } Some(Token::Comma) | Some(Token::RightSquare) | Some(Token::LeftCurly) => { @@ -1173,33 +1230,31 @@ impl<'this> ASTGenerator<'this> { Some(Token::Ident(v)) => { let name = *v; self.advance_stream(); - let param = self.consume_path_param(); - out.push(PathNode::Named { name, param }); - continue; - } - Some(Token::Slash) => { - self.advance_stream(); - continue; + let generics = self.consume_generics(); + out.push(PathNode::Singly { name, generics }); + if self.next_is(Token::Backslash) { + self.advance_stream(); + continue; + } else { + break; + } } Some(Token::LeftParenthesis) => { self.advance_stream(); let mut vals = Vec::new(); loop { self.consume_whitespace(); - match self.advance_stream() { - Some(Token::Ident(v)) => { - vals.push(v); - continue; - } - Some(Token::RightParenthesis) => { - break; - } - Some(Token::Comma) => { - continue; - } - _v => {} + vals.push(self.consume_a_path()); + self.consume_whitespace(); + if self.next_is(Token::Comma) { + self.advance_stream(); + continue; + } else { + break; } } + out.push(PathNode::Multi(vals)); + self.must(Token::RightParenthesis); } _ => { break; @@ -1209,62 +1264,12 @@ impl<'this> ASTGenerator<'this> { Path(out) } - #[inline] - pub(crate) fn consume_path_param(&mut self) -> Option { - match self.peek_stream() { - Some(Token::LeftParenthesis) => { - if let Expression::TupleExpression { values } = self.consume_tuple_expression() { - return Some(FunctionNodeParams::Tuple(values)); - } - // TODO : compiler error - unreachable!(); - } - Some(Token::LeftAngle) => Some(FunctionNodeParams::Angles(self.consume_angle_params())), - _v => None, - } - } #[inline] pub(crate) fn consume_whitespace(&mut self) { while self.tokens.peek() == &Some(Token::Whitespace) { self.tokens.next_token(); } } - - #[inline] - pub(crate) fn consume_angle_params(&mut self) -> Vec { - self.must(Token::LeftAngle); - let mut out = Vec::new(); - loop { - self.consume_whitespace(); - match self.peek_stream() { - Some(Token::Ident(_)) => { - out.push(self.consume_a_path()); - self.consume_whitespace(); - match self.peek_stream() { - Some(Token::Comma) => { - self.advance_stream(); - continue; - } - Some(Token::Ident(_)) => { - continue; - } - Some(Token::RightAngle) => { - break; - } - _ => { - //TODO : compiler error - unreachable!() - } - } - } - _ => { - //TODO : compiler error - unreachable!() - } - } - } - out - } } #[derive(Clone, Debug, Hash)] @@ -1273,11 +1278,8 @@ pub struct Path(pub Vec); #[derive(Debug, Clone, Hash)] pub enum PathNode { - Named { - name: Span, - param: Option, - }, - Tuple(Vec), + Singly { name: Span, generics: Generics }, + Multi(Vec), } #[derive(Debug, Clone, Hash)] @@ -1327,6 +1329,12 @@ pub enum ASTNode { supertraits: Traits, tree: ASTTree, }, + ImplementBlock { + generics: Generics, + traitpath: Option, + implementor: Path, + block: ASTTree, + }, Public(Box), Attributed(Vec, Box), EOF, @@ -1335,6 +1343,7 @@ pub enum ASTNode { #[derive(Debug, Clone)] pub enum Attribute { LanguageAttribute(Span), + Inline, } #[derive(Debug, Clone)] @@ -1501,10 +1510,10 @@ pub struct FunctionDeclarationParameter { pub arg_type: Path, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub struct Generics(pub Vec); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] #[allow(unused)] pub struct Generic { name: Span, @@ -1512,18 +1521,11 @@ pub struct Generic { traits: Traits, } -#[derive(Debug, Clone, Default)] -#[allow(unused)] -pub struct Traits(Vec); - -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash, Default)] #[allow(unused)] -pub struct Trait { - name: Span, - generics: Generics, -} +pub struct Traits(Vec); -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Hash)] pub enum GenericType { Lifetime, Generic, diff --git a/compiler/pipec-ast/src/tokenizer/mod.rs b/compiler/pipec-ast/src/tokenizer/mod.rs index 2586643..3a3df72 100644 --- a/compiler/pipec-ast/src/tokenizer/mod.rs +++ b/compiler/pipec-ast/src/tokenizer/mod.rs @@ -81,10 +81,12 @@ impl<'chars> Tokenizer<'chars> { '=' => self.consume_equal_sign(), '"' => self.consume_string(), '#' => self.consume_hash(), + '\\' => self.consume_backslash(), v if v.is_ascii_whitespace() => self.consume_whitespace(), v if v.is_ascii_alphabetic() => self.consume_ident_token(), v if v.is_ascii_digit() => self.consume_digit_token(), _v => { + println!("unexpected token {_v}"); //TODO : compiler error unreachable!() } @@ -106,6 +108,12 @@ impl<'chars> Tokenizer<'chars> { } } + #[inline] + pub(crate) fn consume_backslash(&mut self) -> Token { + self.advance_stream(); + Token::Backslash + } + #[inline] pub(crate) fn consume_left_paranthesis(&mut self) -> Token { self.advance_stream(); @@ -436,6 +444,8 @@ impl<'chars> Tokenizer<'chars> { "switch" => SwitchKeyword, "type" => TypeKeyword, "trait" => TraitKeyword, + "implement" => ImplementKeyword, + "for" => ForKeyword, _ => Token::Ident(input), } } @@ -529,6 +539,8 @@ pub enum Token { RightAngle, /// # Hash, + /// \ + Backslash, /// (whitespace) Whitespace, /// using @@ -565,6 +577,10 @@ pub enum Token { TypeKeyword, /// trait TraitKeyword, + /// implement + ImplementKeyword, + /// for + ForKeyword, /// 21213 Digit { val: Span, digittype: DigitType }, /// things_like_this or this_2 diff --git a/compiler/pipec-gst/src/lib.rs b/compiler/pipec-gst/src/lib.rs index a49738a..beeaa46 100644 --- a/compiler/pipec-gst/src/lib.rs +++ b/compiler/pipec-gst/src/lib.rs @@ -132,7 +132,7 @@ impl<'this> GlobalSymbolTree<'this> { let first = vec.first(); match first { None => {} - Some(PathNode::Named { name, param: _ }) => { + Some(PathNode::Singly { name, generics: _ }) => { let name = name.parse_arena(self.src, self.arena); match name { "integer8" => return Integer8, @@ -167,7 +167,7 @@ impl<'this> GlobalSymbolTree<'this> { if next.is_none() { break; } - if let Some(PathNode::Named { name, param: _ }) = next { + if let Some(PathNode::Singly { name, generics: _ }) = next { let parsed = name.parse_arena(self.src, self.arena).to_string(); out.path.push(parsed); }