mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
intrinsic
This commit is contained in:
parent
1079d53f05
commit
0ee36feecb
|
@ -36,12 +36,15 @@ impl Codegen {
|
|||
format!("{} {} = {};\n", type_hint, name, self.gen_ir(value))
|
||||
},
|
||||
IRKind::Call { name, args } => {
|
||||
format!("{}({});\n", name, args.iter().map(|arg| self.gen_ir(arg)).collect::<Vec<_>>().join(", "))
|
||||
},
|
||||
IRKind::Intrinsic { name, args } => {
|
||||
match name.as_str() {
|
||||
"write" => { format!("std::cout << {};\n", self.gen_ir(&args[0])) },
|
||||
"read" => { format!("std::cin >> {};\n", self.gen_ir(&args[0])) },
|
||||
_ => format!("{}({});\n", name, args.iter().map(|arg| self.gen_ir(arg)).collect::<Vec<_>>().join(", ")),
|
||||
_ => unreachable!(format!("Unknown intrinsic: {}", name)) // Shoul be handled by lowering
|
||||
}
|
||||
},
|
||||
}
|
||||
IRKind::Fun { name, return_type_hint, args, body } => {
|
||||
let args = args.iter().map(|arg| format!("{} {}", arg.1, arg.0)).collect::<Vec<_>>().join(", ");
|
||||
format!("{} {}({}) {{\n{}}}\n", return_type_hint, name, args, self.gen_ir(body))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::ops::Range;
|
||||
use parser::Expr;
|
||||
|
||||
const INTRINSICS: [&str; 2] = ["write", "read"];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Value { Int(i64), Boolean(bool), String(String), Ident(String) }
|
||||
|
||||
|
@ -9,6 +11,7 @@ pub enum IRKind {
|
|||
Define { name: String, type_hint: String, value: Box<Self> },
|
||||
Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box<Self> },
|
||||
Call { name: String, args: Vec<Self> },
|
||||
Intrinsic { name: String, args: Vec<Self> },
|
||||
Do { body: Vec<Self> },
|
||||
If { cond: Box<Self>, body: Box<Self>, else_body: Box<Self> },
|
||||
Value { value: Value },
|
||||
|
@ -63,7 +66,12 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
|||
},
|
||||
Expr::Call { name, args } => {
|
||||
let name = match &name.0 {
|
||||
Expr::Identifier(s) => s.clone(),
|
||||
Expr::Identifier(s) => {
|
||||
if INTRINSICS.contains(&s.as_str()) { s.clone() }
|
||||
else {
|
||||
return (None, Some(LoweringError { span: name.1.clone(), message: format!("Unknown intrinsic: {}", s) }));
|
||||
}
|
||||
}
|
||||
// Should never happen because the parser should have caught this
|
||||
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
||||
};
|
||||
|
@ -82,6 +90,20 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
|||
let ir_kind = IRKind::Call { name, args: largs };
|
||||
return (Some(ir_kind), None);
|
||||
},
|
||||
Expr::Intrinsic { name, args } => {
|
||||
let name = match &name.0 {
|
||||
Expr::Identifier(s) => s.clone(),
|
||||
_ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string() }))
|
||||
};
|
||||
let mut largs = Vec::new();
|
||||
for arg in &args.0 {
|
||||
let arg = expr_to_ir(&arg.0);
|
||||
if let Some(err) = arg.1 { return (None, Some(err)); }
|
||||
else { largs.push(arg.0.unwrap()); }
|
||||
}
|
||||
let ir_kind = IRKind::Intrinsic { name, args: largs };
|
||||
return (Some(ir_kind), None);
|
||||
},
|
||||
Expr::Fun { name, type_hint, args, body } => {
|
||||
// Iterate each argument and give it a type hint
|
||||
let args = args.0.iter().map(|arg| (arg.0.0.clone(), gen_type_hint(&arg.1.0))).collect::<Vec<_>>();
|
||||
|
|
|
@ -15,12 +15,13 @@ pub enum Token {
|
|||
// Operators
|
||||
Plus, Minus, Multiply, Divide,
|
||||
Not, Equal, NotEqual, Less, Greater,
|
||||
|
||||
|
||||
// Symbols & Delimiters
|
||||
Assign,
|
||||
Dot, Comma,
|
||||
Colon, SemiColon,
|
||||
OpenParen, CloseParen,
|
||||
At,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Token {
|
||||
|
@ -49,7 +50,7 @@ impl std::fmt::Display for Token {
|
|||
Token::NotEqual => write!(f, "!="),
|
||||
Token::Less => write!(f, "<"),
|
||||
Token::Greater => write!(f, ">"),
|
||||
|
||||
|
||||
Token::Assign => write!(f, "="),
|
||||
Token::Dot => write!(f, "."),
|
||||
Token::Comma => write!(f, ","),
|
||||
|
@ -57,6 +58,7 @@ impl std::fmt::Display for Token {
|
|||
Token::SemiColon => write!(f, ";"),
|
||||
Token::OpenParen => write!(f, "("),
|
||||
Token::CloseParen => write!(f, ")"),
|
||||
Token::At => write!(f, "@"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +90,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
|||
just(';').to(Token::SemiColon),
|
||||
just('(').to(Token::OpenParen),
|
||||
just(')').to(Token::CloseParen),
|
||||
just('@').to(Token::At),
|
||||
));
|
||||
|
||||
let keyword = text::ident().map(|s: String| match s.as_str() {
|
||||
|
|
|
@ -11,6 +11,7 @@ pub enum Expr {
|
|||
Unary { op: String, rhs: Box<Spanned<Self>> },
|
||||
Binary { lhs: Box<Spanned<Self>>, op: String, rhs: Box<Spanned<Self>> },
|
||||
Call { name: Box<Spanned<Self>>, args: Spanned<Vec<Spanned<Self>>> },
|
||||
Intrinsic { name: Box<Spanned<Self>>, args: Spanned<Vec<Spanned<Self>>> },
|
||||
|
||||
Let {
|
||||
name: String,
|
||||
|
@ -60,7 +61,7 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
|||
// .delimited_by(just(Token::OpenParen), just(Token::CloseParen)))
|
||||
.labelled("atom");
|
||||
|
||||
let call = atom
|
||||
let call = atom.clone()
|
||||
.then(
|
||||
args.clone()
|
||||
.delimited_by(
|
||||
|
@ -79,11 +80,31 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
|||
)
|
||||
});
|
||||
|
||||
let intrinsic = just(Token::At)
|
||||
.ignore_then(atom)
|
||||
.then(
|
||||
args.clone()
|
||||
.delimited_by(
|
||||
just(Token::OpenParen),
|
||||
just(Token::CloseParen),
|
||||
)
|
||||
.repeated()
|
||||
)
|
||||
.foldl(|name, args| {
|
||||
(
|
||||
Expr::Intrinsic {
|
||||
name: Box::new(name.clone()),
|
||||
args: (args, name.1.clone()),
|
||||
},
|
||||
name.1,
|
||||
)
|
||||
});
|
||||
|
||||
let unary = choice((
|
||||
just(Token::Plus),
|
||||
just(Token::Minus)))
|
||||
.repeated()
|
||||
.then(call)
|
||||
.then(call.or(intrinsic))
|
||||
.foldr(|op, rhs| {
|
||||
(
|
||||
Expr::Unary {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
fun main: int = do
|
||||
write("Hello, World!\n");
|
||||
@write("Hello, World!\n");
|
||||
return 0;
|
||||
end;
|
Loading…
Reference in a new issue