use-declarations with shadowing

This commit is contained in:
Victor Taelin 2024-03-12 18:01:12 -03:00
parent dc993b5de0
commit 0c34404c0b
22 changed files with 287 additions and 146 deletions

View File

@ -50,4 +50,4 @@ BBT.balance.lft_heavier
rgt
)
use tip = (BBT.tip K V)
(~lft P bin tip)
(~lft P bin tip)

View File

@ -15,4 +15,4 @@ BBT.get
use gtn = λcmp λkey (BBT.get K V cmp key next.rgt)
(~(cmp key next.key) P ltn eql gtn cmp key)
use tip = (Maybe.none V)
(~map P bin tip)
(~map P bin tip)

View File

@ -1,7 +1,9 @@
Bool.and
: ∀(a: Bool) ∀(b: Bool) Bool
= λa
use P = λa ∀(b: Bool) Bool
use true = λb b
use false = λb Bool.false
(~a P true false)
Bool.and (a: Bool) (b: Bool) : Bool =
match b {
Bool.true: b
Bool.false: Bool.false
}
//use P = λa ∀(b: Bool) Bool
//use true = λb b
//use false = λb Bool.false
//((~a P true false) b)

View File

@ -1,3 +1,2 @@
Bool.false
: Bool
= ~λP λt λf f
Bool.false : Bool =
~λP λt λf f

View File

@ -1,7 +1,3 @@
Bool
: *
= $(self: Bool)
∀(P: ∀(x: Bool) *)
∀(true: (P Bool.true))
∀(false: (P Bool.false))
(P self)
data Bool
| true
| false

View File

@ -1,3 +1,2 @@
Bool.true
: Bool
= ~λP λt λf t
Bool.true : Bool =
~λP λt λf t

View File

@ -58,4 +58,4 @@ Kind.Term
∀(var:
∀(nam: String) ∀(idx: Nat) (P (Kind.var nam idx))
)
(P self)
(P self)

View File

@ -1,7 +1,10 @@
List.length
: ∀(A: *) ∀(a: (List A)) Nat
= λA λa
match a {
List.cons: (Nat.succ (List.length A a.tail))
List.nil: Nat.zero
use List.{cons,nil}
use Nat.{succ,zero}
length A (xs: (List A)) : Nat =
match xs {
cons:
(succ (length A xs.tail))
nil:
zero
}

8
book/Monad.new.kind2 Normal file
View File

@ -0,0 +1,8 @@
Monad.new
: ∀(M: ∀(T: *) *)
∀(bind: ∀(A: *) ∀(B: *) ∀(a: (M A)) ∀(b: ∀(a: A) (M B)) (M B))
∀(pure: ∀(A: *) ∀(a: A) (M A))
(Monad M)
= λM λbind λpure
~λP λnew
(new bind pure)

View File

@ -1,3 +1,3 @@
Nat.succ
: ∀(n: Nat) Nat
= λn ~λP λsucc λzero (succ n)
= λn ~λP λsucc λzero (succ n)

View File

@ -1,3 +1,3 @@
String
: *
= (List Char)
= (List Char)

View File

@ -4,4 +4,4 @@ U60.abs_diff
use P = λx #U60
use true = #(- b a)
use false = #(- a b)
(~(U60.to_bool #(< a b)) P true false)
(~(U60.to_bool #(< a b)) P true false)

View File

@ -6,4 +6,4 @@ U60.cmp
Cmp
(U60.if #(< a b) Cmp Cmp.gtn Cmp.ltn)
Cmp.eql
)
)

View File

@ -4,4 +4,4 @@ U60.equal
#match x = #(== a b) {
#0: Bool.false
#+: Bool.true
}: Bool
}: Bool

View File

@ -4,4 +4,4 @@ U60.from_nat
use P = λx #U60
use succ = λn.pred #(+ #1 (U60.from_nat n.pred))
use zero = #0
(~n P succ zero)
(~n P succ zero)

View File

@ -1,3 +1,3 @@
U60.min
: ∀(a: #U60) ∀(b: #U60) #U60
= λa λb (~(U60.to_bool #(< a b)) λx #U60 a b)
= λa λb (~(U60.to_bool #(< a b)) λx #U60 a b)

View File

@ -8,17 +8,30 @@ mod parse;
mod show;
// <book> ::=
// DEF_ANN | <name> : <term> = <term> <book>
// DEF_VAL | <name> = <term> <book>
// END | <eof>
// USE | use <alias> <book>
// ADT | <adt> <book>
// ANN | <name> : <term> = <term> <book>
// DEF | <name> = <term> <book>
// END | <eof>
#[derive(Clone, Debug)]
pub struct Book {
pub defs: BTreeMap<String, Term>,
pub fids: BTreeMap<String, u64>,
}
// Shadows a name on the uses map
pub fn shadow(key: &str, uses: &Uses) -> Uses {
let mut uses = uses.clone();
uses.insert(key.to_string(), key.to_string());
return uses;
}
// Maps short names ("cons") to full names ("Data.List.cons")
pub type Uses = im::HashMap<String, String>;
impl Book {
// Creates an empty book
pub fn new() -> Self {
Book {
defs: BTreeMap::new(),
@ -26,43 +39,51 @@ impl Book {
}
}
pub fn load(name: &str) -> Result<Self, String> {
fn load_go(name: &str, book: &mut Book) -> Result<(), String> {
//println!("... {}", name);
if !book.defs.contains_key(name) {
let file = format!("./{}.kind2", name);
let text = std::fs::read_to_string(&file).map_err(|_| format!("Could not read file: {}", file))?;
let fid = book.get_file_id(&file);
//println!("... parsing: {}", name);
let defs = KindParser::new(&text).parse_book(fid)?;
//println!("... parsed: {}", name);
for (def_name, def_value) in &defs.defs {
book.defs.insert(def_name.clone(), def_value.clone());
}
//println!("laoding deps for: {}", name);
for (_, def_term) in defs.defs.into_iter() {
let mut dependencies = BTreeSet::new();
def_term.get_free_vars(im::Vector::new(), &mut dependencies);
//println!("{} deps: {:?}", name, dependencies);
for ref_name in dependencies {
load_go(&ref_name, book)?;
// Creates a book, loading a term, its dependencies, and stdlib
pub fn boot(name: &str) -> Result<Self, String> {
let mut book = Book::new();
book.load(name)?;
book.load("String")?;
book.load("String.cons")?;
book.load("String.nil")?;
book.load("Nat")?;
book.load("Nat.succ")?;
book.load("Nat.zero")?;
return Ok(book);
}
// Handles an unbound definition
pub fn handle_unbound(&self, file: &str, name: &str) -> Result<(), String> {
return Err(format!("ERROR\n- unbound: '{}'\n- on_file: {}", name, file));
}
// Same as load, mutably adding to a 'book'
pub fn load(&mut self, name: &str) -> Result<(), String> {
if !self.defs.contains_key(name) {
// Parses a file into a new book
let file = format!("./{}.kind2", name);
let text = std::fs::read_to_string(&file).map_err(|_| format!("Could not read file: {}", file))?;
let fid = self.get_file_id(&file);
let defs = KindParser::new(&text).parse_book(name, fid)?;
// Merges new book into book
for (def_name, def_value) in &defs.defs {
self.defs.insert(def_name.clone(), def_value.clone());
}
// Finds dependencies and loads them
for (_, def_term) in defs.defs.into_iter() {
let mut dependencies = BTreeSet::new();
def_term.get_free_vars(im::Vector::new(), &mut dependencies);
for ref_name in dependencies {
if let Err(_) = self.load(&ref_name) {
self.handle_unbound(&file, &ref_name)?;
}
}
}
return Ok(());
}
let mut book = Book::new();
load_go(name, &mut book)?;
load_go("String", &mut book)?;
load_go("String.cons", &mut book)?;
load_go("String.nil", &mut book)?;
load_go("Nat", &mut book)?;
load_go("Nat.succ", &mut book)?;
load_go("Nat.zero", &mut book)?;
//println!("DONE!");
Ok(book)
return Ok(());
}
// Gets a file id from its name
pub fn get_file_id(&mut self, name: &str) -> u64 {
if let Some(id) = self.fids.get(name) {
*id
@ -73,7 +94,7 @@ impl Book {
}
}
// FIXME: asymptotics
// Gets a file name from its id (FIXME: asymptotics)
pub fn get_file_name(&self, id: u64) -> Option<String> {
for (name, &fid) in &self.fids {
if fid == id {

View File

@ -5,11 +5,50 @@ use std::collections::BTreeSet;
impl<'i> KindParser<'i> {
pub fn parse_def(&mut self, fid: u64) -> Result<(String, Term), String> {
// Parses a top-level use-declaration
fn parse_use(&mut self, fid: u64, nam: String, uses: &mut Uses) -> Result<(), String> {
self.skip_trivia();
let add = self.parse_name()?;
self.skip_trivia();
let nam = format!("{}{}", nam, add);
if self.peek_one() == Some('{') {
self.consume("{")?;
self.skip_trivia();
loop {
self.parse_use(fid, nam.clone(), uses)?;
self.skip_trivia();
match self.peek_one() {
Some(',') => { self.consume(",")?; continue; }
Some('}') => { self.consume("}")?; break; }
_ => { return self.expected("comma (`,`) or semicolon (`;`)"); }
}
}
} else {
let pts = nam.split('.').collect::<Vec<&str>>();
let key = pts.last().unwrap().to_string();
//println!("use {} ~> {}", key, nam);
uses.insert(key, nam);
}
return Ok(());
}
// Parses many top-level use-declarations
fn parse_uses(&mut self, fid: u64) -> Result<Uses, String> {
let mut uses = im::HashMap::new();
self.skip_trivia();
while self.peek_many(4) == Some("use ") {
self.consume("use")?;
self.parse_use(fid, String::new(), &mut uses)?;
self.skip_trivia();
}
return Ok(uses);
}
// Parses a top-level definition (datatype or term)
pub fn parse_def(&mut self, fid: u64, uses: &Uses) -> Result<(String, Term), String> {
// Top-level datatype
if self.peek_many(5) == Some("data ") {
let adt = self.parse_adt(fid)?;
let adt = self.parse_adt(fid, uses)?;
let mut typ = Term::Set;
let mut val = Term::new_adt(&adt);
for (idx_nam, idx_typ) in adt.idxs.iter().rev() {
@ -29,28 +68,68 @@ impl<'i> KindParser<'i> {
// Top level definition
self.skip_trivia();
let nam = self.parse_name()?;
let nam = uses.get(&nam).unwrap_or(&nam).to_string();
self.skip_trivia();
// Parameters (optional)
let mut pars = vec![];
while self.peek_one().map_or(false, |c| c.is_ascii_alphabetic()) {
let par = self.parse_name()?;
self.skip_trivia();
pars.push(par);
}
// Arguments (optional)
let mut args = vec![];
while self.peek_one() == Some('(') {
self.consume("(")?;
let arg_name = self.parse_name()?;
self.consume(":")?;
let arg_type = self.parse_term(fid, uses)?;
self.consume(")")?;
args.push((arg_name, arg_type));
self.skip_trivia();
}
// Type annotation (optional)
let mut typ;
if self.peek_one() == Some(':') {
self.consume(":")?;
let typ = self.parse_term(fid)?;
self.consume("=")?;
let val = self.parse_term(fid)?;
return Ok((nam, Term::Ann { chk: false, val: Box::new(val), typ: Box::new(typ) }));
typ = self.parse_term(fid, uses)?;
} else {
typ = Term::Met {};
}
// Value (mandatory)
self.consume("=")?;
let val = self.parse_term(fid)?;
let mut val = self.parse_term(fid, uses)?;
return Ok((nam, val));
// Adds arguments to val/typ
for (arg_nam, arg_typ) in args.iter().rev() {
typ = Term::All { nam: arg_nam.clone(), inp: Box::new(arg_typ.clone()), bod: Box::new(typ.clone()) };
val = Term::Lam { nam: arg_nam.clone(), bod: Box::new(val.clone()) };
}
// Adds parameters to val/typ
for par in pars.iter().rev() {
typ = Term::All { nam: par.clone(), inp: Box::new(Term::Met{}), bod: Box::new(typ.clone()) };
val = Term::Lam { nam: par.clone(), bod: Box::new(val.clone()) };
}
//println!("- def: {}", nam);
//println!("- typ: {}", typ.show());
//println!("- val: {}", val.show());
return Ok((nam, Term::Ann { chk: false, val: Box::new(val), typ: Box::new(typ) }));
}
pub fn parse_book(&mut self, fid: u64) -> Result<Book, String> {
pub fn parse_book(&mut self, name: &str, fid: u64) -> Result<Book, String> {
let mut book = Book::new();
let mut uses = self.parse_uses(fid)?;
// Adds the default 'use Path.to.file'
uses.insert(name.split('.').last().unwrap().to_string(), name.to_string());
while *self.index() < self.input().len() {
let (name, term) = self.parse_def(fid)?;
let (name, term) = self.parse_def(fid, &mut uses)?;
book.defs.insert(name, term);
self.skip_trivia();
}

View File

@ -1,8 +1,5 @@
use crate::{*};
//./../main.rs//
//./mod.rs//
impl<'i> KindParser<'i> {
pub fn parse_info(&mut self) -> Result<Info, String> {
@ -15,11 +12,11 @@ impl<'i> KindParser<'i> {
self.consume("found")?;
self.consume("{")?;
let nam = self.parse_name()?;
let typ = self.parse_term(0)?;
let typ = self.parse_term(0, &im::HashMap::new())?;
self.consume("[")?;
let mut ctx = Vec::new();
while self.peek_one() != Some(']') {
ctx.push(self.parse_term(0)?);
ctx.push(self.parse_term(0, &im::HashMap::new())?);
self.skip_trivia();
}
self.consume("]")?;
@ -29,9 +26,9 @@ impl<'i> KindParser<'i> {
Some('e') => {
self.consume("error")?;
self.consume("{")?;
let exp = self.parse_term(0)?;
let det = self.parse_term(0)?;
let bad = self.parse_term(0)?;
let exp = self.parse_term(0, &im::HashMap::new())?;
let det = self.parse_term(0, &im::HashMap::new())?;
let bad = self.parse_term(0, &im::HashMap::new())?;
let src = Src::from_u64(self.parse_u64()?);
self.consume("}")?;
Ok(Info::Error {
@ -45,7 +42,7 @@ impl<'i> KindParser<'i> {
self.consume("solve")?;
self.consume("{")?;
let nam = self.parse_name()?;
let val = self.parse_term(0)?;
let val = self.parse_term(0, &im::HashMap::new())?;
self.consume("}")?;
Ok(Info::Solve { nam, val })
}
@ -59,7 +56,7 @@ impl<'i> KindParser<'i> {
Some('p') => {
self.consume("print")?;
self.consume("{")?;
let val = self.parse_term(0)?;
let val = self.parse_term(0, &im::HashMap::new())?;
self.consume("}")?;
Ok(Info::Print { val })
}

View File

@ -62,7 +62,7 @@ fn main() {
//println!("loading");
match cmd.as_str() {
"check" | "run" => {
match Book::load(arg) {
match Book::boot(arg) {
Ok(book) => {
// Auto-formats the definition.
//let defn = book.defs.get(arg).unwrap();

View File

@ -15,11 +15,10 @@ pub struct ADT {
pub ctrs: Vec<Constructor>, // constructors
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct Constructor {
pub name: String, // constructor name
pub flds: Vec<(String,Term)>, // constructor fields
//pub rtyp: Term, // constructor type; NOTE: refactored. now, instead of storing `rtyp=(Vec A 0)`, we store just `idxs=[0]`, for ex.
pub idxs: Vec<Term>, // constructor type indices
}
@ -564,7 +563,7 @@ impl Term {
bod: Box::new(term)
};
println!("PARSED:\n{}", term.show());
//println!("PARSED:\n{}", term.show());
// 8. Return 'term'
return term;
@ -576,7 +575,7 @@ impl ADT {
// Loads an ADT from its λ-encoded file.
pub fn load(name: &str) -> Result<ADT, String> {
let book = Book::load(name)?;
let book = Book::boot(name)?;
if let Some(term) = book.defs.get(name) {
let mut term = &term.clean();
// Skips all Anns
@ -719,11 +718,11 @@ impl Match {
impl<'i> KindParser<'i> {
pub fn parse_list(&mut self, fid: u64) -> Result<crate::sugar::List, String> {
pub fn parse_list(&mut self, fid: u64, uses: &Uses) -> Result<crate::sugar::List, String> {
self.consume("[")?;
let mut vals = Vec::new();
while self.peek_one() != Some(']') {
vals.push(Box::new(self.parse_term(fid)?));
vals.push(Box::new(self.parse_term(fid, uses)?));
self.skip_trivia();
if self.peek_one() == Some(',') {
self.consume(",")?;
@ -733,16 +732,19 @@ impl<'i> KindParser<'i> {
return Ok(crate::sugar::List { vals });
}
pub fn parse_adt(&mut self, fid: u64) -> Result<crate::sugar::ADT, String> {
// FIXME: handle shadowing
pub fn parse_adt(&mut self, fid: u64, uses: &Uses) -> Result<crate::sugar::ADT, String> {
self.consume("data ")?;
let name = self.parse_name()?;
let mut pars = Vec::new();
let mut idxs = Vec::new();
let mut uses = uses.clone();
// Parses ADT parameters (if any)
self.skip_trivia();
while self.peek_one().map_or(false, |c| c.is_ascii_alphabetic()) {
let par = self.parse_name()?;
self.skip_trivia();
uses = shadow(&par, &uses);
pars.push(par);
}
// Parses ADT fields
@ -750,8 +752,9 @@ impl<'i> KindParser<'i> {
self.consume("(")?;
let idx_name = self.parse_name()?;
self.consume(":")?;
let idx_type = self.parse_term(fid)?;
let idx_type = self.parse_term(fid, &uses)?;
self.consume(")")?;
uses = shadow(&idx_name, &uses);
idxs.push((idx_name, idx_type));
self.skip_trivia();
}
@ -761,6 +764,7 @@ impl<'i> KindParser<'i> {
while self.peek_one() == Some('|') {
self.consume("|")?;
let ctr_name = self.parse_name()?;
let mut uses = uses.clone();
let mut flds = Vec::new();
// Parses constructor fields
self.skip_trivia();
@ -768,8 +772,9 @@ impl<'i> KindParser<'i> {
self.consume("(")?;
let fld_name = self.parse_name()?;
self.consume(":")?;
let fld_type = self.parse_term(fid)?;
let fld_type = self.parse_term(fid, &uses)?;
self.consume(")")?;
uses = shadow(&fld_name, &uses);
flds.push((fld_name, fld_type));
self.skip_trivia();
}
@ -791,7 +796,7 @@ impl<'i> KindParser<'i> {
}
// Parses the indices
while self.peek_one() != Some(')') {
let ctr_index = self.parse_term(fid)?;
let ctr_index = self.parse_term(fid, &uses)?;
ctr_indices.push(ctr_index);
self.skip_trivia();
}
@ -817,51 +822,74 @@ impl<'i> KindParser<'i> {
// The ADT match syntax is similar to the numeric match syntax, including the same optionals,
// but it allows any number of <name>:<term> cases. Also, similarly to the List syntax, there
// is no built-in "Mat" syntax on the Term type, so we must convert it to an applicative form:
// match x = val {
// match x:
// List.cons: x.head
// List.nil: #0
// }: #U60
// : #U60
// Would be converted to:
// (~val _ (λx.head λx.tail x.tail) 0)
// Which is the same as:
// (APP (APP (APP (INS (VAR "val")) MET) (LAM "x.head" (LAM "x.tail" (VAR "x.head")))) (NUM 0))
pub fn parse_match(&mut self, fid: u64) -> Result<Match, String> {
// FIXME: handle shadowing
pub fn parse_match(&mut self, fid: u64, uses: &Uses) -> Result<Match, String> {
// Parses the header: 'match <name> = <expr>'
self.consume("match ")?;
let name = self.parse_name()?;
self.skip_trivia();
let expr = if self.peek_one() == Some('=') {
self.consume("=")?;
self.parse_term(fid)?
self.parse_term(fid, uses)?
} else {
Term::Var { nam: name.clone() }
};
// Parses the cases: '{ Type.constructor: value ... }'
self.consume("{")?;
let mut adt = "Empty".to_string();
let mut cses = Vec::new();
while self.peek_one() != Some('}') {
let ctr_name = self.parse_name()?;
let cse_name = self.parse_name()?;
let cse_name = uses.get(&cse_name).unwrap_or(&cse_name).to_string();
// Infers the local ADT name
let adt_name = {
let pts = cse_name.split('.').collect::<Vec<&str>>();
if pts.len() < 2 {
return self.expected("Type.constructor");
} else {
pts[..pts.len() - 1].join(".")
}
};
// Sets the global ADT name
if adt == "Empty" {
adt = adt_name.clone();
} else if adt != adt_name {
return self.expected(&format!("{}.constructor", adt));
}
// Finds this case's constructor
let cnm = cse_name.split('.').last().unwrap().to_string();
let ctr = ADT::load(&adt).ok().and_then(|adt| adt.ctrs.iter().find(|ctr| ctr.name == cnm).cloned());
if ctr.is_none() {
return self.expected(&format!("a valid constructor ({}.{} doesn't exit)", adt_name, cnm));
}
// Shadows this constructor's field variables
let mut uses = uses.clone();
for (fld_name, _) in &ctr.unwrap().flds {
uses = shadow(&format!("{}.{}", name, fld_name), &uses);
}
// Parses the return value
self.consume(":")?;
let ctr_body = self.parse_term(fid)?;
cses.push((ctr_name, ctr_body));
let cse_body = self.parse_term(fid, &uses)?;
cses.push((cse_name, cse_body));
self.skip_trivia();
}
self.consume("}")?;
// Parses the motive: ': return_type'
let moti = if self.peek_one() == Some(':') {
self.consume(":")?;
Some(self.parse_term(fid)?)
Some(self.parse_term(fid, uses)?)
} else {
None
};
let adt_name = if cses.is_empty() {
"Empty".to_string()
} else {
let first_case = &cses[0].0;
let parts: Vec<&str> = first_case.split('.').collect();
if parts.len() < 2 {
return Err("Expected a constructor with a datatype (e.g., 'DataType.constructor')".to_string());
}
parts[..parts.len()-1].join(".")
};
Ok(Match { adt: adt_name, name, expr, cses, moti })
return Ok(Match { adt, name, expr, cses, moti });
}
}

View File

@ -1,5 +1,6 @@
use crate::{*};
impl<'i> KindParser<'i> {
pub fn parse_oper(&mut self) -> Result<Oper, String> {
@ -33,7 +34,7 @@ impl<'i> KindParser<'i> {
}
}
pub fn parse_term(&mut self, fid: u64) -> Result<Term, String> {
pub fn parse_term(&mut self, fid: u64, uses: &Uses) -> Result<Term, String> {
self.skip_trivia();
//println!("parsing ||{}", self.input[self.index..].replace("\n",""));
@ -44,9 +45,9 @@ impl<'i> KindParser<'i> {
self.consume("(")?;
let nam = self.parse_name()?;
self.consume(":")?;
let inp = Box::new(self.parse_term(fid)?);
let inp = Box::new(self.parse_term(fid, uses)?);
self.consume(")")?;
let bod = Box::new(self.parse_term(fid)?);
let bod = Box::new(self.parse_term(fid, &shadow(&nam, uses))?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::All { nam, inp, bod }) });
@ -57,7 +58,7 @@ impl<'i> KindParser<'i> {
let ini = *self.index() as u64;
self.consume("λ")?;
let nam = self.parse_name()?;
let bod = Box::new(self.parse_term(fid)?);
let bod = Box::new(self.parse_term(fid, &shadow(&nam, uses))?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Lam { nam, bod }) });
@ -67,10 +68,10 @@ impl<'i> KindParser<'i> {
if self.starts_with("(") {
let ini = *self.index() as u64;
self.consume("(")?;
let fun = Box::new(self.parse_term(fid)?);
let fun = Box::new(self.parse_term(fid, uses)?);
let mut args = Vec::new();
while self.peek_one() != Some(')') {
args.push(Box::new(self.parse_term(fid)?));
args.push(Box::new(self.parse_term(fid, uses)?));
self.skip_trivia();
}
self.consume(")")?;
@ -87,9 +88,9 @@ impl<'i> KindParser<'i> {
if self.starts_with("{") {
let ini = *self.index() as u64;
self.consume("{")?;
let val = Box::new(self.parse_term(fid)?);
let val = Box::new(self.parse_term(fid, uses)?);
self.consume(":")?;
let typ = Box::new(self.parse_term(fid)?);
let typ = Box::new(self.parse_term(fid, uses)?);
self.consume("}")?;
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
@ -103,9 +104,9 @@ impl<'i> KindParser<'i> {
self.consume("(")?;
let nam = self.parse_name()?;
self.consume(":")?;
let typ = Box::new(self.parse_term(fid)?);
let typ = Box::new(self.parse_term(fid, uses)?);
self.consume(")")?;
let bod = Box::new(self.parse_term(fid)?);
let bod = Box::new(self.parse_term(fid, &shadow(&nam, uses))?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Slf { nam, typ, bod }) });
@ -115,7 +116,7 @@ impl<'i> KindParser<'i> {
if self.starts_with("~") {
let ini = *self.index() as u64;
self.consume("~")?;
let val = Box::new(self.parse_term(fid)?);
let val = Box::new(self.parse_term(fid, uses)?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Ins { val }) });
@ -144,8 +145,8 @@ impl<'i> KindParser<'i> {
let ini = *self.index() as u64;
self.consume("#(")?;
let opr = self.parse_oper()?;
let fst = Box::new(self.parse_term(fid)?);
let snd = Box::new(self.parse_term(fid)?);
let fst = Box::new(self.parse_term(fid, uses)?);
let snd = Box::new(self.parse_term(fid, uses)?);
self.consume(")")?;
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
@ -162,21 +163,21 @@ impl<'i> KindParser<'i> {
self.skip_trivia();
let x = if self.peek_one() == Some('=') {
self.consume("=")?;
Box::new(self.parse_term(fid)?)
Box::new(self.parse_term(fid, uses)?)
} else {
Box::new(Term::Var { nam: nam.clone() })
};
self.consume("{")?;
self.consume("#0")?;
self.consume(":")?;
let z = Box::new(self.parse_term(fid)?);
let z = Box::new(self.parse_term(fid, uses)?);
self.consume("#+")?;
self.consume(":")?;
let s = Box::new(self.parse_term(fid)?);
let s = Box::new(self.parse_term(fid, &shadow(&format!("{}-1",nam), uses))?);
self.consume("}")?;
let p = if self.peek_one() == Some(':') {
self.consume(":")?;
Box::new(self.parse_term(fid)?)
Box::new(self.parse_term(fid, &shadow(&nam, uses))?)
} else {
Box::new(Term::Met {})
};
@ -229,8 +230,8 @@ impl<'i> KindParser<'i> {
self.consume("let ")?;
let nam = self.parse_name()?;
self.consume("=")?;
let val = Box::new(self.parse_term(fid)?);
let bod = Box::new(self.parse_term(fid)?);
let val = Box::new(self.parse_term(fid, uses)?);
let bod = Box::new(self.parse_term(fid, &shadow(&nam, uses))?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Let { nam, val, bod }) });
@ -242,8 +243,8 @@ impl<'i> KindParser<'i> {
self.consume("use ")?;
let nam = self.parse_name()?;
self.consume("=")?;
let val = Box::new(self.parse_term(fid)?);
let bod = Box::new(self.parse_term(fid)?);
let val = Box::new(self.parse_term(fid, uses)?);
let bod = Box::new(self.parse_term(fid, &shadow(&nam, uses))?);
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Use { nam, val, bod }) });
@ -261,7 +262,7 @@ impl<'i> KindParser<'i> {
// LST ::= [ <term> , ... ]
if self.starts_with("[") {
let ini = *self.index() as u64;
let lst = self.parse_list(fid)?;
let lst = self.parse_list(fid, uses)?;
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
let val = Box::new(Term::new_list(&lst));
@ -283,7 +284,7 @@ impl<'i> KindParser<'i> {
// | ...
if self.starts_with("data ") {
let ini = *self.index() as u64;
let adt = self.parse_adt(fid)?;
let adt = self.parse_adt(fid, uses)?;
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::new_adt(&adt)) });
@ -292,7 +293,7 @@ impl<'i> KindParser<'i> {
// MAT ::= match <name> = <term> { <name> : <term> <...> }: <term>
if self.starts_with("match ") {
let ini = *self.index() as u64;
let mat = self.parse_match(fid)?;
let mat = self.parse_match(fid, uses)?;
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::new_match(&mat)) });
@ -300,11 +301,19 @@ impl<'i> KindParser<'i> {
// VAR ::= <name>
let ini = *self.index() as u64;
let nam = self.parse_name()?;
let old = self.parse_name()?;
let nam = uses.get(&old).unwrap_or(&old).to_string();
//if old != nam { println!("{} -> {}", old, nam); }
let end = *self.index() as u64;
let src = Src::new(fid, ini, end);
return Ok(Term::Src { src, val: Box::new(Term::Var { nam }) });
}
// Parses a name that can be aliased (via the 'uses' map)
//pub fn parse_nick(&mut self, uses: &Uses) -> Result<String, String> {
//let nam = self.parse_name()?;
//Ok(uses.get(&nam).cloned().unwrap_or(nam))
//}
}