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({
|
||||||
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));
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
@ -63,9 +63,10 @@ impl Display for Token {
|
||||||
Token::Lambda => write!(f, "\\"),
|
Token::Lambda => write!(f, "\\"),
|
||||||
Token::Arrow => write!(f, "->"),
|
Token::Arrow => write!(f, "->"),
|
||||||
|
|
||||||
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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,12 +120,13 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
|
|
||||||
let kw = text::ident()
|
let kw = text::ident()
|
||||||
.map(|s: String| match s.as_str() {
|
.map(|s: String| match s.as_str() {
|
||||||
"true" => Token::Bool(true),
|
"true" => Token::Bool(true),
|
||||||
"false" => Token::Bool(false),
|
"false" => Token::Bool(false),
|
||||||
"let" => Token::Let,
|
"let" => Token::Let,
|
||||||
"in" => Token::In,
|
"in" => Token::In,
|
||||||
"func" => Token::Func,
|
"func" => Token::Func,
|
||||||
_ => Token::Sym(s),
|
"return" => Token::Return,
|
||||||
|
_ => Token::Sym(s),
|
||||||
});
|
});
|
||||||
|
|
||||||
let token = num
|
let token = num
|
||||||
|
@ -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");
|
||||||
|
|
|
@ -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>>,
|
||||||
|
},
|
||||||
}
|
}
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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))),
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue