mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
some c backend
This commit is contained in:
parent
0e992d9324
commit
0e3cd664af
|
@ -1,12 +1,9 @@
|
||||||
let foo = if 1 == 1 then
|
let foo = 1;
|
||||||
5
|
let bar = true;
|
||||||
|
let baz = "qux";
|
||||||
|
|
||||||
|
if (bar == true) then
|
||||||
|
print(baz);
|
||||||
else
|
else
|
||||||
10
|
print("quux");
|
||||||
end;
|
end;
|
||||||
|
|
||||||
do
|
|
||||||
print(1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
fun bar a b = a + b;
|
|
||||||
let baz = bar(34 35);
|
|
76
src/back/c.rs
Normal file
76
src/back/c.rs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
use crate::front::parse::Expr;
|
||||||
|
|
||||||
|
pub struct Codegen {
|
||||||
|
pub emitted: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Codegen {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
emitted: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit(&mut self, s: String) {
|
||||||
|
self.emitted.push_str(s.as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gen(&mut self, exprs: &[Expr]) {
|
||||||
|
self.emit("#include <stdio.h>\n#include <stdbool.h>\nint main() {\n".to_string());
|
||||||
|
for expr in exprs {
|
||||||
|
self.gen_expr(expr);
|
||||||
|
}
|
||||||
|
self.emit("return 0;\n}\n".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_expr(&mut self, expr: &Expr) {
|
||||||
|
match expr {
|
||||||
|
Expr::Let { name, value } => {
|
||||||
|
match &**value {
|
||||||
|
Expr::Int(i) => self.emit(format!("int {} = {};\n", name, i)),
|
||||||
|
Expr::Float(f) => self.emit(format!("double {} = {};\n", name, f)),
|
||||||
|
Expr::Boolean(b) => self.emit(format!("bool {} = {};\n", name, b)),
|
||||||
|
Expr::String(s) => self.emit(format!("char *{} = \"{}\";\n", name, s)),
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expr::Call { name, args } => {
|
||||||
|
match &**name {
|
||||||
|
Expr::Ident(func) => {
|
||||||
|
match func.as_str() {
|
||||||
|
"print" => {
|
||||||
|
self.emit(format!("printf({});\n", match &args[0] {
|
||||||
|
Expr::String(s) => format!("\"{}\"", s),
|
||||||
|
Expr::Ident(s) => s.to_string(),
|
||||||
|
_ => todo!(),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expr::If { cond, then, else_ } => {
|
||||||
|
self.emit("if ".to_string());
|
||||||
|
self.gen_expr(&cond);
|
||||||
|
self.emit(" {\n".to_string());
|
||||||
|
self.gen_expr(&then);
|
||||||
|
self.emit("} else {\n".to_string());
|
||||||
|
self.gen_expr(&else_);
|
||||||
|
self.emit("}\n".to_string());
|
||||||
|
},
|
||||||
|
Expr::Binary { left, op, right } => {
|
||||||
|
self.emit("(".to_string());
|
||||||
|
self.gen_expr(&left);
|
||||||
|
self.emit(format!(" {} ", op.to_string()));
|
||||||
|
self.gen_expr(&right);
|
||||||
|
self.emit(")".to_string());
|
||||||
|
},
|
||||||
|
Expr::Ident(s) => self.emit(s.to_string()),
|
||||||
|
Expr::Boolean(b) => self.emit(format!("{}", b)),
|
||||||
|
_ => { println!("{:?}", expr); todo!() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
2
src/back/mod.rs
Normal file
2
src/back/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/// C compiler backend
|
||||||
|
pub mod c;
|
|
@ -26,6 +26,7 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = Simple<char>> {
|
||||||
let int = text::int(10)
|
let int = text::int(10)
|
||||||
.map(|s: String| Token::Int(s.parse().unwrap()));
|
.map(|s: String| Token::Int(s.parse().unwrap()));
|
||||||
|
|
||||||
|
// TODO: this is not working somehow
|
||||||
let float = text::int(10)
|
let float = text::int(10)
|
||||||
.then_ignore(just('.'))
|
.then_ignore(just('.'))
|
||||||
.chain::<char, _, _>(text::digits(10))
|
.chain::<char, _, _>(text::digits(10))
|
||||||
|
@ -328,7 +329,7 @@ impl Expr {
|
||||||
&format!("(fun {} ({})\n {})", name, args.join(" "), body.to_sexpr())),
|
&format!("(fun {} ({})\n {})", name, args.join(" "), body.to_sexpr())),
|
||||||
|
|
||||||
Self::If { cond, then, else_ } => out.push_str(
|
Self::If { cond, then, else_ } => out.push_str(
|
||||||
&format!("(if {}\n {}\n {})", cond.to_sexpr(), then.to_sexpr(), else_.to_sexpr())),
|
&format!("(if {} {} {})", cond.to_sexpr(), then.to_sexpr(), else_.to_sexpr())),
|
||||||
|
|
||||||
Self::Do { body } => out.push_str(
|
Self::Do { body } => out.push_str(
|
||||||
&format!("(do {})", body.iter().map(|x| x.to_sexpr()).collect::<Vec<_>>().join(" "))),
|
&format!("(do {})", body.iter().map(|x| x.to_sexpr()).collect::<Vec<_>>().join(" "))),
|
||||||
|
|
|
@ -12,6 +12,10 @@ use args::{Args, Options};
|
||||||
pub mod front;
|
pub mod front;
|
||||||
use front::parse::{lexer, parser};
|
use front::parse::{lexer, parser};
|
||||||
|
|
||||||
|
/// Back-end of the language.
|
||||||
|
/// Contains code generator.
|
||||||
|
pub mod back;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
match args.options {
|
match args.options {
|
||||||
|
@ -24,7 +28,10 @@ fn main() {
|
||||||
if parse_error.is_empty() {
|
if parse_error.is_empty() {
|
||||||
match ast {
|
match ast {
|
||||||
Some(ast) => {
|
Some(ast) => {
|
||||||
println!("{}", ast.iter().map(|e| e.to_sexpr()).collect::<Vec<String>>().join("\n\n"));
|
// println!("{}", ast.iter().map(|e| e.to_sexpr()).collect::<Vec<String>>().join("\n\n"));
|
||||||
|
let mut codegen = back::c::Codegen::new();
|
||||||
|
codegen.gen(&ast);
|
||||||
|
print!("{}", codegen.emitted);
|
||||||
},
|
},
|
||||||
None => println!("no ast :("),
|
None => println!("no ast :("),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue