if expression

pull/5/head
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,
y: num = 35
let x: num = 1,
y: num = 2,
in
println(x + y);
let foo: num = 69;
println(foo);
println(if x + y == 3 then 69 else 0);

View File

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

View File

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

View File

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

View File

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

View File

@ -93,6 +93,11 @@ pub fn translate_expr(expr: PExpr) -> Expr {
}).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) => {
exprs_to_lam(es.into_iter().map(|e| e.0).collect())
},
@ -172,6 +177,11 @@ pub fn translate_js_expr(expr: Expr) -> JSExpr {
args,
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)| {
(name, translate_js_expr(val))
}).collect()),