Compare commits

...

1 Commits
main ... letin

@ -1,15 +1,6 @@
(*
*)
ast = term ast = term
| "\", {ident, [":", tagged type], ","}, ident, [":", tagged type], ".", ast ; | "\", {ident, [":", tagged type], ","}, ident, [":", tagged type], ".", ast
| "let", {ident, [":", tagged type], ":=", ast, ","}, ident, [":", tagged type], ":=", ast, [","], "in", ast ;
term = ident term = ident
| constant | constant

@ -30,6 +30,7 @@ impl Ast {
DeBrujinAst::Abstraction(var, t, Box::new(ast.into_de_brujin_inter(gamma))) DeBrujinAst::Abstraction(var, t, Box::new(ast.into_de_brujin_inter(gamma)))
} }
Ast::LetIn(_var, _t, _bind, _ast) => todo!(),
Ast::Application(lhs, rhs) => DeBrujinAst::Application( Ast::Application(lhs, rhs) => DeBrujinAst::Application(
Box::new(lhs.into_de_brujin_inter(gamma.clone())), Box::new(lhs.into_de_brujin_inter(gamma.clone())),
Box::new(rhs.into_de_brujin_inter(gamma)), Box::new(rhs.into_de_brujin_inter(gamma)),

@ -41,6 +41,7 @@ pub enum Constant {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Ast { pub enum Ast {
Abstraction(Ident, Option<TaggedType>, Box<Ast>), // \0:1.2 Abstraction(Ident, Option<TaggedType>, Box<Ast>), // \0:1.2
LetIn(Ident, Option<TaggedType>, Box<Ast>, Box<Ast>), // let 0:1 := 2 in 3
Application(Box<Ast>, Box<Ast>), // 0 1 Application(Box<Ast>, Box<Ast>), // 0 1
Variable(Ident), // x Variable(Ident), // x
Constant(Constant), // true | false | n Constant(Constant), // true | false | n
@ -86,6 +87,12 @@ impl Display for Ast {
match self { match self {
Ast::Abstraction(var, Some(typ), ast) => write!(f, "(\\{var}:{typ}.{ast})"), Ast::Abstraction(var, Some(typ), ast) => write!(f, "(\\{var}:{typ}.{ast})"),
Ast::Abstraction(var, None, ast) => write!(f, "(\\{var}.{ast})"), Ast::Abstraction(var, None, ast) => write!(f, "(\\{var}.{ast})"),
Ast::LetIn(var, Some(typ), bind, ast) => {
write!(f, "(let {var}: {typ} := {bind} in {ast})")
}
Ast::LetIn(var, None, bind, ast) => {
write!(f, "(let {var} := {bind} in {ast})")
}
Ast::Application(lhs, rhs) => write!(f, "{lhs} {rhs}"), Ast::Application(lhs, rhs) => write!(f, "{lhs} {rhs}"),
Ast::Variable(v) => write!(f, "{v}"), Ast::Variable(v) => write!(f, "{v}"),
Ast::Constant(constant) => write!(f, "{constant}"), Ast::Constant(constant) => write!(f, "{constant}"),

@ -194,6 +194,91 @@ fn parse_abstraction() {
); );
} }
#[test]
fn parse_let_in() {
let parser = parser::AstParser::new();
let ast = parser.parse(Lexer::new(r"let x:Nat := 5 in x")).unwrap();
assert_eq!(
ast,
Ast::LetIn(
"x".to_string(),
Some(Type::Primitive(PrimitiveType::Nat).into()),
Box::new(Ast::Constant(Constant::Nat(5))),
Box::new(Ast::Variable("x".to_string()))
)
);
let ast = parser
.parse(Lexer::new(
r#"
let
x:Nat := 5,
y:Any a => a -> a := \x.x,
in
y x
"#,
))
.unwrap();
assert_eq!(
ast,
Ast::LetIn(
"x".to_string(),
Some(Type::Primitive(PrimitiveType::Nat).into()),
Box::new(Ast::Constant(Constant::Nat(5))),
Box::new(Ast::LetIn(
"y".to_string(),
Some(TaggedType::Tagged(
TypeTag::Any,
"a".to_string(),
Box::new(TaggedType::Concrete(Type::arrow("a", "a")))
)),
Box::new(Ast::Abstraction(
"x".to_string(),
None,
Box::new(Ast::Variable("x".to_string()))
)),
Box::new(Ast::Application(
Box::new(Ast::Variable("y".to_string())),
Box::new(Ast::Variable("x".to_string()))
))
))
)
);
let ast = parser
.parse(Lexer::new(
r#"
let
x := 5,
y := \x.x,
in
y x
"#,
))
.unwrap();
assert_eq!(
ast,
Ast::LetIn(
"x".to_string(),
None,
Box::new(Ast::Constant(Constant::Nat(5))),
Box::new(Ast::LetIn(
"y".to_string(),
None,
Box::new(Ast::Abstraction(
"x".to_string(),
None,
Box::new(Ast::Variable("x".to_string()))
)),
Box::new(Ast::Application(
Box::new(Ast::Variable("y".to_string())),
Box::new(Ast::Variable("x".to_string()))
))
))
)
);
}
#[test] #[test]
fn parse_application() { fn parse_application() {
let parser = parser::AstParser::new(); let parser = parser::AstParser::new();

@ -41,6 +41,11 @@ pub enum Token {
#[regex(r#"[_a-zA-Z][_a-zA-Z0-9]*'*"#, |lex| lex.slice().to_string())] #[regex(r#"[_a-zA-Z][_a-zA-Z0-9]*'*"#, |lex| lex.slice().to_string())]
Ident(String), Ident(String),
#[token("let")]
Let,
#[token("in")]
In,
#[token(r"\")] #[token(r"\")]
Lambda, Lambda,
#[token("=>")] #[token("=>")]
@ -53,6 +58,8 @@ pub enum Token {
Period, Period,
#[token(",")] #[token(",")]
Comma, Comma,
#[token(":=")]
Becomes,
#[token("=")] #[token("=")]
Equals, Equals,
@ -139,6 +146,9 @@ impl Display for Token {
Token::Float(n) => write!(f, "{n}"), Token::Float(n) => write!(f, "{n}"),
Token::Bool(b) => write!(f, "{b}"), Token::Bool(b) => write!(f, "{b}"),
Token::Ident(i) => write!(f, "{i}"), Token::Ident(i) => write!(f, "{i}"),
Token::Let => write!(f, "let"),
Token::In => write!(f, "in"),
Token::Becomes => write!(f, ":="),
} }
} }
} }

@ -17,12 +17,16 @@ extern {
Ident => lexer::Token::Ident(<String>), Ident => lexer::Token::Ident(<String>),
"let" => lexer::Token::Let,
"in" => lexer::Token::In,
r"\" => lexer::Token::Lambda, r"\" => lexer::Token::Lambda,
"=>" => lexer::Token::FatArrow, "=>" => lexer::Token::FatArrow,
"->" => lexer::Token::ThinArrow, "->" => lexer::Token::ThinArrow,
":" => lexer::Token::Colon, ":" => lexer::Token::Colon,
"." => lexer::Token::Period, "." => lexer::Token::Period,
"," => lexer::Token::Comma, "," => lexer::Token::Comma,
":=" => lexer::Token::Becomes,
"=" => lexer::Token::Equals, "=" => lexer::Token::Equals,
"<>" => lexer::Token::NotEquals, "<>" => lexer::Token::NotEquals,
@ -44,19 +48,31 @@ extern {
} }
Multi<T>: Vec<T> = { // (1) Multi<T>: Vec<T> = {
<mut v:(<T> ",")*> <e:T> => { <mut v:(<T> ",")*> <e:T> => {
v.push(e); v.push(e);
v v
} }
}; };
MultiTr<T>: Vec<T> = {
<mut v:(<T> ",")*> <e:T> ","? => {
v.push(e);
v
}
};
pub Ast: Ast = { pub Ast: Ast = {
Term => <>, Term => <>,
r"\" <args:Multi<IdentAndType>> "." <ast:Ast> => args.into_iter().rev().fold(ast, |ast, (i, t)| Ast::Abstraction(i, t, Box::new(ast))), r"\" <args:Multi<IdentAndType>> "." <ast:Ast> =>
args.into_iter().rev().fold(ast, |ast, (i, t)| Ast::Abstraction(i, t, Box::new(ast))),
"let" <binds:MultiTr<LetBind>> "in" <ast:Ast> =>
binds.into_iter().rev().fold(ast, |ast, (i, t, b)| Ast::LetIn(i, t, Box::new(b), Box::new(ast))),
}; };
pub IdentAndType: (String, Option<TaggedType>) = <x:Ident> <t:(":" <TaggedType>)?> => (<>); IdentAndType: (String, Option<TaggedType>) = <x:Ident> <t:(":" <TaggedType>)?> => (<>);
LetBind: (String, Option<TaggedType>, Ast) = <x:Ident> <t:(":" <TaggedType>)?> ":=" <a:Ast> => (<>);
Term: Ast = { Term: Ast = {

Loading…
Cancel
Save