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:
parent
29ad3b32e8
commit
74a3422271
|
@ -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!() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, "_"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +77,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
.then_ignore(just('"'))
|
.then_ignore(just('"'))
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
.map(Token::String);
|
.map(Token::String);
|
||||||
|
|
||||||
let symbol = choice((
|
let symbol = choice((
|
||||||
just('+').to(Token::Plus),
|
just('+').to(Token::Plus),
|
||||||
just('-').to(Token::Minus),
|
just('-').to(Token::Minus),
|
||||||
|
@ -89,7 +91,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
|
|
||||||
just('<').to(Token::Less),
|
just('<').to(Token::Less),
|
||||||
just('>').to(Token::Greater),
|
just('>').to(Token::Greater),
|
||||||
|
|
||||||
just('=').to(Token::Assign),
|
just('=').to(Token::Assign),
|
||||||
just('.').to(Token::Dot),
|
just('.').to(Token::Dot),
|
||||||
just(',').to(Token::Comma),
|
just(',').to(Token::Comma),
|
||||||
|
@ -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() {
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -1,4 +1,4 @@
|
||||||
fun main: int = do
|
fun main: int = do
|
||||||
@time()
|
@time()
|
||||||
|> @write();
|
|> @write(_);
|
||||||
end;
|
end;
|
Loading…
Reference in a new issue