block + return expressions

pull/5/head
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("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);

View File

@ -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));
}
}

View File

@ -20,7 +20,7 @@ pub enum Token {
Open(Delim), Close(Delim),
Lambda, Arrow,
Let, In, Func,
Let, In, Func, Return,
}
impl Display for Token {
@ -63,9 +63,10 @@ impl Display for Token {
Token::Lambda => write!(f, "\\"),
Token::Arrow => write!(f, "->"),
Token::Let => write!(f, "let"),
Token::In => write!(f, "in"),
Token::Func => write!(f, "func"),
Token::Let => write!(f, "let"),
Token::In => write!(f, "in"),
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()
.map(|s: String| match s.as_str() {
"true" => Token::Bool(true),
"false" => Token::Bool(false),
"let" => Token::Let,
"in" => Token::In,
"func" => Token::Func,
_ => Token::Sym(s),
"true" => Token::Bool(true),
"false" => Token::Bool(false),
"let" => Token::Let,
"in" => Token::In,
"func" => Token::Func,
"return" => Token::Return,
_ => Token::Sym(s),
});
let token = num
@ -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");

View File

@ -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>>,
},
}

View File

@ -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),
}
}
}

View File

@ -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),
}
}
}

View File

@ -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))),
}
}