mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
No commits in common. "ebaee0ea0c38be241e5a1007edbeaa7dab88ead9" and "04e35046b2bd8f0c343469df34145d29f4cc555e" have entirely different histories.
ebaee0ea0c
...
04e35046b2
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -151,7 +151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "hazure"
|
||||
name = "hc"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Hazure
|
||||
# Hades
|
||||
Programming language that compiles to C++!
|
||||
|
||||
```sml
|
||||
|
|
|
@ -58,10 +58,7 @@ impl Codegen {
|
|||
out.push_str(&self.gen_ir(&expr));
|
||||
}
|
||||
out
|
||||
},
|
||||
IRKind::If { cond, body, else_body } => {
|
||||
format!("if ({}) {{\n{}}} else {{\n{}}}\n", self.gen_ir(cond), self.gen_ir(body), self.gen_ir(else_body))
|
||||
},
|
||||
}
|
||||
|
||||
IRKind::Value { value } => {
|
||||
match value {
|
||||
|
|
|
@ -51,24 +51,19 @@ pub fn ast_to_ir(ast: Vec<(Expr, Range<usize>)>) -> (Vec<IR>, Vec<LoweringError>
|
|||
(irs, errors)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! if_err_return {
|
||||
($value:expr) => {
|
||||
if let Some(err) = $value { return (None, Some(err)); };
|
||||
};
|
||||
}
|
||||
|
||||
pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||
match expr {
|
||||
Expr::Let { name, type_hint, value } => {
|
||||
let value = expr_to_ir(&value.0);
|
||||
if_err_return!(value.1);
|
||||
|
||||
let value = value.0.unwrap();
|
||||
let ir_kind = IRKind::Define { name: name.clone(), type_hint: type_hint.clone(), value: Box::new(value) };
|
||||
return (Some(ir_kind), None);
|
||||
if let Some(err) = value.1 {
|
||||
// Return error
|
||||
return (None, Some(err));
|
||||
} else {
|
||||
let value = value.0.unwrap(); // Unwrapping because it should always be Some
|
||||
let ir_kind = IRKind::Define { name: name.clone(), type_hint: type_hint.clone(), value: Box::new(value) };
|
||||
return (Some(ir_kind), None);
|
||||
}
|
||||
},
|
||||
|
||||
Expr::Call { name, args } => {
|
||||
let name = match &name.0 {
|
||||
Expr::Identifier(s) => {
|
||||
|
@ -85,13 +80,16 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
|||
for arg in &args.0 {
|
||||
// Lower each argument, if there is an error then return early
|
||||
let arg = expr_to_ir(&arg.0);
|
||||
if_err_return!(arg.1);
|
||||
largs.push(arg.0.unwrap());
|
||||
if let Some(err) = arg.1 {
|
||||
return (None, Some(err));
|
||||
} else {
|
||||
// Else push the lowered argument
|
||||
largs.push(arg.0.unwrap());
|
||||
}
|
||||
}
|
||||
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(),
|
||||
|
@ -100,64 +98,48 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
|||
let mut largs = Vec::new();
|
||||
for arg in &args.0 {
|
||||
let arg = expr_to_ir(&arg.0);
|
||||
if_err_return!(arg.1);
|
||||
|
||||
largs.push(arg.0.unwrap());
|
||||
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<_>>();
|
||||
|
||||
let body = expr_to_ir(&body.0);
|
||||
if_err_return!(body.1);
|
||||
|
||||
let body = body.0.unwrap();
|
||||
let ir_kind = IRKind::Fun { name: name.clone(), return_type_hint: gen_type_hint(type_hint), args, body: Box::new(body) };
|
||||
return (Some(ir_kind), None);
|
||||
if let Some(err) = body.1 {
|
||||
return (None, Some(err));
|
||||
} else {
|
||||
let body = body.0.unwrap();
|
||||
let ir_kind = IRKind::Fun { name: name.clone(), return_type_hint: gen_type_hint(type_hint), args, body: Box::new(body) };
|
||||
return (Some(ir_kind), None);
|
||||
}
|
||||
},
|
||||
|
||||
Expr::Return { expr } => {
|
||||
let expr = expr_to_ir(&expr.0);
|
||||
if_err_return!(expr.1);
|
||||
|
||||
let expr = expr.0.unwrap();
|
||||
let ir_kind = IRKind::Return { value: Box::new(expr) };
|
||||
return (Some(ir_kind), None);
|
||||
if let Some(err) = expr.1 {
|
||||
return (None, Some(err));
|
||||
} else {
|
||||
let expr = expr.0.unwrap();
|
||||
let ir_kind = IRKind::Return { value: Box::new(expr) };
|
||||
return (Some(ir_kind), None);
|
||||
}
|
||||
},
|
||||
|
||||
Expr::Do { body } => {
|
||||
let mut lbody = Vec::new();
|
||||
for expr in body {
|
||||
let expr = expr_to_ir(&expr.0);
|
||||
if_err_return!(expr.1);
|
||||
lbody.push(expr.0.unwrap());
|
||||
if let Some(err) = expr.1 {
|
||||
return (None, Some(err));
|
||||
} else {
|
||||
lbody.push(expr.0.unwrap());
|
||||
}
|
||||
}
|
||||
let ir_kind = IRKind::Do { body: lbody };
|
||||
return (Some(ir_kind), None);
|
||||
},
|
||||
|
||||
Expr::If { cond, body, else_body } => {
|
||||
let cond = expr_to_ir(&cond.0);
|
||||
if_err_return!(cond.1);
|
||||
|
||||
let body = expr_to_ir(&body.0);
|
||||
if_err_return!(body.1);
|
||||
|
||||
let else_body = expr_to_ir(&else_body.0);
|
||||
if_err_return!(else_body.1);
|
||||
|
||||
let ir_kind = IRKind::If {
|
||||
cond: Box::new(cond.0.unwrap()),
|
||||
body: Box::new(body.0.unwrap()),
|
||||
else_body: Box::new(else_body.0.unwrap())
|
||||
};
|
||||
return (Some(ir_kind), None);
|
||||
},
|
||||
|
||||
// TODO: Handle primitive types error (e.g. overflow)
|
||||
// For now it just leaves the value as is and let the target compiler handle it
|
||||
Expr::Int(value) => (Some(IRKind::Value { value: Value::Int(*value) }), None),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "hazure"
|
||||
name = "hc"
|
||||
license = "MIT OR Apache-2.0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
|
|
@ -17,7 +17,7 @@ pub mod util;
|
|||
use crate::util::log;
|
||||
|
||||
fn main() {
|
||||
let config_file = fs::read_to_string("./hazure.toml");
|
||||
let config_file = fs::read_to_string("./hades.toml");
|
||||
let config: config::Config;
|
||||
match config_file {
|
||||
Ok(content) => {
|
||||
|
|
|
@ -28,8 +28,8 @@ pub enum Expr {
|
|||
|
||||
If {
|
||||
cond: Box<Spanned<Self>>,
|
||||
body: Box<Spanned<Self>>,
|
||||
else_body: Box<Spanned<Self>>
|
||||
then: Box<Spanned<Self>>,
|
||||
else_: Box<Spanned<Self>>
|
||||
},
|
||||
Do {
|
||||
body: Vec<Spanned<Self>>
|
||||
|
@ -243,35 +243,10 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
|||
)
|
||||
});
|
||||
|
||||
let if_block = just(Token::KwIf)
|
||||
.ignore_then(expr.clone())
|
||||
.then_ignore(just(Token::KwThen))
|
||||
.then(
|
||||
do_block.clone()
|
||||
.or(expr.clone())
|
||||
)
|
||||
.then_ignore(just(Token::KwElse))
|
||||
.then(
|
||||
do_block.clone()
|
||||
.or(expr.clone())
|
||||
)
|
||||
.then_ignore(just(Token::KwEnd))
|
||||
.map(|((cond, then), else_)| {
|
||||
(
|
||||
Expr::If {
|
||||
cond: Box::new(cond.clone()),
|
||||
body: Box::new(then),
|
||||
else_body: Box::new(else_.clone()),
|
||||
},
|
||||
cond.1.start..else_.1.end,
|
||||
)
|
||||
});
|
||||
|
||||
let_
|
||||
.or(fun)
|
||||
.or(return_)
|
||||
.or(do_block)
|
||||
.or(if_block)
|
||||
.or(compare)
|
||||
}).labelled("expression");
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
fun main: int = do
|
||||
if true then
|
||||
@write("True")
|
||||
else
|
||||
@write("False")
|
||||
end;
|
||||
end;
|
Loading…
Reference in a new issue