fix: parser and expanded tree for more nodes

This commit is contained in:
Felipe g 2022-10-09 15:11:36 -03:00
parent 938fec8ca4
commit e742466d5c
17 changed files with 1049 additions and 514 deletions

View File

@ -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<Box<Expr>, SyntaxError> {
fn parse_pi_or_lambda(&mut self) -> Result<Box<Expr>, 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<Box<Expr>, 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<Box<Expr>, SyntaxError> {
fn parse_call(&mut self, multiline: bool) -> Result<Box<Expr>, 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<Box<Expr>, SyntaxError> {
let mut head = self.parse_call()?;
fn parse_arrow(&mut self, multiline: bool) -> Result<Box<Expr>, 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<Box<Sttm>, 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<Box<Expr>, 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<Box<Expr>, 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<Box<Expr>, SyntaxError> {
pub fn parse_expr(&mut self, multiline: bool) -> Result<Box<Expr>, 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)
}
}
}

View File

@ -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,
'\\' => {

View File

@ -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<Box<SyntaxError>>) -> (Token, Span) {
pub fn get_next_no_error(&mut self, vec: &Sender<Box<SyntaxError>>) -> (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)),
}
}

View File

@ -12,7 +12,6 @@ pub struct Lexer<'a> {
pub ctx: SyntaxCtxIndex,
// Modes
pub semis: u16,
pub comment_depth: u16,
pub errs: Vec<Box<SyntaxError>>,
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<char> {

View File

@ -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(_))
}
}

View File

@ -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;

114
src/kind-parser/src/pat.rs Normal file
View File

@ -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<Box<Pat>, 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<Box<Pat>, 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<Box<Pat>, 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<Box<Pat>, 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<Box<Pat>, SyntaxError> {
let id = self.parse_id()?;
Ok(Box::new(Pat {
span: id.span,
data: PatKind::Var(id),
}))
}
fn parse_pat_list(&mut self) -> Result<Box<Pat>, 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<Box<Pat>, 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![])
}
}
}

View File

@ -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<Box<SyntaxError>>,
pub queue: VecDeque<(Token, Span)>,
pub breaks: VecDeque<bool>,
pub errs: &'a Sender<Box<SyntaxError>>,
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<Box<SyntaxError>>) -> 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<T>(&mut self, expect: Vec<Token>) -> Result<T, SyntaxError> {
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<T>(&mut self, expect: fn(&Token) -> Option<T>) -> Result<T, SyntaxError> {
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<T>(&mut self, expect: Vec<Token>) -> Result<T, SyntaxError> {
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<T>(&mut self, expect: fn(&Token) -> Option<T>) -> Result<T, SyntaxError> {
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<T>(&mut self, fun: &dyn Fn(&mut Parser<'a>) -> Result<T, SyntaxError>) -> Result<Option<T>, SyntaxError> {
let current = self.eaten;
match fun(self) {

View File

@ -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 })
}
}

View File

@ -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,
},
}
}

View File

@ -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<Ident>, Box<Expr>, Box<Sttm>),
Let(Ident, Box<Expr>, Box<Sttm>),
Open(Ident, Ident, Option<Box<Expr>>, Box<Sttm>),
Return(Box<Expr>)
Return(Box<Expr>),
}
#[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<Ident>, Box<Expr>, Box<Expr>),
/// A anonymous function that receives one argument
Lambda(Ident, Box<Expr>),
Lambda(Ident, Option<Box<Expr>>, Box<Expr>),
/// Application of a expression to a spine of expressions
App(Box<Expr>, Spine),
/// Declaration of a local variable
@ -113,7 +113,7 @@ pub enum ExprKind {
/// Binary operation (e.g. 2 + 3)
Binary(Operator, Box<Expr>, Box<Expr>),
/// 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<Open>),
/// Do notation
Do(Box<Sttm>),
Do(Ident, Box<Sttm>),
/// If else statement
If(Box<Expr>,Box<Expr>,Box<Expr>),
If(Box<Expr>, Box<Expr>, Box<Expr>),
/// If else statement
Pair(Box<Expr>,Box<Expr>),
Pair(Box<Expr>, Box<Expr>),
/// Array
List(Vec<Expr>)
List(Vec<Expr>),
/// 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::<String>()),
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::<Vec<String>>().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),
}
}
}

View File

@ -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<AttributeStyle>,
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<Box<Expr>>,
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<Box<Pat>>,
pub body: Box<Expr>,
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<String>,
pub args: Vec<Box<Argument>>,
pub tipo: Box<Expr>,
pub rules: Vec<Box<Rule>>,
pub attrs: Vec<Attribute>,
pub span: Span,
}
// A book is a collection of entries.
#[derive(Clone, Debug, Default)]
pub struct Book {
pub names: Vec<Ident>,
pub entrs: HashMap<String, Box<Entry>>,
}
// 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)
}
}

View File

@ -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<Box<Pat>>),
// Hole
Num(u64),
// Pair
Pair(Box<Pat>, Box<Pat>),
// List
List(Vec<Pat>),
// 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::<String>()),
List(vec) => write!(f, "[{}]", vec.iter().map(|x| format!("{}", x)).collect::<Vec<String>>().join(" ")),
Str(str) => write!(f, "\"{}\"", str),
Num(num) => write!(f, "{}", num),
Pair(fst, snd) => write!(f, "({}, {})", fst, snd),
Hole => write!(f, "_"),
}
}
}

View File

@ -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<T: Visitor>(_: &mut T, _: &mut Span) {}
fn walk_syntax_ctx<T: Visitor>(_: &mut T, _: &mut SyntaxCtxIndex) {}
fn walk_operator<T: Visitor>(_: &mut T, _: &mut expr::Operator) {}
fn walk_literal<T: Visitor>(_: &mut T, _: &mut Literal) {}
fn walk_ident<T: Visitor>(ctx: &mut T, ident: &mut Ident) {
ctx.visit_span(&mut ident.span);
ctx.visit_syntax_ctx(&mut ident.ctx);
}
fn walk_open<T: Visitor>(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<T: Visitor>(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<T: Visitor>(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<T: Visitor>(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<T: Visitor>(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<T: Visitor>(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<T: Visitor>(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<T: Visitor>(ctx: &mut T, book: &mut Book) {
for entr in book.entrs.values_mut() {
ctx.visit_entry(entr);
}
}
fn walk_substitution<T: Visitor>(ctx: &mut T, subst: &mut Substitution) {
ctx.visit_expr(&mut subst.expr);
ctx.visit_ident(&mut subst.name);
}
fn walk_sttm<T: Visitor>(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<T: Visitor>(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),
}
}

View File

@ -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<Box<Expr>>;
#[derive(Clone, Debug)]
pub enum ExprKind {
/// Name of a variable
Var(Ident),
/// The dependent function space (e.g. (x : Int) -> y)
All(Option<Ident>, Box<Expr>, Box<Expr>),
/// A anonymous function that receives one argument
Lambda(Ident, Box<Expr>),
/// Application of a expression to a spine of expressions
App(Box<Expr>, Spine),
/// Declaration of a local variable
Let(Ident, Box<Expr>, Box<Expr>),
/// Type ascription (x : y)
Ann(Box<Expr>, Box<Expr>),
/// Type Literal
Typ,
/// U60 Type
U60,
/// Number literal
Num(u64),
/// Binary operation (e.g. 2 + 3)
Binary(Operator, Box<Expr>, Box<Expr>),
/// 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<Expr>,
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<Box<Expr>>,
pub body: Box<Expr>,
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<Box<Argument>>,
pub tipo: Box<Expr>,
pub rules: Vec<Box<Rule>>,
pub span: Span,
}
// A book is a collection of entries.
#[derive(Clone, Debug, Default)]
pub struct Book {
pub names: Vec<Ident>,
pub entrs: HashMap<String, Box<Entry>>,
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::<String>()),
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)
}
}

View File

@ -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<AttributeStyle>,
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<Expr>,
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<Box<Expr>>,
pub body: Box<Expr>,
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<String>,
pub args: Vec<Box<Argument>>,
pub tipo: Box<Expr>,
pub rules: Vec<Box<Rule>>,
pub attrs: Vec<Attribute>,
pub span: Span,
}
// A book is a collection of entries.
#[derive(Clone, Debug, Default)]
pub struct Book {
pub names: Vec<Ident>,
pub entrs: HashMap<String, Box<Entry>>,
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)
}
}

View File

@ -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),
}
}
}