mirror of
https://github.com/HigherOrderCO/Kind.git
synced 2024-10-05 19:27:30 +03:00
initial port from ts to rust
This commit is contained in:
parent
bcf7fd28b9
commit
ee3c1550d9
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/target
|
||||
.tmp/
|
||||
.kind21/
|
86
Cargo.lock
generated
Normal file
86
Cargo.lock
generated
Normal file
@ -0,0 +1,86 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "TSPL"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7f7bc3c167472f0599b71590ead5067418477b7d512ec251b25b4aa78fa808f"
|
||||
dependencies = [
|
||||
"highlight_error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitmaps"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "highlight_error"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
|
||||
|
||||
[[package]]
|
||||
name = "im"
|
||||
version = "15.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9"
|
||||
dependencies = [
|
||||
"bitmaps",
|
||||
"rand_core",
|
||||
"rand_xoshiro",
|
||||
"sized-chunks",
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kind2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"TSPL",
|
||||
"im",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "rand_xoshiro"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sized-chunks"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
|
||||
dependencies = [
|
||||
"bitmaps",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "kind2"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
TSPL = "0.0.1"
|
||||
im = "15.1.0"
|
71
book/A.kind2
71
book/A.kind2
@ -1,71 +0,0 @@
|
||||
//TRY-0
|
||||
//-----
|
||||
|
||||
//A.one : A = ~λP λnew (new Nat.zero)
|
||||
//A.bad : A = ~λP λnew (new (Nat.succ Nat.zero) ?UE)
|
||||
|
||||
//A : * =
|
||||
//$self
|
||||
//∀(P: ∀(x: A) *)
|
||||
//∀(new: ∀(tag: Nat)
|
||||
//let R = λx(*)
|
||||
//let zero = (P A.one)
|
||||
//let succ = λp∀(x:Empty)*
|
||||
//(~tag R succ zero))
|
||||
//(P self)
|
||||
|
||||
//A.elim : ∀(a: A) ∀(P: ∀(x: A) *) ∀(t: (P A.one)) (P a) =
|
||||
//λa λP λt
|
||||
//(~a P λtag(~tag λx(~x λx(*) λp(Empty) (P A.one)) λp(?B) t))
|
||||
|
||||
// TRY-1
|
||||
// -----
|
||||
|
||||
A.one : A = ~λP λnew (new #0)
|
||||
A.bad : A = ~λP λnew (new #1 ?UE)
|
||||
|
||||
A.sel
|
||||
: ∀(P: ∀(x: A) *)
|
||||
∀(k: #U60)
|
||||
*
|
||||
= λP λk #match tag = k {
|
||||
#0: (P A.one)
|
||||
#+: ∀(e: Empty) *
|
||||
}: *
|
||||
|
||||
A : * =
|
||||
$self
|
||||
∀(P: ∀(x: A) *)
|
||||
∀(new: ∀(tag: #U60) (A.sel P tag))
|
||||
(P self)
|
||||
|
||||
A.match : ∀(a: A) ∀(P: ∀(x: A) *) ∀(t: (P A.one)) (P a) =
|
||||
λa λP λt
|
||||
(~a P λtag #match tag = tag {
|
||||
#0: t
|
||||
#+: λx (~x λx(*))
|
||||
}: (A.sel P tag))
|
||||
|
||||
// TRY-2
|
||||
// -----
|
||||
|
||||
//A.one
|
||||
//: A
|
||||
//= ~ λP λnew (new #0 Unit.one)
|
||||
|
||||
//A : * = (Sigma #U60 λtag #match tag = tag {
|
||||
//#0: Unit
|
||||
//#+: Empty
|
||||
//}: *)
|
||||
|
||||
//A.match : ∀(a: A) ∀(P: ∀(x: A) *) ∀(t: (P A.one)) (P a) =
|
||||
//λa λP λt
|
||||
//(~a P λx #match x = x {
|
||||
//#0: λb ?A
|
||||
//#+: λb ?B
|
||||
//}: ∀(b: (#match x = x { #0: Unit #+: Empty }: *))
|
||||
//(P (Sigma.new #U60 λtag(#match tag = tag { #0: Unit #+: Empty }: *) x b)))
|
||||
|
||||
|
||||
|
||||
//(P (Sigma.new #U60 Unit b))
|
@ -1 +0,0 @@
|
||||
B = *
|
451
src/main.rs
Normal file
451
src/main.rs
Normal file
@ -0,0 +1,451 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use TSPL::Parser;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
//use std::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Oper {
|
||||
Add , Sub , Mul , Div ,
|
||||
Mod , Eq , Ne , Lt ,
|
||||
Gt , Lte , Gte , And ,
|
||||
Or , Xor , Lsh , Rsh ,
|
||||
}
|
||||
|
||||
// Term variables use Bruijn Levels.
|
||||
#[derive(Clone)]
|
||||
enum Term {
|
||||
All { nam: String, inp: Box<Term>, bod: Box<Term> },
|
||||
Lam { nam: String, bod: Box<Term> },
|
||||
App { fun: Box<Term>, arg: Box<Term> },
|
||||
Ann { val: Box<Term>, typ: Box<Term> },
|
||||
Slf { nam: String, bod: Box<Term> },
|
||||
Ins { val: Box<Term> },
|
||||
Set,
|
||||
U60,
|
||||
Num { val: u64 },
|
||||
Op2 { opr: Oper, fst: Box<Term>, snd: Box<Term> },
|
||||
Mat { nam: String, x: Box<Term>, z: Box<Term>, s: Box<Term>, p: Box<Term> },
|
||||
Txt { txt: String },
|
||||
Let { nam: String, val: Box<Term>, bod: Box<Term> },
|
||||
Hol { nam: String },
|
||||
Var { nam: String },
|
||||
}
|
||||
|
||||
struct Book {
|
||||
defs: HashMap<String, Term>,
|
||||
}
|
||||
|
||||
// NOT USED ANYMORE
|
||||
//fn name(numb: usize) -> String {
|
||||
//let mut name = String::new();
|
||||
//let mut numb = numb as i64;
|
||||
//loop {
|
||||
//name.insert(0, ((97 + (numb % 26)) as u8) as char);
|
||||
//numb = numb / 26 - 1;
|
||||
//if numb < 0 { break; }
|
||||
//}
|
||||
//name
|
||||
//}
|
||||
|
||||
pub fn cons<A>(vector: &im::Vector<A>, value: A) -> im::Vector<A> where A: Clone {
|
||||
let mut new_vector = vector.clone();
|
||||
new_vector.push_back(value);
|
||||
new_vector
|
||||
}
|
||||
|
||||
impl Oper {
|
||||
fn show(&self) -> &'static str {
|
||||
match self {
|
||||
Oper::Add => "+",
|
||||
Oper::Sub => "-",
|
||||
Oper::Mul => "*",
|
||||
Oper::Div => "/",
|
||||
Oper::Mod => "%",
|
||||
Oper::Eq => "==",
|
||||
Oper::Ne => "!=",
|
||||
Oper::Lt => "<",
|
||||
Oper::Gt => ">",
|
||||
Oper::Lte => "<=",
|
||||
Oper::Gte => ">=",
|
||||
Oper::And => "&",
|
||||
Oper::Or => "|",
|
||||
Oper::Xor => "^",
|
||||
Oper::Lsh => "<<",
|
||||
Oper::Rsh => ">>",
|
||||
}
|
||||
}
|
||||
|
||||
fn to_hvm1(&self) -> &'static str {
|
||||
match self {
|
||||
Oper::Add => "ADD",
|
||||
Oper::Sub => "SUB",
|
||||
Oper::Mul => "MUL",
|
||||
Oper::Div => "DIV",
|
||||
Oper::Mod => "MOD",
|
||||
Oper::Eq => "EQ",
|
||||
Oper::Ne => "NE",
|
||||
Oper::Lt => "LT",
|
||||
Oper::Gt => "GT",
|
||||
Oper::Lte => "LTE",
|
||||
Oper::Gte => "GTE",
|
||||
Oper::And => "AND",
|
||||
Oper::Or => "OR",
|
||||
Oper::Xor => "XOR",
|
||||
Oper::Lsh => "LSH",
|
||||
Oper::Rsh => "RSH",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Term {
|
||||
fn show(&self) -> String {
|
||||
match self {
|
||||
Term::All { nam, inp, bod } => format!("∀({}: {}) {}", nam, inp.show(), bod.show()),
|
||||
Term::Lam { nam, bod } => format!("λ{} {}", nam, bod.show()),
|
||||
Term::App { fun, arg } => format!("({} {})", fun.show(), arg.show()),
|
||||
Term::Ann { val, typ } => format!("{{{}: {}}}", val.show(), typ.show()),
|
||||
Term::Slf { nam, bod } => format!("${} {}", nam, bod.show()),
|
||||
Term::Ins { val } => format!("~{}", val.show()),
|
||||
Term::Set => "*".to_string(),
|
||||
Term::U60 => "#U60".to_string(),
|
||||
Term::Num { val } => format!("#{}", val),
|
||||
Term::Op2 { opr, fst, snd } => format!("#({} {} {})", opr.show(), fst.show(), snd.show()),
|
||||
Term::Mat { nam, x, z, s, p } => format!("#match {} = {} {{ #0: {}; #+: {} }}: {}", nam, x.show(), z.show(), s.show(), p.show()),
|
||||
Term::Txt { txt } => format!("\"{}\"", txt),
|
||||
Term::Let { nam, val, bod } => format!("let {} = {} in {}", nam, val.show(), bod.show()),
|
||||
Term::Hol { nam } => format!("?{}", nam),
|
||||
Term::Var { nam } => nam.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_hvm1(&self, env: im::Vector<String>) -> String {
|
||||
match self {
|
||||
Term::All { nam, inp, bod } => format!("(All \"{}\" {} λ{} {})", nam, inp.to_hvm1(env.clone()), nam, bod.to_hvm1(cons(&env, nam.clone()))),
|
||||
Term::Lam { nam, bod } => format!("(Lam \"{}\" λ{} {})", nam, nam, bod.to_hvm1(cons(&env, nam.clone()))),
|
||||
Term::App { fun, arg } => format!("(App {} {})", fun.to_hvm1(env.clone()), arg.to_hvm1(env.clone())),
|
||||
Term::Ann { val, typ } => format!("(Ann {} {})", val.to_hvm1(env.clone()), typ.to_hvm1(env.clone())),
|
||||
Term::Slf { nam, bod } => format!("(Slf \"{}\" λ{} {})", nam, nam, bod.to_hvm1(cons(&env, nam.clone()))),
|
||||
Term::Ins { val } => format!("(Ins {})", val.to_hvm1(env.clone())),
|
||||
Term::Set => "(Set)".to_string(),
|
||||
Term::U60 => "(U60)".to_string(),
|
||||
Term::Num { val } => format!("(Num {})", val),
|
||||
Term::Op2 { opr, fst, snd } => format!("(Op2 {} {} {})", opr.to_hvm1(), fst.to_hvm1(env.clone()), snd.to_hvm1(env.clone())),
|
||||
Term::Mat { nam, x, z, s, p } => format!("(Mat \"{}\" {} {} λ{} {} λ{} {})", nam, x.to_hvm1(env.clone()), z.to_hvm1(env.clone()), nam, s.to_hvm1(cons(&env, nam.clone())), nam, p.to_hvm1(cons(&env, nam.clone()))),
|
||||
Term::Txt { txt } => format!("(Txt \"{}\")", txt),
|
||||
Term::Let { nam, val, bod } => format!("(Let \"{}\" {} λ{} {})", nam, val.to_hvm1(env.clone()), nam, bod.to_hvm1(cons(&env, nam.clone()))),
|
||||
Term::Hol { nam } => format!("(Hol \"{}\" [{}])", nam, env.iter().map(|n| format!("\"{}\"", n)).collect::<Vec<_>>().join(",")),
|
||||
Term::Var { nam } => if env.contains(nam) { nam.clone() } else { format!("(Book.{})", nam) },
|
||||
}
|
||||
}
|
||||
|
||||
fn get_free_vars(&self, env: im::Vector<String>, free: &mut HashSet<String>) {
|
||||
match self {
|
||||
Term::All { nam, inp, bod } => {
|
||||
inp.get_free_vars(env.clone(), free);
|
||||
bod.get_free_vars(cons(&env, nam.clone()), free);
|
||||
},
|
||||
Term::Lam { nam, bod } => {
|
||||
bod.get_free_vars(cons(&env, nam.clone()), free);
|
||||
},
|
||||
Term::App { fun, arg } => {
|
||||
fun.get_free_vars(env.clone(), free);
|
||||
arg.get_free_vars(env.clone(), free);
|
||||
},
|
||||
Term::Ann { val, typ } => {
|
||||
val.get_free_vars(env.clone(), free);
|
||||
typ.get_free_vars(env.clone(), free);
|
||||
},
|
||||
Term::Slf { nam, bod } => {
|
||||
bod.get_free_vars(cons(&env, nam.clone()), free);
|
||||
},
|
||||
Term::Ins { val } => {
|
||||
val.get_free_vars(env.clone(), free);
|
||||
},
|
||||
Term::Set => {},
|
||||
Term::U60 => {},
|
||||
Term::Num { val: _ } => {},
|
||||
Term::Op2 { opr: _, fst, snd } => {
|
||||
fst.get_free_vars(env.clone(), free);
|
||||
snd.get_free_vars(env.clone(), free);
|
||||
},
|
||||
Term::Mat { nam, x, z, s, p } => {
|
||||
x.get_free_vars(env.clone(), free);
|
||||
z.get_free_vars(env.clone(), free);
|
||||
s.get_free_vars(cons(&env, nam.clone()), free);
|
||||
p.get_free_vars(cons(&env, nam.clone()), free);
|
||||
},
|
||||
Term::Txt { txt: _ } => {},
|
||||
Term::Let { nam, val, bod } => {
|
||||
val.get_free_vars(env.clone(), free);
|
||||
bod.get_free_vars(cons(&env, nam.clone()), free);
|
||||
},
|
||||
Term::Hol { nam: _ } => {},
|
||||
Term::Var { nam } => {
|
||||
if !env.contains(nam) {
|
||||
free.insert(nam.clone());
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TSPL::new_parser!(KindParser);
|
||||
|
||||
impl<'i> KindParser<'i> {
|
||||
fn parse_oper(&mut self) -> Result<Oper, String> {
|
||||
self.skip_trivia();
|
||||
match self.peek_one() {
|
||||
Some('+') => { self.advance_one(); Ok(Oper::Add) }
|
||||
Some('-') => { self.advance_one(); Ok(Oper::Sub) }
|
||||
Some('*') => { self.advance_one(); Ok(Oper::Mul) }
|
||||
Some('/') => { self.advance_one(); Ok(Oper::Div) }
|
||||
Some('%') => { self.advance_one(); Ok(Oper::Mod) }
|
||||
Some('=') => { self.consume("=")?; Ok(Oper::Eq) }
|
||||
Some('!') => { self.consume("!=")?; Ok(Oper::Ne) }
|
||||
Some('<') => {
|
||||
match self.peek_many(2) {
|
||||
Some("<=") => { self.advance_many(2); Ok(Oper::Lte) }
|
||||
_ => { self.advance_one(); Ok(Oper::Lt) }
|
||||
}
|
||||
}
|
||||
Some('>') => {
|
||||
match self.peek_many(2) {
|
||||
Some(">=") => { self.advance_many(2); Ok(Oper::Gte) }
|
||||
_ => { self.advance_one(); Ok(Oper::Gt) }
|
||||
}
|
||||
}
|
||||
Some('&') => { self.advance_one(); Ok(Oper::And) }
|
||||
Some('|') => { self.advance_one(); Ok(Oper::Or) }
|
||||
Some('^') => { self.advance_one(); Ok(Oper::Xor) }
|
||||
Some('l') => { self.consume("<<")?; Ok(Oper::Lsh) }
|
||||
Some('r') => { self.consume(">>")?; Ok(Oper::Rsh) }
|
||||
_ => self.expected("operator"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_term(&mut self) -> Result<Term, String> {
|
||||
self.skip_trivia();
|
||||
match self.peek_one() {
|
||||
Some('∀') => {
|
||||
self.consume("∀")?;
|
||||
self.consume("(")?;
|
||||
let nam = self.parse_name()?;
|
||||
self.consume(":")?;
|
||||
let inp = Box::new(self.parse_term()?);
|
||||
self.consume(")")?;
|
||||
let bod = Box::new(self.parse_term()?);
|
||||
Ok(Term::All { nam, inp, bod })
|
||||
}
|
||||
Some('λ') => {
|
||||
self.consume("λ")?;
|
||||
let nam = self.parse_name()?;
|
||||
let bod = Box::new(self.parse_term()?);
|
||||
Ok(Term::Lam { nam, bod })
|
||||
}
|
||||
Some('(') => {
|
||||
self.consume("(")?;
|
||||
let fun = Box::new(self.parse_term()?);
|
||||
let mut args = Vec::new();
|
||||
while self.peek_one() != Some(')') {
|
||||
args.push(Box::new(self.parse_term()?));
|
||||
}
|
||||
self.consume(")")?;
|
||||
let mut app = fun;
|
||||
for arg in args {
|
||||
app = Box::new(Term::App { fun: app, arg });
|
||||
}
|
||||
Ok(*app)
|
||||
}
|
||||
Some('{') => {
|
||||
self.consume("{")?;
|
||||
let val = Box::new(self.parse_term()?);
|
||||
self.consume(":")?;
|
||||
let typ = Box::new(self.parse_term()?);
|
||||
self.consume("}")?;
|
||||
Ok(Term::Ann { val, typ })
|
||||
}
|
||||
Some('$') => {
|
||||
self.consume("$")?;
|
||||
let nam = self.parse_name()?;
|
||||
let bod = Box::new(self.parse_term()?);
|
||||
Ok(Term::Slf { nam, bod })
|
||||
}
|
||||
Some('~') => {
|
||||
self.consume("~")?;
|
||||
let val = Box::new(self.parse_term()?);
|
||||
Ok(Term::Ins { val })
|
||||
}
|
||||
Some('*') => {
|
||||
self.consume("*")?;
|
||||
Ok(Term::Set)
|
||||
}
|
||||
Some('#') => {
|
||||
self.consume("#")?;
|
||||
match self.peek_one() {
|
||||
Some('U') => {
|
||||
self.consume("U60")?;
|
||||
Ok(Term::U60)
|
||||
}
|
||||
Some('(') => {
|
||||
self.consume("(")?;
|
||||
let opr = self.parse_oper()?;
|
||||
let fst = Box::new(self.parse_term()?);
|
||||
let snd = Box::new(self.parse_term()?);
|
||||
self.consume(")")?;
|
||||
Ok(Term::Op2 { opr, fst, snd })
|
||||
}
|
||||
Some('m') => {
|
||||
self.consume("match")?;
|
||||
let nam = self.parse_name()?;
|
||||
self.consume("=")?;
|
||||
let x = Box::new(self.parse_term()?);
|
||||
self.consume("{")?;
|
||||
self.consume("#0")?;
|
||||
self.consume(":")?;
|
||||
let z = Box::new(self.parse_term()?);
|
||||
self.consume("#+")?;
|
||||
self.consume(":")?;
|
||||
let s = Box::new(self.parse_term()?);
|
||||
self.consume("}")?;
|
||||
self.consume(":")?;
|
||||
let p = Box::new(self.parse_term()?);
|
||||
Ok(Term::Mat { nam, x, z, s, p })
|
||||
}
|
||||
Some(_) => {
|
||||
let val = self.parse_u64()?;
|
||||
Ok(Term::Num { val })
|
||||
}
|
||||
_ => {
|
||||
self.expected("numeric-expression")
|
||||
}
|
||||
}
|
||||
}
|
||||
Some('?') => {
|
||||
self.consume("?")?;
|
||||
let nam = self.parse_name()?;
|
||||
Ok(Term::Hol { nam })
|
||||
}
|
||||
Some('\'') => {
|
||||
let chr = self.parse_quoted_char()?;
|
||||
Ok(Term::Num { val: chr as u64 })
|
||||
}
|
||||
Some('"') => {
|
||||
let txt = self.parse_quoted_string()?;
|
||||
Ok(Term::Txt { txt })
|
||||
}
|
||||
_ => {
|
||||
if self.peek_many(4) == Some("let ") {
|
||||
self.advance_many(4);
|
||||
let nam = self.parse_name()?;
|
||||
self.consume("=")?;
|
||||
let val = Box::new(self.parse_term()?);
|
||||
let bod = Box::new(self.parse_term()?);
|
||||
Ok(Term::Let { nam, val, bod })
|
||||
} else {
|
||||
let nam = self.parse_name()?;
|
||||
Ok(Term::Var { nam })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_def(&mut self) -> Result<(String, Term), String> {
|
||||
let nam = self.parse_name()?;
|
||||
self.skip_trivia();
|
||||
if self.peek_one() == Some(':') {
|
||||
self.consume(":")?;
|
||||
let typ = self.parse_term()?;
|
||||
self.consume("=")?;
|
||||
let val = self.parse_term()?;
|
||||
Ok((nam, Term::Ann { val: Box::new(val), typ: Box::new(typ) }))
|
||||
} else {
|
||||
self.consume("=")?;
|
||||
let val = self.parse_term()?;
|
||||
Ok((nam, val))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_book(&mut self) -> Result<Book, String> {
|
||||
let mut book = Book::new();
|
||||
while *self.index() < self.input().len() {
|
||||
let (name, term) = self.parse_def()?;
|
||||
book.defs.insert(name, term);
|
||||
self.skip_trivia();
|
||||
}
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Book {
|
||||
fn new() -> Self {
|
||||
Book {
|
||||
defs: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_hvm1(&self) -> String {
|
||||
let mut used = HashSet::new();
|
||||
let mut code = String::new();
|
||||
for (name, term) in &self.defs {
|
||||
code.push_str(&format!("Book.{} = (Ref \"{}\" {})\n", name, name, term.to_hvm1(im::Vector::new())));
|
||||
used.insert(name.clone());
|
||||
}
|
||||
code
|
||||
}
|
||||
|
||||
fn show(&self) -> String {
|
||||
let mut book_str = String::new();
|
||||
for (name, term) in &self.defs {
|
||||
book_str.push_str(&format!("{} = {}\n", name, term.show()));
|
||||
}
|
||||
book_str
|
||||
}
|
||||
|
||||
fn load_file(filename: &str) -> Result<Self, String> {
|
||||
std::fs::read_to_string(filename)
|
||||
.map_err(|_| format!("Could not read file: {}", filename))
|
||||
.and_then(|contents| KindParser::new(&contents).parse_book())
|
||||
}
|
||||
|
||||
fn load(name: &str) -> Result<Self, String> {
|
||||
fn load_term(name: &str, book: &mut Book) -> Result<(), String> {
|
||||
if !book.defs.contains_key(name) {
|
||||
let file = format!("./book/{}.kind2", name);
|
||||
let text = std::fs::read_to_string(&file).map_err(|_| format!("Could not read file: {}", file))?;
|
||||
let defs = KindParser::new(&text).parse_book()?;
|
||||
for (def_name, def_term) in &defs.defs {
|
||||
book.defs.insert(def_name.clone(), def_term.clone());
|
||||
}
|
||||
for (_, def_term) in defs.defs.into_iter() {
|
||||
let mut dependencies = HashSet::new();
|
||||
def_term.get_free_vars(im::Vector::new(), &mut dependencies);
|
||||
for ref_name in dependencies {
|
||||
load_term(&ref_name, book)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let mut book = Book::new();
|
||||
load_term(name, &mut book)?;
|
||||
Ok(book)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
let book = Book::load("Bool")?;
|
||||
//let book = KindParser::new("f : * = ∀(a: *) λf λx (ID (f (f a b c)))").parse_book()?;
|
||||
println!("{}", book.show());
|
||||
println!("{}", book.to_hvm1());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = run() {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user