diff --git a/a.hlm b/a.hlm index abdc8fd..744948e 100644 --- a/a.hlm +++ b/a.hlm @@ -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); \ No newline at end of file + println(if x + y == 3 then 69 else 0); \ No newline at end of file diff --git a/src/asts/ast.rs b/src/asts/ast.rs index d58b46f..aed7bbb 100644 --- a/src/asts/ast.rs +++ b/src/asts/ast.rs @@ -34,6 +34,11 @@ pub enum Expr { args: Vec, body: Vec, }, + If { + cond: Box, + t: Box, + f: Box, + }, Defines(Vec<(String, Self)>), Return(Box), } @@ -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 { }, } } -} \ No newline at end of file +} diff --git a/src/asts/js.rs b/src/asts/js.rs index 49b6385..1ef385e 100644 --- a/src/asts/js.rs +++ b/src/asts/js.rs @@ -19,6 +19,11 @@ pub enum JSExpr { args: Vec, body: Vec, }, + If { + cond: Box, + t: Box, + f: Box, + }, Defines(Vec<(String, Self)>), Return(Box), } @@ -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() { diff --git a/src/asts/past.rs b/src/asts/past.rs index 6b01db1..93cbd54 100644 --- a/src/asts/past.rs +++ b/src/asts/past.rs @@ -38,6 +38,11 @@ pub enum PExpr { vars: Vec<(String, Type, Spanned)>, body: Option>>, }, + If { + cond: Box>, + t: Box>, + f: Box>, + }, Block(Vec>), Return(Box>), } @@ -51,4 +56,4 @@ pub enum PStmt { ret: Type, body: Box>, }, -} \ No newline at end of file +} diff --git a/src/read/parse.rs b/src/read/parse.rs index 60942d9..6a47f2c 100644 --- a/src/read/parse.rs +++ b/src/read/parse.rs @@ -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, Error = Simple> { "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> { .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> { .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> { .or(let_def) .or(block) .or(ret) + .or(ifelse) .map_with_span(|e, s| (e, s)) .boxed() .labelled("atom"); diff --git a/src/trans/low.rs b/src/trans/low.rs index 8e0b1f2..ca02aab 100644 --- a/src/trans/low.rs +++ b/src/trans/low.rs @@ -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()),