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

This commit is contained in:
Nicolas Abril 2022-11-30 16:31:19 +01:00
commit 0f6cf15915
23 changed files with 455 additions and 399 deletions

132
Cargo.lock generated
View File

@ -14,7 +14,7 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
"winapi 0.3.9",
]
@ -132,14 +132,14 @@ dependencies = [
[[package]]
name = "clap"
version = "4.0.22"
version = "4.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91b9970d7505127a162fdaa9b96428d28a479ba78c9ec7550a63a5d9863db682"
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
dependencies = [
"atty",
"bitflags",
"clap_derive 4.0.21",
"clap_lex 0.3.0",
"is-terminal",
"once_cell",
"strsim",
"termcolor",
@ -250,9 +250,9 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
version = "0.9.12"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bf8df95e795db1a4aca2957ad884a2df35413b24bbeb3114422f3cc21498e8"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg 1.1.0",
"cfg-if",
@ -263,9 +263,9 @@ dependencies = [
[[package]]
name = "crossbeam-queue"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebb3d1683412e9be6a15533314f00ec223c0762c522a3f77f048b265aab4470c"
checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add"
dependencies = [
"cfg-if",
"crossbeam-utils",
@ -273,9 +273,9 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
version = "0.8.12"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
@ -330,6 +330,27 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "fixed-hash"
version = "0.7.0"
@ -405,6 +426,15 @@ dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hex"
version = "0.4.3"
@ -419,8 +449,8 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
[[package]]
name = "hvm"
version = "1.0.4-beta"
source = "git+https://github.com/Kindelia/HVM.git#169f82733a4cbfe15f3d49d45a8aef02c24de18d"
version = "1.0.5-beta"
source = "git+https://github.com/Kindelia/HVM.git#0b191cdb5f8997a7e9c257d709c522e06d331b73"
dependencies = [
"clap 3.2.23",
"crossbeam",
@ -501,6 +531,28 @@ dependencies = [
"web-sys",
]
[[package]]
name = "io-lifetimes"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
dependencies = [
"hermit-abi 0.2.6",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -554,7 +606,7 @@ dependencies = [
name = "kind-cli"
version = "0.3.0"
dependencies = [
"clap 4.0.22",
"clap 4.0.29",
"kind-checker",
"kind-driver",
"kind-query",
@ -700,7 +752,7 @@ dependencies = [
[[package]]
name = "kindelia_common"
version = "0.1.5"
source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#5a59c6b0798c561bb1ec42a6e786a93af9151276"
source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#ff2f75e319c167cbc9d19cbc35fbe0d9a510b56a"
dependencies = [
"bit-vec",
"hex",
@ -714,7 +766,7 @@ dependencies = [
[[package]]
name = "kindelia_lang"
version = "0.1.0"
source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#5a59c6b0798c561bb1ec42a6e786a93af9151276"
source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#ff2f75e319c167cbc9d19cbc35fbe0d9a510b56a"
dependencies = [
"hex",
"kindelia_common",
@ -733,6 +785,12 @@ version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "linux-raw-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
[[package]]
name = "lock_api"
version = "0.4.9"
@ -817,7 +875,7 @@ version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"hermit-abi 0.1.19",
"libc",
]
@ -841,9 +899,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "os_str_bytes"
version = "6.3.1"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "output_vt100"
@ -882,9 +940,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"cfg-if",
"libc",
@ -1188,6 +1246,20 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6"
[[package]]
name = "rustix"
version = "0.36.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "same-file"
version = "1.0.6"
@ -1224,18 +1296,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.147"
version = "1.0.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.147"
version = "1.0.148"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
dependencies = [
"proc-macro2",
"quote",
@ -1284,9 +1356,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.103"
version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
dependencies = [
"proc-macro2",
"quote",
@ -1295,9 +1367,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.26.7"
version = "0.26.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c375d5fd899e32847b8566e10598d6e9f1d9b55ec6de3cdf9e7da4bdc51371bc"
checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6"
dependencies = [
"cfg-if",
"core-foundation-sys",
@ -1400,9 +1472,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "uint"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601"
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
dependencies = [
"byteorder",
"crunchy",

View File

@ -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!(

View File

@ -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
});
}
}
}

View File

@ -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())
}

View File

@ -81,6 +81,7 @@ impl<'a> Visitor for Subst<'a> {
PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (),
PatKind::Hole => (),
PatKind::List(ls) => {
for pat in ls {

View File

@ -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())
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -295,6 +295,7 @@ impl<'a> DesugarState<'a> {
PatKind::U60(n) => desugared::Expr::num_u60(pat.range, *n),
PatKind::U120(n) => desugared::Expr::num_u120(pat.range, *n),
PatKind::F60(n) => desugared::Expr::num_f60(pat.range, *n),
PatKind::Char(n) => desugared::Expr::num_u60(pat.range, *n as u64),
PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd),
PatKind::List(ls) => self.desugar_list_pat(pat.range, ls),
PatKind::Str(string) => desugared::Expr::str(pat.range, string.to_owned()),

View File

@ -54,7 +54,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,
@ -99,7 +99,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();
@ -189,9 +189,9 @@ impl<'a> ErasureState<'a> {
}
if self.failed {
None
Err(())
} else {
Some(new_book)
Ok(new_book)
}
}

View File

@ -338,6 +338,7 @@ impl Visitor for UnboundCollector {
PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (),
PatKind::Hole => (),
PatKind::List(ls) => {
for pat in ls {

View File

@ -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 {

View File

@ -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);
@ -24,5 +24,5 @@ pub fn compile_book(
let file = compile::compile_book(&flattened, sender, namespace)?;
let file = linearize::linearize_file(file);
Some(file)
Ok(file)
}

View 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)
})
}

View File

@ -1,7 +1,7 @@
ERROR Type mismatch
* Got : (Eq _ 123u120 123u120)
* Expected : (Eq _ 123u120 124u120)
* Got : (Eq _ (U120.new 0 123) (U120.new 0 123))
* Expected : (Eq _ (U120.new 0 123) (U120.new 0 124))
/--[suite/checker/derive/fail/WrongU120Eq.kind2:12:9]

View File

@ -0,0 +1,7 @@
ctr {U120.new a b}
ctr {List.cons h t}
fun (TestFunc xs) {
(TestFunc {List.cons ~ x1}) = (!@x1.0 (!@x2 dup c.0 x2.0 = x2; dup x2.1 x2.2 = c.0; (!@x3 (!@x3.0 (!@~ {List.cons (& (+ x2.0 x3.0) #1152921504606846975) x1.0} {U120.new #0 #4}) x3) (& (+ x2.1 x2.2) #1152921504606846975)) {U120.new #0 #2}) x1)
}

View File

@ -0,0 +1,14 @@
U120 : Type
U120.new (a: U60) (b: U60) : U120
List : Type
List.nil : List
List.cons (h: U120) (t: List) : Type
#keep
TestFunc (xs: List) : List
TestFunc (List.cons h t) =
let aa = 2u120
let bb = (+ aa aa)
let cc = 4u120
List.cons (+ aa bb) t

View File

@ -1,5 +1,5 @@
fun (A ) {
{A} = #2
(A) = #2
}
run {

View File

@ -1,4 +1,4 @@
fun (A ) {
{A} = (& (+ (B) #1) #1152921504606846975)
(A) = (& (+ (B) #1) #1152921504606846975)
}

View File

@ -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()
},
_ => {

View File

@ -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,

View File

@ -31,6 +31,8 @@ pub enum PatKind {
List(Vec<Pat>),
/// Str
Str(String),
///
Char(char),
/// Wildcard
Hole,
}
@ -65,6 +67,7 @@ impl Display for Pat {
U60(num) => write!(f, "{}", num),
U120(num) => write!(f, "{}u120", num),
F60(_num) => todo!(),
Char(chr) => write!(f, "\'{}\'", chr),
Pair(fst, snd) => write!(f, "({}, {})", fst, snd),
Hole => write!(f, "_"),
}

View File

@ -283,6 +283,7 @@ pub fn walk_pat<T: Visitor>(ctx: &mut T, pat: &mut Pat) {
PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (),
PatKind::Hole => (),
PatKind::List(ls) => {
for pat in ls {