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

positional argument in piping

This commit is contained in:
Natapat Samutpong 2022-03-13 12:03:07 +07:00
parent 29ad3b32e8
commit 74a3422271
6 changed files with 67 additions and 25 deletions

View file

@ -9,10 +9,10 @@ const INTRINSICS: [&str; 5] = [
"time", "time",
]; ];
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Value { Int(i64), Boolean(bool), String(String), Ident(String) } pub enum Value { Int(i64), Boolean(bool), String(String), Ident(String) }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum IRKind { pub enum IRKind {
Define { name: String, type_hint: String, value: Box<Self> }, Define { name: String, type_hint: String, value: Box<Self> },
Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box<Self> }, Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box<Self> },
@ -110,28 +110,63 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
match &rhs.0 { match &rhs.0 {
call @ Expr::Call { name, args } call @ Expr::Call { name, args }
| call @ Expr::Intrinsic { name, args } => { | call @ Expr::Intrinsic { name, args } => {
let name = match &name.0 { let cname = match &name.0 {
Expr::Identifier(s) => s.clone(), Expr::Identifier(s) => s.clone(),
// Should never happen because the parser should have caught this // Should never happen because the parser should have caught this
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string(), note: None })) _ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string(), note: None }))
}; };
let call = expr_to_ir(&call); // Remove all `Hole`(s) from the args
if_err_return!(call.1); let index = args.0.iter().position(|arg| match arg.0 {
Expr::Hole => true,
_ => false
});
let mut largs = Vec::new(); if let None = index {
for arg in &args.0 { return (None, Some(LoweringError {
let arg = expr_to_ir(&arg.0); span: rhs.1.clone(),
if_err_return!(arg.1); message: "Expected hole in piping".to_string(),
largs.push(arg.0.unwrap()); note: None
}));
} }
let mut args = vec![lhs_ir.0.unwrap()]; let mut new_args = args.0.clone();
args.append(&mut largs); new_args.remove(index.unwrap());
let ir_kind = match call.0.unwrap() { // Make a new call expression with the new args
IRKind::Call { .. } => IRKind::Call { name, args }, let new_call = match call {
IRKind::Intrinsic { .. } => IRKind::Intrinsic { name, args }, Expr::Call { name, args } => Expr::Call{
name: name.clone(),
args: (new_args, args.1.clone())
},
Expr::Intrinsic { name, args } => Expr::Intrinsic {
name: name.clone(),
args: (new_args, args.1.clone())
},
_ => unreachable!()
};
let new_call = expr_to_ir(&new_call);
if_err_return!(new_call.1);
// Lower all args
let mut largs = Vec::new();
for arg in &args.0 {
match arg.0 {
Expr::Hole => {
largs.push(lhs_ir.0.clone().unwrap());
},
_ => {
let arg = expr_to_ir(&arg.0);
if_err_return!(arg.1);
largs.push(arg.0.unwrap());
}
}
}
// Match the call to the right IRKind
let ir_kind = match new_call.0.unwrap() {
IRKind::Call { .. } => IRKind::Call { name: cname, args: largs },
IRKind::Intrinsic { .. } => IRKind::Intrinsic { name: cname, args: largs },
_ => unreachable!() _ => unreachable!()
}; };
@ -235,6 +270,7 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
Expr::Boolean(value) => (Some(IRKind::Value { value: Value::Boolean(*value) }), None), Expr::Boolean(value) => (Some(IRKind::Value { value: Value::Boolean(*value) }), None),
Expr::String(value) => (Some(IRKind::Value { value: Value::String(value.clone()) }), None), Expr::String(value) => (Some(IRKind::Value { value: Value::String(value.clone()) }), None),
Expr::Identifier(value) => (Some(IRKind::Value { value: Value::Ident(value.clone()) }), None), Expr::Identifier(value) => (Some(IRKind::Value { value: Value::Ident(value.clone()) }), None),
Expr::Hole => (None, None),
_ => { dbg!(expr); todo!() } _ => { dbg!(expr); todo!() }
} }
} }

View file

@ -23,6 +23,7 @@ pub enum Token {
Colon, SemiColon, Colon, SemiColon,
OpenParen, CloseParen, OpenParen, CloseParen,
At, At,
Hole,
} }
impl std::fmt::Display for Token { impl std::fmt::Display for Token {
@ -61,6 +62,7 @@ impl std::fmt::Display for Token {
Token::OpenParen => write!(f, "("), Token::OpenParen => write!(f, "("),
Token::CloseParen => write!(f, ")"), Token::CloseParen => write!(f, ")"),
Token::At => write!(f, "@"), Token::At => write!(f, "@"),
Token::Hole => write!(f, "_"),
} }
} }
} }
@ -98,6 +100,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
just('(').to(Token::OpenParen), just('(').to(Token::OpenParen),
just(')').to(Token::CloseParen), just(')').to(Token::CloseParen),
just('@').to(Token::At), just('@').to(Token::At),
just('_').to(Token::Hole),
)); ));
let keyword = text::ident().map(|s: String| match s.as_str() { let keyword = text::ident().map(|s: String| match s.as_str() {

View file

@ -35,6 +35,8 @@ pub enum Expr {
Do { Do {
body: Vec<Spanned<Self>> body: Vec<Spanned<Self>>
}, },
Hole,
} }
fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>> + Clone { fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>> + Clone {
@ -47,6 +49,7 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
Token::Int(i) => Ok((Expr::Int(i), span)), Token::Int(i) => Ok((Expr::Int(i), span)),
Token::Boolean(b) => Ok((Expr::Boolean(b), span)), Token::Boolean(b) => Ok((Expr::Boolean(b), span)),
Token::String(s) => Ok((Expr::String(s), span)), Token::String(s) => Ok((Expr::String(s), span)),
Token::Hole => Ok((Expr::Hole, span)),
_ => Err(Simple::expected_input_found(span, Vec::new(), Some(token))), _ => Err(Simple::expected_input_found(span, Vec::new(), Some(token))),
}).labelled("literal"); }).labelled("literal");

View file

@ -2,13 +2,13 @@ fun foo (xs: int): int = return xs + 1;
fun bar (xs: int) (x: int): int = return xs - x; fun bar (xs: int) (x: int): int = return xs - x;
fun main: int = do fun main: int = do
foo(69) foo(69) -- 69 + 1 => 70
|> bar(1) |> bar(_, 1) -- '70 - 1 => 69
|> @write(); |> @write(_); -- '69 => stdout
@write("\n"); @write("\n");
68 foo(60) -- 60 + 1 => 61
|> foo() |> bar(130, _) -- 130 - '61 => 69
|> @write(); |> @write(_); -- '69 => stdout
end; end;

View file

@ -1,4 +1,4 @@
fun main: int = do fun main: int = do
@read_file("./example/quine.hz") -- Run this from root folder @read_file("./example/quine.hz") -- Run this from root folder
|> @write(); |> @write(_);
end; end;

View file

@ -1,4 +1,4 @@
fun main: int = do fun main: int = do
@time() @time()
|> @write(); |> @write(_);
end; end;