mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
let
This commit is contained in:
parent
fa7e2e6986
commit
2e1258f09a
12
b.hlm
12
b.hlm
|
@ -1,4 +1,12 @@
|
||||||
println((\x: num -> x + 35)(34));
|
println((\x: num -> x + 35)(34));
|
||||||
16---1*3/-f(16)+8%-2;
|
16---1*3/-16+8%-2;
|
||||||
|
|
||||||
a(b, c(d(e, f), g(h), i), j(k, l), m);
|
let a: num = 1 in
|
||||||
|
println(a);
|
||||||
|
|
||||||
|
let b: num = 1;
|
||||||
|
let x: num = 34, y: num = 35;
|
||||||
|
|
||||||
|
let c: num = 5 in
|
||||||
|
let d: num = 10, e: num = 2 in
|
||||||
|
println(c * d + b - 2);
|
|
@ -39,7 +39,8 @@ fn main() {
|
||||||
let jsexprs = nexprs.into_iter().map(translate_js).collect::<Vec<_>>();
|
let jsexprs = nexprs.into_iter().map(translate_js).collect::<Vec<_>>();
|
||||||
|
|
||||||
for expr in &jsexprs {
|
for expr in &jsexprs {
|
||||||
println!("{}", expr);
|
let s = format!("{}", expr);
|
||||||
|
println!("{}{}", s, if s.ends_with(';') { "" } else { ";" });
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub enum Token {
|
||||||
Open(Delim), Close(Delim),
|
Open(Delim), Close(Delim),
|
||||||
Lambda, Arrow,
|
Lambda, Arrow,
|
||||||
|
|
||||||
Let, Func,
|
Let, In, Func,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Token {
|
impl Display for Token {
|
||||||
|
@ -64,6 +64,7 @@ impl Display for Token {
|
||||||
Token::Arrow => write!(f, "->"),
|
Token::Arrow => write!(f, "->"),
|
||||||
|
|
||||||
Token::Let => write!(f, "let"),
|
Token::Let => write!(f, "let"),
|
||||||
|
Token::In => write!(f, "in"),
|
||||||
Token::Func => write!(f, "func"),
|
Token::Func => write!(f, "func"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,6 +122,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
"true" => Token::Bool(true),
|
"true" => Token::Bool(true),
|
||||||
"false" => Token::Bool(false),
|
"false" => Token::Bool(false),
|
||||||
"let" => Token::Let,
|
"let" => Token::Let,
|
||||||
|
"in" => Token::In,
|
||||||
"func" => Token::Func,
|
"func" => Token::Func,
|
||||||
_ => Token::Sym(s),
|
_ => Token::Sym(s),
|
||||||
});
|
});
|
||||||
|
@ -275,11 +277,42 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
|
||||||
})
|
})
|
||||||
.labelled("lambda");
|
.labelled("lambda");
|
||||||
|
|
||||||
|
let let_binds = symbol_parser()
|
||||||
|
.then_ignore(just(Token::Colon))
|
||||||
|
.then(type_parser())
|
||||||
|
.then_ignore(just(Token::Assign))
|
||||||
|
.then(expr.clone())
|
||||||
|
.map(|((sym, ty), body)| (sym, ty, body))
|
||||||
|
.separated_by(just(Token::Comma))
|
||||||
|
.allow_trailing()
|
||||||
|
.labelled("let bindings");
|
||||||
|
|
||||||
|
let let_in = just(Token::Let)
|
||||||
|
.ignore_then(let_binds.clone())
|
||||||
|
.then_ignore(just(Token::In))
|
||||||
|
.then(expr.clone())
|
||||||
|
.map(|(vars, body)| PExpr::Let {
|
||||||
|
vars,
|
||||||
|
body: Some(Box::new(body)),
|
||||||
|
})
|
||||||
|
.boxed()
|
||||||
|
.labelled("let..in");
|
||||||
|
|
||||||
|
let let_def = just(Token::Let)
|
||||||
|
.ignore_then(let_binds)
|
||||||
|
.map(|vars| PExpr::Let {
|
||||||
|
vars,
|
||||||
|
body: None,
|
||||||
|
})
|
||||||
|
.labelled("let");
|
||||||
|
|
||||||
let atom = lit
|
let atom = lit
|
||||||
.or(sym)
|
.or(sym)
|
||||||
.or(vec)
|
.or(vec)
|
||||||
.or(paren_expr)
|
.or(paren_expr)
|
||||||
.or(lam)
|
.or(lam)
|
||||||
|
.or(let_in)
|
||||||
|
.or(let_def)
|
||||||
.map_with_span(|e, s| (e, s))
|
.map_with_span(|e, s| (e, s))
|
||||||
.boxed()
|
.boxed()
|
||||||
.labelled("atom");
|
.labelled("atom");
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub enum PExpr {
|
||||||
body: Box<Spanned<Self>>,
|
body: Box<Spanned<Self>>,
|
||||||
},
|
},
|
||||||
Let {
|
Let {
|
||||||
vars: Vec<(String, Type, Self)>,
|
vars: Vec<(String, Type, Spanned<Self>)>,
|
||||||
body: Box<Self>,
|
body: Option<Box<Spanned<Self>>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
|
@ -34,6 +34,7 @@ pub enum Expr {
|
||||||
args: Vec<(String, Type)>,
|
args: Vec<(String, Type)>,
|
||||||
body: Box<Self>,
|
body: Box<Self>,
|
||||||
},
|
},
|
||||||
|
Define(Vec<(String, Box<Self>)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Expr {
|
impl Display for Expr {
|
||||||
|
@ -71,6 +72,11 @@ impl Display for Expr {
|
||||||
}
|
}
|
||||||
write!(f, " {})", body)
|
write!(f, " {})", body)
|
||||||
},
|
},
|
||||||
|
Expr::Define(vars) => {
|
||||||
|
vars.iter().try_for_each(|(name, val)| {
|
||||||
|
write!(f, "(define {} {})", name, val)
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,6 +19,7 @@ pub enum JSExpr {
|
||||||
args: Vec<(String, Type)>,
|
args: Vec<(String, Type)>,
|
||||||
body: Box<Self>,
|
body: Box<Self>,
|
||||||
},
|
},
|
||||||
|
Let(Vec<(String, Box<Self>)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for JSExpr {
|
impl Display for JSExpr {
|
||||||
|
@ -76,6 +77,11 @@ impl Display for JSExpr {
|
||||||
}
|
}
|
||||||
write!(f, ") => {})", body)
|
write!(f, ") => {})", body)
|
||||||
},
|
},
|
||||||
|
JSExpr::Let(vars) => {
|
||||||
|
vars.iter().try_for_each(|(name, expr)| {
|
||||||
|
write!(f, "let {} = {};", name, expr)
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -52,21 +52,34 @@ pub fn translate_expr(expr: PExpr) -> Expr {
|
||||||
body: Box::new(translate_expr((*body).0)),
|
body: Box::new(translate_expr((*body).0)),
|
||||||
},
|
},
|
||||||
PExpr::Let { vars, body } => {
|
PExpr::Let { vars, body } => {
|
||||||
let mut expr: Expr = translate_expr(*body); // The expression we're building up
|
if let Some(body) = body {
|
||||||
for (name, ty, val) in vars.into_iter().rev() { // Reverse so we can build up the lambda
|
let mut expr: Expr = translate_expr(body.0); // The expression we're building up
|
||||||
// e.g.: let x : t = e1 in e2 end => (lambda (x : t) = e2)(e1)
|
for (name, ty, val) in vars.into_iter().rev() { // Reverse so we can build up the lambda
|
||||||
|
// e.g.: let x : t = e1 in e2; => (lambda (x : t) = e2)(e1)
|
||||||
|
|
||||||
// Build up the lambda
|
// Build up the lambda
|
||||||
expr = Expr::Lambda {
|
expr = Expr::Lambda {
|
||||||
args: vec![(name, ty)],
|
args: vec![(name, ty)],
|
||||||
body: Box::new(expr),
|
body: Box::new(expr),
|
||||||
};
|
};
|
||||||
// Call the lambda with the value
|
// Call the lambda with the value
|
||||||
let val = translate_expr(val);
|
let val = translate_expr(val.0);
|
||||||
expr = Expr::Call(Box::new(expr), vec![val]);
|
expr = Expr::Call(Box::new(expr), vec![val]);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr
|
||||||
|
} else {
|
||||||
|
// e.g. let a : t = 1; => (define a 1)
|
||||||
|
// let a : t = 2, b : t = 3; => (define a 2) (define b 3)
|
||||||
|
let mut xs: Vec<(String, Box<Expr>)> = vec![];
|
||||||
|
|
||||||
|
for (name, _, val) in vars {
|
||||||
|
let val = translate_expr(val.0);
|
||||||
|
xs.push((name, Box::new(val)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr::Define(xs)
|
||||||
}
|
}
|
||||||
|
|
||||||
expr
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,5 +143,13 @@ pub fn translate_js(expr: Expr) -> JSExpr {
|
||||||
args,
|
args,
|
||||||
body: Box::new(translate_js(*body)),
|
body: Box::new(translate_js(*body)),
|
||||||
},
|
},
|
||||||
|
Expr::Define(xs) => {
|
||||||
|
let ns = xs
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, val)| (name, Box::new(translate_js(*val))))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
JSExpr::Let(ns)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue