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

block + return expressions

This commit is contained in:
azur 2023-03-03 03:31:52 +07:00
parent f877bcf20b
commit 05be758881
7 changed files with 87 additions and 35 deletions

20
a.hlm
View file

@ -1,15 +1,5 @@
let name: str = "john"; println({
println("Hello, " + name + "!"); println("Hello");
return let x: num = 17 * 2 in
let a: num = 17, b: num = 35 in x + 1;
let c: num = a * 2 in } + 34);
println(b + c);
// func foo (a: int, b: int) {
// let c = a * 2;
//
// let res = b + c in
// return res + a;
// }
println((\x: int -> x + 1)(1));

View file

@ -49,6 +49,6 @@ fn main() {
.into_iter() .into_iter()
.map(|e| e.map(|c| c.to_string())) .map(|e| e.map(|c| c.to_string()))
.chain(parse_errs.into_iter().map(|e| e.map(|t| t.to_string()))) .chain(parse_errs.into_iter().map(|e| e.map(|t| t.to_string())))
.for_each(|e| println!("{}", e)); .for_each(|e| println!("[{:?} {:?}] {}", e.span(), e.label(), e));
} }
} }

View file

@ -20,7 +20,7 @@ pub enum Token {
Open(Delim), Close(Delim), Open(Delim), Close(Delim),
Lambda, Arrow, Lambda, Arrow,
Let, In, Func, Let, In, Func, Return,
} }
impl Display for Token { impl Display for Token {
@ -66,6 +66,7 @@ impl Display for Token {
Token::Let => write!(f, "let"), Token::Let => write!(f, "let"),
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"),
} }
} }
} }
@ -124,6 +125,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
"let" => Token::Let, "let" => Token::Let,
"in" => Token::In, "in" => Token::In,
"func" => Token::Func, "func" => Token::Func,
"return" => Token::Return,
_ => Token::Sym(s), _ => Token::Sym(s),
}); });
@ -298,12 +300,30 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
.boxed() .boxed()
.labelled("let..in"); .labelled("let..in");
let block = nested_parser(
expr.clone()
.separated_by(just(Token::Semicolon))
.allow_trailing(),
Delim::Brace,
|_| Vec::new(),
)
.map(PExpr::Block)
.labelled("block");
let ret = just(Token::Return)
.ignore_then(expr.clone())
.map(Box::new)
.map(PExpr::Return)
.labelled("return");
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_in)
.or(block)
.or(ret)
.map_with_span(|e, s| (e, s)) .map_with_span(|e, s| (e, s))
.boxed() .boxed()
.labelled("atom"); .labelled("atom");

View file

@ -18,7 +18,6 @@ pub enum PBinaryOp {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PLiteral { Num(i64), Str(String), Bool(bool) } pub enum PLiteral { Num(i64), Str(String), Bool(bool) }
/// Enum to represent a parsed expression
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum PExpr { pub enum PExpr {
Error, Error,
@ -39,4 +38,17 @@ pub enum PExpr {
vars: Vec<(String, Type, Spanned<Self>)>, vars: Vec<(String, Type, Spanned<Self>)>,
body: Box<Spanned<Self>>, body: Box<Spanned<Self>>,
}, },
Block(Vec<Spanned<Self>>),
Return(Box<Spanned<Self>>),
}
#[derive(Clone, Debug)]
pub enum PStmt {
Expr(Spanned<PExpr>),
Let(Vec<(String, Type, Spanned<PExpr>)>),
Func {
name: String,
args: Vec<(String, Type)>,
body: Box<Spanned<PExpr>>,
},
} }

View file

@ -32,8 +32,9 @@ pub enum Expr {
Call(Box<Self>, Vec<Self>), Call(Box<Self>, Vec<Self>),
Lambda { Lambda {
args: Vec<(String, Type)>, args: Vec<(String, Type)>,
body: Box<Self>, body: Vec<Self>,
}, },
Return(Box<Self>),
} }
impl Display for Expr { impl Display for Expr {
@ -69,8 +70,17 @@ impl Display for Expr {
for (name, ty) in args { for (name, ty) in args {
write!(f, "[{} {}]", name, ty)?; write!(f, "[{} {}]", name, ty)?;
} }
write!(f, " {})", body) if body.len() == 1 {
write!(f, " {})", body[0])
} else {
write!(f, " (do")?;
for e in body {
write!(f, " {}", e)?;
}
write!(f, "))")
}
}, },
Expr::Return(e) => write!(f, "(return {})", e),
} }
} }
} }

View file

@ -17,8 +17,9 @@ pub enum JSExpr {
Method(Box<Self>, String, Vec<Self>), Method(Box<Self>, String, Vec<Self>),
Lambda { Lambda {
args: Vec<(String, Type)>, args: Vec<(String, Type)>,
body: Box<Self>, body: Vec<Self>,
}, },
Return(Box<Self>),
} }
impl Display for JSExpr { impl Display for JSExpr {
@ -74,8 +75,18 @@ impl Display for JSExpr {
} }
write!(f, "{}", name)?; write!(f, "{}", name)?;
} }
write!(f, ") => {})", body) // write!(f, ") => {})", body)
if body.len() == 1 {
write!(f, ") => {})", body[0])
} else {
write!(f, ") => {{")?;
for e in body {
write!(f, "{};", e)?;
}
write!(f, "}})")
}
}, },
JSExpr::Return(e) => write!(f, "return {}", e),
} }
} }
} }

View file

@ -49,7 +49,7 @@ pub fn translate_expr(expr: PExpr) -> Expr {
), ),
PExpr::Lambda { args, body } => Expr::Lambda { PExpr::Lambda { args, body } => Expr::Lambda {
args, args,
body: Box::new(translate_expr((*body).0)), body: vec![translate_expr((*body).0)],
}, },
PExpr::Let { vars, body } => { PExpr::Let { vars, body } => {
let mut expr: Expr = translate_expr(body.0); // The expression we're building up let mut expr: Expr = translate_expr(body.0); // The expression we're building up
@ -58,14 +58,22 @@ pub fn translate_expr(expr: PExpr) -> Expr {
// 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: vec![expr],
}; };
// Call the lambda with the value // Call the lambda with the value
let val = translate_expr(val.0); let val = translate_expr(val.0);
expr = Expr::Call(Box::new(expr), vec![val]); expr = Expr::Call(Box::new(expr), vec![val]);
} }
expr expr
} },
PExpr::Block(es) => {
let lam = Expr::Lambda {
args: vec![],
body: es.into_iter().map(|e| translate_expr(e.0)).collect(),
};
Expr::Call(Box::new(lam), vec![])
},
PExpr::Return(e) => Expr::Return(Box::new(translate_expr((*e).0))),
} }
} }
@ -126,7 +134,8 @@ pub fn translate_js(expr: Expr) -> JSExpr {
} }
Expr::Lambda { args, body } => JSExpr::Lambda { Expr::Lambda { args, body } => JSExpr::Lambda {
args, args,
body: Box::new(translate_js(*body)), body: body.into_iter().map(translate_js).collect(),
}, },
Expr::Return(e) => JSExpr::Return(Box::new(translate_js(*e))),
} }
} }