style: changed Diagnostic struct to a trait

This commit is contained in:
felipegchi 2022-11-16 20:01:25 -03:00
parent 16467dedce
commit f22d92da95
33 changed files with 383 additions and 405 deletions

View File

@ -40,17 +40,19 @@ fn eval_ctr(quote: bool, head: TermTag) -> String {
/// Just lifts the spine into an `args` constructor that is useful
/// to avoid the arity limit of the type checker.
fn lift_spine(spine: Vec<Box<Term>>) -> Vec<Box<Term>> {
if spine.len() >= 14 {
vec![Box::new(Term::Ctr {
name: format!("Kind.Term.args{}", spine.len()),
args: spine,
})]
if spine.len() > 16 {
let mut start = spine[..2].to_vec();
start.push(Box::new(Term::Ctr {
name: format!("Kind.Term.args{}", spine.len() - 2),
args: spine[2..].to_vec(),
}));
start
} else {
spine
}
}
fn mk_quoted_ctr(head: String, spine: Vec<Box<Term>>) -> Box<Term> {
fn mk_lifted_ctr(head: String, spine: Vec<Box<Term>>) -> Box<Term> {
let args = lift_spine(spine);
Box::new(Term::Ctr { name: head, args })
}
@ -88,7 +90,7 @@ fn span_to_num(span: Span) -> Box<Term> {
}
fn set_origin(ident: &Ident) -> Box<Term> {
mk_quoted_ctr(
mk_lifted_ctr(
"Kind.Term.set_origin".to_owned(),
vec![
span_to_num(Span::Locatable(ident.range)),
@ -129,9 +131,9 @@ fn codegen_all_expr(
use kind_tree::desugared::ExprKind::*;
match &expr.data {
Typ => mk_quoted_ctr(eval_ctr(quote, TermTag::Typ), vec![span_to_num(expr.span)]),
Typ => mk_lifted_ctr(eval_ctr(quote, TermTag::Typ), vec![span_to_num(expr.span)]),
NumType(kind_tree::NumType::U60) => {
mk_quoted_ctr(eval_ctr(quote, TermTag::U60), vec![span_to_num(expr.span)])
mk_lifted_ctr(eval_ctr(quote, TermTag::U60), vec![span_to_num(expr.span)])
}
NumType(kind_tree::NumType::U120) => todo!(),
Var(ident) => {
@ -139,7 +141,7 @@ fn codegen_all_expr(
set_origin(ident)
} else if lhs_rule {
*num += 1;
mk_quoted_ctr(
mk_lifted_ctr(
eval_ctr(quote, TermTag::Var),
vec![
span_to_num(expr.span),
@ -151,7 +153,7 @@ fn codegen_all_expr(
mk_var(ident.to_str())
}
}
All(name, typ, body) => mk_quoted_ctr(
All(name, typ, body) => mk_lifted_ctr(
eval_ctr(quote, TermTag::All),
vec![
span_to_num(expr.span),
@ -160,7 +162,7 @@ fn codegen_all_expr(
lam(name, codegen_all_expr(lhs_rule, lhs, num, quote, body)),
],
),
Lambda(name, body, _erased) => mk_quoted_ctr(
Lambda(name, body, _erased) => mk_lifted_ctr(
eval_ctr(quote, TermTag::Lambda),
vec![
span_to_num(expr.span),
@ -171,7 +173,7 @@ fn codegen_all_expr(
App(head, spine) => spine.iter().fold(
codegen_all_expr(lhs_rule, lhs, num, quote, head),
|left, right| {
mk_quoted_ctr(
mk_lifted_ctr(
eval_ctr(quote, TermTag::App),
vec![
span_to_num(expr.span),
@ -181,7 +183,7 @@ fn codegen_all_expr(
)
},
),
Ctr(name, spine) => mk_quoted_ctr(
Ctr(name, spine) => mk_lifted_ctr(
eval_ctr(quote, TermTag::Ctr(spine.len())),
vec_preppend![
mk_ctr_name(name),
@ -196,7 +198,7 @@ fn codegen_all_expr(
.map(|x| codegen_all_expr(lhs_rule, lhs, num, quote, &x))
.collect();
if quote {
mk_quoted_ctr(
mk_lifted_ctr(
eval_ctr(quote, TermTag::Fun(new_spine.len())),
vec_preppend![
mk_ctr_name(name),
@ -205,7 +207,7 @@ fn codegen_all_expr(
],
)
} else {
mk_quoted_ctr(
mk_ctr(
TermTag::HoasF(name.to_string()).to_string(),
vec_preppend![
span_to_num(expr.span);
@ -214,7 +216,7 @@ fn codegen_all_expr(
)
}
}
Let(name, val, body) => mk_quoted_ctr(
Let(name, val, body) => mk_ctr(
eval_ctr(quote, TermTag::Let),
vec![
span_to_num(expr.span),
@ -223,7 +225,7 @@ fn codegen_all_expr(
lam(name, codegen_all_expr(lhs_rule, lhs, num, quote, body)),
],
),
Ann(val, typ) => mk_quoted_ctr(
Ann(val, typ) => mk_ctr(
eval_ctr(quote, TermTag::Ann),
vec![
span_to_num(expr.span),
@ -231,7 +233,7 @@ fn codegen_all_expr(
codegen_all_expr(lhs_rule, lhs, num, quote, typ),
],
),
Sub(name, idx, rdx, inside) => mk_quoted_ctr(
Sub(name, idx, rdx, inside) => mk_ctr(
eval_ctr(quote, TermTag::Sub),
vec![
span_to_num(expr.span),
@ -241,12 +243,12 @@ fn codegen_all_expr(
codegen_all_expr(lhs_rule, lhs, num, quote, inside),
],
),
Num(kind_tree::Number::U60(n)) => mk_quoted_ctr(
Num(kind_tree::Number::U60(n)) => mk_lifted_ctr(
eval_ctr(quote, TermTag::Num),
vec![span_to_num(expr.span), mk_u60(*n)],
),
Num(kind_tree::Number::U120(_)) => todo!(),
Binary(operator, left, right) => mk_quoted_ctr(
Binary(operator, left, right) => mk_lifted_ctr(
eval_ctr(quote, TermTag::Binary),
vec![
mk_single_ctr(operator_to_constructor(*operator).to_owned()),
@ -255,11 +257,11 @@ fn codegen_all_expr(
codegen_all_expr(lhs_rule, lhs, num, quote, right),
],
),
Hole(num) => mk_quoted_ctr(
Hole(num) => mk_lifted_ctr(
eval_ctr(quote, TermTag::Hole),
vec![span_to_num(expr.span), mk_u60(*num)],
),
Hlp(_) => mk_quoted_ctr(eval_ctr(quote, TermTag::Hlp), vec![span_to_num(expr.span)]),
Hlp(_) => mk_lifted_ctr(eval_ctr(quote, TermTag::Hlp), vec![span_to_num(expr.span)]),
Str(input) => codegen_str(input),
Err => panic!("Internal Error: Was not expecting an ERR node inside the HVM checker"),
}
@ -276,7 +278,7 @@ fn codegen_pattern(args: &mut usize, quote: bool, expr: &Expr) -> Box<Term> {
fn codegen_type(args: &[desugared::Argument], typ: &desugared::Expr) -> Box<lang::Term> {
if !args.is_empty() {
let arg = &args[0];
mk_quoted_ctr(
mk_lifted_ctr(
eval_ctr(true, TermTag::All),
vec![
span_to_num(Span::Locatable(arg.span)),
@ -300,11 +302,9 @@ where
}
fn codegen_rule_end(file: &mut lang::File, rule: &desugared::Rule) {
let base_vars = lift_spine(
(0..rule.pats.len())
.map(|x| mk_var(&format!("x{}", x)))
.collect::<Vec<Box<lang::Term>>>(),
);
let base_vars = (0..rule.pats.len())
.map(|x| mk_var(&format!("x{}", x)))
.collect::<Vec<Box<lang::Term>>>();
file.rules.push(lang::Rule {
lhs: mk_ctr(
@ -314,7 +314,7 @@ fn codegen_rule_end(file: &mut lang::File, rule: &desugared::Rule) {
base_vars
],
),
rhs: mk_quoted_ctr(
rhs: mk_lifted_ctr(
eval_ctr(false, TermTag::Fun(base_vars.len())),
vec_preppend![
mk_ctr_name(&rule.name),
@ -332,7 +332,7 @@ fn codegen_rule_end(file: &mut lang::File, rule: &desugared::Rule) {
base_vars
],
),
rhs: mk_quoted_ctr(
rhs: mk_lifted_ctr(
eval_ctr(false, TermTag::Fun(base_vars.len())),
vec_preppend![
mk_ctr_name(&rule.name),
@ -451,19 +451,19 @@ fn codegen_entry(file: &mut lang::File, entry: &desugared::Entry) {
.collect::<Vec<Box<lang::Term>>>();
file.rules.push(lang::Rule {
lhs: mk_ctr(
lhs: mk_lifted_ctr(
format!("Kind.Term.FN{}", entry.args.len()),
vec_preppend![
mk_ctr_name(&entry.name),
mk_var("orig");
lift_spine(base_vars.clone())
base_vars.clone()
],
),
rhs: mk_quoted_ctr(
rhs: mk_ctr(
TermTag::HoasF(entry.name.to_string()).to_string(),
vec_preppend![
mk_var("orig");
lift_spine(base_vars.clone())
base_vars.clone()
],
),
});
@ -474,14 +474,14 @@ fn codegen_entry(file: &mut lang::File, entry: &desugared::Entry) {
vec_preppend![
mk_ctr_name(&entry.name),
mk_var("orig");
lift_spine(base_vars.clone())
base_vars.clone()
],
),
rhs: mk_quoted_ctr(
rhs: mk_ctr(
TermTag::HoasQ(entry.name.to_string()).to_string(),
vec_preppend![
mk_var("orig");
lift_spine(base_vars)
base_vars
],
),
});

View File

@ -1,6 +1,6 @@
//! Errors created by the type checker.
use kind_report::data::{Color, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_span::Range;
use kind_tree::desugared::Expr;
@ -18,7 +18,7 @@ pub(crate) enum TypeError {
TypeMismatch(Context, Range, Box<Expr>, Box<Expr>),
}
fn context_to_subtitles(ctx: Context, subtitles: &mut Vec<Subtitle>) {
fn context_to_subtitles(ctx: &Context, subtitles: &mut Vec<Subtitle>) {
subtitles.push(Subtitle::LineBreak);
if !ctx.0.is_empty() {
@ -35,7 +35,7 @@ fn context_to_subtitles(ctx: Context, subtitles: &mut Vec<Subtitle>) {
.map(|x| x.0.len())
.unwrap_or(0);
for (name, typ, vals) in ctx.0 {
for (name, typ, vals) in &ctx.0 {
subtitles.push(Subtitle::Phrase(
Color::Snd,
vec![
@ -57,9 +57,9 @@ fn context_to_subtitles(ctx: Context, subtitles: &mut Vec<Subtitle>) {
}
}
impl From<TypeError> for DiagnosticFrame {
fn from(err: TypeError) -> Self {
match err {
impl Diagnostic for TypeError {
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
match self {
TypeError::TypeMismatch(ctx, range, detected, expected) => {
let mut subtitles = vec![
Subtitle::Phrase(
@ -85,7 +85,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles,
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -111,7 +111,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles,
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Snd,
text: "Here!".to_string(),
no_code: false,
@ -141,7 +141,7 @@ impl From<TypeError> for DiagnosticFrame {
],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -155,7 +155,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -169,7 +169,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -183,7 +183,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -197,7 +197,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -211,7 +211,7 @@ impl From<TypeError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,

View File

@ -10,7 +10,7 @@ pub mod report;
use std::sync::mpsc::Sender;
use hvm::Term;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_tree::desugared::Book;
use crate::report::parse_report;
@ -29,7 +29,7 @@ pub fn gen_checker(book: &Book) -> String {
/// Type checks a dessugared book. It spawns an HVM instance in order
/// to run a compiled version of the book
pub fn type_check(book: &Book, tx: Sender<DiagnosticFrame>) -> bool {
pub fn type_check(book: &Book, tx: Sender<Box<dyn Diagnostic>>) -> bool {
let check_code = gen_checker(book);
let mut runtime = hvm::Runtime::from_code(&check_code).unwrap();
@ -43,7 +43,7 @@ pub fn type_check(book: &Book, tx: Sender<DiagnosticFrame>) -> bool {
let succeeded = errs.is_empty();
for err in errs {
tx.send(err.into()).unwrap()
tx.send(Box::new(err)).unwrap()
}
succeeded

View File

@ -4,7 +4,7 @@ use std::{fmt, io};
use clap::{Parser, Subcommand};
use kind_driver::session::Session;
use kind_report::data::{Diagnostic, DiagnosticFrame, Log};
use kind_report::data::{Diagnostic, Log};
use kind_report::report::{FileCache, Report};
use kind_report::RenderConfig;
@ -136,7 +136,7 @@ pub fn compile_in_session<T>(
let res = fun(&mut session);
let diagnostics = tx.try_iter().collect::<Vec<DiagnosticFrame>>();
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
if diagnostics.is_empty() && res.is_some() {
render_to_stderr(&render_config, &session, &Log::Checked(start.elapsed()));
@ -146,7 +146,6 @@ pub fn compile_in_session<T>(
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
eprintln!();
for diagnostic in diagnostics {
let diagnostic: Diagnostic = (&diagnostic).into();
render_to_stderr(&render_config, &session, &diagnostic)
}
None
@ -221,10 +220,10 @@ pub fn run_cli(config: Cli) {
}
Command::Watch { file: _ } => {
todo!()
},
}
Command::Repl => {
todo!()
},
}
Command::ToKDL {
file: _,
namespace: _,

View File

@ -1,5 +1,5 @@
use kind_driver::session::Session;
use kind_report::data::{Diagnostic, DiagnosticFrame};
use kind_report::data::Diagnostic;
use kind_report::report::Report;
use kind_report::RenderConfig;
@ -46,7 +46,7 @@ fn test_checker() -> Result<(), Error> {
let check = driver::type_check_book(&mut session, &PathBuf::from(path));
let diagnostics = tx.try_iter().collect::<Vec<DiagnosticFrame>>();
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
let render = RenderConfig::ascii(2);
kind_report::check_if_colors_are_supported(true);
@ -56,8 +56,7 @@ fn test_checker() -> Result<(), Error> {
_ => {
let mut res_string = String::new();
for diagnostic in diagnostics {
let diag = Into::<Diagnostic>::into(&diagnostic);
for diag in diagnostics {
diag.render(&mut session, &render, &mut res_string).unwrap();
}
@ -78,20 +77,17 @@ fn test_eval() -> Result<(), Error> {
let check = driver::compile_book_to_hvm(&mut session, &PathBuf::from(path));
let diagnostics = tx.try_iter().collect::<Vec<DiagnosticFrame>>();
let diagnostics = tx.try_iter().collect::<Vec<_>>();
let render = RenderConfig::ascii(2);
kind_report::check_if_colors_are_supported(true);
match check {
Some(file) if diagnostics.is_empty() => {
driver::execute_file(&file).to_string()
},
Some(file) if diagnostics.is_empty() => driver::execute_file(&file).to_string(),
_ => {
let mut res_string = String::new();
for diagnostic in diagnostics {
let diag = Into::<Diagnostic>::into(&diagnostic);
for diag in diagnostics {
diag.render(&mut session, &render, &mut res_string).unwrap();
}

View File

@ -1,7 +1,9 @@
type Nat {
succ (pred : Nat)
zero
succ
}
Nat.zero : U60
Nat.zero = 2
type Vec (t: Type) ~ (n: Nat) {
cons <size : Nat> (x : t) (xs : Vec t size) : Vec t (Nat.succ size)
nil : Vec t Nat.zero
}

View File

@ -0,0 +1,16 @@
ERROR Defined multiple times for the same name
/--[tests/suite/checker/derive/fail/RepeatedDef.kind2:2:5]
|
1 | type Nat {
2 | zero
| v---
| \ The first ocorrence
3 | succ
:
6 | Nat.zero : U60
| v-------
| \ Second occorrence here!
Hint: Rename one of the definitions or remove and look at how names work in Kind at https://kind.kindelia.org/hints/names

View File

@ -0,0 +1,7 @@
type Nat {
zero
succ
}
Nat.zero : U60
Nat.zero = 2

View File

@ -37,7 +37,10 @@ pub fn derive_open(range: Range, rec: &RecordDecl) -> concrete::Entry {
})
};
let name = rec.name.add_segment(rec.constructor.to_str()).add_segment("open");
let name = rec
.name
.add_segment(rec.constructor.to_str())
.add_segment("open");
let mut types = Telescope::default();

View File

@ -17,6 +17,4 @@ kind-target-hvm = { path = "../kind-target-hvm" }
hvm = "0.1.81"
strsim = "0.10.0"
fxhash = "0.2.1"
dashmap = "5.4.0"
eyre = "0.6.8"
notify-debouncer-mini = "0.2.1"
dashmap = "5.4.0"

View File

@ -3,7 +3,7 @@
use std::path::PathBuf;
use kind_report::data::{Color, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity, Subtitle, Word};
use kind_tree::symbol::{Ident, QualifiedIdent};
/// Describes all of the possible errors inside each
@ -15,9 +15,9 @@ pub(crate) enum DriverError {
DefinedMultipleTimes(QualifiedIdent, QualifiedIdent),
}
impl From<DriverError> for DiagnosticFrame {
fn from(err: DriverError) -> Self {
match err {
impl Diagnostic for DriverError {
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
match self {
DriverError::UnboundVariable(idents, suggestions) => DiagnosticFrame {
code: 100,
severity: Severity::Error,

View File

@ -41,8 +41,8 @@ pub fn type_check_book(session: &mut Session, path: &PathBuf) -> Option<desugare
pub fn to_book(session: &mut Session, path: &PathBuf) -> Option<concrete::Book> {
let mut concrete_book = resolution::parse_and_store_book(session, path)?;
expand::expand_book(&mut concrete_book);
expand::expand_book(session.diagnostic_sender.clone(), &mut concrete_book);
let failed = resolution::check_unbound_top_level(session, &mut concrete_book);
if failed {

View File

@ -10,8 +10,9 @@ use std::path::{Path, PathBuf};
use std::rc::Rc;
use strsim::jaro;
use kind_pass::unbound::{self};
use kind_report::data::DiagnosticFrame;
use kind_pass::unbound::{self, UnboundCollector};
use kind_report::data::Diagnostic;
use kind_tree::concrete::visitor::Visitor;
use kind_tree::concrete::{Book, Module, TopLevel};
use kind_tree::symbol::{Ident, QualifiedIdent};
@ -26,7 +27,7 @@ const EXT: &str = "kind2";
fn accumulate_neighbour_paths(
ident: &QualifiedIdent,
raw_path: &Path,
) -> Result<Option<PathBuf>, DiagnosticFrame> {
) -> Result<Option<PathBuf>, Box<dyn Diagnostic>> {
let mut canon_path = raw_path.to_path_buf();
let mut dir_file_path = raw_path.to_path_buf();
let dir_path = raw_path.to_path_buf();
@ -34,9 +35,12 @@ fn accumulate_neighbour_paths(
canon_path.set_extension(EXT);
dir_file_path.push("_");
dir_file_path.set_extension(EXT);
if canon_path.exists() && dir_path.exists() && canon_path.is_file() && dir_path.is_dir() {
Err(DriverError::MultiplePaths(ident.clone(), vec![canon_path, dir_path]).into())
Err(Box::new(DriverError::MultiplePaths(
ident.clone(),
vec![canon_path, dir_path],
)))
} else if canon_path.is_file() {
Ok(Some(canon_path))
} else if dir_file_path.is_file() {
@ -54,7 +58,7 @@ fn ident_to_path(
root: &Path,
ident: &QualifiedIdent,
search_on_parent: bool,
) -> Result<Option<PathBuf>, DiagnosticFrame> {
) -> Result<Option<PathBuf>, Box<dyn Diagnostic>> {
let name = ident.root.to_string();
let segments = name.as_str().split('.').collect::<Vec<&str>>();
let mut raw_path = root.to_path_buf();
@ -78,7 +82,10 @@ fn try_to_insert_new_name<'a>(
if let Some(first_occorence) = book.names.get(ident.to_string().as_str()) {
session
.diagnostic_sender
.send(DriverError::DefinedMultipleTimes(first_occorence.clone(), ident).into())
.send(Box::new(DriverError::DefinedMultipleTimes(
first_occorence.clone(),
ident,
)))
.unwrap();
*failed = true;
false
@ -172,7 +179,9 @@ fn parse_and_store_book_by_path<'a>(
if !path.exists() {
session
.diagnostic_sender
.send(DriverError::CannotFindFile(path.to_str().unwrap().to_string()).into())
.send(Box::new(DriverError::CannotFindFile(
path.to_str().unwrap().to_string(),
)))
.unwrap();
return true;
}
@ -189,7 +198,9 @@ fn parse_and_store_book_by_path<'a>(
Err(_) => {
session
.diagnostic_sender
.send(DriverError::CannotFindFile(path.to_str().unwrap().to_string()).into())
.send(Box::new(DriverError::CannotFindFile(
path.to_str().unwrap().to_string(),
)))
.unwrap();
return true;
}
@ -201,15 +212,15 @@ fn parse_and_store_book_by_path<'a>(
let (mut module, mut failed) =
kind_parser::parse_book(session.diagnostic_sender.clone(), ctx_id, &input);
let (unbound_vars, unbound_top_level) =
unbound::get_module_unbound(session.diagnostic_sender.clone(), &mut module, false);
let mut state = UnboundCollector::new(session.diagnostic_sender.clone(), false);
state.visit_module(&mut module);
for idents in unbound_vars.values() {
for idents in state.unbound.values() {
unbound_variable(session, book, idents);
failed = true;
}
for idents in unbound_top_level.values() {
for idents in state.unbound_top_level.values() {
failed |= parse_and_store_book_by_identifier(session, &idents.iter().nth(0).unwrap(), book);
}
@ -229,7 +240,10 @@ fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) {
.collect();
session
.diagnostic_sender
.send(DriverError::UnboundVariable(idents.to_vec(), similar_names).into())
.send(Box::new(DriverError::UnboundVariable(
idents.to_vec(),
similar_names,
)))
.unwrap();
}
@ -249,7 +263,11 @@ pub fn check_unbound_top_level(session: &mut Session, book: &mut Book) -> bool {
unbound::get_book_unbound(session.diagnostic_sender.clone(), book, true);
for (_, unbound) in unbound_tops {
let res: Vec<Ident> = unbound.iter().filter(|x| !x.used_by_sugar).map(|x| x.to_ident()).collect();
let res: Vec<Ident> = unbound
.iter()
.filter(|x| !x.used_by_sugar)
.map(|x| x.to_ident())
.collect();
if !res.is_empty() {
unbound_variable(session, &book, &res);
failed = true;

View File

@ -8,7 +8,7 @@ use std::rc::Rc;
use std::sync::mpsc::Sender;
use fxhash::FxHashMap;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
#[derive(Debug, Clone)]
pub struct Session {
@ -20,14 +20,14 @@ pub struct Session {
/// to make the public and private decls
pub public_names: FxHashMap<PathBuf, HashSet<String>>,
pub diagnostic_sender: Sender<DiagnosticFrame>,
pub diagnostic_sender: Sender<Box<dyn Diagnostic>>,
pub root: PathBuf,
pub book_counter: usize,
}
impl Session {
pub fn new(root: PathBuf, sender: Sender<DiagnosticFrame>) -> Session {
pub fn new(root: PathBuf, sender: Sender<Box<dyn Diagnostic>>) -> Session {
Session {
loaded_paths: Vec::new(),
loaded_sources: Vec::new(),

View File

@ -1,7 +1,7 @@
//! All of the sintatic erros both from the
//! lexer and the parser.
use kind_report::data::{Color, DiagnosticFrame, Marker, Severity};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_span::Range;
use crate::lexer::tokens::Token;
@ -44,9 +44,9 @@ fn encode_name(encode: EncodeSequence) -> &'static str {
}
}
impl From<SyntaxError> for DiagnosticFrame {
fn from(err: SyntaxError) -> Self {
match err {
impl Diagnostic for SyntaxError {
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
match self {
SyntaxError::UnfinishedString(range) => DiagnosticFrame {
code: 1,
severity: Severity::Error,
@ -54,7 +54,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["You need to close the string with another quote, take a look at the beggining".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "The string starts in this position!".to_string(),
no_code: false,
@ -68,7 +68,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["Put it on the end of the clause or remove it.".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "It should not be in the middle of this!".to_string(),
no_code: false,
@ -82,7 +82,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["Take a look at the rules for doc comments at https://kind.kindelia.org/hints/documentation-strings".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::For,
text: "Remove the entire comment or transform it in a simple comment with '//'".to_string(),
no_code: false,
@ -96,7 +96,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["You need to close the character with another quote, take a look at the beginning".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "The char starts in this position!".to_string(),
no_code: false,
@ -114,7 +114,7 @@ impl From<SyntaxError> for DiagnosticFrame {
format!("Change it to '{}{}'", fst, c.as_str())
}],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Wrong case for this name".to_string(),
no_code: false,
@ -129,14 +129,14 @@ impl From<SyntaxError> for DiagnosticFrame {
hints: vec!["If you indend to make another clause, just replace the name in red.".to_string()],
positions: vec![
Marker {
position: snd,
position: *snd,
color: Color::Fst,
text: "This is the unexpected token".to_string(),
no_code: false,
main: true,
},
Marker {
position: fst,
position: *fst,
color: Color::Snd,
text: "This is the definition. All clauses should use the same name.".to_string(),
no_code: false,
@ -151,7 +151,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["You need to close the string with '*/', take a look at the beggining".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "The comment starts in this position!".to_string(),
no_code: false,
@ -161,11 +161,11 @@ impl From<SyntaxError> for DiagnosticFrame {
SyntaxError::InvalidEscapeSequence(kind, range) => DiagnosticFrame {
code: 8,
severity: Severity::Error,
title: format!("The {} character sequence is invalid!", encode_name(kind)),
title: format!("The {} character sequence is invalid!", encode_name(kind.clone())),
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -175,11 +175,11 @@ impl From<SyntaxError> for DiagnosticFrame {
SyntaxError::InvalidNumberRepresentation(repr, range) => DiagnosticFrame {
code: 9,
severity: Severity::Error,
title: format!("The {} number sequence is invalid!", encode_name(repr)),
title: format!("The {} number sequence is invalid!", encode_name(repr.clone())),
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -193,7 +193,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["Try to remove it!".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -207,7 +207,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: true,
@ -221,7 +221,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec!["Remove this documentation comment or place it in a correct place.".to_string()],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -235,7 +235,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -249,7 +249,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Starts here! try to add another one".to_string(),
no_code: false,
@ -263,7 +263,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Move it to the beggining".to_string(),
no_code: false,
@ -277,7 +277,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Use the entire name here!".to_string(),
no_code: false,
@ -291,7 +291,7 @@ impl From<SyntaxError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -304,6 +304,6 @@ impl From<SyntaxError> for DiagnosticFrame {
impl From<Box<SyntaxError>> for DiagnosticFrame {
fn from(err: Box<SyntaxError>) -> Self {
(*err).into()
(err).into()
}
}

View File

@ -66,7 +66,7 @@ impl<'a> Parser<'a> {
}
if unused {
self.errs
.send(SyntaxError::UnusedDocString(start.mix(last)).into())
.send(Box::new(SyntaxError::UnusedDocString(start.mix(last))))
.unwrap()
}
}

View File

@ -8,7 +8,7 @@
use std::sync::mpsc::Sender;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::Range;
use crate::errors::SyntaxError;
@ -68,12 +68,12 @@ impl<'a> Lexer<'a> {
}
}
pub fn get_next_no_error(&mut self, vec: Sender<DiagnosticFrame>) -> (Token, Range) {
pub fn get_next_no_error(&mut self, vec: Sender<Box<dyn Diagnostic>>) -> (Token, Range) {
loop {
let (token, span) = self.lex_token();
match token {
Token::Error(x) => {
vec.send(x.into()).unwrap();
vec.send(x).unwrap();
continue;
}
Token::Comment(false, _) => continue,

View File

@ -9,13 +9,13 @@ pub mod top_level;
pub mod lexer;
use std::sync::mpsc::Sender;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::SyntaxCtxIndex;
use kind_tree::concrete::Module;
pub use lexer::state::*;
use state::Parser;
pub fn parse_book(errs: Sender<DiagnosticFrame>, ctx_id: usize, input: &str) -> (Module, bool) {
pub fn parse_book(errs: Sender<Box<dyn Diagnostic>>, ctx_id: usize, input: &str) -> (Module, bool) {
let peekable = input.chars().peekable();
let lexer = Lexer::new(input, peekable, SyntaxCtxIndex::new(ctx_id));
let mut parser = Parser::new(lexer, errs);

View File

@ -2,7 +2,7 @@
use std::{collections::VecDeque, sync::mpsc::Sender};
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::Range;
use crate::{errors::SyntaxError, lexer::tokens::Token, Lexer};
@ -20,7 +20,7 @@ pub struct Parser<'a> {
/// because it's a ring buffer.
pub queue: VecDeque<(Token, Range)>,
pub breaks: VecDeque<bool>,
pub errs: Sender<DiagnosticFrame>,
pub errs: Sender<Box<dyn Diagnostic>>,
/// It's useful when we have to try to parse something
/// that fails in the first token. as the parser ignores some
/// tokens, we cannot rely on the count provided by the
@ -30,7 +30,7 @@ pub struct Parser<'a> {
}
impl<'a> Parser<'a> {
pub fn new(mut lexer: Lexer<'a>, sender: Sender<DiagnosticFrame>) -> Parser<'a> {
pub fn new(mut lexer: Lexer<'a>, sender: Sender<Box<dyn Diagnostic>>) -> Parser<'a> {
let mut queue = VecDeque::with_capacity(3);
let mut breaks = VecDeque::with_capacity(3);
for _ in 0..3 {

View File

@ -281,7 +281,7 @@ impl<'a> Parser<'a> {
uses.insert(alias, origin);
}
Err(err) => {
self.errs.send(err.into()).unwrap();
self.errs.send(Box::new(err)).unwrap();
self.failed = true;
break;
}
@ -293,7 +293,7 @@ impl<'a> Parser<'a> {
Ok(entry) => entries.push(entry),
Err(err) => {
self.advance();
self.errs.send(err.into()).unwrap();
self.errs.send(Box::new(err)).unwrap();
self.failed = true;
while (!self.is_top_level_start() || !self.is_linebreak())
&& !self.get().same_variant(&Token::Eof)
@ -309,7 +309,7 @@ impl<'a> Parser<'a> {
match res {
Ok(_) => (),
Err(err) => {
self.errs.send(err.into()).unwrap();
self.errs.send(Box::new(err)).unwrap();
self.failed = true;
}
}

View File

@ -69,7 +69,10 @@ impl<'a> DesugarState<'a> {
Destruct::Destruct(_, typ, case, jump_rest) => {
let count = self.old_book.count.get(&typ.to_string()).unwrap();
let rec = count.is_record_cons_of.clone().and_then(|name| self.old_book.entries.get(&name.to_string()));
let rec = count
.is_record_cons_of
.clone()
.and_then(|name| self.old_book.entries.get(&name.to_string()));
let record = if let Some(TopLevel::RecordType(record)) = rec {
record

View File

@ -8,7 +8,7 @@
use std::sync::mpsc::Sender;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::{Range, Span};
use kind_tree::{
concrete::{self},
@ -25,7 +25,7 @@ pub mod expr;
pub mod top_level;
pub struct DesugarState<'a> {
pub errors: Sender<DiagnosticFrame>,
pub errors: Sender<Box<dyn Diagnostic>>,
pub old_book: &'a concrete::Book,
pub new_book: desugared::Book,
pub name_count: u64,
@ -34,7 +34,7 @@ pub struct DesugarState<'a> {
}
pub fn desugar_book(
errors: Sender<DiagnosticFrame>,
errors: Sender<Box<dyn Diagnostic>>,
book: &concrete::Book,
) -> Option<desugared::Book> {
let mut state = DesugarState {
@ -72,7 +72,7 @@ impl<'a> DesugarState<'a> {
}
fn send_err(&mut self, err: PassError) {
self.errors.send(err.into()).unwrap();
self.errors.send(Box::new(err)).unwrap();
self.failed = true;
}

View File

@ -15,7 +15,7 @@ use std::sync::mpsc::Sender;
use fxhash::{FxHashMap, FxHashSet};
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::Range;
use kind_tree::{
@ -32,7 +32,7 @@ pub enum Relevance {
Hole(usize),
}
pub struct ErasureState<'a> {
errs: Sender<DiagnosticFrame>,
errs: Sender<Box<dyn Diagnostic>>,
book: &'a Book,
ctx: im::HashMap<String, (Range, (Option<Range>, Relevance))>,
@ -44,7 +44,7 @@ pub struct ErasureState<'a> {
pub fn erase_book(
book: &Book,
errs: Sender<DiagnosticFrame>,
errs: Sender<Box<dyn Diagnostic>>,
entrypoint: FxHashSet<String>,
) -> Option<Book> {
let mut state = ErasureState {
@ -114,7 +114,11 @@ impl<'a> ErasureState<'a> {
declared_ty: Option<Range>,
) {
self.errs
.send(PassError::CannotUseIrrelevant(declared_val, used, declared_ty).into())
.send(Box::new(PassError::CannotUseIrrelevant(
declared_val,
used,
declared_ty,
)))
.unwrap();
self.failed = true;
}
@ -232,7 +236,7 @@ impl<'a> ErasureState<'a> {
Fun(name, spine) | Ctr(name, spine) if on.1 == Relevance::Irrelevant => {
let range = pat.span.to_range().unwrap_or_else(|| name.range.clone());
self.errs
.send(PassError::CannotPatternMatchOnErased(range).into())
.send(Box::new(PassError::CannotPatternMatchOnErased(range)))
.unwrap();
self.failed = true;
self.erase_pat_spine(on, &name, spine);

View File

@ -1,4 +1,4 @@
use kind_report::data::{Color, DiagnosticFrame, Marker, Severity};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_span::{Range, Span};
pub enum Sugar {
@ -13,7 +13,6 @@ pub enum Sugar {
/// of the passes inside this crate.
pub enum PassError {
RepeatedVariable(Range, Range),
CannotUseNamed(Range, Range),
IncorrectArity(Range, Vec<Range>, usize, usize),
DuplicatedNamed(Range, Range),
LetDestructOnlyForRecord(Range),
@ -30,17 +29,16 @@ pub enum PassError {
NotATypeConstructor(Range, Range),
ShouldBeAParameter(Span, Range),
NoFieldCoverage(Range, Vec<String>),
DuplicatedConstructor(Range, Range),
CannotPatternMatchOnErased(Range),
}
// TODO: A way to build an error message with methods
impl From<PassError> for DiagnosticFrame {
fn from(err: PassError) -> Self {
match err {
impl Diagnostic for PassError {
fn to_diagnostic_frame(&self) -> DiagnosticFrame {
match self {
PassError::CannotUseIrrelevant(var_decl, place, declarated_place) => {
let mut positions = vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "It's in relevant position!".to_string(),
no_code: false,
@ -49,7 +47,7 @@ impl From<PassError> for DiagnosticFrame {
if let Some(range) = declarated_place {
positions.push(Marker {
position: range,
position: *range,
color: Color::Snd,
text: "Declared here as erased (or implicit without '+')".to_string(),
no_code: false,
@ -59,7 +57,7 @@ impl From<PassError> for DiagnosticFrame {
if let Some(range) = var_decl {
positions.push(Marker {
position: range,
position: *range,
color: Color::Thr,
text: "This variable corresponds to the erased argument".to_string(),
no_code: false,
@ -83,7 +81,7 @@ impl From<PassError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -97,7 +95,7 @@ impl From<PassError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -126,15 +124,15 @@ impl From<PassError> for DiagnosticFrame {
severity: Severity::Error,
title: "This rule is with the incorrect arity.".to_string(),
subtitles: vec![],
hints: vec![if expected == 0 {
hints: vec![if *expected == 0 {
"This rule expects no arguments".to_string()
} else if hidden == 0 {
} else if *hidden == 0 {
format!("This rule expects {} arguments", expected)
} else {
format!("This rule expects {} arguments or {} (without hidden ones)", expected, expected - hidden)
}],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -154,7 +152,7 @@ impl From<PassError> for DiagnosticFrame {
Sugar::BoolIf => "You must implement 'Bool.if' in order to use the if notation.".to_string(),
}],
positions: vec![Marker {
position: expr_place,
position: *expr_place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -168,7 +166,7 @@ impl From<PassError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
@ -183,14 +181,14 @@ impl From<PassError> for DiagnosticFrame {
hints: vec![],
positions: vec![
Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
main: true,
},
Marker {
position: def_name,
position: *def_name,
color: Color::Snd,
text: "This is the definition name".to_string(),
no_code: false,
@ -206,14 +204,14 @@ impl From<PassError> for DiagnosticFrame {
hints: vec![],
positions: vec![
Marker {
position: place,
position: *place,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
main: true,
},
Marker {
position: def_name,
position: *def_name,
color: Color::Snd,
text: "This is the definition name".to_string(),
no_code: false,
@ -228,7 +226,7 @@ impl From<PassError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![format!("Need a case for {}", other.iter().map(|x| format!("'{}'", x)).collect::<Vec<String>>().join(", "))],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "This is the incomplete case".to_string(),
no_code: false,
@ -237,7 +235,7 @@ impl From<PassError> for DiagnosticFrame {
},
PassError::IncorrectArity(head_range, got, expected, hidden) => {
let positions = vec![Marker {
position: head_range,
position: *head_range,
color: Color::Fst,
text: "This function requires a fixed number of arguments".to_string(),
no_code: false,
@ -249,9 +247,9 @@ impl From<PassError> for DiagnosticFrame {
severity: Severity::Error,
title: "Incorrect arity.".to_string(),
subtitles: vec![],
hints: vec![if expected == 0 {
hints: vec![if *expected == 0 {
format!("This function expects no arguments but got {}", got.len())
} else if hidden == 0 {
} else if *hidden == 0 {
format!("This function expects {} arguments but got {}", expected, got.len())
} else {
format!(
@ -274,9 +272,9 @@ impl From<PassError> for DiagnosticFrame {
)],
positions: vec![
Marker {
position: head_range,
position: *head_range,
color: Color::Fst,
text: if expected == 0 {
text: if *expected == 0 {
"This rule expects no arguments".to_string()
} else {
format!("This rule expects {} explicit arguments", expected)
@ -285,7 +283,7 @@ impl From<PassError> for DiagnosticFrame {
main: true,
},
Marker {
position: place_range,
position: *place_range,
color: Color::Snd,
text: "This is what triggers the sugar".to_string(),
no_code: false,
@ -301,14 +299,14 @@ impl From<PassError> for DiagnosticFrame {
hints: vec![],
positions: vec![
Marker {
position: last_decl,
position: *last_decl,
color: Color::Fst,
text: "Second occurence".to_string(),
no_code: false,
main: true,
},
Marker {
position: first_decl,
position: *first_decl,
color: Color::Snd,
text: "First occurence".to_string(),
no_code: false,
@ -316,29 +314,6 @@ impl From<PassError> for DiagnosticFrame {
},
],
},
PassError::CannotUseNamed(fun_range, binding_range) => DiagnosticFrame {
code: 213,
severity: Severity::Error,
title: "Cannot use named parameters in this type of function application".to_string(),
subtitles: vec![],
hints: vec![],
positions: vec![
Marker {
position: fun_range,
color: Color::Fst,
text: "This is the head of the application".to_string(),
no_code: false,
main: true,
},
Marker {
position: binding_range,
color: Color::Snd,
text: "This isn't allowed for this kind of application".to_string(),
no_code: false,
main: false,
},
],
},
PassError::RepeatedVariable(first_decl, last_decl) => DiagnosticFrame {
code: 214,
severity: Severity::Error,
@ -347,14 +322,14 @@ impl From<PassError> for DiagnosticFrame {
hints: vec!["Rename one of the occurences".to_string()],
positions: vec![
Marker {
position: last_decl,
position: *last_decl,
color: Color::Fst,
text: "Second occurence".to_string(),
no_code: false,
main: true,
},
Marker {
position: first_decl,
position: *first_decl,
color: Color::Snd,
text: "First occurence".to_string(),
no_code: false,
@ -369,7 +344,7 @@ impl From<PassError> for DiagnosticFrame {
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: range,
position: *range,
color: Color::Fst,
text: format!("Cannot find alias for '{}'", name),
no_code: false,
@ -382,7 +357,7 @@ impl From<PassError> for DiagnosticFrame {
match error_range {
Span::Generated => (),
Span::Locatable(error_range) => positions.push(Marker {
position: error_range,
position: *error_range,
color: Color::Fst,
text: "This expression is not the parameter".to_string(),
no_code: false,
@ -391,7 +366,7 @@ impl From<PassError> for DiagnosticFrame {
}
positions.push(Marker {
position: declaration_range,
position:* declaration_range,
color: Color::Snd,
text: "This is the parameter that should be used".to_string(),
no_code: false,
@ -415,14 +390,14 @@ impl From<PassError> for DiagnosticFrame {
hints: vec![],
positions: vec![
Marker {
position: error_range,
position: *error_range,
color: Color::Fst,
text: "This is not the type that is being declared".to_string(),
no_code: false,
main: true,
},
Marker {
position: declaration_range,
position: *declaration_range,
color: Color::Snd,
text: "This is the type that should be used instead".to_string(),
no_code: false,
@ -440,36 +415,13 @@ impl From<PassError> for DiagnosticFrame {
other.iter().map(|x| format!("'{}'", x)).collect::<Vec<String>>().join(", ")
)],
positions: vec![Marker {
position: place,
position: *place,
color: Color::Fst,
text: "This is the incomplete case".to_string(),
no_code: false,
main: true,
}],
},
PassError::DuplicatedConstructor(place, other) => DiagnosticFrame {
code: 209,
severity: Severity::Error,
title: "Duplicated constructor name".to_string(),
subtitles: vec![],
hints: vec![],
positions: vec![
Marker {
position: place,
color: Color::Fst,
text: "Here".to_string(),
no_code: false,
main: true,
},
Marker {
position: other,
color: Color::Fst,
text: "Here".to_string(),
no_code: false,
main: false,
},
],
},
}
}
}

View File

@ -2,145 +2,19 @@
//! Currently it just derives `match` and `open` for sum type
//! and record types respectively.
use std::sync::mpsc::Sender;
use fxhash::FxHashMap;
use kind_derive::matching::derive_match;
use kind_derive::open::derive_open;
use kind_tree::concrete::{
self, expr::Expr, Argument, Binding, Book, Entry, EntryMeta, ExprKind, Literal, RecordDecl,
SumTypeDecl, Telescope, TopLevel,
};
use kind_report::data::Diagnostic;
use kind_tree::concrete::{Book, TopLevel};
/// Expands sum type and record definitions to a lot of
/// helper definitions like eliminators and replace qualified identifiers
/// by their module names.
pub mod uses;
pub fn expand_record_type(book: &mut FxHashMap<String, (Entry, EntryMeta)>, rec_type: &RecordDecl) {
let type_constructor = Entry {
name: rec_type.name.clone(),
args: rec_type.parameters.clone(),
docs: rec_type.docs.clone(),
typ: Box::new(Expr {
data: ExprKind::Lit(Literal::Type),
range: rec_type.name.range,
}),
rules: Vec::new(),
range: rec_type.name.range,
attrs: rec_type.attrs.clone(),
};
book.insert(
rec_type.name.to_string(),
(type_constructor, rec_type.extract_book_info()),
);
let irrelevant_params = rec_type.parameters.map(|x| x.to_implicit());
let args = irrelevant_params
.iter()
.map(|x| {
Binding::Positional(Box::new(Expr {
data: ExprKind::Var(x.name.clone()),
range: x.range,
}))
})
.collect::<Vec<Binding>>();
let typ = Box::new(Expr {
data: ExprKind::Constr(rec_type.name.clone(), args),
range: rec_type.name.range,
});
let cons_ident = rec_type.name.add_segment(rec_type.constructor.to_str());
let data_constructor = Entry {
name: cons_ident.clone(),
args: irrelevant_params.extend(&Telescope::new(rec_type.fields.clone()).map(
|(ident, _, ty)| Argument {
hidden: false,
erased: false,
name: ident.clone(),
typ: Some(ty.clone()),
range: ident.range,
},
)),
typ,
rules: Vec::new(),
range: rec_type.constructor.range,
attrs: Vec::new(),
docs: vec![],
};
book.insert(
cons_ident.to_string(),
(
data_constructor,
rec_type.extract_book_info_of_constructor(),
),
);
}
pub fn expand_sum_type(book: &mut FxHashMap<String, (Entry, EntryMeta)>, sum_type: &SumTypeDecl) {
let params = sum_type.parameters.clone();
let indices = sum_type.indices.clone();
let type_constructor = Entry {
name: sum_type.name.clone(),
args: sum_type.parameters.extend(&sum_type.indices),
docs: sum_type.docs.clone(),
typ: Box::new(Expr {
data: ExprKind::Lit(Literal::Type),
range: sum_type.name.range,
}),
rules: Vec::new(),
range: sum_type.name.range,
attrs: sum_type.attrs.clone(),
};
let extracted = sum_type.extract_book_info();
book.insert(sum_type.name.to_string(), (type_constructor, extracted));
let irrelevant_params = params.map(|x| x.to_implicit());
let irelevant_indices = indices.map(|x| x.to_implicit());
for cons in &sum_type.constructors {
let cons_ident = sum_type.name.add_segment(cons.name.to_str());
let pre_indices = if cons.typ.is_none() {
irelevant_indices.clone()
} else {
Telescope::new(vec![])
};
let typ = cons.typ.clone().unwrap_or_else(|| {
let args = params.extend(&pre_indices).map(|x| {
concrete::Binding::Positional(Box::new(Expr {
data: ExprKind::Var(x.name.clone()),
range: x.range,
}))
});
Box::new(Expr {
data: ExprKind::Constr(sum_type.name.clone(), args.to_vec()),
range: sum_type.name.range,
})
});
let data_constructor = Entry {
name: cons_ident.clone(),
args: irrelevant_params.extend(&pre_indices).extend(&cons.args),
typ,
rules: Vec::new(),
attrs: Vec::new(),
docs: vec![],
range: cons_ident.range,
};
let book_info = cons.extract_book_info(sum_type);
book.insert(cons_ident.to_string(), (data_constructor, book_info));
}
}
pub fn expand_book(book: &mut Book) {
pub fn expand_book(error_channel: Sender<Box<dyn Diagnostic>>, book: &mut Book) {
let mut entries = FxHashMap::default();
for entry in book.entries.values() {
match entry {

View File

@ -1,5 +1,5 @@
use fxhash::FxHashMap;
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_tree::concrete::{visitor::Visitor, Module};
/// Expands sum type and record definitions to a lot of
/// helper definitions like eliminators and replace qualified identifiers
@ -10,7 +10,7 @@ use crate::errors::PassError;
pub struct Expand {
pub names: FxHashMap<String, String>,
pub errors: Sender<DiagnosticFrame>,
pub errors: Sender<Box<dyn Diagnostic>>,
pub failed: bool,
}
@ -23,7 +23,10 @@ impl Visitor for Expand {
Some(path) => path,
None => {
self.errors
.send(PassError::CannotFindAlias(ident.root.to_string(), ident.range).into())
.send(Box::new(PassError::CannotFindAlias(
ident.root.to_string(),
ident.range,
)))
.unwrap();
self.failed = true;
return;
@ -39,7 +42,7 @@ impl Visitor for Expand {
}
}
pub fn expand_uses(module: &mut Module, errors: Sender<DiagnosticFrame>) -> bool {
pub fn expand_uses(module: &mut Module, errors: Sender<Box<dyn Diagnostic>>) -> bool {
let mut session = Expand {
names: module.uses.clone(),
errors,

View File

@ -8,7 +8,7 @@
use std::sync::mpsc::Sender;
use fxhash::{FxHashMap, FxHashSet};
use kind_report::data::DiagnosticFrame;
use kind_report::data::Diagnostic;
use kind_span::Range;
use kind_tree::concrete::expr::{Binding, Case, CaseBinding, Destruct};
use kind_tree::concrete::pat::PatIdent;
@ -26,7 +26,7 @@ use kind_tree::{visit_opt, visit_vec};
use crate::errors::PassError;
pub struct UnboundCollector {
pub errors: Sender<DiagnosticFrame>,
pub errors: Sender<Box<dyn Diagnostic>>,
// Utils for keeping variables tracking and report duplicated ones.
pub context_vars: Vec<(Range, String)>,
@ -38,7 +38,10 @@ pub struct UnboundCollector {
}
impl UnboundCollector {
pub fn new(diagnostic_sender: Sender<DiagnosticFrame>, emit_errs: bool) -> UnboundCollector {
pub fn new(
diagnostic_sender: Sender<Box<dyn Diagnostic>>,
emit_errs: bool,
) -> UnboundCollector {
Self {
errors: diagnostic_sender,
context_vars: Default::default(),
@ -51,7 +54,7 @@ impl UnboundCollector {
}
pub fn get_module_unbound(
diagnostic_sender: Sender<DiagnosticFrame>,
diagnostic_sender: Sender<Box<dyn Diagnostic>>,
module: &mut Module,
emit_errs: bool,
) -> (
@ -64,7 +67,7 @@ pub fn get_module_unbound(
}
pub fn get_book_unbound(
diagnostic_sender: Sender<DiagnosticFrame>,
diagnostic_sender: Sender<Box<dyn Diagnostic>>,
book: &mut Book,
emit_errs: bool,
) -> (
@ -135,7 +138,7 @@ impl Visitor for UnboundCollector {
{
if self.emit_errs {
self.errors
.send(PassError::RepeatedVariable(fst.0, ident.0.range).into())
.send(Box::new(PassError::RepeatedVariable(fst.0, ident.0.range)))
.unwrap()
}
} else {
@ -157,7 +160,10 @@ impl Visitor for UnboundCollector {
if let Some(fst) = res {
if self.emit_errs {
self.errors
.send(PassError::RepeatedVariable(fst.0, argument.name.range).into())
.send(Box::new(PassError::RepeatedVariable(
fst.0,
argument.name.range,
)))
.unwrap()
}
} else {
@ -268,7 +274,11 @@ impl Visitor for UnboundCollector {
fn visit_destruct(&mut self, destruct: &mut Destruct) {
match destruct {
Destruct::Destruct(range, ty, bindings, _) => {
self.visit_qualified_ident(&mut QualifiedIdent::add_segment(ty, "open").to_sugar().to_generated());
self.visit_qualified_ident(
&mut QualifiedIdent::add_segment(ty, "open")
.to_sugar()
.to_generated(),
);
self.visit_range(range);
self.visit_qualified_ident(ty);
for bind in bindings {

View File

@ -6,3 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
kind-parser = { path = "../kind-parser" }
kind-tree = { path = "../kind-tree" }
kind-span = { path = "../kind-span" }
kind-report = { path = "../kind-report" }
kind-checker = { path = "../kind-checker" }
kind-pass = { path = "../kind-pass" }
kind-target-hvm = { path = "../kind-target-hvm" }
fxhash = "0.2.1"

View File

@ -0,0 +1,63 @@
use std::collections::HashMap;
use fxhash::FxHashSet;
struct Node<T> {
data: T,
invalidated: bool,
children: FxHashSet<usize>,
parents: FxHashSet<usize>,
}
#[derive(Default)]
pub struct Graph<T> {
// Using a hashmap to make it easier to add or remove node.s
nodes: HashMap<usize, Node<T>>,
count: usize,
}
impl<T> Graph<T> {
pub fn add(&mut self, data: T, parent: usize) {
self.nodes.insert(
self.count,
Node {
data,
invalidated: false,
children: FxHashSet::default(),
parents: FxHashSet::from_iter(vec![parent]),
},
);
self.count += 1;
}
pub fn remove(&mut self, node_idx: usize) {
if let Some(node) = self.nodes.get(&node_idx) {
let children = node.children.clone();
let parents = node.parents.clone();
for child in children {
if let Some(child) = self.nodes.get_mut(&child) {
child.parents.remove(&node_idx);
}
}
for parent in parents {
if let Some(parent) = self.nodes.get_mut(&parent) {
parent.children.remove(&node_idx);
}
self.flood_invalidation(parent);
}
}
}
fn flood_invalidation(&mut self, node: usize) {
if let Some(node) = self.nodes.get_mut(&node) {
if node.invalidated {
node.invalidated = true;
for parent in node.parents.clone() {
self.flood_invalidation(parent)
}
}
}
}
}

View File

@ -1,3 +1,34 @@
fn main() {
println!("Hello, world!");
//! This module is a generalization of the driver
//! module. It is useful both for LSPs, Watch, Repl
//! and many other things.
use std::path::PathBuf;
use fxhash::FxHashMap;
use graph::Graph;
mod graph;
use kind_report::data::Diagnostic;
use kind_tree::concrete;
pub struct Resource<T> {
path: PathBuf,
concrete_tree: concrete::Module,
/// Accumulated diagnostics while
diagnostics: Vec<Box<dyn Diagnostic>>,
/// Useful for LSP URIs
ext: T,
}
#[derive(Default)]
pub struct Session<T> {
/// Stores
graph: Graph<usize>,
/// Useful for removing and adding resources
resources: FxHashMap<usize, Resource<T>>,
}
impl<T> Session<T> {
pub fn check() {}
}

View File

@ -53,25 +53,12 @@ pub struct DiagnosticFrame {
pub positions: Vec<Marker>,
}
impl<'a> DiagnosticFrame {
pub fn to_diagnostic(&'a self) -> Diagnostic<'a> {
Diagnostic { frame: self }
}
}
#[derive(Debug, Clone)]
pub struct Diagnostic<'a> {
pub frame: &'a DiagnosticFrame,
}
pub enum Log {
Checking(String),
Checked(Duration),
Failed(Duration),
}
impl<'a> From<&'a DiagnosticFrame> for Diagnostic<'a> {
fn from(frame: &'a DiagnosticFrame) -> Self {
Diagnostic { frame }
}
pub trait Diagnostic {
fn to_diagnostic_frame(&self) -> DiagnosticFrame;
}

View File

@ -393,7 +393,7 @@ pub trait Report {
) -> std::fmt::Result;
}
impl<'a> Report for Diagnostic<'a> {
impl Report for Box<dyn Diagnostic> {
fn render<T: Write + Sized, C: FileCache>(
&self,
cache: &C,
@ -401,14 +401,17 @@ impl<'a> Report for Diagnostic<'a> {
fmt: &mut T,
) -> std::fmt::Result {
write!(fmt, " ")?;
render_tag(&self.frame.severity, fmt)?;
writeln!(fmt, "{}", Paint::new(&self.frame.title).bold())?;
if !self.frame.subtitles.is_empty() {
let frame = self.to_diagnostic_frame();
render_tag(&frame.severity, fmt)?;
writeln!(fmt, "{}", Paint::new(&frame.title).bold())?;
if !frame.subtitles.is_empty() {
writeln!(fmt)?;
}
for subtitle in &self.frame.subtitles {
for subtitle in &frame.subtitles {
match subtitle {
Subtitle::Normal(color, phr) => {
let colorizer = get_colorizer(color);
@ -452,7 +455,7 @@ impl<'a> Report for Diagnostic<'a> {
}
}
let groups = group_markers(&self.frame.positions);
let groups = group_markers(&frame.positions);
let is_empty = groups.is_empty();
for (ctx, group) in groups {
@ -468,7 +471,7 @@ impl<'a> Report for Diagnostic<'a> {
writeln!(fmt)?;
}
for hint in &self.frame.hints {
for hint in &frame.hints {
writeln!(
fmt,
"{:>5} {} {}",
@ -478,7 +481,7 @@ impl<'a> Report for Diagnostic<'a> {
)?;
}
if !self.frame.hints.is_empty() {
if !frame.hints.is_empty() {
writeln!(fmt)?;
}

View File

@ -187,7 +187,7 @@ pub struct EntryMeta {
pub arguments: Telescope<Argument>,
pub is_ctr: bool,
pub range: Range,
pub is_record_cons_of: Option<QualifiedIdent>
pub is_record_cons_of: Option<QualifiedIdent>,
}
/// A book stores definitions by name. It's generated
@ -468,7 +468,7 @@ impl SumTypeDecl {
arguments,
is_ctr: true,
range: self.name.range,
is_record_cons_of: None
is_record_cons_of: None,
}
}
}
@ -509,7 +509,7 @@ impl Constructor {
arguments,
is_ctr: true,
range: self.name.range,
is_record_cons_of: None
is_record_cons_of: None,
}
}
}
@ -547,7 +547,7 @@ impl RecordDecl {
arguments,
is_ctr: true,
range: self.name.range,
is_record_cons_of: None
is_record_cons_of: None,
}
}
@ -576,7 +576,7 @@ impl RecordDecl {
arguments,
is_ctr: true,
range: self.name.range,
is_record_cons_of: Some(self.name.clone())
is_record_cons_of: Some(self.name.clone()),
}
}
}
@ -599,7 +599,7 @@ impl Entry {
arguments,
is_ctr: self.rules.is_empty(),
range: self.name.range,
is_record_cons_of: None
is_record_cons_of: None,
}
}
}