diff --git a/src/kind-parser/src/expr.rs b/src/kind-parser/src/expr.rs index a83c7eae..30e8366b 100644 --- a/src/kind-parser/src/expr.rs +++ b/src/kind-parser/src/expr.rs @@ -1,4 +1,4 @@ -use kind_tree::expr::{Expr, ExprKind, Literal, Match, Open, Operator, Sttm, SttmKind, Substitution}; +use kind_tree::concrete::expr::*; use kind_tree::symbol::{Ident, Symbol}; use crate::errors::SyntaxError; @@ -75,7 +75,7 @@ impl<'a> Parser<'a> { let name = self.parse_id()?; self.eat_variant(Token::Slash)?; let redx = self.parse_num_lit()?; - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; let span = start.mix(expr.span); Ok(Box::new(Expr { data: ExprKind::Subst(Substitution { name, redx, indx: 0, expr }), @@ -96,31 +96,38 @@ impl<'a> Parser<'a> { let ident = self.parse_id()?; self.bump(); // '=>' - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; let end_range = expr.span; Ok(Box::new(Expr { - data: ExprKind::Lambda(ident, expr), + data: ExprKind::Lambda(ident, None, expr), span: name_span.mix(end_range), })) } - fn parse_pi(&mut self) -> Result, SyntaxError> { + fn parse_pi_or_lambda(&mut self) -> Result, SyntaxError> { let span = self.span(); self.bump(); // '(' let ident = self.parse_id()?; self.bump(); // ':' - let typ = self.parse_expr()?; + let typ = self.parse_expr(false)?; let _ = self.eat_variant(Token::RPar)?; - self.eat_keyword(Token::RightArrow); - let body = self.parse_expr()?; - - Ok(Box::new(Expr { - span: span.mix(body.span), - data: ExprKind::All(Some(ident), typ, body), - })) + if self.eat_keyword(Token::FatArrow) { + let body = self.parse_expr(false)?; + Ok(Box::new(Expr { + span: span.mix(body.span), + data: ExprKind::Lambda(ident, Some(typ), body), + })) + } else { + self.eat_keyword(Token::RightArrow); + let body = self.parse_expr(false)?; + Ok(Box::new(Expr { + span: span.mix(body.span), + data: ExprKind::All(Some(ident), typ, body), + })) + } } fn parse_sigma_type(&mut self) -> Result, SyntaxError> { @@ -128,12 +135,12 @@ impl<'a> Parser<'a> { self.bump(); // '[' let ident = self.parse_id()?; self.bump(); // ':' - let typ = self.parse_expr()?; + let typ = self.parse_expr(false)?; self.eat_variant(Token::RPar)?; let end = self.eat_variant(Token::RightArrow)?.1; - let body = self.parse_expr()?; + let body = self.parse_expr(false)?; Ok(Box::new(Expr { span: span.mix(end), @@ -194,7 +201,7 @@ impl<'a> Parser<'a> { return Ok(Box::new(Expr { span, data: ExprKind::List(vec) })); } - vec.push(*self.parse_expr()?); + vec.push(*self.parse_expr(false)?); let mut initialized = false; let mut with_comma = false; loop { @@ -205,7 +212,7 @@ impl<'a> Parser<'a> { } if with_comma { self.eat_keyword(Token::Comma); - match self.try_single(&|x| x.parse_expr())? { + match self.try_single(&|x| x.parse_expr(false))? { Some(res) => vec.push(*res), None => break, } @@ -229,10 +236,10 @@ impl<'a> Parser<'a> { } else { let span = self.span(); self.bump(); // '(' - let mut expr = self.parse_expr()?; + let mut expr = self.parse_expr(true)?; if self.get().same_variant(Token::ColonColon) { self.bump(); // '::' - let typ = self.parse_expr()?; + let typ = self.parse_expr(false)?; let span = span.mix(self.eat_variant(Token::RPar)?.1); Ok(Box::new(Expr { data: ExprKind::Ann(expr, typ), @@ -254,7 +261,7 @@ impl<'a> Parser<'a> { data: ExprKind::Help(Ident { data: Symbol(str), ctx: self.ctx, - span + span, }), })) } @@ -282,12 +289,12 @@ impl<'a> Parser<'a> { } } - fn parse_call(&mut self) -> Result, SyntaxError> { + fn parse_call(&mut self, multiline: bool) -> Result, SyntaxError> { let head = self.parse_atom()?; let start = head.span; let mut spine = Vec::new(); let mut end = head.span; - while !self.breaks[0] && !self.get().same_variant(Token::Eof) { + while (!self.is_linebreak() || multiline) && !self.get().same_variant(Token::Eof) { let res = self.try_single(&|parser| parser.parse_atom())?; match res { Some(atom) => { @@ -307,10 +314,10 @@ impl<'a> Parser<'a> { } } - fn parse_arrow(&mut self) -> Result, SyntaxError> { - let mut head = self.parse_call()?; + fn parse_arrow(&mut self, multiline: bool) -> Result, SyntaxError> { + let mut head = self.parse_call(multiline)?; while self.eat_keyword(Token::RightArrow) { - let next = self.parse_expr()?; + let next = self.parse_expr(false)?; let span = head.span.mix(next.span); head = Box::new(Expr { data: ExprKind::All(None, head, next), @@ -318,12 +325,12 @@ impl<'a> Parser<'a> { }); } if self.eat_keyword(Token::ColonColon) { - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; Ok(Box::new(Expr { span: head.span.mix(expr.span), data: ExprKind::Ann(head, expr), })) - }else { + } else { Ok(head) } } @@ -340,7 +347,7 @@ impl<'a> Parser<'a> { None }; - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; self.eat_keyword(Token::Semi); let next = self.parse_sttm()?; let end = expr.span; @@ -355,7 +362,7 @@ impl<'a> Parser<'a> { self.bump(); // 'let' let name = self.parse_id()?; self.eat_variant(Token::Eq)?; - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; self.eat_keyword(Token::Semi); let next = self.parse_sttm()?; let end = expr.span; @@ -368,7 +375,7 @@ impl<'a> Parser<'a> { pub fn parse_return(&mut self) -> Result, SyntaxError> { let start = self.span(); self.bump(); // 'return' - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; let end = expr.span; Ok(Box::new(Sttm { data: SttmKind::Return(expr), @@ -385,7 +392,7 @@ impl<'a> Parser<'a> { } else if self.check_actual(Token::Let) { self.parse_monadic_let() } else { - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; if self.get().same_variant(Token::RBrace) { let end = expr.span; Ok(Box::new(Sttm { @@ -406,11 +413,12 @@ impl<'a> Parser<'a> { pub fn parse_do(&mut self) -> Result, SyntaxError> { let start = self.span(); self.bump(); // 'do' + let typ = self.parse_id()?; self.eat_variant(Token::LBrace)?; let sttm = self.parse_sttm()?; let end = self.eat_variant(Token::RBrace)?.1; Ok(Box::new(Expr { - data: ExprKind::Do(sttm), + data: ExprKind::Do(typ, sttm), span: start.mix(end), })) } @@ -421,7 +429,7 @@ impl<'a> Parser<'a> { let tipo = self.parse_id()?; let name = self.parse_id()?; - let expr = if self.eat_keyword(Token::Eq) { Some(self.parse_expr()?) } else { None }; + let expr = if self.eat_keyword(Token::Eq) { Some(self.parse_expr(false)?) } else { None }; self.eat_variant(Token::LBrace)?; @@ -429,16 +437,16 @@ impl<'a> Parser<'a> { while !self.get().same_variant(Token::RBrace) { let case = self.parse_id()?; self.eat_variant(Token::FatArrow)?; - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; cases.push((case, expr)) } let mut end = self.eat_variant(Token::RBrace)?.1; let motive = if self.eat_keyword(Token::Colon) { - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; end = expr.span; - Some(self.parse_expr()?) + Some(self.parse_expr(false)?) } else { None }; @@ -457,9 +465,9 @@ impl<'a> Parser<'a> { let tipo = self.parse_id()?; let name = self.parse_id()?; - let expr = if self.eat_keyword(Token::Eq) { Some(self.parse_expr()?) } else { None }; + let expr = if self.eat_keyword(Token::Eq) { Some(self.parse_expr(false)?) } else { None }; - let body = self.parse_expr()?; + let body = self.parse_expr(false)?; let end = body.span; let open = Box::new(Open { tipo, name, expr, body }); @@ -475,9 +483,9 @@ impl<'a> Parser<'a> { self.bump(); // 'let' let name = self.parse_id()?; self.eat_variant(Token::Eq)?; - let expr = self.parse_expr()?; + let expr = self.parse_expr(false)?; self.eat_keyword(Token::Semi); - let next = self.parse_expr()?; + let next = self.parse_expr(false)?; let end = next.span; Ok(Box::new(Expr { data: ExprKind::Let(name, expr, next), @@ -500,13 +508,13 @@ impl<'a> Parser<'a> { fn parse_if(&mut self) -> Result, SyntaxError> { let start = self.span(); self.bump(); // 'if' - let cond = self.parse_expr()?; + let cond = self.parse_expr(false)?; self.eat_variant(Token::LBrace)?; - let if_ = self.parse_expr()?; + let if_ = self.parse_expr(false)?; self.eat_variant(Token::RBrace)?; self.eat_variant(Token::Else)?; self.eat_variant(Token::LBrace)?; - let els_ = self.parse_expr()?; + let els_ = self.parse_expr(false)?; let end = self.eat_variant(Token::RBrace)?.1; let span = start.mix(end); Ok(Box::new(Expr { @@ -518,7 +526,7 @@ impl<'a> Parser<'a> { /// The infinite hell of else ifs. But it's the most readable way /// to check if the queue of tokens match a pattern as we need /// some looakhead tokens. - pub fn parse_expr(&mut self) -> Result, SyntaxError> { + pub fn parse_expr(&mut self, multiline: bool) -> Result, SyntaxError> { if self.check_actual(Token::Do) { self.parse_do() } else if self.check_actual(Token::Match) { @@ -534,13 +542,13 @@ impl<'a> Parser<'a> { } else if self.is_lambda() { self.parse_lambda() } else if self.is_pi_type() { - self.parse_pi() + self.parse_pi_or_lambda() } else if self.is_sigma_type() { self.parse_sigma_type() } else if self.is_substitution() { self.parse_substitution() } else { - self.parse_arrow() + self.parse_arrow(multiline) } } } diff --git a/src/kind-parser/src/lexer/literals.rs b/src/kind-parser/src/lexer/literals.rs index f1843aec..b776d92c 100644 --- a/src/kind-parser/src/lexer/literals.rs +++ b/src/kind-parser/src/lexer/literals.rs @@ -61,7 +61,7 @@ impl<'a> Lexer<'a> { /// Lex numbers with decimal, hexadecimal, binary or octal. pub fn lex_number(&mut self) -> (Token, Span) { - let start = self.pos; + let start = self.span(); match self.peekable.peek() { None => (Token::Eof, self.mk_span(start)), Some('0') => { @@ -86,7 +86,7 @@ impl<'a> Lexer<'a> { /// acummulate the error until the end of the string. /// TODO: Accumulate multiple encoding errors? pub fn lex_string(&mut self) -> (Token, Span) { - let start = self.pos; + let start = self.span(); self.next_char(); @@ -94,7 +94,7 @@ impl<'a> Lexer<'a> { let mut error: Option<(Token, Span)> = None; while let Some(&x) = self.peekable.peek() { - let chr_start = self.pos; + let chr_start = self.span(); match x { '\"' => break, '\\' => { diff --git a/src/kind-parser/src/lexer/mod.rs b/src/kind-parser/src/lexer/mod.rs index 6082d869..a82691ca 100644 --- a/src/kind-parser/src/lexer/mod.rs +++ b/src/kind-parser/src/lexer/mod.rs @@ -1,3 +1,5 @@ +use std::sync::mpsc::Sender; + use kind_span::Span; use crate::errors::SyntaxError; @@ -22,8 +24,7 @@ fn is_valid_id_start(chr: char) -> bool { } impl<'a> Lexer<'a> { - pub fn single_token(&mut self, token: Token) -> (Token, Span) { - let start = self.pos; + pub fn single_token(&mut self, token: Token, start: usize) -> (Token, Span) { self.next_char(); (token, self.mk_span(start)) } @@ -49,12 +50,12 @@ impl<'a> Lexer<'a> { } } - pub fn get_next_no_error(&mut self, vec: &mut Vec>) -> (Token, Span) { + pub fn get_next_no_error(&mut self, vec: &Sender>) -> (Token, Span) { loop { let (token, span) = self.lex_token(); match token { Token::Error(x) => { - vec.push(x); + let _ = vec.send(x); continue; } Token::Comment(false, _) => continue, @@ -66,7 +67,7 @@ impl<'a> Lexer<'a> { } pub fn lex_token(&mut self) -> (Token, Span) { - let start = self.pos; + let start = self.span(); match self.peekable.peek() { None => (Token::Eof, self.mk_span(start)), Some(chr) => match chr { @@ -83,40 +84,40 @@ impl<'a> Lexer<'a> { let str = self.accumulate_while(&is_valid_id); (Lexer::to_keyword(str), self.mk_span(start)) } - '(' => self.single_token(Token::LPar), - ')' => self.single_token(Token::RPar), - '[' => self.single_token(Token::LBracket), - ']' => self.single_token(Token::RBracket), - '{' => self.single_token(Token::LBrace), - '}' => self.single_token(Token::RBrace), + '(' => self.single_token(Token::LPar, start), + ')' => self.single_token(Token::RPar, start), + '[' => self.single_token(Token::LBracket, start), + ']' => self.single_token(Token::RBracket, start), + '{' => self.single_token(Token::LBrace, start), + '}' => self.single_token(Token::RBrace, start), '#' => { self.next_char(); match self.peekable.peek() { - Some('#') => self.single_token(Token::HashHash), + Some('#') => self.single_token(Token::HashHash, start), _ => (Token::Hash, self.mk_span(start)), } } '=' => { self.next_char(); match self.peekable.peek() { - Some('>') => self.single_token(Token::FatArrow), - Some('=') => self.single_token(Token::EqEq), + Some('>') => self.single_token(Token::FatArrow, start), + Some('=') => self.single_token(Token::EqEq, start), _ => (Token::Eq, self.mk_span(start)), } } '>' => { self.next_char(); match self.peekable.peek() { - Some('>') => self.single_token(Token::GreaterGreater), - Some('=') => self.single_token(Token::GreaterEq), + Some('>') => self.single_token(Token::GreaterGreater, start), + Some('=') => self.single_token(Token::GreaterEq, start), _ => (Token::Greater, self.mk_span(start)), } } '<' => { self.next_char(); match self.peekable.peek() { - Some('<') => self.single_token(Token::LessLess), - Some('=') => self.single_token(Token::LessEq), + Some('<') => self.single_token(Token::LessLess, start), + Some('=') => self.single_token(Token::LessEq, start), _ => (Token::Less, self.mk_span(start)), } } @@ -131,26 +132,26 @@ impl<'a> Lexer<'a> { ':' => { self.next_char(); match self.peekable.peek() { - Some(':') => self.single_token(Token::ColonColon), + Some(':') => self.single_token(Token::ColonColon, start), _ => (Token::Colon, self.mk_span(start)), } } - ';' => self.single_token(Token::Semi), - '$' => self.single_token(Token::Dollar), - ',' => self.single_token(Token::Comma), - '+' => self.single_token(Token::Plus), + ';' => self.single_token(Token::Semi, start), + '$' => self.single_token(Token::Dollar, start), + ',' => self.single_token(Token::Comma, start), + '+' => self.single_token(Token::Plus, start), '-' => { self.next_char(); match self.peekable.peek() { - Some('>') => self.single_token(Token::RightArrow), + Some('>') => self.single_token(Token::RightArrow, start), _ => (Token::Minus, self.mk_span(start)), } } - '*' => self.single_token(Token::Star), - '%' => self.single_token(Token::Percent), - '&' => self.single_token(Token::Ampersand), - '|' => self.single_token(Token::Bar), - '^' => self.single_token(Token::Hat), + '*' => self.single_token(Token::Star, start), + '%' => self.single_token(Token::Percent, start), + '&' => self.single_token(Token::Ampersand, start), + '|' => self.single_token(Token::Bar, start), + '^' => self.single_token(Token::Hat, start), '"' => self.lex_string(), '?' => { self.next_char(); @@ -160,7 +161,7 @@ impl<'a> Lexer<'a> { '!' => { self.next_char(); match self.peekable.peek() { - Some('=') => self.single_token(Token::BangEq), + Some('=') => self.single_token(Token::BangEq, start), _ => (Token::Bang, self.mk_span(start)), } } diff --git a/src/kind-parser/src/lexer/state.rs b/src/kind-parser/src/lexer/state.rs index 497f3b3c..37fce473 100644 --- a/src/kind-parser/src/lexer/state.rs +++ b/src/kind-parser/src/lexer/state.rs @@ -12,7 +12,6 @@ pub struct Lexer<'a> { pub ctx: SyntaxCtxIndex, // Modes - pub semis: u16, pub comment_depth: u16, pub errs: Vec>, pub emit_comment: bool, @@ -25,15 +24,18 @@ impl<'a> Lexer<'a> { pos: 0, ctx, peekable, - semis: 0, comment_depth: 0, errs: Vec::new(), emit_comment: false, } } + pub fn span(&self) -> usize { + self.pos + } + pub fn mk_span(&self, start: usize) -> Span { - Span::new(Range::new(Pos(start as u32), Pos(self.pos as u32), self.ctx)) + Span::new(Range::new(Pos { index: start as u32 }, Pos { index: self.pos as u32 }, self.ctx)) } pub fn next_char(&mut self) -> Option { diff --git a/src/kind-parser/src/lexer/tokens.rs b/src/kind-parser/src/lexer/tokens.rs index a3c8752a..20175648 100644 --- a/src/kind-parser/src/lexer/tokens.rs +++ b/src/kind-parser/src/lexer/tokens.rs @@ -77,4 +77,12 @@ impl Token { pub fn is_id(&self) -> bool { matches!(self, Token::Id(_)) } + + pub fn is_str(&self) -> bool { + matches!(self, Token::Str(_)) + } + + pub fn is_num(&self) -> bool { + matches!(self, Token::Num(_)) + } } diff --git a/src/kind-parser/src/lib.rs b/src/kind-parser/src/lib.rs index 1264e479..777867f3 100644 --- a/src/kind-parser/src/lib.rs +++ b/src/kind-parser/src/lib.rs @@ -1,7 +1,7 @@ -mod errors; - +pub mod errors; pub mod expr; pub mod macros; +pub mod pat; pub mod state; pub mod top_level; diff --git a/src/kind-parser/src/pat.rs b/src/kind-parser/src/pat.rs new file mode 100644 index 00000000..aa5b81ad --- /dev/null +++ b/src/kind-parser/src/pat.rs @@ -0,0 +1,114 @@ +use kind_tree::concrete::pat::{Pat, PatKind}; + +use crate::errors::SyntaxError; +use crate::lexer::tokens::Token; +use crate::macros::eat_single; +use crate::state::Parser; + +impl<'a> Parser<'a> { + pub fn is_pat_cons(&self) -> bool { + self.get().same_variant(Token::LPar) && self.peek(1).is_id() + } + + pub fn parse_pat_constructor(&mut self) -> Result, SyntaxError> { + let start = self.span(); + self.bump(); // '(' + let name = self.parse_id()?; + let mut pats = Vec::new(); + while let Some(res) = self.try_single(&|s| s.parse_pat())? { + pats.push(res) + } + let end = self.eat_variant(Token::RPar)?.1; + Ok(Box::new(Pat { + span: start.mix(end), + data: PatKind::App(name, pats), + })) + } + + pub fn parse_pat_num(&mut self) -> Result, SyntaxError> { + let start = self.span(); + let num = eat_single!(self, Token::Num(n) => *n)?; + Ok(Box::new(Pat { + span: start, + data: PatKind::Num(num), + })) + } + + pub fn parse_pat_str(&mut self) -> Result, SyntaxError> { + let start = self.span(); + let string = eat_single!(self, Token::Str(str) => str.clone())?; + Ok(Box::new(Pat { + span: start, + data: PatKind::Str(string), + })) + } + + pub fn parse_pat_group(&mut self) -> Result, SyntaxError> { + let start = self.span(); + self.bump(); // '(' + let mut pat = self.parse_pat()?; + let end = self.eat_variant(Token::RPar)?.1; + pat.span = start.mix(end); + Ok(pat) + } + + pub fn parse_pat_var(&mut self) -> Result, SyntaxError> { + let id = self.parse_id()?; + Ok(Box::new(Pat { + span: id.span, + data: PatKind::Var(id), + })) + } + + fn parse_pat_list(&mut self) -> Result, SyntaxError> { + let span = self.span(); + self.bump(); // '[' + let mut vec = Vec::new(); + + if self.check_actual(Token::RBracket) { + let span = self.advance().1.mix(span); + return Ok(Box::new(Pat { span, data: PatKind::List(vec) })); + } + + vec.push(*self.parse_pat()?); + let mut initialized = false; + let mut with_comma = false; + loop { + let ate_comma = self.eat_keyword(Token::Comma); + if !initialized { + initialized = true; + with_comma = ate_comma; + } + if with_comma { + self.eat_keyword(Token::Comma); + } + + match self.try_single(&|x| x.parse_pat())? { + Some(res) => vec.push(*res), + None => break, + } + } + + let span = self.eat_variant(Token::RBracket)?.1.mix(span); + + Ok(Box::new(Pat { span, data: PatKind::List(vec) })) + } + + pub fn parse_pat(&mut self) -> Result, SyntaxError> { + if self.is_pat_cons() { + self.parse_pat_constructor() + } else if self.get().is_str() { + self.parse_pat_str() + } else if self.get().is_num() { + self.parse_pat_num() + } else if self.check_actual(Token::LPar) { + self.parse_pat_group() + } else if self.get().is_id() { + self.parse_pat_var() + } else if self.check_actual(Token::LBrace) { + self.parse_pat_list() + } else { + self.fail(vec![]) + } + } +} diff --git a/src/kind-parser/src/state.rs b/src/kind-parser/src/state.rs index 08d5a351..99f6862b 100644 --- a/src/kind-parser/src/state.rs +++ b/src/kind-parser/src/state.rs @@ -1,3 +1,6 @@ +use std::collections::VecDeque; +use std::sync::mpsc::Sender; + use kind_span::{Span, SyntaxCtxIndex}; use crate::{errors::SyntaxError, lexer::tokens::Token, Lexer}; @@ -12,83 +15,42 @@ pub struct Parser<'a> { // We have to shift these things one position // to the left so idk what i should use it here // probably the movement will not affect it so much. - pub queue: [(Token, Span); 3], - pub breaks: [bool; 3], - pub errs: Vec>, + pub queue: VecDeque<(Token, Span)>, + pub breaks: VecDeque, + pub errs: &'a Sender>, pub eaten: u32, pub ctx: SyntaxCtxIndex, } impl<'a> Parser<'a> { - pub fn new(mut lexer: Lexer<'a>, ctx: SyntaxCtxIndex) -> Parser<'a> { - let mut errs = Vec::new(); - let mut queue = [(Token::Eof, Span::Generated), (Token::Eof, Span::Generated), (Token::Eof, Span::Generated)]; - let mut breaks = [false, false, false]; - for i in 0..3 { - breaks[i] = lexer.is_linebreak(); - queue[i] = lexer.get_next_no_error(&mut errs); + pub fn new(mut lexer: Lexer<'a>, ctx: SyntaxCtxIndex, sender: &'a Sender>) -> Parser<'a> { + let mut queue = VecDeque::with_capacity(3); + let mut breaks = VecDeque::with_capacity(3); + for _ in 0..3 { + breaks.push_back(lexer.is_linebreak()); + queue.push_back(lexer.get_next_no_error(sender)); } Parser { lexer, queue, breaks, - errs, + errs: sender, eaten: 0, ctx, } } pub fn advance(&mut self) -> (Token, Span) { - let cur = self.queue[0].clone(); - for i in 0..2 { - self.breaks[i] = self.breaks[i + 1]; - self.queue[i] = self.queue[i + 1].clone(); - } - self.breaks[2] = self.lexer.is_linebreak(); - self.queue[2] = self.lexer.get_next_no_error(&mut self.errs); + let cur = self.queue.pop_front().unwrap(); + self.breaks.pop_front(); + self.breaks.push_back(self.lexer.is_linebreak()); + self.queue.push_back(self.lexer.get_next_no_error(self.errs)); self.eaten += 1; cur } - #[inline] - pub fn bump(&mut self) { - self.advance(); - } - - #[inline] - pub fn fail(&mut self, expect: Vec) -> Result { - Err(SyntaxError::UnexpectedToken(self.queue[0].0.clone(), self.queue[0].1, expect)) - } - - pub fn eat_variant(&mut self, expect: Token) -> Result<(Token, Span), SyntaxError> { - if self.queue[0].0.same_variant(expect.clone()) { - Ok(self.advance()) - } else { - self.fail(vec![expect]) - } - } - - pub fn eat(&mut self, expect: fn(&Token) -> Option) -> Result { - match expect(&self.queue[0].0) { - None => self.fail(vec![]), - Some(res) => { - self.advance(); - Ok(res) - } - } - } - - pub fn eat_keyword(&mut self, expect: Token) -> bool { - if self.queue[0].0.same_variant(expect) { - self.advance(); - true - } else { - false - } - } - - pub fn check_actual(&mut self, expect: Token) -> bool { - self.queue[0].0.same_variant(expect) + pub fn is_linebreak(&self) -> bool { + self.breaks[0] } #[inline] @@ -106,6 +68,47 @@ impl<'a> Parser<'a> { self.queue[0].1 } + #[inline] + pub fn bump(&mut self) { + self.advance(); + } + + #[inline] + pub fn fail(&mut self, expect: Vec) -> Result { + Err(SyntaxError::UnexpectedToken(self.get().clone(), self.span(), expect)) + } + + pub fn eat_variant(&mut self, expect: Token) -> Result<(Token, Span), SyntaxError> { + if self.get().same_variant(expect.clone()) { + Ok(self.advance()) + } else { + self.fail(vec![expect]) + } + } + + pub fn eat(&mut self, expect: fn(&Token) -> Option) -> Result { + match expect(self.get()) { + None => self.fail(vec![]), + Some(res) => { + self.advance(); + Ok(res) + } + } + } + + pub fn eat_keyword(&mut self, expect: Token) -> bool { + if self.get().same_variant(expect) { + self.advance(); + true + } else { + false + } + } + + pub fn check_actual(&mut self, expect: Token) -> bool { + self.get().same_variant(expect) + } + pub fn try_single(&mut self, fun: &dyn Fn(&mut Parser<'a>) -> Result) -> Result, SyntaxError> { let current = self.eaten; match fun(self) { diff --git a/src/kind-parser/src/top_level.rs b/src/kind-parser/src/top_level.rs index bbe3b2ac..bbd115b1 100644 --- a/src/kind-parser/src/top_level.rs +++ b/src/kind-parser/src/top_level.rs @@ -1,6 +1,8 @@ +/// Parses all of the top level structures +/// like Book, Entry, Rule and Argument. use std::collections::HashMap; -use kind_tree::{Argument, Entry, Rule, Book}; +use kind_tree::concrete::{Argument, Book, Entry, Rule}; use crate::errors::SyntaxError; use crate::lexer::tokens::Token; @@ -23,7 +25,7 @@ impl<'a> Parser<'a> { let start = self.span(); let erased = self.eat_keyword(Token::Minus); - let keep = self.eat_keyword(Token::Plus); + let keep = self.eat_keyword(Token::Plus); let complement = self.complement_binding_op(); match &complement { @@ -34,7 +36,7 @@ impl<'a> Parser<'a> { let hidden = is_hidden_arg(complement.as_ref().unwrap()); let name = self.parse_id()?; - let tipo = if self.eat_keyword(Token::Colon) { Some(self.parse_expr()?) } else { None }; + let tipo = if self.eat_keyword(Token::Colon) { Some(self.parse_expr(false)?) } else { None }; let erased = if hidden { !keep } else { erased }; let res = self.eat_variant(complement.unwrap())?.1; @@ -56,10 +58,10 @@ impl<'a> Parser<'a> { } let mut pats = Vec::new(); while !self.get().same_variant(Token::Eq) && !self.get().same_variant(Token::Eof) { - pats.push(self.parse_atom()?); + pats.push(self.parse_pat()?); } self.eat_variant(Token::Eq)?; - let body = self.parse_expr()?; + let body = self.parse_expr(false)?; let end = start.mix(body.span); Ok(Box::new(Rule { name: ident, @@ -81,7 +83,7 @@ impl<'a> Parser<'a> { args.push(self.parse_argument()?); } self.eat_variant(Token::Colon)?; - let tipo = self.parse_expr()?; + let tipo = self.parse_expr(false)?; let mut rules = Vec::new(); loop { let res = self.try_single(&|parser| parser.parse_rule(ident.data.0.clone()))?; @@ -90,7 +92,7 @@ impl<'a> Parser<'a> { None => break, } } - let end = rules.last().as_ref().map(|x| x.span.clone()).unwrap_or(tipo.span); + let end = rules.last().as_ref().map(|x| x.span).unwrap_or(tipo.span); Ok(Box::new(Entry { name: ident, docs, @@ -110,14 +112,12 @@ impl<'a> Parser<'a> { break; } let entry = self.parse_entry()?; - if let Some(_) = entrs.get(&entry.name.data.0) { - - } else { + if entrs.get(&entry.name.data.0).is_none() { names.push(entry.name.clone()); entrs.insert(entry.name.data.0.clone(), entry); } } self.eat_variant(Token::Eof)?; - Ok(Book { names, entrs, holes: 0 }) + Ok(Book { names, entrs }) } } diff --git a/src/kind-span/src/lib.rs b/src/kind-span/src/lib.rs index 87dae87c..2300c131 100644 --- a/src/kind-span/src/lib.rs +++ b/src/kind-span/src/lib.rs @@ -1,10 +1,12 @@ // Position in a syntax context. #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct Pos(pub u32); +pub struct Pos { + pub index: u32, +} // A syntax context index. #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] -pub struct SyntaxCtxIndex(pub u32); +pub struct SyntaxCtxIndex(pub usize); // A span in the encoded format that is required by // kind2. @@ -60,7 +62,7 @@ impl Range { #[inline] pub fn encode(&self) -> EncodedSpan { - EncodedSpan(((self.ctx.0 as u64) << 48) | ((self.start.0 as u64) & 0xFFFFFF) | (((self.end.0 as u64) & 0xFFFFFF) << 24)) + EncodedSpan(((self.ctx.0 as u64) << 48) | ((self.start.index as u64) & 0xFFFFFF) | (((self.end.index as u64) & 0xFFFFFF) << 24)) } } @@ -107,9 +109,13 @@ impl EncodedSpan { /// Transforms a encoded span back into a range. pub fn to_range(&self) -> Range { Range { - ctx: SyntaxCtxIndex((self.0 >> 48) as u32), - start: Pos((self.0 & 0xFFFFFF) as u32), - end: Pos(((self.0 >> 24) & 0xFFFFFF) as u32), + ctx: SyntaxCtxIndex((self.0 >> 48) as usize), + start: Pos { + index: (self.0 & 0xFFFFFF) as u32, + }, + end: Pos { + index: ((self.0 >> 24) & 0xFFFFFF) as u32, + }, } } diff --git a/src/kind-tree/src/expr.rs b/src/kind-tree/src/concrete/expr.rs similarity index 90% rename from src/kind-tree/src/expr.rs rename to src/kind-tree/src/concrete/expr.rs index 5ff6e148..4ca4c127 100644 --- a/src/kind-tree/src/expr.rs +++ b/src/kind-tree/src/concrete/expr.rs @@ -2,11 +2,11 @@ /// without parenthesis. It helps when it comes to /// a static analysis of the tree with the syntax sugars /// and it makes it easier to split phases. - -use crate::symbol::Ident; use kind_span::Span; use std::fmt::{Display, Error, Formatter}; +use crate::symbol::Ident; + /// Enum of binary operators. #[derive(Copy, Clone, Debug)] pub enum Operator { @@ -83,13 +83,13 @@ pub enum SttmKind { Ask(Option, Box, Box), Let(Ident, Box, Box), Open(Ident, Ident, Option>, Box), - Return(Box) + Return(Box), } #[derive(Clone, Debug)] pub struct Sttm { pub data: SttmKind, - pub span: Span + pub span: Span, } #[derive(Clone, Debug)] @@ -101,7 +101,7 @@ pub enum ExprKind { /// The dependent product space (e.g. [x : Int] -> y) Sigma(Option, Box, Box), /// A anonymous function that receives one argument - Lambda(Ident, Box), + Lambda(Ident, Option>, Box), /// Application of a expression to a spine of expressions App(Box, Spine), /// Declaration of a local variable @@ -113,7 +113,7 @@ pub enum ExprKind { /// Binary operation (e.g. 2 + 3) Binary(Operator, Box, Box), /// A expression open to unification (e.g. _) - Hole(u64), + Hole, /// Substituion Subst(Substitution), /// A match block that will be translated @@ -123,13 +123,15 @@ pub enum ExprKind { /// into the eliminator of a record datatype. Open(Box), /// Do notation - Do(Box), + Do(Ident, Box), /// If else statement - If(Box,Box,Box), + If(Box, Box, Box), /// If else statement - Pair(Box,Box), + Pair(Box, Box), /// Array - List(Vec) + List(Vec), + /// Help + Help(Ident), } #[derive(Clone, Debug)] @@ -238,17 +240,17 @@ impl Display for Match { write!(f, "match {} {}", self.tipo, self.name)?; match &self.expr { None => Ok(()), - Some(res) => write!(f, " = {}", res) + Some(res) => write!(f, " = {}", res), }?; match &self.motive { None => Ok(()), - Some(res) => write!(f, " : {}", res) + Some(res) => write!(f, " : {}", res), }?; - write!(f," {{ ")?; + write!(f, " {{ ")?; for (case, expr) in &self.cases { write!(f, "{} => {}; ", case, expr)? } - write!(f,"}}") + write!(f, "}}") } } @@ -257,13 +259,12 @@ impl Display for Open { write!(f, "open {} {}", self.tipo, self.name)?; match &self.expr { None => Ok(()), - Some(res) => write!(f, " = {}", res) + Some(res) => write!(f, " = {}", res), }?; write!(f, " {}", self.body) } } - impl Display for Substitution { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { write!(f, "## {} / {} {}", self.name, self.redx, self.expr) @@ -274,12 +275,13 @@ impl Display for Expr { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { use ExprKind::*; match &self.data { - Do(sttms) => write!(f, "({})", sttms), + Do(id, sttms) => write!(f, "do {} ({})", id, sttms), All(_, _, _) => write!(f, "({})", self.traverse_pi_types()), Sigma(_, _, _) => write!(f, "({})", self.traverse_pi_types()), Lit(lit) => write!(f, "{}", lit), Var(name) => write!(f, "{}", name), - Lambda(binder, body) => write!(f, "({} => {})", binder, body), + Lambda(binder, None, body) => write!(f, "({} => {})", binder, body), + Lambda(binder, Some(typ), body) => write!(f, "(({} : {}) => {})", binder, typ, body), Pair(fst, snd) => write!(f, "($ {} {})", fst, snd), App(head, spine) => write!(f, "({}{})", head, spine.iter().map(|x| format!(" {}", x)).collect::()), Let(name, expr, body) => write!(f, "(let {} = {}; {})", name, expr, body), @@ -287,10 +289,11 @@ impl Display for Expr { List(vec) => write!(f, "[{}]", vec.iter().map(|x| format!("{}", x)).collect::>().join(" ")), Ann(expr, typ) => write!(f, "({} : {})", expr, typ), Binary(op, expr, typ) => write!(f, "({} {} {})", op, expr, typ), - Hole(_) => write!(f, "_"), + Hole => write!(f, "_"), Match(matcher) => write!(f, "({})", matcher), Open(open) => write!(f, "({})", open), - Subst(subst) => write!(f, "({})", subst), + Subst(subst) => write!(f, "({})", subst), + Help(name) => write!(f, "?{}", name), } } } diff --git a/src/kind-tree/src/concrete/mod.rs b/src/kind-tree/src/concrete/mod.rs new file mode 100644 index 00000000..bd5f40dc --- /dev/null +++ b/src/kind-tree/src/concrete/mod.rs @@ -0,0 +1,133 @@ +use std::collections::HashMap; +use std::fmt::{Display, Error, Formatter}; + +use crate::symbol::Ident; +use expr::Expr; +use kind_span::Span; + +use self::pat::Pat; + +pub mod expr; +pub mod pat; +pub mod visitor; + +/// A value of a attribute +#[derive(Clone, Debug)] +pub enum AttributeStyle { + Ident(Ident), + String(String), + Number(Span, u64), +} + +/// A attribute is a kind of declaration +/// that usually is on the top of a declaration +/// and can be attached to a function declaration +/// it express some compiler properties +#[derive(Clone, Debug)] +pub struct Attribute { + pub name: Ident, + pub value: Option, + pub span: Span, +} + +/// An argument is a 'binding' of a name to a type +/// it has some other options like +/// eras: that express the erasure of this type when +/// compiled. +/// hide: that express a implicit argument (that will +/// be discovered through unification). +#[derive(Clone, Debug)] +pub struct Argument { + pub hidden: bool, + pub erased: bool, + pub name: Ident, + pub tipo: Option>, + pub span: Span, +} + +/// A rule is a equation that in the left-hand-side +/// contains a list of patterns @pats@ and on the +/// right hand side a value. +#[derive(Clone, Debug)] +pub struct Rule { + pub name: Ident, + pub pats: Vec>, + pub body: Box, + pub span: Span, +} + +/// An entry describes a function that is typed +/// and has rules. The type of the function +/// consists of the arguments @args@ and the +/// return type @tipo@. +#[derive(Clone, Debug)] +pub struct Entry { + pub name: Ident, + pub docs: Option, + pub args: Vec>, + pub tipo: Box, + pub rules: Vec>, + pub attrs: Vec, + pub span: Span, +} + +// A book is a collection of entries. +#[derive(Clone, Debug, Default)] +pub struct Book { + pub names: Vec, + pub entrs: HashMap>, +} + +// Display + +impl Display for Book { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + for name in &self.names { + writeln!(f, "{}\n", self.entrs.get(&name.data.0).unwrap())?; + } + Ok(()) + } +} + +impl Display for Argument { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + let (open, close) = match (self.erased, self.hidden) { + (false, false) => ("(", ")"), + (false, true) => ("+<", ">"), + (true, false) => ("-(", ")"), + (true, true) => ("<", ">"), + }; + match &self.tipo { + Some(tipo) => write!(f, "{}{}: {}{}", open, self.name, tipo, close), + None => write!(f, "{}{}:{}", open, self.name, close), + } + } +} + +impl Display for Entry { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.name.clone())?; + + for arg in &self.args { + write!(f, " {}", arg)?; + } + + write!(f, " : {}", &self.tipo)?; + + for rule in &self.rules { + write!(f, "\n{}", rule)? + } + + Ok(()) + } +} + +impl Display for Rule { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.name)?; + for pat in &self.pats { + write!(f, " {}", pat)?; + } + write!(f, " = {}", self.body) + } +} diff --git a/src/kind-tree/src/concrete/pat.rs b/src/kind-tree/src/concrete/pat.rs new file mode 100644 index 00000000..892588cc --- /dev/null +++ b/src/kind-tree/src/concrete/pat.rs @@ -0,0 +1,43 @@ +use std::fmt::{Display, Error, Formatter}; + +use kind_span::Span; + +use crate::symbol::Ident; + +#[derive(Clone, Debug)] +pub enum PatKind { + /// Name of a variable + Var(Ident), + // Application of a constructor + App(Ident, Vec>), + // Hole + Num(u64), + // Pair + Pair(Box, Box), + // List + List(Vec), + // Str + Str(String), + Hole, +} + +#[derive(Clone, Debug)] +pub struct Pat { + pub data: PatKind, + pub span: Span, +} + +impl Display for Pat { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + use PatKind::*; + match &self.data { + Var(name) => write!(f, "{}", name), + App(head, spine) => write!(f, "({}{})", head, spine.iter().map(|x| format!(" {}", x)).collect::()), + List(vec) => write!(f, "[{}]", vec.iter().map(|x| format!("{}", x)).collect::>().join(" ")), + Str(str) => write!(f, "\"{}\"", str), + Num(num) => write!(f, "{}", num), + Pair(fst, snd) => write!(f, "({}, {})", fst, snd), + Hole => write!(f, "_"), + } + } +} diff --git a/src/kind-tree/src/concrete/visitor.rs b/src/kind-tree/src/concrete/visitor.rs new file mode 100644 index 00000000..f20945f5 --- /dev/null +++ b/src/kind-tree/src/concrete/visitor.rs @@ -0,0 +1,315 @@ +use kind_span::{Span, SyntaxCtxIndex}; + +use crate::concrete::expr::*; +use crate::symbol::*; + +use super::{ + expr, + pat::{Pat, PatKind}, + Argument, Attribute, Book, Entry, Rule, +}; + +/// A visitor trait following the visitor pattern +/// because it's easier to walk the entire tree +/// just by some nodes without writing some functions +/// to walk through everything (yeah i really hate +/// OOP patterns but this time it's really useful.) +/// +/// All of these functions are implemented so we can easily +/// change these default implementations. + +pub trait Visitor: Sized { + fn visit_span(&mut self, x: &mut Span) { + walk_span(self, x); + } + + fn visit_syntax_ctx(&mut self, synt: &mut SyntaxCtxIndex) { + walk_syntax_ctx(self, synt); + } + + fn visit_operator(&mut self, op: &mut expr::Operator) { + walk_operator(self, op); + } + + fn visit_literal(&mut self, lit: &mut Literal) { + walk_literal(self, lit); + } + + fn visit_ident(&mut self, ident: &mut Ident) { + walk_ident(self, ident); + } + + fn visit_open(&mut self, open: &mut Open) { + walk_open(self, open); + } + + fn visit_match(&mut self, matcher: &mut Match) { + walk_match(self, matcher); + } + + fn visit_argument(&mut self, argument: &mut Argument) { + walk_argument(self, argument); + } + + fn visit_entry(&mut self, entry: &mut Entry) { + walk_entry(self, entry); + } + + fn visit_attr(&mut self, attr: &mut Attribute) { + walk_attr(self, attr); + } + + fn visit_pat(&mut self, pat: &mut Pat) { + walk_pat(self, pat); + } + + fn visit_rule(&mut self, rule: &mut Rule) { + walk_rule(self, rule); + } + + fn visit_book(&mut self, book: &mut Book) { + walk_book(self, book); + } + + fn visit_substitution(&mut self, subst: &mut Substitution) { + walk_substitution(self, subst); + } + + fn visit_sttm(&mut self, sttm: &mut Sttm) { + walk_sttm(self, sttm); + } + + fn visit_expr(&mut self, expr: &mut Expr) { + walk_expr(self, expr); + } +} + +fn walk_span(_: &mut T, _: &mut Span) {} + +fn walk_syntax_ctx(_: &mut T, _: &mut SyntaxCtxIndex) {} + +fn walk_operator(_: &mut T, _: &mut expr::Operator) {} + +fn walk_literal(_: &mut T, _: &mut Literal) {} + +fn walk_ident(ctx: &mut T, ident: &mut Ident) { + ctx.visit_span(&mut ident.span); + ctx.visit_syntax_ctx(&mut ident.ctx); +} + +fn walk_open(ctx: &mut T, open: &mut Open) { + ctx.visit_expr(&mut open.body); + match &mut open.expr { + Some(expr) => ctx.visit_expr(expr), + None => (), + } + ctx.visit_ident(&mut open.tipo); + ctx.visit_ident(&mut open.name); +} + +fn walk_match(ctx: &mut T, matcher: &mut Match) { + match &mut matcher.expr { + Some(expr) => ctx.visit_expr(expr), + None => (), + } + match &mut matcher.motive { + Some(expr) => ctx.visit_expr(expr), + None => (), + } + ctx.visit_ident(&mut matcher.tipo); + ctx.visit_ident(&mut matcher.name); + for (name, body) in &mut matcher.cases { + ctx.visit_expr(body); + ctx.visit_ident(name); + } +} + +fn walk_argument(ctx: &mut T, argument: &mut Argument) { + ctx.visit_ident(&mut argument.name); + match &mut argument.tipo { + Some(tipo) => ctx.visit_expr(tipo), + None => (), + } + ctx.visit_span(&mut argument.span); +} + +fn walk_entry(ctx: &mut T, entry: &mut Entry) { + ctx.visit_ident(&mut entry.name); + for arg in &mut entry.args { + ctx.visit_argument(arg) + } + ctx.visit_expr(&mut entry.tipo); + for rule in &mut entry.rules { + ctx.visit_rule(rule) + } + for attr in &mut entry.attrs { + ctx.visit_attr(attr); + } + ctx.visit_span(&mut entry.span); +} + +fn walk_attr(ctx: &mut T, attr: &mut Attribute) { + ctx.visit_ident(&mut attr.name); + ctx.visit_span(&mut attr.span); + // TODO: Visit inner side of the attribute +} + +fn walk_pat(ctx: &mut T, pat: &mut Pat) { + ctx.visit_span(&mut pat.span); + match &mut pat.data { + PatKind::Var(ident) => ctx.visit_ident(ident), + PatKind::Str(_) => (), + PatKind::Num(_) => (), + PatKind::Hole => (), + PatKind::List(ls) => { + for pat in ls { + ctx.visit_pat(pat) + } + } + PatKind::Pair(fst, snd) => { + ctx.visit_pat(fst); + ctx.visit_pat(snd); + } + PatKind::App(t, ls) => { + ctx.visit_ident(t); + for pat in ls { + ctx.visit_pat(pat) + } + } + } +} + +fn walk_rule(ctx: &mut T, rule: &mut Rule) { + ctx.visit_ident(&mut rule.name); + for pat in &mut rule.pats { + ctx.visit_pat(pat); + } + ctx.visit_expr(&mut rule.body); + ctx.visit_span(&mut rule.span); +} + +fn walk_book(ctx: &mut T, book: &mut Book) { + for entr in book.entrs.values_mut() { + ctx.visit_entry(entr); + } +} + +fn walk_substitution(ctx: &mut T, subst: &mut Substitution) { + ctx.visit_expr(&mut subst.expr); + ctx.visit_ident(&mut subst.name); +} + +fn walk_sttm(ctx: &mut T, sttm: &mut Sttm) { + ctx.visit_span(&mut sttm.span); + match &mut sttm.data { + SttmKind::Ask(Some(ident), val, next) => { + ctx.visit_ident(ident); + ctx.visit_expr(val); + ctx.visit_sttm(next); + } + SttmKind::Let(ident, val, next) => { + ctx.visit_ident(ident); + ctx.visit_expr(val); + ctx.visit_sttm(next); + } + SttmKind::Open(tipo, ident, val, next) => { + ctx.visit_ident(tipo); + ctx.visit_ident(ident); + match val { + Some(val) => ctx.visit_expr(val), + None => (), + } + ctx.visit_sttm(next); + } + SttmKind::Ask(None, val, next) => { + ctx.visit_expr(val); + ctx.visit_sttm(next); + } + SttmKind::Expr(expr, next) => { + ctx.visit_expr(expr); + ctx.visit_sttm(next); + } + SttmKind::Return(expr) => { + ctx.visit_expr(expr); + } + } +} + +fn walk_expr(ctx: &mut T, expr: &mut Expr) { + ctx.visit_span(&mut expr.span); + match &mut expr.data { + ExprKind::Var(ident) => ctx.visit_ident(ident), + ExprKind::All(None, typ, body) => { + ctx.visit_expr(typ); + ctx.visit_expr(body); + } + ExprKind::Pair(fst, snd) => { + ctx.visit_expr(fst); + ctx.visit_expr(snd); + } + ExprKind::All(Some(ident), typ, body) => { + ctx.visit_ident(ident); + ctx.visit_expr(typ); + ctx.visit_expr(body); + } + ExprKind::Sigma(None, typ, body) => { + ctx.visit_expr(typ); + ctx.visit_expr(body); + } + ExprKind::If(cond, if_, else_) => { + ctx.visit_expr(cond); + ctx.visit_expr(if_); + ctx.visit_expr(else_); + } + ExprKind::Sigma(Some(ident), typ, body) => { + ctx.visit_ident(ident); + ctx.visit_expr(typ); + ctx.visit_expr(body); + } + ExprKind::Do(ident, sttm) => { + ctx.visit_ident(ident); + ctx.visit_sttm(sttm) + } + ExprKind::Lambda(ident, binder, body) => { + ctx.visit_ident(ident); + match binder { + Some(x) => ctx.visit_expr(x), + None => (), + } + ctx.visit_expr(body); + } + ExprKind::App(expr, spine) => { + ctx.visit_expr(expr); + for arg in spine { + ctx.visit_expr(arg); + } + } + ExprKind::List(spine) => { + for arg in spine { + ctx.visit_expr(arg); + } + } + ExprKind::Let(ident, val, body) => { + ctx.visit_ident(ident); + ctx.visit_expr(val); + ctx.visit_expr(body); + } + ExprKind::Ann(val, ty) => { + ctx.visit_expr(val); + ctx.visit_expr(ty); + } + ExprKind::Lit(lit) => { + ctx.visit_literal(lit); + } + ExprKind::Binary(op, a, b) => { + ctx.visit_operator(op); + ctx.visit_expr(a); + ctx.visit_expr(b); + } + ExprKind::Help(id) => ctx.visit_ident(id), + ExprKind::Hole => {} + ExprKind::Subst(subst) => ctx.visit_substitution(subst), + ExprKind::Match(matcher) => ctx.visit_match(matcher), + ExprKind::Open(open) => ctx.visit_open(open), + } +} diff --git a/src/kind-tree/src/desugared.rs b/src/kind-tree/src/desugared.rs new file mode 100644 index 00000000..da25cb04 --- /dev/null +++ b/src/kind-tree/src/desugared.rs @@ -0,0 +1,227 @@ +use std::{ + collections::HashMap, + fmt::{Display, Error, Formatter}, +}; + +use kind_span::Span; + +use crate::symbol::Ident; + +/// Enum of binary operators. +#[derive(Copy, Clone, Debug)] +pub enum Operator { + Add, + Sub, + Mul, + Div, + Mod, + And, + Or, + Xor, + Shl, + Shr, + Ltn, + Lte, + Eql, + Gte, + Gtn, + Neq, +} + +pub type Spine = Vec>; + +#[derive(Clone, Debug)] +pub enum ExprKind { + /// Name of a variable + Var(Ident), + /// The dependent function space (e.g. (x : Int) -> y) + All(Option, Box, Box), + /// A anonymous function that receives one argument + Lambda(Ident, Box), + /// Application of a expression to a spine of expressions + App(Box, Spine), + /// Declaration of a local variable + Let(Ident, Box, Box), + /// Type ascription (x : y) + Ann(Box, Box), + /// Type Literal + Typ, + /// U60 Type + U60, + /// Number literal + Num(u64), + /// Binary operation (e.g. 2 + 3) + Binary(Operator, Box, Box), + /// A expression open to unification (e.g. _) + Hole, + /// Help + Help(Ident), +} + +#[derive(Clone, Debug)] +pub struct Expr { + pub data: ExprKind, + pub span: Span, +} + +/// An argument is a 'binding' of a name to a type +/// it has some other options like +/// eras: that express the erasure of this type when +/// compiled. +/// hide: that express a implicit argument (that will +/// be discovered through unification). +#[derive(Clone, Debug)] +pub struct Argument { + pub hidden: bool, + pub erased: bool, + pub name: Ident, + pub tipo: Box, + pub span: Span, +} + +/// A rule is a equation that in the left-hand-side +/// contains a list of patterns @pats@ and on the +/// right hand side a value. +#[derive(Clone, Debug)] +pub struct Rule { + pub name: Ident, + pub pats: Vec>, + pub body: Box, + pub span: Span, +} + +/// An entry describes a function that is typed +/// and has rules. The type of the function +/// consists of the arguments @args@ and the +/// return type @tipo@. +#[derive(Clone, Debug)] +pub struct Entry { + pub name: Ident, + pub args: Vec>, + pub tipo: Box, + pub rules: Vec>, + pub span: Span, +} + +// A book is a collection of entries. +#[derive(Clone, Debug, Default)] +pub struct Book { + pub names: Vec, + pub entrs: HashMap>, + pub holes: u64, +} + +// Display + +impl Display for Operator { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + use Operator::*; + + match self { + Add => write!(f, "+"), + Sub => write!(f, "-"), + Mul => write!(f, "*"), + Div => write!(f, "/"), + Mod => write!(f, "%"), + And => write!(f, "&"), + Or => write!(f, "|"), + Xor => write!(f, "^"), + Shl => write!(f, "<<"), + Shr => write!(f, ">>"), + Ltn => write!(f, "<"), + Lte => write!(f, "<="), + Eql => write!(f, "=="), + Gte => write!(f, ">="), + Gtn => write!(f, ">"), + Neq => write!(f, "!="), + } + } +} + +impl Expr { + pub fn new_var(name: Ident) -> Expr { + Expr { + span: Span::Generated, + data: ExprKind::Var(name), + } + } + + pub fn traverse_pi_types(&self) -> String { + match &self.data { + ExprKind::All(binder, typ, body) => match binder { + None => format!("{} -> {}", typ, body.traverse_pi_types()), + Some(binder) => format!("({} : {}) -> {}", binder, typ, body.traverse_pi_types()), + }, + _ => format!("{}", self), + } + } +} + +impl Display for Expr { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + use ExprKind::*; + match &self.data { + Typ => write!(f, "Type"), + U60 => write!(f, "U60"), + Num(n) => write!(f, "{}", n), + All(_, _, _) => write!(f, "({})", self.traverse_pi_types()), + Var(name) => write!(f, "{}", name), + Lambda(binder, body) => write!(f, "({} => {})", binder, body), + App(head, spine) => write!(f, "({}{})", head, spine.iter().map(|x| format!(" {}", x)).collect::()), + Let(name, expr, body) => write!(f, "(let {} = {}; {})", name, expr, body), + Ann(expr, typ) => write!(f, "({} : {})", expr, typ), + Binary(op, expr, typ) => write!(f, "({} {} {})", op, expr, typ), + Hole => write!(f, "_"), + Help(name) => write!(f, "?{}", name), + } + } +} + +impl Display for Book { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + for name in &self.names { + writeln!(f, "{}\n", self.entrs.get(&name.data.0).unwrap())?; + } + Ok(()) + } +} + +impl Display for Argument { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + let (open, close) = match (self.erased, self.hidden) { + (false, false) => ("(", ")"), + (false, true) => ("+<", ">"), + (true, false) => ("-(", ")"), + (true, true) => ("<", ">"), + }; + write!(f, "{}{}: {}{}", open, self.name, self.tipo, close) + } +} + +impl Display for Entry { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.name.clone())?; + + for arg in &self.args { + write!(f, " {}", arg)?; + } + + write!(f, " : {}", &self.tipo)?; + + for rule in &self.rules { + write!(f, "\n{}", rule)? + } + + Ok(()) + } +} + +impl Display for Rule { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + write!(f, "{}", self.name)?; + for pat in &self.pats { + write!(f, " {}", pat)?; + } + write!(f, " = {}", self.body) + } +} diff --git a/src/kind-tree/src/lib.rs b/src/kind-tree/src/lib.rs index 6f30a221..d7d64839 100644 --- a/src/kind-tree/src/lib.rs +++ b/src/kind-tree/src/lib.rs @@ -1,130 +1,11 @@ -use std::collections::HashMap; -use std::fmt::{Display, Error, Formatter}; +/// The concrete tree with all of the sugars. it's useful to +/// generate documentation or related without thinking about +/// the generated code. +pub mod concrete; -use expr::Expr; -use kind_span::{Span, SyntaxCtxIndex}; -use symbol::Ident; -use visitor::Visitor; +pub mod desugared; -pub mod expr; +/// Describes symbols (identifiers) on the language. It will +/// be really useful when we change the Symbol to take a number +/// instead of a string due to optimizations. pub mod symbol; -pub mod visitor; - -/// A value of a attribute -#[derive(Clone, Debug)] -pub enum AttributeStyle { - Ident(Ident), - String(String), - Number(Span, u64), -} - -/// A attribute is a kind of declaration -/// that usually is on the top of a declaration -/// and can be attached to a function declaration -/// it express some compiler properties -#[derive(Clone, Debug)] -pub struct Attribute { - pub name: Ident, - pub value: Option, - pub span: Span, -} - -/// An argument is a 'binding' of a name to a type -/// it has some other options like -/// eras: that express the erasure of this type when -/// compiled. -/// hide: that express a implicit argument (that will -/// be discovered through unification). -#[derive(Clone, Debug)] -pub struct Argument { - pub hidden: bool, - pub erased: bool, - pub name: Ident, - pub tipo: Box, - pub span: Span, -} - -/// A rule is a equation that in the left-hand-side -/// contains a list of patterns @pats@ and on the -/// right hand side a value. -#[derive(Clone, Debug)] -pub struct Rule { - pub name: Ident, - pub pats: Vec>, - pub body: Box, - pub span: Span, -} - -/// An entry describes a function that is typed -/// and has rules. The type of the function -/// consists of the arguments @args@ and the -/// return type @tipo@. -#[derive(Clone, Debug)] -pub struct Entry { - pub name: Ident, - pub docs: Option, - pub args: Vec>, - pub tipo: Box, - pub rules: Vec>, - pub attrs: Vec, - pub span: Span, -} - -// A book is a collection of entries. -#[derive(Clone, Debug, Default)] -pub struct Book { - pub names: Vec, - pub entrs: HashMap>, - pub holes: u64, -} - -// Display - -impl Display for Book { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - for name in &self.names { - writeln!(f, "{}\n", self.entrs.get(&name.data.0).unwrap())?; - } - Ok(()) - } -} - -impl Display for Argument { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - let (open, close) = match (self.erased, self.hidden) { - (false, false) => ("(", ")"), - (false, true) => ("+<", ">"), - (true, false) => ("-(", ")"), - (true, true) => ("<", ">"), - }; - write!(f, "{}{}: {}{}", open, self.name, &self.tipo, close) - } -} - -impl Display for Entry { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.name.clone())?; - - for arg in &self.args { - write!(f, " {}", arg)?; - } - - write!(f, " : {}", &self.tipo)?; - - for rule in &self.rules { - write!(f, "\n{}", rule)? - } - - Ok(()) - } -} - -impl Display for Rule { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - write!(f, "{}", self.name)?; - for pat in &self.pats { - write!(f, " {}", pat)?; - } - write!(f, " = {}", self.body) - } -} diff --git a/src/kind-tree/src/visitor.rs b/src/kind-tree/src/visitor.rs deleted file mode 100644 index a17fb96d..00000000 --- a/src/kind-tree/src/visitor.rs +++ /dev/null @@ -1,209 +0,0 @@ -use kind_span::Span; - -use crate::expr::{ExprKind, Literal, Match, Open, Sttm, SttmKind, Substitution}; -use crate::symbol::*; -use crate::*; - -/// A visitor trait following the visitor pattern -/// because it's easier to walk the entire tree -/// just by some nodes without writing some functions -/// to walk through everything (yeah i really hate -/// OOP patterns but this time it's really useful.) -/// -/// All of these functions are implemented so we can easily -/// change these default implementations. -pub trait Visitor { - fn visit_span(&mut self, _: &mut Span) {} - - fn visit_syntax_ctx(&mut self, _: &mut SyntaxCtxIndex) {} - - fn visit_operator(&mut self, _: &mut expr::Operator) {} - - fn visit_literal(&mut self, _: &mut Literal) {} - - fn visit_ident(&mut self, ident: &mut Ident) { - self.visit_span(&mut ident.span); - self.visit_syntax_ctx(&mut ident.ctx); - } - - fn visit_open(&mut self, open: &mut Open) { - self.visit_expr(&mut open.body); - match &mut open.expr { - Some(expr) => self.visit_expr(expr), - None => (), - } - self.visit_ident(&mut open.tipo); - self.visit_ident(&mut open.name); - } - - fn visit_match(&mut self, matcher: &mut Match) { - match &mut matcher.expr { - Some(expr) => self.visit_expr(expr), - None => (), - } - match &mut matcher.motive { - Some(expr) => self.visit_expr(expr), - None => (), - } - self.visit_ident(&mut matcher.tipo); - self.visit_ident(&mut matcher.name); - for (name, body) in &mut matcher.cases { - self.visit_expr(body); - self.visit_ident(name); - } - } - - fn visit_argument(&mut self, argument: &mut Argument) { - self.visit_ident(&mut argument.name); - self.visit_expr(&mut argument.tipo); - self.visit_span(&mut argument.span); - } - - fn visit_entry(&mut self, entry: &mut Entry) { - self.visit_ident(&mut entry.name); - for arg in &mut entry.args { - self.visit_argument(arg) - } - self.visit_expr(&mut entry.tipo); - for rule in &mut entry.rules { - self.visit_rule(rule) - } - for attr in &mut entry.attrs { - self.visit_attr(attr); - } - self.visit_span(&mut entry.span); - } - - fn visit_attr(&mut self, attr: &mut Attribute) { - self.visit_ident(&mut attr.name); - self.visit_span(&mut attr.span); - // TODO: Visit inner side of the attribute - } - - fn visit_rule(&mut self, rule: &mut Rule) { - self.visit_ident(&mut rule.name); - for pat in &mut rule.pats { - self.visit_expr(pat); - } - self.visit_expr(&mut rule.body); - self.visit_span(&mut rule.span); - } - - fn visit_book(&mut self, book: &mut Book) { - for entr in book.entrs.values_mut() { - self.visit_entry(entr); - } - } - - fn visit_substitution(&mut self, subst: &mut Substitution) { - self.visit_expr(&mut subst.expr); - self.visit_ident(&mut subst.name); - } - - fn visit_sttm(&mut self, sttm: &mut Sttm) { - self.visit_span(&mut sttm.span); - match &mut sttm.data { - SttmKind::Ask(Some(ident), val, next) => { - self.visit_ident(ident); - self.visit_expr(val); - self.visit_sttm(next); - } - SttmKind::Let(ident, val, next) => { - self.visit_ident(ident); - self.visit_expr(val); - self.visit_sttm(next); - } - SttmKind::Open(tipo, ident, val, next) => { - self.visit_ident(tipo); - self.visit_ident(ident); - match val { - Some(val) => self.visit_expr(val), - None => (), - } - self.visit_sttm(next); - } - SttmKind::Ask(None, val, next) => { - self.visit_expr(val); - self.visit_sttm(next); - } - SttmKind::Expr(expr, next) => { - self.visit_expr(expr); - self.visit_sttm(next); - } - SttmKind::Return(expr) => { - self.visit_expr(expr); - } - } - } - - fn visit_expr(&mut self, expr: &mut Expr) { - self.visit_span(&mut expr.span); - match &mut expr.data { - ExprKind::Var(ident) => self.visit_ident(ident), - ExprKind::All(None, typ, body) => { - self.visit_expr(typ); - self.visit_expr(body); - } - ExprKind::Pair(fst, snd) => { - self.visit_expr(fst); - self.visit_expr(snd); - } - ExprKind::All(Some(ident), typ, body) => { - self.visit_ident(ident); - self.visit_expr(typ); - self.visit_expr(body); - } - ExprKind::Sigma(None, typ, body) => { - self.visit_expr(typ); - self.visit_expr(body); - } - ExprKind::If(cond, if_, else_) => { - self.visit_expr(cond); - self.visit_expr(if_); - self.visit_expr(else_); - } - ExprKind::Sigma(Some(ident), typ, body) => { - self.visit_ident(ident); - self.visit_expr(typ); - self.visit_expr(body); - } - ExprKind::Do(sttm) => self.visit_sttm(sttm), - ExprKind::Lambda(ident, body) => { - self.visit_ident(ident); - self.visit_expr(body); - } - ExprKind::App(expr, spine) => { - self.visit_expr(expr); - for arg in spine { - self.visit_expr(arg); - } - } - ExprKind::List(spine) => { - for arg in spine { - self.visit_expr(arg); - } - } - ExprKind::Let(ident, val, body) => { - self.visit_ident(ident); - self.visit_expr(val); - self.visit_expr(body); - } - ExprKind::Ann(val, ty) => { - self.visit_expr(val); - self.visit_expr(ty); - } - ExprKind::Lit(lit) => { - self.visit_literal(lit); - } - ExprKind::Binary(op, a, b) => { - self.visit_operator(op); - self.visit_expr(a); - self.visit_expr(b); - } - ExprKind::Hole(_) => {} - ExprKind::Subst(subst) => self.visit_substitution(subst), - ExprKind::Match(matcher) => self.visit_match(matcher), - ExprKind::Open(open) => self.visit_open(open), - } - } -}