mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
2 commits
cf3dccca2c
...
8ca4abe394
Author | SHA1 | Date | |
---|---|---|---|
Natapat Samutpong | 8ca4abe394 | ||
Natapat Samutpong | 4e6acf7038 |
|
@ -31,9 +31,10 @@ impl Codegen {
|
||||||
macro_rules! semicolon { () => { if should_gen_semicolon { ";" } else { "" } }; }
|
macro_rules! semicolon { () => { if should_gen_semicolon { ";" } else { "" } }; }
|
||||||
|
|
||||||
match ir {
|
match ir {
|
||||||
IRKind::Define { name, type_hint, value, mutable } => {
|
IRKind::Define { public, name, type_hint, value, mutable } => {
|
||||||
format!(
|
format!(
|
||||||
"{} v_{}: {} = {}{}\n",
|
"{} {} v_{}: {} = {}{}\n",
|
||||||
|
if *public { "export" } else { "" },
|
||||||
if *mutable { "let" } else { "const" },
|
if *mutable { "let" } else { "const" },
|
||||||
name,
|
name,
|
||||||
type_hint,
|
type_hint,
|
||||||
|
@ -67,14 +68,15 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
IRKind::Fun { name, return_type_hint, args, body } => {
|
IRKind::Fun { public, name, return_type_hint, args, body } => {
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| format!("v_{}: {}", arg.0, arg.1))
|
.map(|arg| format!("v_{}: {}", arg.0, arg.1))
|
||||||
.collect::<Vec<_>>().
|
.collect::<Vec<_>>().
|
||||||
join(", ");
|
join(", ");
|
||||||
format!(
|
format!(
|
||||||
"const f_{} = ({}): {} => {};\n",
|
"{} const f_{} = ({}): {} => {};\n",
|
||||||
|
if *public { "export" } else { "" },
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
return_type_hint,
|
return_type_hint,
|
||||||
|
|
|
@ -47,7 +47,6 @@ impl Diagnostics {
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Lowering error
|
|
||||||
lex_error.into_iter()
|
lex_error.into_iter()
|
||||||
.map(|e| e.map(|e| e.to_string()))
|
.map(|e| e.map(|e| e.to_string()))
|
||||||
.chain(parse_error.into_iter().map(|e| e.map(|tok| tok.to_string())))
|
.chain(parse_error.into_iter().map(|e| e.map(|tok| tok.to_string())))
|
||||||
|
|
|
@ -14,8 +14,21 @@ pub enum Value { Int(i64), Boolean(bool), String(String), Ident(String) }
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum IRKind {
|
pub enum IRKind {
|
||||||
Define { name: String, type_hint: String, value: Box<Self>, mutable: bool },
|
Define {
|
||||||
Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box<Self> },
|
public: bool,
|
||||||
|
name: String,
|
||||||
|
type_hint: String,
|
||||||
|
value: Box<Self>,
|
||||||
|
mutable: bool
|
||||||
|
},
|
||||||
|
Fun {
|
||||||
|
public: bool,
|
||||||
|
name: String,
|
||||||
|
return_type_hint: String,
|
||||||
|
args: Vec<(String, String)>,
|
||||||
|
body: Box<Self>
|
||||||
|
},
|
||||||
|
|
||||||
Call { name: String, args: Vec<Self> },
|
Call { name: String, args: Vec<Self> },
|
||||||
Intrinsic { name: String, args: Vec<Self> },
|
Intrinsic { name: String, args: Vec<Self> },
|
||||||
Do { body: Vec<Self> },
|
Do { body: Vec<Self> },
|
||||||
|
@ -40,21 +53,19 @@ pub struct LoweringError {
|
||||||
pub note: Option<String>,
|
pub note: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IR {
|
|
||||||
pub fn new(kind: IRKind, span: Range<usize>) -> Self {
|
|
||||||
Self { kind, span }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ast_to_ir(ast: Vec<(Expr, Range<usize>)>) -> (Vec<IR>, Vec<LoweringError>) {
|
pub fn ast_to_ir(ast: Vec<(Expr, Range<usize>)>) -> (Vec<IR>, Vec<LoweringError>) {
|
||||||
let mut irs = Vec::new();
|
let mut irs = Vec::new();
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
for expr in ast {
|
for expr in ast {
|
||||||
let ir_kind = expr_to_ir(&expr.0);
|
let ir_kind = expr_to_ir(&expr.0);
|
||||||
if let Some(err) = ir_kind.1 {
|
match ir_kind {
|
||||||
|
(Some(ir), None) => {
|
||||||
|
irs.push(IR { kind: ir, span: expr.1 });
|
||||||
|
},
|
||||||
|
(None, Some(err)) => {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
} else {
|
},
|
||||||
irs.push(IR::new(ir_kind.0.unwrap(), expr.1));
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(irs, errors)
|
(irs, errors)
|
||||||
|
@ -188,12 +199,13 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Let { name, type_hint, value, mutable } => {
|
Expr::Let { public, name, type_hint, value, mutable } => {
|
||||||
let value = expr_to_ir(&value.0);
|
let value = expr_to_ir(&value.0);
|
||||||
if_err_return!(value.1);
|
if_err_return!(value.1);
|
||||||
|
|
||||||
let value = value.0.unwrap();
|
let value = value.0.unwrap();
|
||||||
let ir_kind = IRKind::Define {
|
let ir_kind = IRKind::Define {
|
||||||
|
public: *public,
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
type_hint: gen_type_hint(type_hint),
|
type_hint: gen_type_hint(type_hint),
|
||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
|
@ -235,7 +247,7 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||||
return (Some(ir_kind), None);
|
return (Some(ir_kind), None);
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Fun { name, type_hint, args, body } => {
|
Expr::Fun { public, name, type_hint, args, body } => {
|
||||||
// Iterate each argument and give it a type hint
|
// 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 args = args.0.iter().map(|arg| (arg.0.0.clone(), gen_type_hint(&arg.1.0))).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -243,7 +255,13 @@ pub fn expr_to_ir(expr: &Expr) -> (Option<IRKind>, Option<LoweringError>) {
|
||||||
if_err_return!(body.1);
|
if_err_return!(body.1);
|
||||||
|
|
||||||
let body = body.0.unwrap();
|
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) };
|
let ir_kind = IRKind::Fun {
|
||||||
|
public: *public,
|
||||||
|
name: name.clone(),
|
||||||
|
return_type_hint: gen_type_hint(type_hint),
|
||||||
|
args,
|
||||||
|
body: Box::new(body)
|
||||||
|
};
|
||||||
return (Some(ir_kind), None);
|
return (Some(ir_kind), None);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub enum Token {
|
||||||
KwIf, KwThen, KwElse,
|
KwIf, KwThen, KwElse,
|
||||||
KwCase, KwOf,
|
KwCase, KwOf,
|
||||||
KwReturn,
|
KwReturn,
|
||||||
|
KwPub,
|
||||||
|
|
||||||
// Literals
|
// Literals
|
||||||
Int(i64), Boolean(bool),
|
Int(i64), Boolean(bool),
|
||||||
|
@ -42,6 +43,7 @@ impl std::fmt::Display for Token {
|
||||||
Token::KwCase => write!(f, "case"),
|
Token::KwCase => write!(f, "case"),
|
||||||
Token::KwOf => write!(f, "of"),
|
Token::KwOf => write!(f, "of"),
|
||||||
Token::KwReturn => write!(f, "return"),
|
Token::KwReturn => write!(f, "return"),
|
||||||
|
Token::KwPub => write!(f, "pub"),
|
||||||
|
|
||||||
Token::Int(i) => write!(f, "{}", i),
|
Token::Int(i) => write!(f, "{}", i),
|
||||||
Token::Boolean(b) => write!(f, "{}", b),
|
Token::Boolean(b) => write!(f, "{}", b),
|
||||||
|
@ -130,6 +132,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
"case" => Token::KwCase,
|
"case" => Token::KwCase,
|
||||||
"of" => Token::KwOf,
|
"of" => Token::KwOf,
|
||||||
"return" => Token::KwReturn,
|
"return" => Token::KwReturn,
|
||||||
|
"pub" => Token::KwPub,
|
||||||
_ => Token::Identifier(s),
|
_ => Token::Identifier(s),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,14 @@ pub enum Expr {
|
||||||
Intrinsic { name: Box<Spanned<Self>>, args: Spanned<Vec<Spanned<Self>>> },
|
Intrinsic { name: Box<Spanned<Self>>, args: Spanned<Vec<Spanned<Self>>> },
|
||||||
|
|
||||||
Let {
|
Let {
|
||||||
|
public: bool,
|
||||||
name: String,
|
name: String,
|
||||||
type_hint: String,
|
type_hint: String,
|
||||||
value: Box<Spanned<Self>>,
|
value: Box<Spanned<Self>>,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
},
|
},
|
||||||
Fun {
|
Fun {
|
||||||
|
public: bool,
|
||||||
name: String,
|
name: String,
|
||||||
type_hint: String,
|
type_hint: String,
|
||||||
args: Spanned<Vec<(Spanned<String>, Spanned<String>)>>,
|
args: Spanned<Vec<(Spanned<String>, Spanned<String>)>>,
|
||||||
|
@ -198,16 +200,18 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let let_ = just(Token::KwLet)
|
let let_ = just(Token::KwPub).or_not()
|
||||||
.ignore_then(just(Token::KwMut).or_not())
|
.then_ignore(just(Token::KwLet))
|
||||||
|
.then(just(Token::KwMut).or_not())
|
||||||
.then(identifier)
|
.then(identifier)
|
||||||
.then_ignore(just(Token::Colon))
|
.then_ignore(just(Token::Colon))
|
||||||
.then(identifier)
|
.then(identifier)
|
||||||
.then_ignore(just(Token::Assign))
|
.then_ignore(just(Token::Assign))
|
||||||
.then(expr.clone())
|
.then(expr.clone())
|
||||||
.map(|(((mutable, name), type_hint), value)| {
|
.map(|((((public, mutable), name), type_hint), value)| {
|
||||||
(
|
(
|
||||||
Expr::Let {
|
Expr::Let {
|
||||||
|
public: public.is_some(),
|
||||||
name: name.0.clone(),
|
name: name.0.clone(),
|
||||||
type_hint: type_hint.0,
|
type_hint: type_hint.0,
|
||||||
value: Box::new(value.clone()),
|
value: Box::new(value.clone()),
|
||||||
|
@ -217,8 +221,9 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let fun = just(Token::KwFun)
|
let fun = just(Token::KwPub).or_not()
|
||||||
.ignore_then(identifier)
|
.then_ignore(just(Token::KwFun))
|
||||||
|
.then(identifier)
|
||||||
.then(
|
.then(
|
||||||
identifier
|
identifier
|
||||||
.then_ignore(just(Token::Colon))
|
.then_ignore(just(Token::Colon))
|
||||||
|
@ -233,9 +238,10 @@ fn expr_parser() -> impl Parser<Token, Vec<Spanned<Expr>>, Error = Simple<Token>
|
||||||
.then(identifier)
|
.then(identifier)
|
||||||
.then_ignore(just(Token::Assign))
|
.then_ignore(just(Token::Assign))
|
||||||
.then(expr.clone())
|
.then(expr.clone())
|
||||||
.map(|(((name, args), type_hint), body)| {
|
.map(|((((public, name), args), type_hint), body)| {
|
||||||
(
|
(
|
||||||
Expr::Fun {
|
Expr::Fun {
|
||||||
|
public: public.is_some(),
|
||||||
name: name.0.clone(),
|
name: name.0.clone(),
|
||||||
type_hint: type_hint.0,
|
type_hint: type_hint.0,
|
||||||
args: (args, name.1.clone()),
|
args: (args, name.1.clone()),
|
||||||
|
|
4
example/export.hz
Normal file
4
example/export.hz
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub fun print_something: void = @emit("console.log('something')");
|
||||||
|
|
||||||
|
fun main: void = do
|
||||||
|
end;
|
Loading…
Reference in a new issue