mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-09-19 04:37:28 +03:00
fix: parser and expanded tree for more nodes
This commit is contained in:
parent
938fec8ca4
commit
e742466d5c
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
'\\' => {
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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(_))
|
||||
}
|
||||
}
|
||||
|
@ -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
114
src/kind-parser/src/pat.rs
Normal 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![])
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
133
src/kind-tree/src/concrete/mod.rs
Normal file
133
src/kind-tree/src/concrete/mod.rs
Normal 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)
|
||||
}
|
||||
}
|
43
src/kind-tree/src/concrete/pat.rs
Normal file
43
src/kind-tree/src/concrete/pat.rs
Normal 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, "_"),
|
||||
}
|
||||
}
|
||||
}
|
315
src/kind-tree/src/concrete/visitor.rs
Normal file
315
src/kind-tree/src/concrete/visitor.rs
Normal 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),
|
||||
}
|
||||
}
|
227
src/kind-tree/src/desugared.rs
Normal file
227
src/kind-tree/src/desugared.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user