mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-10-26 12:27:36 +03:00
style: changed Diagnostic struct to a trait
This commit is contained in:
parent
16467dedce
commit
f22d92da95
@ -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
|
||||
],
|
||||
),
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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: _,
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
@ -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
|
||||
|
@ -0,0 +1,7 @@
|
||||
type Nat {
|
||||
zero
|
||||
succ
|
||||
}
|
||||
|
||||
Nat.zero : U60
|
||||
Nat.zero = 2
|
@ -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();
|
||||
|
||||
|
@ -18,5 +18,3 @@ 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"
|
@ -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,
|
||||
|
@ -41,7 +41,7 @@ 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);
|
||||
|
||||
|
@ -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();
|
||||
@ -36,7 +37,10 @@ fn accumulate_neighbour_paths(
|
||||
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;
|
||||
|
@ -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(),
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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"
|
63
src/kind-query/src/graph.rs
Normal file
63
src/kind-query/src/graph.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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() {}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)?;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user