WIP, starting working with KindAI soon

This commit is contained in:
Victor Taelin 2024-07-10 19:42:18 -03:00
parent bf2d62a572
commit 3062ce4b6e
38 changed files with 415 additions and 80 deletions

View File

@ -1,3 +1,14 @@
/// Performs the logical AND operation on two boolean values.
///
/// # Inputs
///
/// * `a` - The first boolean value.
/// * `b` - The second boolean value.
///
/// # Output
///
/// Returns `true` if both `a` and `b` are `true`, otherwise returns `false`.
use Bool/{true,false,and}
and

View File

@ -1,3 +1,9 @@
/// Represents the 'false' boolean value.
///
/// # Output
///
/// The 'false' value of type Bool.
false
: Bool

View File

@ -1,8 +1,23 @@
/// Conditional expression for Bool values.
///
/// # Parameters
///
/// * `P` - The type of the result.
///
/// # Inputs
///
/// * `b` - The boolean condition.
/// * `t` - The value to return if the condition is true.
/// * `f` - The value to return if the condition is false.
///
/// # Output
///
/// Returns `t` if `b` is true, otherwise returns `f`.
use Bool/{true,false}
if
if <P: *>
- b: Bool
- P: *
- t: P
- f: P
: P

View File

@ -1,3 +1,16 @@
/// Provides a way to pattern match on boolean values.
///
/// # Inputs
///
/// * `P` - The motive of the elimination, a type family indexed by Bool.
/// * `t` - The case for when the boolean is true.
/// * `f` - The case for when the boolean is false.
/// * `b` - The boolean value to match on.
///
/// # Output
///
/// The result of the elimination, which has type `(P b)`.
use Bool/{true,false}
match

View File

@ -1,3 +1,13 @@
/// Negates a boolean value.
///
/// # Input
///
/// * `x` - The boolean value to negate.
///
/// # Output
///
/// The negation of the input boolean.
use Bool/{true,false}
not

View File

@ -1,3 +1,14 @@
/// Performs the logical OR operation on two boolean values.
///
/// # Inputs
///
/// * `a` - The first boolean value.
/// * `b` - The second boolean value.
///
/// # Output
///
/// The result of `a OR b`.
use Bool/{true,false}
or
@ -8,4 +19,4 @@ or
match a {
true: true
false: b
}
}

View File

@ -1,8 +1,10 @@
apply <A: *> <B: *> <a: A> <b: B>
use Equal/refl
apply <A: *> <B: *> <a: A> <b: A>
- f: A -> B
- e: (Equal A a b)
: (Equal B (f a) (f b))
match e {
Equal/refl: ~λPλe(e (f e.a))
}: (Equal B (f a) (f b))
refl: ~λPλe(e (f e.a))
}: (Equal B (f e.a) (f e.b))

View File

@ -1,3 +1,14 @@
/// Computes the logical AND of all boolean values in a list.
///
/// # Input
///
/// * `list` - A list of boolean values.
///
/// # Output
///
/// Returns `true` if all elements in the list are `true`, otherwise `false`.
/// An empty list returns `true` (vacuous truth).
use List/{cons,nil}
use Bool/{true}
@ -8,4 +19,4 @@ and
fold list {
cons: (Bool/and list.head list.tail)
nil: true
}
}

View File

@ -7,9 +7,11 @@ filter <A>
: (List A)
match list {
nil: (nil _)
cons: match result = (cond list.head) {
true: (cons _ list.head (filter _ cond list.tail))
false: (filter _ cond list.tail)
}
cons:
let test = (cond list.head)
let head = match test { true: (cons _ list.head) false: λx x }: (List A) -> (List A)
let tail = (filter _ cond list.tail)
(head tail)
nil:
(nil _)
}

View File

@ -3,14 +3,16 @@ use List/{cons,nil}
use Maybe/{some,none}
find <A>
- cond: A -> Bool
- fn: A -> Bool
- xs: (List A)
: (Maybe A)
match xs {
cons: match result = (cond xs.head) {
true: (some _ xs.head)
false: (find _ cond xs.tail)
}
cons:
let result = (fn xs.head)
match result {
true: (some _ xs.head)
false: (find _ fn xs.tail)
}
nil: (none _)
}

View File

@ -1,3 +1,19 @@
/// Maps a function over a list, transforming each element.
///
/// # Parameters
///
/// * `A` - The type of elements in the input list.
/// * `B` - The type of elements in the output list.
///
/// # Inputs
///
/// * `xs` - The input list of type (List A).
/// * `fn` - A function that transforms elements from type A to type B.
///
/// # Output
///
/// A new list of type (List B) with the function applied to each element.
use List/{cons,nil}
map <A> <B>
@ -5,7 +21,11 @@ map <A> <B>
- fn: A -> B
: (List B)
fold xs {
cons: (cons _ (fn xs.head) xs.tail)
nil: (nil _)
match xs {
cons:
let head = (fn xs.head)
let tail = (List/map _ _ xs.tail fn)
(cons _ head tail)
nil:
(nil _)
}

View File

@ -1,3 +1,13 @@
/// Performs a logical OR operation on a list of booleans.
///
/// # Input
///
/// * `list` - A list of boolean values.
///
/// # Output
///
/// The result of applying OR to all elements in the list.
use List/{cons,nil}
use Bool/{false}
@ -8,4 +18,4 @@ or
fold list {
cons: (Bool/or list.head list.tail)
nil: false
}
}

View File

@ -1,3 +1,14 @@
/// Adds two natural numbers.
///
/// # Inputs
///
/// * `a` - The first natural number.
/// * `b` - The second natural number.
///
/// # Output
///
/// The sum of `a` and `b`.
use Nat/{succ,zero}
add

View File

@ -1,3 +1,13 @@
/// Doubles a natural number.
///
/// # Input
///
/// * `n` - The natural number to be doubled.
///
/// # Output
///
/// The result of doubling `n`.
use Nat/{succ,zero}
double

View File

@ -1,3 +1,14 @@
/// Checks if two natural numbers are equal.
///
/// # Inputs
///
/// * `a` - The first natural number.
/// * `b` - The second natural number.
///
/// # Output
///
/// `true` if `a` and `b` are equal, `false` otherwise.
use Nat/{succ,zero}
use Bool/{true,false}

View File

@ -1,3 +1,21 @@
/// Computes half of a natural number, rounding down.
///
/// # Input
///
/// * `n` - The natural number to halve.
///
/// # Output
///
/// Half of `n`, rounded down to the nearest natural number.
///
/// # Examples
///
/// * `(half 0) = 0`
/// * `(half 1) = 0`
/// * `(half 2) = 1`
/// * `(half 3) = 1`
/// * `(half 4) = 2`
use Nat/{succ,zero}
half

24
book/Nat/is_even.kind2 Normal file
View File

@ -0,0 +1,24 @@
/// Determines if a natural number is even.
///
/// # Input
///
/// * `n` - The natural number to check.
///
/// # Output
///
/// `true` if `n` is even, `false` otherwise.
use Nat/{succ,zero}
use Bool/{true,false}
is_even
- n: Nat
: Bool
match n {
succ: match n.pred {
succ: (is_even n.pred.pred)
zero: false
}
zero: true
}

18
book/Nat/is_gte.kind2 Normal file
View File

@ -0,0 +1,18 @@
use Nat/{succ,zero}
use Bool/{true,false}
is_gtn_or_eql
- a: Nat
- b: Nat
: Bool
match a {
zero: match b {
zero: true
succ: false
}
succ: match b {
zero: true
succ: (is_gtn_or_eql a.pred b.pred)
}
}

View File

@ -1,3 +1,14 @@
/// Checks if the first natural number is greater than the second.
///
/// # Inputs
///
/// * `a` - The first natural number.
/// * `b` - The second natural number.
///
/// # Output
///
/// `true` if `a` is greater than `b`, `false` otherwise.
use Nat/{succ,zero}
use Bool/{true,false}

23
book/Nat/is_lte.kind2 Normal file
View File

@ -0,0 +1,23 @@
/// Checks if a natural number is less than or equal to another.
///
/// # Inputs
///
/// * `a` - The first natural number.
/// * `b` - The second natural number.
///
/// # Output
///
/// `true` if `a` is less than or equal to `b`, `false` otherwise.
use Nat/{succ,zero}
use Bool/{true,false}
is_lte
- a: Nat
- b: Nat
: Bool
match is_lt = (Nat/is_ltn a b) {
true: true
false: (Nat/equal a b)
}

View File

@ -1,12 +0,0 @@
use Nat/{succ,zero}
use Bool/{true,false}
is_ltn_or_eql
- a: Nat
- b: Nat
: Bool
match is_lt = (Nat/is_ltn a b) {
true: true
false: (Nat/equal a b)
}

View File

@ -1,12 +1,10 @@
use Nat/{succ,zero,half,double}
bft (n: Nat) :
(Equal Nat (half (double n)) n) =
match n {
succ:
let ind = (bft n.pred)
let prf = (Equal/apply _ _ _ _ succ ind)
prf
zero:
{=}
}
bft
- n: Nat
: (Equal Nat (half (double n)) n)
match n {
succ: (Equal/apply/ succ (bft n.pred))
zero: {=}
}

View File

@ -1,11 +0,0 @@
use Nat/{succ,zero}
mul
- a: Nat
- b: Nat
: Nat
match b {
succ: (Nat/add a (Nat/mul a b.pred))
zero: zero
}

View File

@ -1,6 +1,9 @@
use Pair/{new}
fst <A> <B> (p: (Pair A B)) : A =
match p {
new: p.fst
}
fst <A> <B>
- p: (Pair A B)
: A
match p {
new: p.fst
}

View File

@ -1,6 +1,10 @@
use Pair/{new}
get <A> <B> <P> (p: (Pair A B)) (f: A -> B -> P) : P =
match p {
new: (f p.fst p.snd)
}
get <A> <B> <P>
- p: (Pair A B)
- f: A -> B -> P
: P
match p {
new: (f p.fst p.snd)
}

View File

@ -1,6 +1,7 @@
match <A> <B>
(P: (Pair A B) -> *)
(new: ∀(fst: A) ∀(snd: B) (P (Pair/new A B fst snd)))
(pair: (Pair A B))
: (P pair) =
(~pair P new)
- P: (Pair A B) -> *
- new: ∀(fst: A) ∀(snd: B) (P (Pair/new A B fst snd))
- pair: (Pair A B)
: (P pair)
(~pair P new)

View File

@ -1,2 +1,6 @@
new <A> <B> (a: A) (b: B) : (Pair A B) =
~λP λnew (new a b)
new <A> <B>
- a: A
- b: B
: (Pair A B)
~λP λnew (new a b)

View File

@ -1,6 +1,9 @@
use Pair/{new}
snd <A> <B> (p: (Pair A B)) : B =
match p {
new: p.snd
}
snd <A> <B>
- p: (Pair A B)
: B
match p {
new: p.snd
}

12
book/Term/_.kind2 Normal file
View File

@ -0,0 +1,12 @@
/// Defines the type for untyped lambda calculus terms using Higher-Order Abstract Syntax (HOAS).
///
/// # Constructors
///
/// * `app` - Represents function application.
/// * `lam` - Represents lambda abstraction.
/// * `var` - Represents a variable.
data Term
| lam (bod: Term -> Term)
| app (fun: Term) (arg: Term)
| var (idx: U48)

19
book/Term/app.kind2 Normal file
View File

@ -0,0 +1,19 @@
/// Constructs an application term in the untyped lambda calculus.
///
/// This function creates a new Term representing the application of one term to another.
///
/// # Inputs
///
/// * `fun` - The function term (the term being applied).
/// * `arg` - The argument term (the term being passed to the function).
///
/// # Output
///
/// A new Term representing the application of `fun` to `arg`.
app
- fun: Term
- arg: Term
: Term
~λP λlam λapp λvar (app fun arg)

17
book/Term/lam.kind2 Normal file
View File

@ -0,0 +1,17 @@
/// Constructs a lambda abstraction term in the untyped lambda calculus.
///
/// This function creates a new Term representing a lambda abstraction.
///
/// # Input
///
/// * `bod` - A function that takes a Term and returns a Term, representing the body of the lambda abstraction.
///
/// # Output
///
/// A new Term representing the lambda abstraction.
lam
- bod: Term -> Term
: Term
~λP λlam λapp λvar (lam bod)

17
book/Term/var.kind2 Normal file
View File

@ -0,0 +1,17 @@
/// Constructs a variable term in the untyped lambda calculus.
///
/// This function creates a new Term representing a variable with a given index.
///
/// # Input
///
/// * `idx` - The index of the variable (represented as a U48).
///
/// # Output
///
/// A new Term representing the variable with the given index.
var
- idx: U48
: Term
~λP λlam λapp λvar (var idx)

View File

@ -1,2 +1,11 @@
/// Defines the Unit type, which has only one inhabitant.
///
/// The Unit type is often used to represent a trivial or empty type,
/// or as a placeholder when no meaningful value is needed.
///
/// # Constructor
///
/// * `new` - The single constructor for the Unit type.
data Unit
| new

View File

@ -8,7 +8,12 @@ concat <T>
- ys: (Vector T ys_len)
: (Vector T (add xs_len ys_len))
match xs {
cons: (cons _ (add xs.len ys_len) xs.head (concat _ xs.len ys_len xs.tail ys))
nil: ys
}: (Vector T (add xs.len ys_len))
(Vector/match _ _ λxs.len(_)
λxs.lenλxs.headλxs.tail(cons _ (add xs.len ys_len) xs.head (concat _ xs.len ys_len xs.tail ys))
ys
xs)
//match xs {
//cons: (cons _ (add xs.len ys_len) xs.head (concat _ xs.len ys_len xs.tail ys))
//nil: ys
//}: (Vector T (add xs.len ys_len))

8
book/Vector/match.kind2 Normal file
View File

@ -0,0 +1,8 @@
match <T> <len: Nat>
- P: ∀(l: Nat) (Vector T l) -> *
- c: ∀(l: Nat) ∀(head: T) ∀(tail: (Vector T l)) (P (Nat/succ l) (Vector/cons T l head tail))
- n: (P Nat/zero (Vector/nil T))
- v: (Vector T len)
: (P len v)
(~v P c n)

View File

@ -39,14 +39,14 @@ impl Info {
pub fn pretty(&self, book: &Book) -> String {
match self {
Info::Found { nam, typ, ctx } => {
let msg = format!("?{} :: {}", nam, typ.show());
let msg = format!("?{} : {}", nam, typ.show());
let mut ctx_str = String::new();
for x in ctx.iter() {
if let Term::Ann { chk: _, val, typ } = x.clean() {
ctx_str.push_str(&format!("\n- {}: {}", val.show(), typ.show()));
}
}
format!("\x1b[1mFOUND:\x1b[0m {}{}", msg, ctx_str)
format!("\x1b[1mGOAL\x1b[0m {}{}", msg, ctx_str)
},
Info::Error { exp, det, bad, src } => {
let exp = format!("- expected: \x1b[32m{}\x1b[0m", exp.show());

View File

@ -82,6 +82,18 @@ fn load_book(name: &str) -> Book {
})
}
fn deps(name: &str) {
let mut book = Book::new();
let cwd = std::env::current_dir().expect("failed to get current directory");
if let Err(e) = book.load(cwd.to_str().unwrap(), name) {
eprintln!("{e}");
std::process::exit(1);
}
for dep in book.defs.keys() {
println!("{}", dep);
}
}
fn main() {
let matches = Command::new("kind2")
.about("The Kind2 Programming Language")
@ -104,6 +116,9 @@ fn main() {
.subcommand(Command::new("compile")
.about("Compiles to KINDC")
.arg(Arg::new("name").required(true)))
.subcommand(Command::new("deps")
.about("Lists all dependencies of a symbol")
.arg(Arg::new("name").required(true)))
.get_matches();
match matches.subcommand() {
@ -124,6 +139,10 @@ fn main() {
let name = sub_matches.get_one::<String>("name").expect("required");
compile(name);
}
Some(("deps", sub_matches)) => {
let name = sub_matches.get_one::<String>("name").expect("required");
deps(name);
}
_ => unreachable!(),
}
}

View File

@ -335,7 +335,7 @@ impl Term {
}
// Expands implicit calls, applying them to the correct number of metavars.
// When a variable name ends with "/", we fill erased arguments with metas.
// When a variable name ends with "!", we fill erased arguments with metas.
pub fn expand_implicits(&mut self, env: im::Vector<String>, implicit_count: &BTreeMap<String, u64>) {
match self {
Term::All { era: _, nam, inp, bod } => {