diff --git a/Cargo.lock b/Cargo.lock index 94c24414..e2966437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -742,6 +742,7 @@ name = "kind-target-kdl" version = "0.1.1" dependencies = [ "fxhash", + "im-rc", "kind-derive", "kind-report", "kind-span", @@ -781,7 +782,7 @@ dependencies = [ [[package]] name = "kind2" -version = "0.3.6" +version = "0.3.7" dependencies = [ "anyhow", "clap 4.0.29", @@ -793,8 +794,9 @@ dependencies = [ [[package]] name = "kindelia_common" -version = "0.1.5" -source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#ff2f75e319c167cbc9d19cbc35fbe0d9a510b56a" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8de1aea9d5b1e5bce50affa6c3d720f48a8bcf59bc8e53be68e6509740554cb" dependencies = [ "bit-vec", "hex", @@ -807,12 +809,14 @@ dependencies = [ [[package]] name = "kindelia_lang" -version = "0.1.0" -source = "git+https://github.com/developedby/Kindelia/?branch=kdl-lang-crate#ff2f75e319c167cbc9d19cbc35fbe0d9a510b56a" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4306d4e6a8215201432d0c0b0010ec6374dd31982a02adab41fa491c453f909f" dependencies = [ "hex", "kindelia_common", "serde", + "thiserror", ] [[package]] diff --git a/crates/kind-checker/Cargo.toml b/crates/kind-checker/Cargo.toml index e18b4034..4a07d053 100644 --- a/crates/kind-checker/Cargo.toml +++ b/crates/kind-checker/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-checker" version = "0.1.1" edition = "2021" license = "MIT" +description = "Type checker for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-checker/src/report.rs b/crates/kind-checker/src/report.rs index d0929450..3fc892d1 100644 --- a/crates/kind-checker/src/report.rs +++ b/crates/kind-checker/src/report.rs @@ -2,10 +2,11 @@ //! a Expr of the kind-tree package. use kind_span::{EncodedRange, Range}; -use kind_tree::backend::Term; use kind_tree::symbol::{Ident, QualifiedIdent}; use kind_tree::{desugared, Operator}; +use hvm::Term; + use crate::diagnostic::TypeDiagnostic; use desugared::Expr; diff --git a/crates/kind-cli/Cargo.toml b/crates/kind-cli/Cargo.toml index 97a90388..95a681ca 100644 --- a/crates/kind-cli/Cargo.toml +++ b/crates/kind-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kind2" -version = "0.3.6" +version = "0.3.7" edition = "2021" description = "A pure functional functional language that uses the HVM." repository = "https://github.com/Kindelia/Kind2" diff --git a/crates/kind-cli/README.md b/crates/kind-cli/README.md new file mode 100644 index 00000000..37f3c777 --- /dev/null +++ b/crates/kind-cli/README.md @@ -0,0 +1,94 @@ +Kind2 +===== + +**Kind2** is a **functional programming language** and **proof assistant**. + +It is a complete rewrite of [Kind1](https://github.com/kindelia/kind-legacy), based on +[HVM](https://github.com/kindelia/hvm), a **lazy**, **non-garbage-collected** and **massively parallel** virtual +machine. In [our benchmarks](https://github.com/kindelia/functional-benchmarks), its type-checker outperforms every +alternative proof assistant by a far margin, and its programs can offer exponential speedups over Haskell's GHC. Kind2 +unleashes the [inherent parallelism of the Lambda +Calculus](https://github.com/VictorTaelin/Symmetric-Interaction-Calculus) to become the ultimate programming language of +the next century. + +**Welcome to the inevitable parallel, functional future of computers!** + +Examples +-------- + +Pure functions are defined via equations, as in [Haskell](https://www.haskell.org/): + +```javascript +// Applies a function to every element of a list +map (list: List a) (f: a -> b) : List b +map a b Nil f = Nil +map a b (Cons head tail) f = Cons (f head) (map tail f) +``` + +Side-effective programs are written via monads, resembling [Rust](https://www.rust-lang.org/) and [TypeScript](https://www.typescriptlang.org/): + +```javascript +// Prints the double of every number up to a limit +Main : IO (Result () String) { + ask limit = IO.prompt "Enter limit:" + for x in (List.range limit) { + IO.print "{} * 2 = {}" x (Nat.double x) + } + return Ok () +} +``` + +Theorems can be proved inductively, as in [Agda](https://wiki.portal.chalmers.se/agda/pmwiki.php) and [Idris](https://www.idris-lang.org/): + +```javascript +// Black Friday Theorem. Proof that, for every Nat n: n * 2 / 2 == n. +black_friday_theorem (n: Nat) : Equal Nat (Nat.half (Nat.double n)) n +black_friday_theorem Nat.zero = Equal.refl +black_friday_theorem (Nat.succ n) = Equal.apply (x => Nat.succ x) (black_friday_theorem n) +``` + +For more examples, check the [Wikind](https://github.com/kindelia/wikind). + +Usage +----- + +First, install [Rust](https://www.rust-lang.org/tools/install) first, then enter: + +``` +cargo install kind2 +``` + +### Warning: +New versions probably are not in `cargo`, so you can install the current version of kind2 by following these instructions: + +1. Install Rust Nightly Toolchain +2. Clone the repository +3. `cargo install --path crates/kind-cli --force` + +Then, use any of the commands below: + +Command | Usage | Note +---------- | ------------------------- | -------------------------------------------------------------- +Check | `kind2 check file.kind2` | Checks all definitions. +Eval | `kind2 eval file.kind2` | Runs using the type-checker's evaluator. +Run | `kind2 run file.kind2` | Runs using HVM's evaluator, on Rust-mode. +To-HVM | `kind2 to-hvm file.kind2` | Generates a [.hvm](https://github.com/kindelia/hvm) file. Can then be compiled to C. +To-KDL | `kind2 to-kdl file.kind2` | Generates a [.kdl](https://github.com/kindelia/kindelia) file. Can then be deployed to [Kindelia](https://github.com/kindelia/kindelia). + +Executables can be generated via HVM: + +``` +kind2 to-hvm file.kind2 +hvm compile file.hvm +clang -O2 file.c -o file +./file +``` + + +--- + +- If you need support related to Kind, email [support.kind@kindelia.org](mailto:support.kind@kindelia.org) + +- For Feedbacks, email [kind@kindelia.org](mailto:kind@kindelia.org) + +- To ask questions and join our community, check our [Discord Server](https://discord.gg/kindelia). diff --git a/crates/kind-derive/Cargo.toml b/crates/kind-derive/Cargo.toml index b6ecb81e..15c79385 100644 --- a/crates/kind-derive/Cargo.toml +++ b/crates/kind-derive/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-derive" version = "0.1.1" edition = "2021" license = "MIT" +description = "Derive generator the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -11,4 +12,4 @@ kind-span = { path = "../kind-span", version = "0.1.1" } kind-tree = { path = "../kind-tree", version = "0.1.1" } kind-report = { path = "../kind-report", version = "0.1.1" } fxhash = "0.2.1" -im-rc = "*" \ No newline at end of file +im-rc = "15.1.0" \ No newline at end of file diff --git a/crates/kind-driver/Cargo.toml b/crates/kind-driver/Cargo.toml index cf465eb6..7f2b8f8c 100644 --- a/crates/kind-driver/Cargo.toml +++ b/crates/kind-driver/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-driver" version = "0.1.1" edition = "2021" license = "MIT" +description = "Driver for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,8 +15,8 @@ kind-report = { path = "../kind-report", version = "0.1.1" } kind-checker = { path = "../kind-checker", version = "0.1.1" } kind-pass = { path = "../kind-pass", version = "0.1.1" } -kind-target-hvm = { path = "../kind-target-hvm" } -kind-target-kdl = { path = "../kind-target-kdl" } +kind-target-hvm = { path = "../kind-target-hvm", version = "0.1.0" } +kind-target-kdl = { path = "../kind-target-kdl", version = "0.1.0" } hvm = "1.0.3" diff --git a/crates/kind-driver/src/lib.rs b/crates/kind-driver/src/lib.rs index 18d2a7e2..edc8fd8d 100644 --- a/crates/kind-driver/src/lib.rs +++ b/crates/kind-driver/src/lib.rs @@ -4,7 +4,8 @@ use kind_pass::{desugar, erasure, inline::inline_book}; use kind_report::report::FileCache; use kind_span::SyntaxCtxIndex; -use kind_tree::{backend, concrete, desugared, untyped}; +use hvm::language::{syntax as backend}; +use kind_tree::{concrete, desugared, untyped}; use resolution::ResolutionError; use session::Session; use std::{path::PathBuf}; diff --git a/crates/kind-parser/Cargo.toml b/crates/kind-parser/Cargo.toml index 06c671a5..11e4a431 100644 --- a/crates/kind-parser/Cargo.toml +++ b/crates/kind-parser/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-parser" version = "0.1.1" edition = "2021" license = "MIT" +description = "Parser for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-pass/Cargo.toml b/crates/kind-pass/Cargo.toml index 7f2ef486..c69db1f6 100644 --- a/crates/kind-pass/Cargo.toml +++ b/crates/kind-pass/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-pass" version = "0.1.1" edition = "2021" license = "MIT" +description = "A lot of compiler passes for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-pass/src/desugar/destruct.rs b/crates/kind-pass/src/desugar/destruct.rs index 4f2f6b70..fa707126 100644 --- a/crates/kind-pass/src/desugar/destruct.rs +++ b/crates/kind-pass/src/desugar/destruct.rs @@ -220,8 +220,8 @@ impl<'a> DesugarState<'a> { if let Some((_, name)) = arg.1 { arguments.push(name) } else { - let id = - Ident::generate(&format!("{}.{}", matcher.scrutinee.to_str(), arg.0)); + let mut id = Ident::generate(&format!("{}.{}", matcher.scrutinee.to_str(), arg.0)); + id.range = case.constructor.range; arguments.push(id); } } diff --git a/crates/kind-pass/src/inline/mod.rs b/crates/kind-pass/src/inline/mod.rs index 0bf3b8f1..0b4c8a95 100644 --- a/crates/kind-pass/src/inline/mod.rs +++ b/crates/kind-pass/src/inline/mod.rs @@ -46,6 +46,7 @@ pub fn inline_book(book: &mut untyped::Book) { for name in &to_remove { book.entrs.remove(name); + book.names.remove(name); } let mut state = InlineState { funs }; diff --git a/crates/kind-query/Cargo.toml b/crates/kind-query/Cargo.toml index 31d36743..5f610ea4 100644 --- a/crates/kind-query/Cargo.toml +++ b/crates/kind-query/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-query" version = "0.1.1" edition = "2021" license = "MIT" +description = "Query module for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-report/Cargo.toml b/crates/kind-report/Cargo.toml index a3f1c320..48ca771e 100644 --- a/crates/kind-report/Cargo.toml +++ b/crates/kind-report/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-report" version = "0.1.1" edition = "2021" license = "MIT" +description = "Report module for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-span/Cargo.toml b/crates/kind-span/Cargo.toml index ab4c4c9a..e7f0c724 100644 --- a/crates/kind-span/Cargo.toml +++ b/crates/kind-span/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-span" version = "0.1.1" edition = "2021" license = "MIT" +description = "Describes locations for the Kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/kind-target-hvm/Cargo.toml b/crates/kind-target-hvm/Cargo.toml index 100dd169..36e625f8 100644 --- a/crates/kind-target-hvm/Cargo.toml +++ b/crates/kind-target-hvm/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-target-hvm" version = "0.1.1" edition = "2021" license = "MIT" +description = "HVM Code generator for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,4 +13,4 @@ kind-tree = { path = "../kind-tree", version = "0.1.1" } kind-report = { path = "../kind-report", version = "0.1.1" } kind-derive = { path = "../kind-derive", version = "0.1.1" } -hvm = "1.0.3" \ No newline at end of file +hvm = "1.0.3" diff --git a/crates/kind-target-hvm/src/lib.rs b/crates/kind-target-hvm/src/lib.rs index 8e1d00ed..e92a1d55 100644 --- a/crates/kind-target-hvm/src/lib.rs +++ b/crates/kind-target-hvm/src/lib.rs @@ -1,9 +1,8 @@ use hvm::u60; -use kind_tree::{ - backend::{File, Rule, Term}, - untyped, -}; +use kind_tree::untyped; + +use hvm::syntax::{File, Rule, Term}; pub fn compile_book(book: untyped::Book, trace: bool) -> File { let mut file = File { diff --git a/crates/kind-target-kdl/Cargo.toml b/crates/kind-target-kdl/Cargo.toml index f7faf0ab..8a3cc3c8 100644 --- a/crates/kind-target-kdl/Cargo.toml +++ b/crates/kind-target-kdl/Cargo.toml @@ -3,6 +3,7 @@ name = "kind-target-kdl" version = "0.1.1" edition = "2021" license = "MIT" +description = "KDL target for the kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,7 +13,8 @@ kind-tree = { path = "../kind-tree", version = "0.1.1" } kind-report = { path = "../kind-report", version = "0.1.1" } kind-derive = { path = "../kind-derive", version = "0.1.1" } -kindelia_lang = { git = "https://github.com/developedby/Kindelia/", branch = "kdl-lang-crate" } +kindelia_lang = "0.1.7" linked-hash-map = "0.5.6" tiny-keccak = "2.0.2" -fxhash = "0.2.1" \ No newline at end of file +fxhash = "0.2.1" +im-rc = "15.1.0" diff --git a/crates/kind-target-kdl/src/compile.rs b/crates/kind-target-kdl/src/compile.rs index cd23394b..8c0fd3de 100644 --- a/crates/kind-target-kdl/src/compile.rs +++ b/crates/kind-target-kdl/src/compile.rs @@ -3,6 +3,7 @@ use std::{fmt::Display, sync::mpsc::Sender}; use fxhash::FxHashMap; use kind_report::data::Diagnostic; use kind_tree::{symbol::QualifiedIdent, untyped}; +use kindelia_lang::ast::Name; use linked_hash_map::LinkedHashMap; use tiny_keccak::Hasher; @@ -13,6 +14,31 @@ use crate::{diagnostic::KdlDiagnostic, GenericCompilationToHVMError}; pub const KDL_NAME_LEN: usize = 12; const U60_MAX: kdl::U120 = kdl::U120(0xFFFFFFFFFFFFFFF); +fn char_to_code(chr: char) -> Result { + let num = match chr { + '.' => 0, + '0'..='9' => 1 + chr as u128 - '0' as u128, + 'A'..='Z' => 11 + chr as u128 - 'A' as u128, + 'a'..='z' => 37 + chr as u128 - 'a' as u128, + '_' => 63, + _ => { + return Err(format!("Invalid Kindelia Name letter '{}'.", chr)); + } + }; + Ok(num) +} + +pub fn from_str(name_txt: &str) -> Result { + let mut num: u128 = 0; + for (i, chr) in name_txt.chars().enumerate() { + if i >= Name::MAX_CHARS { + return Err("Too big".to_string()) + } + num = (num << 6) + char_to_code(chr)?; + } + Ok(Name(num)) +} + #[derive(Debug)] pub struct File { pub ctrs: LinkedHashMap, @@ -26,6 +52,8 @@ pub struct CompileCtx<'a> { kdl_states: Vec, book: &'a untyped::Book, + kdl_used_names: im_rc::HashSet, + sender: Sender>, failed: bool, } @@ -40,6 +68,7 @@ impl<'a> CompileCtx<'a> { }, kdl_names: Default::default(), kdl_states: Default::default(), + kdl_used_names: Default::default(), book, sender, failed: false, @@ -108,10 +137,10 @@ pub fn compile_book( .map(|x| x.to_string()) .unwrap_or_else(|| name_shortener(&entry.name, namespace).to_string()); - if let Ok(new_name) = kdl::Name::from_str(&new_name) { + if let Ok(new_name) = from_str(&new_name) { ctx.kdl_names.insert(name.clone(), new_name); } else { - ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(entry.name.range))); + ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(entry.name.to_string(), entry.name.range))); } } @@ -148,7 +177,80 @@ pub fn err_term() -> kdl::Term { pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kdl::Term { use crate::untyped::ExprKind as From; use kdl::Term as To; + match &expr.data { + From::Var { name } => { + let res_name = from_str(name.to_str()); + ctx.kdl_used_names.remove(name.to_str()); + if let Ok(name) = res_name { + To::Var { name } + } else { + ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(name.to_string(), name.range))); + err_term() + } + } + From::Lambda { + param, + body, + erased: _, + } => { + let name = from_str(param.to_str()); + + let not_used = ctx.kdl_used_names.contains(param.to_str()); + + ctx.kdl_used_names.insert(param.to_string()); + + let body = Box::new(compile_expr(ctx, body)); + + let not_used_now = ctx.kdl_used_names.contains(param.to_str()); + let name = if not_used_now { Ok(from_str("").unwrap()) } else { name }; + + if not_used_now { + ctx.kdl_used_names.remove(param.to_str()); + } + + if not_used { + ctx.kdl_used_names.insert(param.to_string()); + } + + if let Ok(name) = name { + To::Lam { name, body } + } else { + ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(param.to_string(), param.range))); + err_term() + } + } + From::Let { name: param, val, next } => { + let res_name = from_str(param.to_str()); + + let not_used = ctx.kdl_used_names.contains(param.to_str()); + + ctx.kdl_used_names.insert(param.to_string()); + + let expr = Box::new(compile_expr(ctx, next)); + + let not_used_now = ctx.kdl_used_names.contains(param.to_str()); + + let res_name = if not_used_now { Ok(from_str("").unwrap()) } else { res_name }; + + if not_used_now { + ctx.kdl_used_names.remove(param.to_str()); + } + + if not_used { + ctx.kdl_used_names.insert(param.to_string()); + } + + let argm = Box::new(compile_expr(ctx, &val)); + + if let Ok(name) = res_name { + let func = Box::new(To::Lam { name, body: expr }); + To::App { func, argm } + } else { + ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(param.to_string(), param.range))); + err_term() + } + } From::App { fun, args } => { let mut expr = compile_expr(ctx, fun); for binding in args { @@ -324,32 +426,6 @@ pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kdl::Term { } } } - From::Lambda { - param, - body, - erased: _, - } => { - let name = kdl::Name::from_str(param.to_str()); - if let Ok(name) = name { - let body = Box::new(compile_expr(ctx, body)); - To::Lam { name, body } - } else { - ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(param.range))); - err_term() - } - } - From::Let { name, val, next } => { - let res_name = kdl::Name::from_str(name.to_str()); - if let Ok(name) = res_name { - let expr = Box::new(compile_expr(ctx, next)); - let func = Box::new(To::Lam { name, body: expr }); - let argm = Box::new(compile_expr(ctx, &val)); - To::App { func, argm } - } else { - ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(name.range))); - err_term() - } - } From::U60 { numb } => To::Num { numb: kdl::U120(*numb as u128), }, @@ -357,15 +433,6 @@ pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kdl::Term { ctx.send_err(Box::new(KdlDiagnostic::FloatUsed(expr.range))); err_term() } - From::Var { name } => { - let res_name = kdl::Name::from_str(name.to_str()); - if let Ok(name) = res_name { - To::Var { name } - } else { - ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(name.range))); - err_term() - } - } From::Str { val } => { let nil = kdl::Term::Ctr { name: *ctx.kdl_names.get("String.nil").unwrap(), @@ -418,10 +485,10 @@ fn compile_common_function(ctx: &mut CompileCtx, entry: &untyped::Entry) { let mut args = Vec::new(); for (name, range, _strictness) in &entry.args { - if let Ok(name) = kdl::Name::from_str(name) { + if let Ok(name) = from_str(name) { args.push(name) } else { - ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(*range))); + ctx.send_err(Box::new(KdlDiagnostic::InvalidVarName(name.to_string(), *range))); } } @@ -476,8 +543,8 @@ fn compile_common_function(ctx: &mut CompileCtx, entry: &untyped::Entry) { fn compile_u120_new(ctx: &mut CompileCtx, entry: &untyped::Entry) { // U120.new hi lo = (hi << 60) | lo - let hi_name = kdl::Name::from_str("hi").unwrap(); - let lo_name = kdl::Name::from_str("lo").unwrap(); + let hi_name = from_str("hi").unwrap(); + let lo_name = from_str("lo").unwrap(); let hi_var = kdl::Term::Var { name: hi_name.clone(), }; @@ -555,4 +622,4 @@ fn compile_oper(oper: &kind_tree::Operator) -> kdl::Oper { From::Xor => To::Xor, From::Or => To::Or, } -} +} \ No newline at end of file diff --git a/crates/kind-target-kdl/src/diagnostic.rs b/crates/kind-target-kdl/src/diagnostic.rs index 4547a0d4..a0710f9b 100644 --- a/crates/kind-target-kdl/src/diagnostic.rs +++ b/crates/kind-target-kdl/src/diagnostic.rs @@ -2,7 +2,7 @@ use kind_report::data::{Color, Diagnostic, DiagnosticFrame, Marker, Severity}; use kind_span::Range; pub enum KdlDiagnostic { - InvalidVarName(Range), + InvalidVarName(String, Range), ShouldNotHaveArguments(Range), ShouldHaveOnlyOneRule(Range), NoInitEntry(Range), @@ -12,7 +12,7 @@ pub enum KdlDiagnostic { impl Diagnostic for KdlDiagnostic { fn get_syntax_ctx(&self) -> Option { match self { - KdlDiagnostic::InvalidVarName(range) => Some(range.ctx), + KdlDiagnostic::InvalidVarName(_, range) => Some(range.ctx), KdlDiagnostic::ShouldNotHaveArguments(range) => Some(range.ctx), KdlDiagnostic::ShouldHaveOnlyOneRule(range) => Some(range.ctx), KdlDiagnostic::NoInitEntry(range) => Some(range.ctx), @@ -22,10 +22,10 @@ impl Diagnostic for KdlDiagnostic { fn to_diagnostic_frame(&self) -> kind_report::data::DiagnosticFrame { match self { - KdlDiagnostic::InvalidVarName(range) => DiagnosticFrame { + KdlDiagnostic::InvalidVarName(s, range) => DiagnosticFrame { code: 600, severity: Severity::Error, - title: "Invalid variable name for Kindelia.".to_string(), + title: format!("Invalid variable name '{s}' for Kindelia."), subtitles: vec![], hints: vec![], positions: vec![Marker { @@ -98,7 +98,7 @@ impl Diagnostic for KdlDiagnostic { fn get_severity(&self) -> Severity { use KdlDiagnostic::*; match self { - InvalidVarName(_) + InvalidVarName(_, _) | ShouldNotHaveArguments(_) | ShouldHaveOnlyOneRule(_) | NoInitEntry(_) diff --git a/crates/kind-target-kdl/src/linearize.rs b/crates/kind-target-kdl/src/linearize.rs index 6fd1fe1b..f0aef037 100644 --- a/crates/kind-target-kdl/src/linearize.rs +++ b/crates/kind-target-kdl/src/linearize.rs @@ -24,7 +24,7 @@ pub struct LinearizeCtx { impl LinearizeCtx { fn create_name(&mut self) -> Name { - let name = Name::from_str(&format!("x{}", self.name_count)).unwrap(); + let name = Name::from_str_unsafe(&format!("x{}", self.name_count)); self.name_count += 1; name } @@ -153,7 +153,7 @@ pub fn linearize_term(ctx: &mut LinearizeCtx, term: &Term, lhs: bool) -> Box Box, body: Box body, // if used once just make a let (lambda then app) 1 => { - let name = Name::from_str(&format!("{}.0", name)).unwrap(); // TODO: handle err + let name = Name::from_str_unsafe(&format!("{}.0", name)); // TODO: handle err let func = Box::new(Term::Lam { name, body }); let term = Term::App { func, argm: expr }; Box::new(term) @@ -287,12 +287,12 @@ pub fn dup_var(ctx: &mut LinearizeCtx, name: &Name, expr: Box, body: Box, vars: &mut Vec) - } else { let nam0 = vars.pop().unwrap(); let nam1 = vars.pop().unwrap(); - let var_name = Name::from_str(&format!("c.{}", idx - 1)).unwrap(); + let var_name = Name::from_str_unsafe(&format!("c.{}", idx - 1)); let expr = Box::new(Term::Var { name: var_name }); let dup = Term::Dup { nam0, diff --git a/crates/kind-tests/suite/kdl/ISSUE-491-2.golden b/crates/kind-tests/suite/kdl/ISSUE-491-2.golden new file mode 100644 index 00000000..3feed11d --- /dev/null +++ b/crates/kind-tests/suite/kdl/ISSUE-491-2.golden @@ -0,0 +1,17 @@ +ctr {String.nil} +ctr {Pair.new fst snd} +ctr {String.cons head tail} + +fun (Test n) { + (Test ~) = (!@x1 (!@x1.0 (Pair.match x1.0 @x2 (!@x2.0 @~ (String.match x2.0 #1 @~ @~ #2) x2)) x1) {Pair.new {String.cons #84 {String.cons #101 {String.cons #115 {String.cons #116 {String.cons #101 {String.nil}}}}}} #0}) +} + +fun (Pair.match scrutinee new_) { + (Pair.match {Pair.new x0 x1} x2) = (!@x2.0 (!@x1.0 (!@x0.0 (!(!x2.0 x0.0) x1.0) x0) x1) x2) +} + +fun (String.match scrutinee nil_ cons_) { + (String.match {String.nil} x0 ~) = (!@x0.0 x0.0 x0) + (String.match {String.cons x0 x1} ~ x3) = (!@x3.0 (!@x1.0 (!@x0.0 (!(!x3.0 x0.0) x1.0) x0) x1) x3) +} + diff --git a/crates/kind-tests/suite/kdl/ISSUE-491-2.kind2 b/crates/kind-tests/suite/kdl/ISSUE-491-2.kind2 new file mode 100644 index 00000000..476d56e4 --- /dev/null +++ b/crates/kind-tests/suite/kdl/ISSUE-491-2.kind2 @@ -0,0 +1,32 @@ +Char : Type +Char = U60 + +#kdl_name = T2 +#kdl_erase +#derive[match] +record Pair (a) (b) { + constructor new + fst : a + snd : b +} + +#derive[match] +type String { + nil + cons (head: (Char)) (tail: (String)) +} + +#keep +Test (n: U60) : U60 +Test n = + let state = Pair.new "Teste" 0 + match Pair state { + new => + match String state.fst { + nil => + 1 + cons => + 2 + } + } + \ No newline at end of file diff --git a/crates/kind-tests/suite/kdl/ISSUE-491.golden b/crates/kind-tests/suite/kdl/ISSUE-491.golden new file mode 100644 index 00000000..63ee5ff3 --- /dev/null +++ b/crates/kind-tests/suite/kdl/ISSUE-491.golden @@ -0,0 +1,16 @@ +fun (C ) { + (C) = (!@~ (!@~ #2 #3) #2) +} + +fun (B ) { + (B) = @~ @x1 (!@x1.0 x1.0 x1) +} + +fun (A ) { + (A) = (!@~ @~ @x2 (!@x2.0 x2.0 x2) #2) +} + +fun (D ) { + (D) = (!@~ #233 (!@~ #2 @~ #2)) +} + diff --git a/crates/kind-tests/suite/kdl/ISSUE-491.kind2 b/crates/kind-tests/suite/kdl/ISSUE-491.kind2 new file mode 100644 index 00000000..18fe8441 --- /dev/null +++ b/crates/kind-tests/suite/kdl/ISSUE-491.kind2 @@ -0,0 +1,23 @@ +#keep +A { + let xaaaaaaaaaaaaaaaaaaaaaa = 2 + xaaaaaaaaaaaaaaaaaaaaaa => x => x +} + +#keep +B { + xaaaaaaaaaaaaaaaaaaaaaa => x => x +} + +#keep +C { + let aaaaaaaaaaaaaaaaaaaaaa = 2 + let aaaaaaaaaaaaaaaaaaaaaa = 3 + 2 +} + +#keep +D { + let xxxxxxxxxxxx = ((xxxxxxxxxxxx => 2) (xxxxxxxxxxxx => 2)) + 233 +} \ No newline at end of file diff --git a/crates/kind-tree/Cargo.toml b/crates/kind-tree/Cargo.toml index ec3a8236..2c99e368 100644 --- a/crates/kind-tree/Cargo.toml +++ b/crates/kind-tree/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.1" edition = "2021" license = "MIT" +description = "Syntatic trees for Kind compiler" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/crates/kind-tree/src/lib.rs b/crates/kind-tree/src/lib.rs index 55a0af03..b300fae6 100644 --- a/crates/kind-tree/src/lib.rs +++ b/crates/kind-tree/src/lib.rs @@ -24,7 +24,6 @@ pub mod symbol; use std::fmt::{Formatter, Display, Error}; -pub use hvm::syntax as backend; use symbol::Ident; /// Attributes describes some compiler specific aspects