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

Compare commits

...

2 commits

Author SHA1 Message Date
Natapat Samutpong 8ca4abe394 public variable & function 2022-03-20 20:40:51 +07:00
Natapat Samutpong 4e6acf7038 cleanup 2022-03-20 20:25:31 +07:00
7 changed files with 64 additions and 32 deletions

View file

@ -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,
@ -147,4 +149,4 @@ impl Codegen {
_ => { dbg!(ir); todo!() }, _ => { dbg!(ir); todo!() },
} }
} }
} }

View file

@ -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())))
@ -148,4 +147,4 @@ impl Diagnostics {
} }
}); });
} }
} }

View file

@ -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 {
errors.push(err); (Some(ir), None) => {
} else { irs.push(IR { kind: ir, span: expr.1 });
irs.push(IR::new(ir_kind.0.unwrap(), expr.1)); },
(None, Some(err)) => {
errors.push(err);
},
_ => 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);
}, },
@ -351,4 +369,4 @@ fn closet_intrinsic(got: String) -> String {
} }
} }
closest closest
} }

View file

@ -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),
}); });
@ -181,4 +184,4 @@ mod tests {
])); ]));
assert_eq!(err, vec![]); assert_eq!(err, vec![]);
} }
} }

View file

@ -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()),
@ -372,4 +378,4 @@ mod tests {
assert_eq!(err, vec![]); assert_eq!(err, vec![]);
} }
} }

4
example/export.hz Normal file
View file

@ -0,0 +1,4 @@
pub fun print_something: void = @emit("console.log('something')");
fun main: void = do
end;

View file

@ -7,4 +7,4 @@ end;
fun main: void = do fun main: void = do
factorial(5) |> @write(_); factorial(5) |> @write(_);
end; end;