mirror of
https://github.com/HigherOrderCO/Kind1.git
synced 2024-09-11 08:45:32 +03:00
style: changed code style
This commit is contained in:
parent
9f94818d41
commit
83165376bc
@ -17,13 +17,15 @@ use report::parse_report;
|
||||
|
||||
pub const CHECKER: &str = include_str!("checker.hvm");
|
||||
|
||||
pub fn eval(file: &str, term: &str, dbug: bool) -> Result<Box<Term>, String> {
|
||||
pub fn eval(file: &str, term: &str, dbug: bool, tids: Option<usize>) -> Result<Box<Term>, String> {
|
||||
let file = language::syntax::read_file(&format!("{}\nHVM_MAIN_CALL = {}", file, term))?;
|
||||
let book = language::rulebook::gen_rulebook(&file);
|
||||
let mut prog = runtime::Program::new();
|
||||
prog.add_book(&book);
|
||||
let size = runtime::default_heap_size();
|
||||
let tids = runtime::default_heap_tids();
|
||||
|
||||
let tids = tids.unwrap_or_else(runtime::default_heap_tids);
|
||||
|
||||
let heap = runtime::new_heap(size, tids);
|
||||
let tids = runtime::new_tids(tids);
|
||||
runtime::link(
|
||||
@ -53,10 +55,11 @@ pub fn type_check(
|
||||
book: &Book,
|
||||
tx: Sender<Box<dyn Diagnostic>>,
|
||||
functions_to_check: Vec<String>,
|
||||
tids: Option<usize>
|
||||
) -> bool {
|
||||
let file = gen_checker(book, functions_to_check);
|
||||
|
||||
match eval(&file, "Main", false) {
|
||||
match eval(&file, "Main", false, tids) {
|
||||
Ok(term) => {
|
||||
let errs = parse_report(&term).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
|
@ -1,271 +0,0 @@
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use std::{fmt, io};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use kind_driver::session::Session;
|
||||
use kind_report::data::{Diagnostic, Log};
|
||||
use kind_report::report::{FileCache, Report};
|
||||
use kind_report::RenderConfig;
|
||||
|
||||
use kind_driver as driver;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
#[clap(propagate_version = true)]
|
||||
pub struct Cli {
|
||||
/// Configuration file to change information about
|
||||
/// pretty printing or project root.
|
||||
#[arg(short, long, value_name = "FILE")]
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
/// Turn on the debugging information generated
|
||||
/// by the compiler.
|
||||
#[arg(short, long)]
|
||||
pub debug: bool,
|
||||
|
||||
/// Show warning messages
|
||||
#[arg(short, long)]
|
||||
pub warning: bool,
|
||||
|
||||
/// Disable colors in error messages
|
||||
#[arg(short, long)]
|
||||
pub no_color: bool,
|
||||
|
||||
/// Prints all of the functions and their evaluation
|
||||
#[arg(short, long)]
|
||||
pub trace: bool,
|
||||
|
||||
/// Only ascii characters in error messages
|
||||
#[arg(short, long)]
|
||||
pub ascii: bool,
|
||||
|
||||
#[arg(short, long)]
|
||||
entrypoint: Option<String>,
|
||||
|
||||
#[arg(short, long, value_name = "FILE")]
|
||||
pub root: Option<PathBuf>,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub command: Command,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Command {
|
||||
/// Check a file
|
||||
#[clap(aliases = &["c"])]
|
||||
Check { file: String },
|
||||
|
||||
/// Evaluates Main on Kind2
|
||||
#[clap(aliases = &["er"])]
|
||||
Eval { file: String },
|
||||
|
||||
#[clap(aliases = &["k"])]
|
||||
ToKindCore { file: String },
|
||||
|
||||
#[clap(aliases = &["e"])]
|
||||
Erase { file: String },
|
||||
|
||||
/// Runs Main on the HVM
|
||||
#[clap(aliases = &["r"])]
|
||||
Run { file: String },
|
||||
|
||||
/// Generates a checker (.hvm) for a file
|
||||
#[clap(aliases = &["gc"])]
|
||||
GenChecker { file: String },
|
||||
|
||||
/// Stringifies a file
|
||||
#[clap(aliases = &["s"])]
|
||||
Show { file: String },
|
||||
|
||||
/// Compiles a file to Kindelia (.kdl)
|
||||
#[clap(aliases = &["kdl"])]
|
||||
ToKDL {
|
||||
file: String,
|
||||
/// If given, a namespace that goes before each compiled name. Can be at most 10 charaters long.
|
||||
#[clap(long, aliases = &["ns"])]
|
||||
namespace: Option<String>,
|
||||
},
|
||||
|
||||
/// Compiles a file to HVM (.hvm)
|
||||
#[clap(aliases = &["hvm"])]
|
||||
ToHVM { file: String },
|
||||
}
|
||||
|
||||
/// Helper structure to use stderr as fmt::Write
|
||||
struct ToWriteFmt<T>(pub T);
|
||||
|
||||
impl<T> fmt::Write for ToWriteFmt<T>
|
||||
where
|
||||
T: io::Write,
|
||||
{
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_to_stderr<T, E>(render_config: &RenderConfig, session: &T, err: &E)
|
||||
where
|
||||
T: FileCache,
|
||||
E: Report,
|
||||
{
|
||||
Report::render(
|
||||
err,
|
||||
session,
|
||||
render_config,
|
||||
&mut ToWriteFmt(std::io::stderr()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn compile_in_session<T>(
|
||||
render_config: RenderConfig,
|
||||
root: PathBuf,
|
||||
file: String,
|
||||
compiled: bool,
|
||||
fun: &mut dyn FnMut(&mut Session) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
let (rx, tx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut session = Session::new(root, rx);
|
||||
|
||||
eprintln!();
|
||||
|
||||
render_to_stderr(
|
||||
&render_config,
|
||||
&session,
|
||||
&Log::Checking(format!("the file '{}'", file)),
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let res = fun(&mut session);
|
||||
|
||||
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
|
||||
|
||||
if diagnostics.is_empty() && res.is_some() {
|
||||
render_to_stderr(
|
||||
&render_config,
|
||||
&session,
|
||||
&if compiled {
|
||||
Log::Compiled(start.elapsed())
|
||||
} else {
|
||||
Log::Checked(start.elapsed())
|
||||
},
|
||||
);
|
||||
eprintln!();
|
||||
res
|
||||
} else {
|
||||
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
|
||||
eprintln!();
|
||||
for diagnostic in diagnostics {
|
||||
render_to_stderr(&render_config, &session, &diagnostic)
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_cli(config: Cli) {
|
||||
kind_report::check_if_colors_are_supported(config.no_color);
|
||||
|
||||
let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2);
|
||||
let root = config.root.unwrap_or_else(|| PathBuf::from("."));
|
||||
|
||||
let mut entrypoints = vec!["Main".to_string()];
|
||||
|
||||
if let Some(res) = &config.entrypoint {
|
||||
entrypoints.push(res.clone())
|
||||
}
|
||||
|
||||
match config.command {
|
||||
Command::Check { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), false, &mut |session| {
|
||||
driver::type_check_book(session, &PathBuf::from(file.clone()), entrypoints.clone())
|
||||
});
|
||||
}
|
||||
Command::ToHVM { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book =
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())?;
|
||||
Some(driver::compile_book_to_hvm(book, config.trace))
|
||||
})
|
||||
.map(|res| {
|
||||
println!("{}", res);
|
||||
res
|
||||
});
|
||||
}
|
||||
Command::Run { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book =
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())?;
|
||||
driver::check_main_entry(session, &book)?;
|
||||
Some(driver::compile_book_to_hvm(book, config.trace))
|
||||
});
|
||||
|
||||
if let Some(res) = res {
|
||||
match driver::execute_file(&res.to_string()) {
|
||||
Ok(res) => println!("{}", res),
|
||||
Err(err) => println!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::Show { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::to_book(session, &PathBuf::from(file.clone()))
|
||||
})
|
||||
.map(|res| {
|
||||
print!("{}", res);
|
||||
res
|
||||
});
|
||||
}
|
||||
Command::ToKindCore { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::desugar_book(session, &PathBuf::from(file.clone()))
|
||||
})
|
||||
.map(|res| {
|
||||
print!("{}", res);
|
||||
res
|
||||
});
|
||||
}
|
||||
Command::Erase { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())
|
||||
})
|
||||
.map(|res| {
|
||||
print!("{}", res);
|
||||
res
|
||||
});
|
||||
}
|
||||
Command::GenChecker { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::check_erasure_book(session, &PathBuf::from(file.clone()))
|
||||
})
|
||||
.map(|res| {
|
||||
print!("{}", driver::generate_checker(&res));
|
||||
res
|
||||
});
|
||||
}
|
||||
Command::Eval { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
|
||||
driver::check_main_desugared_entry(session, &book)?;
|
||||
Some(book)
|
||||
})
|
||||
.map(|res| println!("{}", driver::eval_in_checker(&res)));
|
||||
}
|
||||
Command::ToKDL { file, namespace } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::compile_book_to_kdl(
|
||||
&PathBuf::from(file.clone()),
|
||||
session,
|
||||
&namespace.clone().unwrap_or("".to_string()),
|
||||
entrypoints.clone(),
|
||||
)
|
||||
})
|
||||
.map(|res| {
|
||||
println!("{}", res);
|
||||
res
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,267 @@
|
||||
use clap::Parser;
|
||||
use kind_cli::{run_cli, Cli};
|
||||
use std::path::PathBuf;
|
||||
use std::time::Instant;
|
||||
use std::{fmt, io};
|
||||
|
||||
pub fn main() {
|
||||
use clap::{Parser, Subcommand};
|
||||
use kind_driver::session::Session;
|
||||
use kind_report::data::{Diagnostic, Log};
|
||||
use kind_report::report::{FileCache, Report};
|
||||
use kind_report::RenderConfig;
|
||||
|
||||
use kind_driver as driver;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
#[clap(propagate_version = true)]
|
||||
pub struct Cli {
|
||||
/// Configuration file to change information about
|
||||
/// pretty printing or project root.
|
||||
#[arg(short, long, value_name = "FILE")]
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
/// Turn on the debugging information generated
|
||||
/// by the compiler.
|
||||
#[arg(short, long)]
|
||||
pub debug: bool,
|
||||
|
||||
/// Show warning messages
|
||||
#[arg(short, long)]
|
||||
pub warning: bool,
|
||||
|
||||
/// Disable colors in error messages
|
||||
#[arg(short, long)]
|
||||
pub no_color: bool,
|
||||
|
||||
/// How much concurrency in HVM
|
||||
#[arg(short, long)]
|
||||
pub tids: Option<usize>,
|
||||
|
||||
/// Prints all of the functions and their evaluation
|
||||
#[arg(short, long)]
|
||||
pub trace: bool,
|
||||
|
||||
/// Only ascii characters in error messages
|
||||
#[arg(short, long)]
|
||||
pub ascii: bool,
|
||||
|
||||
/// Entrypoint of the file that makes the erasure checker
|
||||
/// not remove the entry.
|
||||
#[arg(short, long)]
|
||||
entrypoint: Option<String>,
|
||||
|
||||
#[arg(short, long, value_name = "FILE")]
|
||||
pub root: Option<PathBuf>,
|
||||
|
||||
#[command(subcommand)]
|
||||
pub command: Command,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
pub enum Command {
|
||||
/// Check a file
|
||||
#[clap(aliases = &["c"])]
|
||||
Check { file: String },
|
||||
|
||||
/// Evaluates Main on Kind2
|
||||
#[clap(aliases = &["er"])]
|
||||
Eval { file: String },
|
||||
|
||||
#[clap(aliases = &["k"])]
|
||||
ToKindCore { file: String },
|
||||
|
||||
#[clap(aliases = &["e"])]
|
||||
Erase { file: String },
|
||||
|
||||
/// Runs Main on the HVM
|
||||
#[clap(aliases = &["r"])]
|
||||
Run { file: String },
|
||||
|
||||
/// Generates a checker (.hvm) for a file
|
||||
#[clap(aliases = &["gc"])]
|
||||
GenChecker { file: String },
|
||||
|
||||
/// Stringifies a file
|
||||
#[clap(aliases = &["s"])]
|
||||
Show { file: String },
|
||||
|
||||
/// Compiles a file to Kindelia (.kdl)
|
||||
#[clap(aliases = &["kdl"])]
|
||||
ToKDL {
|
||||
file: String,
|
||||
/// If given, a namespace that goes before each compiled name. Can be at most 10 charaters long.
|
||||
#[clap(long, aliases = &["ns"])]
|
||||
namespace: Option<String>,
|
||||
},
|
||||
|
||||
/// Compiles a file to HVM (.hvm)
|
||||
#[clap(aliases = &["hvm"])]
|
||||
ToHVM { file: String },
|
||||
}
|
||||
|
||||
/// Helper structure to use stderr as fmt::Write
|
||||
struct ToWriteFmt<T>(pub T);
|
||||
|
||||
impl<T> fmt::Write for ToWriteFmt<T>
|
||||
where
|
||||
T: io::Write,
|
||||
{
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
self.0.write_all(s.as_bytes()).map_err(|_| fmt::Error)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_to_stderr<T, E>(render_config: &RenderConfig, session: &T, err: &E)
|
||||
where
|
||||
T: FileCache,
|
||||
E: Report,
|
||||
{
|
||||
Report::render(
|
||||
err,
|
||||
session,
|
||||
render_config,
|
||||
&mut ToWriteFmt(std::io::stderr()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn compile_in_session<T>(
|
||||
render_config: RenderConfig,
|
||||
root: PathBuf,
|
||||
file: String,
|
||||
compiled: bool,
|
||||
fun: &mut dyn FnMut(&mut Session) -> Result<T, ()>,
|
||||
) -> Result<T, ()> {
|
||||
let (rx, tx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut session = Session::new(root, rx);
|
||||
|
||||
eprintln!();
|
||||
|
||||
render_to_stderr(
|
||||
&render_config,
|
||||
&session,
|
||||
&Log::Checking(format!("the file '{}'", file)),
|
||||
);
|
||||
|
||||
let start = Instant::now();
|
||||
|
||||
let res = fun(&mut session);
|
||||
|
||||
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
|
||||
|
||||
if diagnostics.is_empty() && res.is_ok() {
|
||||
render_to_stderr(
|
||||
&render_config,
|
||||
&session,
|
||||
&if compiled {
|
||||
Log::Compiled(start.elapsed())
|
||||
} else {
|
||||
Log::Checked(start.elapsed())
|
||||
},
|
||||
);
|
||||
eprintln!();
|
||||
Ok(res.unwrap())
|
||||
} else {
|
||||
render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed()));
|
||||
eprintln!();
|
||||
for diagnostic in diagnostics {
|
||||
render_to_stderr(&render_config, &session, &diagnostic)
|
||||
}
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_cli(config: Cli) -> Result<(), ()> {
|
||||
kind_report::check_if_colors_are_supported(config.no_color);
|
||||
|
||||
let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2);
|
||||
let root = config.root.unwrap_or_else(|| PathBuf::from("."));
|
||||
|
||||
let mut entrypoints = vec!["Main".to_string()];
|
||||
|
||||
if let Some(res) = &config.entrypoint {
|
||||
entrypoints.push(res.clone())
|
||||
}
|
||||
|
||||
match config.command {
|
||||
Command::Check { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), false, &mut |session| {
|
||||
driver::type_check_book(session, &PathBuf::from(file.clone()), entrypoints.clone(), config.tids)
|
||||
})?;
|
||||
}
|
||||
Command::ToHVM { file } => {
|
||||
let result = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book =
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())?;
|
||||
Ok(driver::compile_book_to_hvm(book, config.trace))
|
||||
})?;
|
||||
|
||||
println!("{}", result);
|
||||
}
|
||||
Command::Run { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book =
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())?;
|
||||
driver::check_main_entry(session, &book)?;
|
||||
Ok(driver::compile_book_to_hvm(book, config.trace))
|
||||
})?;
|
||||
|
||||
match driver::execute_file(&res.to_string(), config.tids) {
|
||||
Ok(res) => println!("{}", res),
|
||||
Err(err) => println!("{}", err),
|
||||
}
|
||||
}
|
||||
Command::Show { file } => {
|
||||
compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::to_book(session, &PathBuf::from(file.clone()))
|
||||
})
|
||||
.map(|res| {
|
||||
print!("{}", res);
|
||||
res
|
||||
})?;
|
||||
}
|
||||
Command::ToKindCore { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::desugar_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
print!("{}", res);
|
||||
}
|
||||
Command::Erase { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone())
|
||||
})?;
|
||||
print!("{}", res);
|
||||
}
|
||||
Command::GenChecker { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::check_erasure_book(session, &PathBuf::from(file.clone()))
|
||||
})?;
|
||||
print!("{}", driver::generate_checker(&res));
|
||||
}
|
||||
Command::Eval { file } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?;
|
||||
driver::check_main_desugared_entry(session, &book)?;
|
||||
Ok(book)
|
||||
})?;
|
||||
println!("{}", driver::eval_in_checker(&res));
|
||||
}
|
||||
Command::ToKDL { file, namespace } => {
|
||||
let res = compile_in_session(render_config, root, file.clone(), true, &mut |session| {
|
||||
driver::compile_book_to_kdl(
|
||||
&PathBuf::from(file.clone()),
|
||||
session,
|
||||
&namespace.clone().unwrap_or("".to_string()),
|
||||
entrypoints.clone(),
|
||||
)
|
||||
})?;
|
||||
println!("{}", res);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() -> Result<(), ()> {
|
||||
run_cli(Cli::parse())
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ impl<'a> Visitor for Subst<'a> {
|
||||
PatKind::Var(ident) => self.visit_pat_ident(ident),
|
||||
PatKind::Str(_) => (),
|
||||
PatKind::Num(_) => (),
|
||||
PatKind::Char(_) => (),
|
||||
PatKind::Hole => (),
|
||||
PatKind::List(ls) => {
|
||||
for pat in ls {
|
||||
|
@ -25,16 +25,17 @@ pub fn type_check_book(
|
||||
session: &mut Session,
|
||||
path: &PathBuf,
|
||||
entrypoints: Vec<String>,
|
||||
) -> Option<untyped::Book> {
|
||||
tids: Option<usize>
|
||||
) -> 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);
|
||||
let succeeded = checker::type_check(&desugared_book, session.diagnostic_sender.clone(), all, tids);
|
||||
|
||||
if !succeeded {
|
||||
return None;
|
||||
return Err(());
|
||||
}
|
||||
|
||||
let mut book = erasure::erase_book(
|
||||
@ -44,26 +45,26 @@ pub fn type_check_book(
|
||||
)?;
|
||||
inline_book(&mut book);
|
||||
|
||||
Some(book)
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
pub fn to_book(session: &mut Session, path: &PathBuf) -> Option<concrete::Book> {
|
||||
pub fn to_book(session: &mut Session, path: &PathBuf) -> 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 None;
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Some(concrete_book)
|
||||
Ok(concrete_book)
|
||||
}
|
||||
|
||||
pub fn erase_book(
|
||||
session: &mut Session,
|
||||
path: &PathBuf,
|
||||
entrypoints: Vec<String>,
|
||||
) -> Option<untyped::Book> {
|
||||
) -> 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(
|
||||
@ -72,19 +73,17 @@ pub fn erase_book(
|
||||
entrypoints,
|
||||
)?;
|
||||
inline_book(&mut book);
|
||||
Some(book)
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> Option<desugared::Book> {
|
||||
pub fn desugar_book(session: &mut Session, path: &PathBuf) -> 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) -> Option<desugared::Book> {
|
||||
pub fn check_erasure_book(session: &mut Session, path: &PathBuf) -> Result<desugared::Book, ()> {
|
||||
let concrete_book = to_book(session, path)?;
|
||||
let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?;
|
||||
|
||||
Some(desugared_book)
|
||||
desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)
|
||||
}
|
||||
|
||||
pub fn compile_book_to_hvm(book: untyped::Book, trace: bool) -> backend::File {
|
||||
@ -96,7 +95,7 @@ pub fn compile_book_to_kdl(
|
||||
session: &mut Session,
|
||||
namespace: &str,
|
||||
entrypoints: Vec<String>,
|
||||
) -> Option<kind_target_kdl::File> {
|
||||
) -> 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(
|
||||
@ -110,32 +109,32 @@ pub fn compile_book_to_kdl(
|
||||
kind_target_kdl::compile_book(book, session.diagnostic_sender.clone(), namespace)
|
||||
}
|
||||
|
||||
pub fn check_main_entry(session: &mut Session, book: &untyped::Book) -> Option<()> {
|
||||
pub fn check_main_entry(session: &mut Session, book: &untyped::Book) -> Result<(), ()> {
|
||||
if !book.entrs.contains_key("Main") {
|
||||
session
|
||||
.diagnostic_sender
|
||||
.send(Box::new(DriverError::ThereIsntAMain))
|
||||
.unwrap();
|
||||
None
|
||||
Err(())
|
||||
} else {
|
||||
Some(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_main_desugared_entry(session: &mut Session, book: &desugared::Book) -> Option<()> {
|
||||
pub fn check_main_desugared_entry(session: &mut Session, book: &desugared::Book) -> Result<(), ()> {
|
||||
if !book.entrs.contains_key("Main") {
|
||||
session
|
||||
.diagnostic_sender
|
||||
.send(Box::new(DriverError::ThereIsntAMain))
|
||||
.unwrap();
|
||||
None
|
||||
Err(())
|
||||
} else {
|
||||
Some(())
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute_file(file: &str) -> Result<String, String> {
|
||||
let res = eval(file, "Main", false)?;
|
||||
pub fn execute_file(file: &str, tids: Option<usize>) -> Result<String, String> {
|
||||
let res = eval(file, "Main", false, tids)?;
|
||||
Ok(res.to_string())
|
||||
}
|
||||
|
||||
|
@ -260,12 +260,12 @@ fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option<Book> {
|
||||
pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Result<Book, ()> {
|
||||
let mut book = Book::default();
|
||||
if parse_and_store_book_by_path(session, path, &mut book) {
|
||||
None
|
||||
Err(())
|
||||
} else {
|
||||
Some(book)
|
||||
Ok(book)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ pub struct DesugarState<'a> {
|
||||
pub fn desugar_book(
|
||||
errors: Sender<Box<dyn Diagnostic>>,
|
||||
book: &concrete::Book,
|
||||
) -> Option<desugared::Book> {
|
||||
) -> Result<desugared::Book, ()> {
|
||||
let mut state = DesugarState {
|
||||
errors,
|
||||
old_book: book,
|
||||
@ -45,9 +45,9 @@ pub fn desugar_book(
|
||||
};
|
||||
state.desugar_book(book);
|
||||
if state.failed {
|
||||
None
|
||||
Err(())
|
||||
} else {
|
||||
Some(state.new_book)
|
||||
Ok(state.new_book)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,6 +293,7 @@ impl<'a> DesugarState<'a> {
|
||||
}
|
||||
PatKind::Var(ident) => desugared::Expr::var(ident.0.clone()),
|
||||
PatKind::Num(kind_tree::Number::U60(n)) => desugared::Expr::num60(pat.range, *n),
|
||||
PatKind::Char(n) => desugared::Expr::num60(pat.range, *n as u64),
|
||||
PatKind::Num(kind_tree::Number::U120(n)) => desugared::Expr::num120(pat.range, *n),
|
||||
PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd),
|
||||
PatKind::List(ls) => self.desugar_list_pat(pat.range, ls),
|
||||
|
@ -55,7 +55,7 @@ pub fn erase_book(
|
||||
book: &desugared::Book,
|
||||
errs: Sender<Box<dyn Diagnostic>>,
|
||||
entrypoints: Vec<String>,
|
||||
) -> Option<untyped::Book> {
|
||||
) -> Result<untyped::Book, ()> {
|
||||
let mut state = ErasureState {
|
||||
errs,
|
||||
book,
|
||||
@ -100,7 +100,7 @@ impl<'a> ErasureState<'a> {
|
||||
&mut self,
|
||||
book: &'a desugared::Book,
|
||||
named_entrypoints: Vec<String>,
|
||||
) -> Option<untyped::Book> {
|
||||
) -> Result<untyped::Book, ()> {
|
||||
let mut vals = FxHashMap::default();
|
||||
|
||||
let mut entrypoints = Vec::new();
|
||||
@ -190,9 +190,9 @@ impl<'a> ErasureState<'a> {
|
||||
}
|
||||
|
||||
if self.failed {
|
||||
None
|
||||
Err(())
|
||||
} else {
|
||||
Some(new_book)
|
||||
Ok(new_book)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,6 +335,7 @@ impl Visitor for UnboundCollector {
|
||||
match &mut pat.data {
|
||||
PatKind::Var(ident) => self.visit_pat_ident(ident),
|
||||
PatKind::Str(_) => (),
|
||||
PatKind::Char(_) => (),
|
||||
PatKind::Num(_) => (),
|
||||
PatKind::Hole => (),
|
||||
PatKind::List(ls) => {
|
||||
|
@ -97,7 +97,7 @@ pub fn compile_book(
|
||||
book: &untyped::Book,
|
||||
sender: Sender<Box<dyn Diagnostic>>,
|
||||
namespace: &str,
|
||||
) -> Option<File> {
|
||||
) -> Result<File, ()> {
|
||||
let mut ctx = CompileCtx::new(book, sender);
|
||||
|
||||
for (name, entry) in &book.entrs {
|
||||
@ -120,10 +120,10 @@ pub fn compile_book(
|
||||
}
|
||||
|
||||
if ctx.failed {
|
||||
return None;
|
||||
return Err(());
|
||||
}
|
||||
|
||||
Some(ctx.file)
|
||||
Ok(ctx.file)
|
||||
}
|
||||
|
||||
pub fn compile_rule(ctx: &mut CompileCtx, rule: &untyped::Rule) -> kindelia_lang::ast::Rule {
|
||||
|
@ -16,7 +16,7 @@ pub fn compile_book(
|
||||
book: untyped::Book,
|
||||
sender: Sender<Box<dyn Diagnostic>>,
|
||||
namespace: &str,
|
||||
) -> Option<compile::File> {
|
||||
) -> Result<compile::File, ()> {
|
||||
// TODO: Remove kdl_states (maybe check if they're ever called?)
|
||||
// TODO: Convert to some sort of Kindelia.Contract
|
||||
let flattened = flatten(book);
|
||||
@ -26,5 +26,5 @@ pub fn compile_book(
|
||||
println!("{}", file);
|
||||
|
||||
let file = linearize::linearize_file(file);
|
||||
Some(file)
|
||||
Ok(file)
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
use std::{fs, path::{PathBuf, Path}};
|
||||
use std::{fs, path::{PathBuf}};
|
||||
|
||||
use driver::{resolution};
|
||||
use kind_driver::session::Session;
|
||||
use kind_pass::{expand::{self, uses::expand_uses}, desugar, erasure};
|
||||
use kind_tree::concrete;
|
||||
use test::Bencher;
|
||||
|
||||
use kind_checker as checker;
|
||||
use kind_driver as driver;
|
||||
|
||||
fn new_session() -> Session {
|
||||
@ -20,15 +18,6 @@ fn new_session() -> Session {
|
||||
Session::new(root, rx)
|
||||
}
|
||||
|
||||
fn get_book(session: &mut Session, path: &str) -> Result<concrete::Book, String> {
|
||||
let path = PathBuf::from(path);
|
||||
|
||||
match resolution::parse_and_store_book(session, &path) {
|
||||
Some(res) => Ok(res),
|
||||
None => Err("Cannot parse".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn exp_paths() -> Vec<&'static str> {
|
||||
vec![
|
||||
"./suite/eval/Getters.kind2",
|
||||
@ -186,27 +175,3 @@ fn bench_exp_pure_to_hvm(b: &mut Bencher) {
|
||||
}).fold(0, |n, _| n + 1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
#[bench]
|
||||
fn bench_exp_pure_check_without_the_checker(b: &mut Bencher) {
|
||||
let mut paths = exp_paths();
|
||||
|
||||
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 book = desugar::desugar_book(session.diagnostic_sender.clone(), &book).unwrap();
|
||||
assert!(!failed);
|
||||
|
||||
(session, book)
|
||||
}).collect();
|
||||
|
||||
b.iter(move || {
|
||||
books.iter().map(move |(session, book)| {
|
||||
let all = book.entrs.iter().map(|x| x.0).cloned().collect();
|
||||
let succeeded = checker::type_check(book, session.diagnostic_sender.clone(), all);
|
||||
assert!(succeeded)
|
||||
}).fold(0, |n, _| n + 1)
|
||||
})
|
||||
}
|
@ -45,7 +45,7 @@ fn test_checker() -> Result<(), Error> {
|
||||
let mut session = Session::new(root, rx);
|
||||
|
||||
let entrypoints = vec!["Main".to_string()];
|
||||
let check = driver::type_check_book(&mut session, &PathBuf::from(path), entrypoints);
|
||||
let check = driver::type_check_book(&mut session, &PathBuf::from(path), entrypoints, Some(1));
|
||||
|
||||
let diagnostics = tx.try_iter().collect::<Vec<Box<dyn Diagnostic>>>();
|
||||
let render = RenderConfig::ascii(2);
|
||||
@ -53,7 +53,7 @@ fn test_checker() -> Result<(), Error> {
|
||||
kind_report::check_if_colors_are_supported(true);
|
||||
|
||||
match check {
|
||||
Some(_) if diagnostics.is_empty() => "Ok!".to_string(),
|
||||
Ok(_) if diagnostics.is_empty() => "Ok!".to_string(),
|
||||
_ => {
|
||||
let mut res_string = String::new();
|
||||
|
||||
@ -86,8 +86,8 @@ fn test_eval() -> Result<(), Error> {
|
||||
kind_report::check_if_colors_are_supported(true);
|
||||
|
||||
match check {
|
||||
Some(file) if diagnostics.is_empty() => {
|
||||
driver::execute_file(&file.to_string()).map_or_else(|e| e, |f| f)
|
||||
Ok(file) if diagnostics.is_empty() => {
|
||||
driver::execute_file(&file.to_string(), Some(1)).map_or_else(|e| e, |f| f)
|
||||
}
|
||||
_ => {
|
||||
let mut res_string = String::new();
|
||||
@ -121,7 +121,7 @@ fn test_kdl() -> Result<(), Error> {
|
||||
kind_report::check_if_colors_are_supported(true);
|
||||
|
||||
match check {
|
||||
Some(file) if diagnostics.is_empty() => {
|
||||
Ok(file) if diagnostics.is_empty() => {
|
||||
file.to_string()
|
||||
},
|
||||
_ => {
|
||||
|
@ -1,16 +1,15 @@
|
||||
//! This module describes a abstract syntax tree
|
||||
//! that is almost like a concrete tree. It helps when it
|
||||
//! we have to statically analyse the tree with better
|
||||
//! error messages.
|
||||
//! we have to statically analyse the tree in order to generate
|
||||
//! better error messages.
|
||||
|
||||
use super::pat::PatIdent;
|
||||
use crate::symbol::{Ident, QualifiedIdent};
|
||||
use crate::Operator;
|
||||
|
||||
use kind_span::{Locatable, Range};
|
||||
use std::fmt::{Display, Error, Formatter};
|
||||
|
||||
pub struct ConsIdent(pub Ident);
|
||||
|
||||
/// A binding express the positional or named argument of
|
||||
/// a constructor or function.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
@ -22,6 +21,7 @@ pub enum Binding {
|
||||
/// Vector of bindings
|
||||
pub type Spine = Vec<Binding>;
|
||||
|
||||
/// A binding that is used inside applications.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct AppBinding {
|
||||
pub data: Box<Expr>,
|
||||
@ -45,11 +45,10 @@ pub enum CaseBinding {
|
||||
Renamed(Ident, Ident),
|
||||
}
|
||||
|
||||
/// A match case with a constructor that will matches the
|
||||
/// strutinizer, bindings to the names of each of arguments
|
||||
/// of the telescope of the constructor and a right-hand side
|
||||
/// value. The ignore_rest flag useful to just fill all of the
|
||||
/// case bindings that are not used with a default name.
|
||||
/// A match case with a constructor that will match the
|
||||
/// strutinizer, bindings to the names of each arguments and
|
||||
/// a right-hand side value. The ignore_rest flag useful to just
|
||||
/// fill all of the case bindings that are not used with a default name.
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct Case {
|
||||
pub constructor: Ident,
|
||||
|
@ -27,6 +27,8 @@ pub enum PatKind {
|
||||
List(Vec<Pat>),
|
||||
/// Str
|
||||
Str(String),
|
||||
///
|
||||
Char(char),
|
||||
/// Wildcard
|
||||
Hole,
|
||||
}
|
||||
@ -58,6 +60,7 @@ impl Display for Pat {
|
||||
.join(" ")
|
||||
),
|
||||
Str(str) => write!(f, "\"{}\"", str),
|
||||
Char(chr) => write!(f, "\'{}\'", chr),
|
||||
Num(crate::Number::U60(num)) => write!(f, "{}", num),
|
||||
Num(crate::Number::U120(num)) => write!(f, "{}u120", num),
|
||||
Pair(fst, snd) => write!(f, "({}, {})", fst, snd),
|
||||
|
@ -280,6 +280,7 @@ pub fn walk_pat<T: Visitor>(ctx: &mut T, pat: &mut Pat) {
|
||||
match &mut pat.data {
|
||||
PatKind::Var(ident) => ctx.visit_pat_ident(ident),
|
||||
PatKind::Str(_) => (),
|
||||
PatKind::Char(_) => (),
|
||||
PatKind::Num(_) => (),
|
||||
PatKind::Hole => (),
|
||||
PatKind::List(ls) => {
|
||||
|
Loading…
Reference in New Issue
Block a user