Merge remote-tracking branch 'origin/experimental' into experimental

This commit is contained in:
Nicolas Abril 2022-11-30 17:56:11 +01:00
commit 8614962426
20 changed files with 280 additions and 136 deletions

16
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "arrayvec"
version = "0.7.2"
@ -351,6 +357,12 @@ dependencies = [
"libc",
]
[[package]]
name = "exitcode"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193"
[[package]]
name = "fixed-hash"
version = "0.7.0"
@ -606,7 +618,9 @@ dependencies = [
name = "kind-cli"
version = "0.3.0"
dependencies = [
"anyhow",
"clap 4.0.29",
"exitcode",
"kind-checker",
"kind-driver",
"kind-query",
@ -628,6 +642,7 @@ dependencies = [
name = "kind-driver"
version = "0.1.0"
dependencies = [
"anyhow",
"dashmap",
"fxhash",
"hvm",
@ -656,6 +671,7 @@ dependencies = [
name = "kind-pass"
version = "0.1.0"
dependencies = [
"anyhow",
"fxhash",
"im-rc",
"kind-derive",

77
FEATURES.md Normal file
View File

@ -0,0 +1,77 @@
It's a entirely new compiler in the 0.3 version. A lot of the features are just simple increments to the old ones but they really help with DX. Lets start by the lexical features:
- Identifiers cannot start with dot
- We can have numbers in a lot of formats now like:
- `0xFF`, `0XFF`, `0o17`, `0O17`, `0b10`, `0B10` and decimals.
- `0u60` and `0u120`, `0n` that describes u120 and u60 literals.
- Numbers can contain lots of underscores (just use one between digits please,
we will change it in the future) e.g `100_000_000`
- There's a distinction between Upper identifiers and Lower identifiers. Upper cased identifiers
can contain a single `'/'` between two parts, if the second part is available then the first one is the name that will be replaced by an 'use' statement.
- each string char and the char inside a char token can contain escape sequences in a looot of format. like `\x12` `\u1234` `\n` `\r` `\t` `\0` `\\` `\'` `\"`
- Comments with `/* */` that can be nested :)
The syntatic features are almost all the same with some small changes.
- Attributes are a little bit more complex and can be seen in some formats.
- Single identifier like: #inline
- With arguments like: #derive[match, open]
- With value like: #kdl_name = Joestar
- Use statements are in the format `use A as B` and they rename upper cased identifiers like `B/c` to `A.c`
- Type definitions now support indices and are in the .kind2 files! e.g:
```js
// Parameters are always in the context like `t` but `n` isnt.
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
}
```
You can use the `match` eliminator to destruct this vec without having to pattern match on this (but you have to derive `match`).
```js
Main : U60
Main =
match Vec (Vec.cons 1 Vec.nil) {
cons xs .. => 0
nil => 1
}
```
Take a look at the section about `match patterns` in order to understand the `xs` and `..` inside the `cons` case.
- Record definitions :D
```js
record User {
constructor new
name : String
age : U60
}
```
You can use the `destruct` notation if you want to destruct a record but you have to derive `open` to make this feature work. `#derive[open]` before the record definition.
```js
// Using
Main : U60
Main = let User.new name .. = User.new "abe" 21
name
```
- Entries stay all the same, except that you cannot put repeated names because it would make the named parameter process a bit harder.
Btw, you can make something like
```js
Dio (n: U60) (i: U60) : Type
// Named parameters :sunglasses:
Main {
Dio (i = 2) (n = 4)
}
```
- All the current syntax sugars are:
- Sigma types
- Substitutions
- Do notation
- Match
- Let
- If
- Doc strings (useful for the future) using `///`

View File

@ -22,7 +22,7 @@ Pure functions are defined via equations, as in [Haskell](https://www.haskell.or
// Applies a function to every element of a list
map <a> <b> (list: List a) (f: a -> b) : List b
map a b Nil f = Nil
map a b (Cons head tail) f = Cons (f x) (map tail f)
map a b (Cons head tail) f = Cons (f head) (map tail f)
```
Side-effective programs are written via monadic monads, resembling [Rust](https://www.rust-lang.org/) and [TypeScript](https://www.typescriptlang.org/):

View File

@ -465,14 +465,6 @@ List.nil)
But underneath the hood, what an implicit argument actually does is automatically put holes in these places.
Moreover, single holes can be shortened as `!`. So it can also be written as:
```
List.cons!(List.cons!(1, List.cons!(2, List.nil!)),
List.cons!(List.cons!(3, List.cons!(4, List.nil!)),
List.nil!))
```
Of course, in this particular example, we can just use the list notation directly:
```

View File

@ -19,4 +19,6 @@ kind-report = { path = "../kind-report" }
kind-checker = { path = "../kind-checker" }
kind-query = { path = "../kind-query" }
clap = { version = "4.0.10", features = ["derive"] }
clap = { version = "4.0.10", features = ["derive"] }
anyhow = "1.0.66"
exitcode = "1.1.2"

View File

@ -3,6 +3,7 @@ use std::time::Instant;
use std::{fmt, io};
use clap::{Parser, Subcommand};
use driver::resolution::ResolutionError;
use kind_driver::session::Session;
use kind_report::data::{Diagnostic, Log};
use kind_report::report::{FileCache, Report};
@ -33,7 +34,7 @@ pub struct Cli {
pub no_color: bool,
/// How much concurrency in HVM
#[arg(short, long)]
#[arg(long)]
pub tids: Option<usize>,
/// Prints all of the functions and their evaluation
@ -129,8 +130,8 @@ pub fn compile_in_session<T>(
root: PathBuf,
file: String,
compiled: bool,
fun: &mut dyn FnMut(&mut Session) -> Result<T, ()>,
) -> Result<T, ()> {
fun: &mut dyn FnMut(&mut Session) -> anyhow::Result<T>,
) -> anyhow::Result<T> {
let (rx, tx) = std::sync::mpsc::channel();
let mut session = Session::new(root, rx);
@ -149,7 +150,8 @@ pub fn compile_in_session<T>(
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
if diagnostics.is_empty() && res.is_ok() {
if diagnostics.is_empty() {
render_to_stderr(
&render_config,
&session,
@ -159,19 +161,27 @@ pub fn compile_in_session<T>(
Log::Checked(start.elapsed())
},
);
eprintln!();
Ok(res.unwrap())
res
} else {
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
eprintln!();
for diagnostic in diagnostics {
render_to_stderr(&render_config, &session, &diagnostic)
}
Err(())
match res {
Ok(_) => Err(ResolutionError.into()),
Err(res) => Err(res)
}
}
}
pub fn run_cli(config: Cli) -> Result<(), ()> {
pub fn run_cli(config: Cli) -> anyhow::Result<()> {
kind_report::check_if_colors_are_supported(config.no_color);
let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2);
@ -262,6 +272,9 @@ pub fn run_cli(config: Cli) -> Result<(), ()> {
Ok(())
}
pub fn main() -> Result<(), ()> {
run_cli(Cli::parse())
pub fn main() {
match run_cli(Cli::parse()) {
Ok(_) => std::process::exit(0),
Err(_) => std::process::exit(1),
}
}

View File

@ -18,6 +18,7 @@ kind-target-kdl = { path = "../kind-target-kdl" }
hvm = { git = "https://github.com/Kindelia/HVM.git" }
anyhow = "1.0.66"
strsim = "0.10.0"
fxhash = "0.2.1"
dashmap = "5.4.0"

View File

@ -56,7 +56,7 @@ impl Diagnostic for DriverError {
DriverError::MultiplePaths(ident, paths) => DiagnosticFrame {
code: 101,
severity: Severity::Error,
title: "Multiple definitions for the same name".to_string(),
title: "Ambiguous definition location for the same name".to_string(),
subtitles: paths
.iter()
.map(|path| Subtitle::Phrase(Color::Fst, vec![Word::White(path.display().to_string())]))

View File

@ -5,6 +5,7 @@ use kind_report::report::FileCache;
use kind_span::SyntaxCtxIndex;
use kind_tree::{backend, concrete, desugared, untyped};
use resolution::ResolutionError;
use session::Session;
use std::path::PathBuf;
@ -25,17 +26,22 @@ pub fn type_check_book(
session: &mut Session,
path: &PathBuf,
entrypoints: Vec<String>,
tids: Option<usize>
) -> Result<untyped::Book, ()> {
tids: Option<usize>,
) -> anyhow::Result<untyped::Book> {
let concrete_book = to_book(session, path)?;
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
let all = desugared_book.entrs.iter().map(|x| x.0).cloned().collect();
let succeeded = checker::type_check(&desugared_book, session.diagnostic_sender.clone(), all, tids);
let succeeded = checker::type_check(
&desugared_book,
session.diagnostic_sender.clone(),
all,
tids,
);
if !succeeded {
return Err(());
return Err(ResolutionError.into());
}
let mut book = erasure::erase_book(
@ -48,14 +54,10 @@ pub fn type_check_book(
Ok(book)
}
pub fn to_book(session: &mut Session, path: &PathBuf) -> Result<concrete::Book, ()> {
pub fn to_book(session: &mut Session, path: &PathBuf) -> anyhow::Result<concrete::Book> {
let mut concrete_book = resolution::parse_and_store_book(session, path)?;
let failed = resolution::check_unbound_top_level(session, &mut concrete_book);
if failed {
return Err(());
}
resolution::check_unbound_top_level(session, &mut concrete_book)?;
Ok(concrete_book)
}
@ -64,24 +66,29 @@ pub fn erase_book(
session: &mut Session,
path: &PathBuf,
entrypoints: Vec<String>,
) -> Result<untyped::Book, ()> {
) -> anyhow::Result<untyped::Book> {
let concrete_book = to_book(session, path)?;
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
let mut book = erasure::erase_book(
&desugared_book,
session.diagnostic_sender.clone(),
entrypoints,
)?;
inline_book(&mut book);
Ok(book)
}
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> Result<desugared::Book, ()> {
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> anyhow::Result<desugared::Book> {
let concrete_book = to_book(session, path)?;
desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)
}
pub fn check_erasure_book(session: &mut Session, path: &PathBuf) -> Result<desugared::Book, ()> {
pub fn check_erasure_book(
session: &mut Session,
path: &PathBuf,
) -> anyhow::Result<desugared::Book> {
let concrete_book = to_book(session, path)?;
desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)
}
@ -95,9 +102,10 @@ pub fn compile_book_to_kdl(
session: &mut Session,
namespace: &str,
entrypoints: Vec<String>,
) -> Result<kind_target_kdl::File, ()> {
) -> anyhow::Result<kind_target_kdl::File> {
let concrete_book = to_book(session, path)?;
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
let mut book = erasure::erase_book(
&desugared_book,
session.diagnostic_sender.clone(),
@ -106,28 +114,29 @@ pub fn compile_book_to_kdl(
inline_book(&mut book);
kind_target_kdl::compile_book(book, session.diagnostic_sender.clone(), namespace)
let res = kind_target_kdl::compile_book(book, session.diagnostic_sender.clone(), namespace)?;
Ok(res)
}
pub fn check_main_entry(session: &mut Session, book: &untyped::Book) -> Result<(), ()> {
pub fn check_main_entry(session: &mut Session, book: &untyped::Book) -> anyhow::Result<()> {
if !book.entrs.contains_key("Main") {
session
.diagnostic_sender
.send(Box::new(DriverError::ThereIsntAMain))
.unwrap();
Err(())
let err = Box::new(DriverError::ThereIsntAMain);
session.diagnostic_sender.send(err).unwrap();
Err(ResolutionError.into())
} else {
Ok(())
}
}
pub fn check_main_desugared_entry(session: &mut Session, book: &desugared::Book) -> Result<(), ()> {
pub fn check_main_desugared_entry(
session: &mut Session,
book: &desugared::Book,
) -> anyhow::Result<()> {
if !book.entrs.contains_key("Main") {
session
.diagnostic_sender
.send(Box::new(DriverError::ThereIsntAMain))
.unwrap();
Err(())
let err = Box::new(DriverError::ThereIsntAMain);
session.diagnostic_sender.send(err).unwrap();
Err(ResolutionError.into())
} else {
Ok(())
}

View File

@ -3,9 +3,11 @@
//! it returns a desugared book of all of the
//! depedencies.
use core::fmt;
use fxhash::FxHashSet;
use kind_pass::expand::expand_module;
use kind_pass::expand::uses::expand_uses;
use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
use std::rc::Rc;
@ -19,6 +21,17 @@ use kind_tree::symbol::{Ident, QualifiedIdent};
use crate::{errors::DriverError, session::Session};
#[derive(Debug)]
pub struct ResolutionError;
impl fmt::Display for ResolutionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "resolution error")
}
}
impl Error for ResolutionError {}
/// The extension of kind2 files.
const EXT: &str = "kind2";
@ -30,10 +43,11 @@ fn accumulate_neighbour_paths(
raw_path: &Path,
) -> 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();
let mut dir_file_path = canon_path.clone();
let dir_path = canon_path.clone();
canon_path.set_extension(EXT);
dir_file_path.push("_");
dir_file_path.set_extension(EXT);
@ -81,13 +95,12 @@ fn try_to_insert_new_name<'a>(
book: &'a mut Book,
) -> bool {
if let Some(first_occorence) = book.names.get(ident.to_string().as_str()) {
session
.diagnostic_sender
.send(Box::new(DriverError::DefinedMultipleTimes(
first_occorence.clone(),
ident,
)))
.unwrap();
let err = Box::new(DriverError::DefinedMultipleTimes(
first_occorence.clone(),
ident,
));
session.diagnostic_sender.send(err).unwrap();
*failed = true;
false
} else {
@ -107,29 +120,30 @@ fn module_to_book<'a>(
for entry in module.entries {
match entry {
TopLevel::SumType(sum) => {
public_names.insert(sum.name.to_string());
let name = sum.name.to_string();
public_names.insert(name.clone());
for cons in &sum.constructors {
let mut cons_ident = sum.name.add_segment(cons.name.to_str());
cons_ident.range = cons.name.range;
if try_to_insert_new_name(failed, session, cons_ident.clone(), book) {
public_names.insert(cons_ident.to_string());
book.count
.insert(cons_ident.to_string(), cons.extract_book_info(&sum));
let cons_name = cons_ident.to_string();
public_names.insert(cons_name.clone());
book.count.insert(cons_name, cons.extract_book_info(&sum));
}
}
if try_to_insert_new_name(failed, session, sum.name.clone(), book) {
book.count
.insert(sum.name.to_string(), sum.extract_book_info());
book.entries
.insert(sum.name.to_string(), TopLevel::SumType(sum));
book.count.insert(name.clone(), sum.extract_book_info());
book.entries.insert(name, TopLevel::SumType(sum));
}
}
TopLevel::RecordType(rec) => {
public_names.insert(rec.name.to_string());
book.count
.insert(rec.name.to_string(), rec.extract_book_info());
let name = rec.name.to_string();
public_names.insert(name.clone());
book.count.insert(name.clone(), rec.extract_book_info());
try_to_insert_new_name(failed, session, rec.name.clone(), book);
let cons_ident = rec.name.add_segment(rec.constructor.to_str());
@ -138,18 +152,18 @@ fn module_to_book<'a>(
cons_ident.to_string(),
rec.extract_book_info_of_constructor(),
);
try_to_insert_new_name(failed, session, cons_ident, book);
book.entries
.insert(rec.name.to_string(), TopLevel::RecordType(rec));
book.entries.insert(name.clone(), TopLevel::RecordType(rec));
}
TopLevel::Entry(entr) => {
let name = entr.name.to_string();
try_to_insert_new_name(failed, session, entr.name.clone(), book);
public_names.insert(entr.name.to_string());
book.count
.insert(entr.name.to_string(), entr.extract_book_info());
book.entries
.insert(entr.name.to_string(), TopLevel::Entry(entr));
public_names.insert(name.clone());
book.count.insert(name.clone(), entr.extract_book_info());
book.entries.insert(name, TopLevel::Entry(entr));
}
}
}
@ -176,25 +190,19 @@ fn parse_and_store_book_by_identifier(
}
}
fn parse_and_store_book_by_path(
session: &mut Session,
path: &PathBuf,
book: &mut Book,
) -> bool {
fn parse_and_store_book_by_path(session: &mut Session, path: &PathBuf, book: &mut Book) -> bool {
if !path.exists() {
session
.diagnostic_sender
.send(Box::new(DriverError::CannotFindFile(
path.to_str().unwrap().to_string(),
)))
.unwrap();
let err = Box::new(DriverError::CannotFindFile(
path.to_str().unwrap().to_string(),
));
session.diagnostic_sender.send(err).unwrap();
return true;
}
if session
.loaded_paths_map
.contains_key(&fs::canonicalize(path).unwrap())
{
let canon_path = &fs::canonicalize(path).unwrap();
if session.loaded_paths_map.contains_key(canon_path) {
return false;
}
@ -213,15 +221,14 @@ fn parse_and_store_book_by_path(
let ctx_id = session.book_counter;
session.add_path(Rc::new(fs::canonicalize(path).unwrap()), input.clone());
let tx = session.diagnostic_sender.clone();
let (mut module, mut failed) =
kind_parser::parse_book(session.diagnostic_sender.clone(), ctx_id, &input);
let (mut module, mut failed) = kind_parser::parse_book(tx.clone(), ctx_id, &input);
expand_uses(&mut module, session.diagnostic_sender.clone());
expand_uses(&mut module, tx.clone());
expand_module(tx.clone(), &mut module);
expand_module(session.diagnostic_sender.clone(), &mut module);
let mut state = UnboundCollector::new(session.diagnostic_sender.clone(), false);
let mut state = UnboundCollector::new(tx.clone(), false);
state.visit_module(&mut module);
for idents in state.unbound.values() {
@ -230,7 +237,7 @@ fn parse_and_store_book_by_path(
}
module_to_book(&mut failed, session, module, book);
for idents in state.unbound_top_level.values() {
let fst = idents.iter().next().unwrap();
if !book.names.contains_key(&fst.to_string()) {
@ -251,41 +258,45 @@ fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) {
similar_names.sort_by(|x, y| x.0.total_cmp(&y.0));
session
.diagnostic_sender
.send(Box::new(DriverError::UnboundVariable(
idents.to_vec(),
similar_names.iter().take(5).map(|x| x.1.clone()).collect(),
)))
.unwrap();
let err = Box::new(DriverError::UnboundVariable(
idents.to_vec(),
similar_names.iter().take(5).map(|x| x.1.clone()).collect(),
));
session.diagnostic_sender.send(err).unwrap();
}
pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Result<Book, ()> {
pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> anyhow::Result<Book> {
let mut book = Book::default();
if parse_and_store_book_by_path(session, path, &mut book) {
Err(())
Err(ResolutionError.into())
} else {
Ok(book)
}
}
pub fn check_unbound_top_level(session: &mut Session, book: &mut Book) -> bool {
pub fn check_unbound_top_level(session: &mut Session, book: &mut Book) -> anyhow::Result<()> {
let mut failed = false;
let (_, unbound_tops) =
unbound::get_book_unbound(session.diagnostic_sender.clone(), book, true);
for (_, unbound) in unbound_tops {
for unbound in unbound_tops.values() {
let res: Vec<Ident> = unbound
.iter()
.filter(|x| !x.generated)
.map(|x| x.to_ident())
.collect();
if !res.is_empty() {
unbound_variable(session, book, &res);
failed = true;
}
}
failed
if failed {
Err(ResolutionError.into())
} else {
Ok(())
}
}

View File

@ -96,8 +96,8 @@ impl<'a> Lexer<'a> {
Some(str)
}
#[inline]
/// Useful as entrypoint
#[inline]
pub fn lex_next(&mut self) -> (Token, Range) {
self.lex_token()
}

View File

@ -1,11 +1,8 @@
use fxhash::FxHashMap;
use kind_tree::concrete::expr::Expr;
use kind_tree::concrete::pat::{Pat, PatIdent, PatKind};
/// Parses all of the top level structures
/// like Book, Entry, Rule and Argument.
use kind_tree::concrete::{
Argument, Attribute, Entry, ExprKind, Module, Rule, Telescope, TopLevel,
};
use kind_tree::concrete::*;
use kind_tree::symbol::QualifiedIdent;
use crate::errors::SyntaxDiagnostic;
@ -85,6 +82,7 @@ impl<'a> Parser<'a> {
fn parse_rule(&mut self, name: String) -> Result<Box<Rule>, SyntaxDiagnostic> {
let start = self.range();
let ident;
if let Token::UpperId(name_id, ext) = self.get() {
let qual = QualifiedIdent::new_static(name_id.as_str(), ext.clone(), start);
if qual.to_string() == name {
@ -95,6 +93,7 @@ impl<'a> Parser<'a> {
} else {
return self.fail(vec![]);
}
let mut pats = Vec::new();
while !self.get().same_variant(&Token::Eq) && !self.get().same_variant(&Token::Eof) {
pats.push(self.parse_pat()?);

View File

@ -13,4 +13,5 @@ kind-derive = { path = "../kind-derive" }
linked-hash-map = "0.5.6"
fxhash = "0.2.1"
im-rc = "15.1.0"
im-rc = "15.1.0"
anyhow = "1.0.66"

View File

@ -16,7 +16,7 @@ use kind_tree::{
symbol::Ident,
};
use crate::errors::PassError;
use crate::errors::{PassError, GenericPassError};
pub mod app;
pub mod attributes;
@ -35,7 +35,7 @@ pub struct DesugarState<'a> {
pub fn desugar_book(
errors: Sender<Box<dyn Diagnostic>>,
book: &concrete::Book,
) -> Result<desugared::Book, ()> {
) -> anyhow::Result<desugared::Book> {
let mut state = DesugarState {
errors,
old_book: book,
@ -45,7 +45,7 @@ pub fn desugar_book(
};
state.desugar_book(book);
if state.failed {
Err(())
Err(GenericPassError.into())
} else {
Ok(state.new_book)
}

View File

@ -245,7 +245,6 @@ impl<'a> DesugarState<'a> {
use concrete::pat::PatKind;
match &pat.data {
PatKind::App(head, spine) => {
// TODO: Fix lol
let entry = self
.old_book
.count

View File

@ -8,7 +8,7 @@ use kind_tree::desugared;
use kind_tree::symbol::QualifiedIdent;
use kind_tree::untyped::{self};
use crate::errors::PassError;
use crate::errors::{PassError, GenericPassError};
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
enum Relevance {
@ -54,7 +54,7 @@ pub fn erase_book(
book: &desugared::Book,
errs: Sender<Box<dyn Diagnostic>>,
entrypoints: Vec<String>,
) -> Result<untyped::Book, ()> {
) -> anyhow::Result<untyped::Book> {
let mut state = ErasureState {
errs,
book,
@ -99,7 +99,7 @@ impl<'a> ErasureState<'a> {
&mut self,
book: &'a desugared::Book,
named_entrypoints: Vec<String>,
) -> Result<untyped::Book, ()> {
) -> anyhow::Result<untyped::Book> {
let mut vals = FxHashMap::default();
let mut entrypoints = Vec::new();
@ -189,7 +189,7 @@ impl<'a> ErasureState<'a> {
}
if self.failed {
Err(())
Err(GenericPassError.into())
} else {
Ok(new_book)
}

View File

@ -1,7 +1,20 @@
use std::{fmt::Display, error::Error};
use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity};
use kind_span::{Range, SyntaxCtxIndex};
use kind_tree::symbol::Ident;
#[derive(Debug)]
pub struct GenericPassError;
impl Display for GenericPassError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "generic pass error")
}
}
impl Error for GenericPassError { }
pub enum Sugar {
DoNotation,
List,

View File

@ -8,7 +8,7 @@ use tiny_keccak::Hasher;
pub use kindelia_lang::ast as kdl;
use crate::errors::KdlError;
use crate::{errors::KdlError, GenericCompilationToHVMError};
pub const KDL_NAME_LEN: usize = 12;
const U60_MAX: kdl::U120 = kdl::U120(0xFFFFFFFFFFFFFFF);
@ -97,7 +97,7 @@ pub fn compile_book(
book: &untyped::Book,
sender: Sender<Box<dyn Diagnostic>>,
namespace: &str,
) -> Result<File, ()> {
) -> Result<File, GenericCompilationToHVMError> {
let mut ctx = CompileCtx::new(book, sender);
for (name, entry) in &book.entrs {
@ -120,7 +120,7 @@ pub fn compile_book(
}
if ctx.failed {
return Err(());
return Err(GenericCompilationToHVMError);
}
Ok(ctx.file)

View File

@ -1,4 +1,4 @@
use std::sync::mpsc::Sender;
use std::{sync::mpsc::Sender, fmt::Display, error::Error};
use flatten::flatten;
use kind_report::data::Diagnostic;
@ -12,11 +12,22 @@ mod flatten;
mod linearize;
mod subst;
#[derive(Debug)]
pub struct GenericCompilationToHVMError;
impl Display for GenericCompilationToHVMError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "generic compilation to hvm error")
}
}
impl Error for GenericCompilationToHVMError { }
pub fn compile_book(
book: untyped::Book,
sender: Sender<Box<dyn Diagnostic>>,
namespace: &str,
) -> Result<compile::File, ()> {
) -> Result<compile::File, GenericCompilationToHVMError> {
// TODO: Remove kdl_states (maybe check if they're ever called?)
// TODO: Convert to some sort of Kindelia.Contract
let flattened = flatten(book);

View File

@ -97,8 +97,8 @@ fn bench_exp_pure_check_unbound(b: &mut Bencher) {
b.iter(|| {
books.iter_mut().map(|(session, book)| {
let failed = resolution::check_unbound_top_level(session, book);
assert!(!failed)
let result = resolution::check_unbound_top_level(session, book);
assert!(result.is_ok());
}).fold(0, |n, _| n + 1)
})
}
@ -110,8 +110,8 @@ fn bench_exp_pure_desugar(b: &mut Bencher) {
let mut books: Vec<_> = paths.iter().map(|x| {
let mut session = new_session();
let mut book = resolution::parse_and_store_book(&mut session, &PathBuf::from(x)).unwrap();
let failed = resolution::check_unbound_top_level(&mut session, &mut book);
assert!(!failed);
let result = resolution::check_unbound_top_level(&mut session, &mut book);
assert!(result.is_ok());
(session, book)
}).collect();
@ -130,9 +130,9 @@ fn bench_exp_pure_erase(b: &mut Bencher) {
let books: Vec<_> = paths.iter().map(|x| {
let mut session = new_session();
let mut book = resolution::parse_and_store_book(&mut session, &PathBuf::from(x)).unwrap();
let failed = resolution::check_unbound_top_level(&mut session, &mut book);
let result = resolution::check_unbound_top_level(&mut session, &mut book);
let book = desugar::desugar_book(session.diagnostic_sender.clone(), &book).unwrap();
assert!(!failed);
assert!(result.is_ok());
(session, book)
}).collect();
@ -156,9 +156,9 @@ fn bench_exp_pure_to_hvm(b: &mut Bencher) {
let books: Vec<_> = paths.iter().map(|x| {
let mut session = new_session();
let mut book = resolution::parse_and_store_book(&mut session, &PathBuf::from(x)).unwrap();
let failed = resolution::check_unbound_top_level(&mut session, &mut book);
let result = resolution::check_unbound_top_level(&mut session, &mut book);
let book = desugar::desugar_book(session.diagnostic_sender.clone(), &book).unwrap();
assert!(!failed);
assert!(result.is_ok());
let book = erasure::erase_book(
&book,