1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

if expression

This commit is contained in:
azur 2023-03-05 22:39:45 +07:00
parent 39b2f10bb5
commit 7ac147de32
6 changed files with 60 additions and 9 deletions

9
a.hlm
View file

@ -1,7 +1,4 @@
let x: num = 34, let x: num = 1,
y: num = 35 y: num = 2,
in in
println(x + y); println(if x + y == 3 then 69 else 0);
let foo: num = 69;
println(foo);

View file

@ -34,6 +34,11 @@ pub enum Expr {
args: Vec<String>, args: Vec<String>,
body: Vec<Self>, body: Vec<Self>,
}, },
If {
cond: Box<Self>,
t: Box<Self>,
f: Box<Self>,
},
Defines(Vec<(String, Self)>), Defines(Vec<(String, Self)>),
Return(Box<Self>), Return(Box<Self>),
} }
@ -93,6 +98,9 @@ impl Display for Expr {
write!(f, "))") write!(f, "))")
} }
}, },
Expr::If { cond, t, f: fe } => {
write!(f, "(if {} {} {})", cond, t, fe)
},
Expr::Defines(defs) => { Expr::Defines(defs) => {
write!(f, "(defs ")?; write!(f, "(defs ")?;
for (name, expr) in defs { for (name, expr) in defs {

View file

@ -19,6 +19,11 @@ pub enum JSExpr {
args: Vec<String>, args: Vec<String>,
body: Vec<Self>, body: Vec<Self>,
}, },
If {
cond: Box<Self>,
t: Box<Self>,
f: Box<Self>,
},
Defines(Vec<(String, Self)>), Defines(Vec<(String, Self)>),
Return(Box<Self>), Return(Box<Self>),
} }
@ -99,6 +104,9 @@ impl Display for JSExpr {
write!(f, "}})") write!(f, "}})")
} }
}, },
JSExpr::If { cond, t, f: fe } => {
write!(f, "({} ? {} : {})", cond, t, fe)
},
JSExpr::Defines(vs) => { JSExpr::Defines(vs) => {
write!(f, "let [")?; write!(f, "let [")?;
for (i, (name, _)) in vs.iter().enumerate() { for (i, (name, _)) in vs.iter().enumerate() {

View file

@ -38,6 +38,11 @@ pub enum PExpr {
vars: Vec<(String, Type, Spanned<Self>)>, vars: Vec<(String, Type, Spanned<Self>)>,
body: Option<Box<Spanned<Self>>>, body: Option<Box<Spanned<Self>>>,
}, },
If {
cond: Box<Spanned<Self>>,
t: Box<Spanned<Self>>,
f: Box<Spanned<Self>>,
},
Block(Vec<Spanned<Self>>), Block(Vec<Spanned<Self>>),
Return(Box<Spanned<Self>>), Return(Box<Spanned<Self>>),
} }

View file

@ -20,7 +20,7 @@ pub enum Token {
Open(Delim), Close(Delim), Open(Delim), Close(Delim),
Lambda, Arrow, Lambda, Arrow,
Let, In, Func, Return, Let, In, Func, Return, If, Then, Else,
} }
impl Display for Token { impl Display for Token {
@ -67,6 +67,9 @@ impl Display for Token {
Token::In => write!(f, "in"), Token::In => write!(f, "in"),
Token::Func => write!(f, "func"), Token::Func => write!(f, "func"),
Token::Return => write!(f, "return"), Token::Return => write!(f, "return"),
Token::If => write!(f, "if"),
Token::Then => write!(f, "then"),
Token::Else => write!(f, "else"),
} }
} }
} }
@ -126,6 +129,9 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
"in" => Token::In, "in" => Token::In,
"func" => Token::Func, "func" => Token::Func,
"return" => Token::Return, "return" => Token::Return,
"if" => Token::If,
"then" => Token::Then,
"else" => Token::Else,
_ => Token::Sym(s), _ => Token::Sym(s),
}); });
@ -285,6 +291,8 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.then_ignore(just(Token::Assign)) .then_ignore(just(Token::Assign))
.then(expr.clone()) .then(expr.clone())
.map(|((sym, ty), body)| (sym, ty, body)) .map(|((sym, ty), body)| (sym, ty, body))
.boxed()
.labelled("let binding")
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
.labelled("let bindings"); .labelled("let bindings");
@ -322,6 +330,20 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.map(PExpr::Return) .map(PExpr::Return)
.labelled("return"); .labelled("return");
let ifelse = just(Token::If)
.ignore_then(expr.clone())
.then_ignore(just(Token::Then))
.then(expr.clone())
.then_ignore(just(Token::Else))
.then(expr.clone())
.map(|((cond, then), f)| PExpr::If {
cond: Box::new(cond),
t: Box::new(then),
f: Box::new(f),
})
.boxed()
.labelled("if else");
let atom = lit let atom = lit
.or(sym) .or(sym)
.or(vec) .or(vec)
@ -331,6 +353,7 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.or(let_def) .or(let_def)
.or(block) .or(block)
.or(ret) .or(ret)
.or(ifelse)
.map_with_span(|e, s| (e, s)) .map_with_span(|e, s| (e, s))
.boxed() .boxed()
.labelled("atom"); .labelled("atom");

View file

@ -93,6 +93,11 @@ pub fn translate_expr(expr: PExpr) -> Expr {
}).collect()) }).collect())
} }
}, },
PExpr::If { cond, t, f } => Expr::If {
cond: Box::new(translate_expr((*cond).0)),
t: Box::new(translate_expr((*t).0)),
f: Box::new(translate_expr((*f).0)),
},
PExpr::Block(es) => { PExpr::Block(es) => {
exprs_to_lam(es.into_iter().map(|e| e.0).collect()) exprs_to_lam(es.into_iter().map(|e| e.0).collect())
}, },
@ -172,6 +177,11 @@ pub fn translate_js_expr(expr: Expr) -> JSExpr {
args, args,
body: body.into_iter().map(translate_js_expr).collect(), body: body.into_iter().map(translate_js_expr).collect(),
}, },
Expr::If { cond, t, f } => JSExpr::If {
cond: Box::new(translate_js_expr(*cond)),
t: Box::new(translate_js_expr(*t)),
f: Box::new(translate_js_expr(*f)),
},
Expr::Defines(defs) => JSExpr::Defines(defs.into_iter().map(|(name, val)| { Expr::Defines(defs) => JSExpr::Defines(defs.into_iter().map(|(name, val)| {
(name, translate_js_expr(val)) (name, translate_js_expr(val))
}).collect()), }).collect()),