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:
parent
f877bcf20b
commit
05be758881
20
a.hlm
20
a.hlm
|
@ -1,15 +1,5 @@
|
|||
let name: str = "john";
|
||||
println("Hello, " + name + "!");
|
||||
|
||||
let a: num = 17, b: num = 35 in
|
||||
let c: num = a * 2 in
|
||||
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));
|
||||
println({
|
||||
println("Hello");
|
||||
return let x: num = 17 * 2 in
|
||||
x + 1;
|
||||
} + 34);
|
|
@ -49,6 +49,6 @@ fn main() {
|
|||
.into_iter()
|
||||
.map(|e| e.map(|c| c.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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ pub enum Token {
|
|||
Open(Delim), Close(Delim),
|
||||
Lambda, Arrow,
|
||||
|
||||
Let, In, Func,
|
||||
Let, In, Func, Return,
|
||||
}
|
||||
|
||||
impl Display for Token {
|
||||
|
@ -66,6 +66,7 @@ impl Display for Token {
|
|||
Token::Let => write!(f, "let"),
|
||||
Token::In => write!(f, "in"),
|
||||
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,
|
||||
"in" => Token::In,
|
||||
"func" => Token::Func,
|
||||
"return" => Token::Return,
|
||||
_ => Token::Sym(s),
|
||||
});
|
||||
|
||||
|
@ -298,12 +300,30 @@ pub fn expr_parser() -> impl P<Spanned<PExpr>> {
|
|||
.boxed()
|
||||
.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
|
||||
.or(sym)
|
||||
.or(vec)
|
||||
.or(paren_expr)
|
||||
.or(lam)
|
||||
.or(let_in)
|
||||
.or(block)
|
||||
.or(ret)
|
||||
.map_with_span(|e, s| (e, s))
|
||||
.boxed()
|
||||
.labelled("atom");
|
||||
|
|
|
@ -18,7 +18,6 @@ pub enum PBinaryOp {
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum PLiteral { Num(i64), Str(String), Bool(bool) }
|
||||
|
||||
/// Enum to represent a parsed expression
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PExpr {
|
||||
Error,
|
||||
|
@ -39,4 +38,17 @@ pub enum PExpr {
|
|||
vars: Vec<(String, Type, 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>>,
|
||||
},
|
||||
}
|
|
@ -32,8 +32,9 @@ pub enum Expr {
|
|||
Call(Box<Self>, Vec<Self>),
|
||||
Lambda {
|
||||
args: Vec<(String, Type)>,
|
||||
body: Box<Self>,
|
||||
body: Vec<Self>,
|
||||
},
|
||||
Return(Box<Self>),
|
||||
}
|
||||
|
||||
impl Display for Expr {
|
||||
|
@ -69,8 +70,17 @@ impl Display for Expr {
|
|||
for (name, ty) in args {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,8 +17,9 @@ pub enum JSExpr {
|
|||
Method(Box<Self>, String, Vec<Self>),
|
||||
Lambda {
|
||||
args: Vec<(String, Type)>,
|
||||
body: Box<Self>,
|
||||
body: Vec<Self>,
|
||||
},
|
||||
Return(Box<Self>),
|
||||
}
|
||||
|
||||
impl Display for JSExpr {
|
||||
|
@ -74,8 +75,18 @@ impl Display for JSExpr {
|
|||
}
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ pub fn translate_expr(expr: PExpr) -> Expr {
|
|||
),
|
||||
PExpr::Lambda { args, body } => Expr::Lambda {
|
||||
args,
|
||||
body: Box::new(translate_expr((*body).0)),
|
||||
body: vec![translate_expr((*body).0)],
|
||||
},
|
||||
PExpr::Let { vars, body } => {
|
||||
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
|
||||
expr = Expr::Lambda {
|
||||
args: vec![(name, ty)],
|
||||
body: Box::new(expr),
|
||||
body: vec![expr],
|
||||
};
|
||||
// Call the lambda with the value
|
||||
let val = translate_expr(val.0);
|
||||
expr = Expr::Call(Box::new(expr), vec![val]);
|
||||
}
|
||||
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 {
|
||||
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))),
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue