mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
bool.h, running clang and clang-format on comp
This commit is contained in:
parent
0e3cd664af
commit
39b79b8c61
4
Makefile
Normal file
4
Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Build the libraries that are used by generated C code.
|
||||||
|
build_lib:
|
||||||
|
sudo mkdir -p /usr/include/hycron
|
||||||
|
sudo cp -r ./lib/* /usr/include/hycron
|
|
@ -1,7 +1,11 @@
|
||||||
# Hycron
|
# Hycron
|
||||||
Programming language
|
Programming language that compiles to C
|
||||||
Note: The syntax can still be changed, if you have an idea, feel free to make an issues about it.
|
Note: The syntax can still be changed, if you have an idea, feel free to make an issues about it.
|
||||||
|
|
||||||
|
# Prerequistie
|
||||||
|
- `clang` and `clang-format`
|
||||||
|
- Rust (if you're going to build from source)
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
- Compliation
|
- Compliation
|
||||||
- Optimization
|
- Optimization
|
||||||
|
|
3
lib/bool.h
Normal file
3
lib/bool.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define bool _Bool
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
|
@ -15,12 +15,19 @@ impl Codegen {
|
||||||
self.emitted.push_str(s.as_str());
|
self.emitted.push_str(s.as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_str(&mut self, s: &str) {
|
||||||
|
self.emitted.push_str(s);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gen(&mut self, exprs: &[Expr]) {
|
pub fn gen(&mut self, exprs: &[Expr]) {
|
||||||
self.emit("#include <stdio.h>\n#include <stdbool.h>\nint main() {\n".to_string());
|
self.emit_str("#include <stdio.h>\n");
|
||||||
|
self.emit_str("#include <hycron/bool.h>\n");
|
||||||
|
self.emit_str("int main() {\n");
|
||||||
for expr in exprs {
|
for expr in exprs {
|
||||||
self.gen_expr(expr);
|
self.gen_expr(expr);
|
||||||
}
|
}
|
||||||
self.emit("return 0;\n}\n".to_string());
|
self.emit_str("return 0;\n");
|
||||||
|
self.emit_str("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_expr(&mut self, expr: &Expr) {
|
fn gen_expr(&mut self, expr: &Expr) {
|
||||||
|
@ -41,7 +48,7 @@ impl Codegen {
|
||||||
"print" => {
|
"print" => {
|
||||||
self.emit(format!("printf({});\n", match &args[0] {
|
self.emit(format!("printf({});\n", match &args[0] {
|
||||||
Expr::String(s) => format!("\"{}\"", s),
|
Expr::String(s) => format!("\"{}\"", s),
|
||||||
Expr::Ident(s) => s.to_string(),
|
Expr::Ident(s) => format!("\"%s\", {}", s),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
70
src/main.rs
70
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::fs;
|
use std::{fs, io::Write, time, process::Command};
|
||||||
|
|
||||||
use chumsky::{Parser, Stream};
|
use chumsky::{Parser, Stream};
|
||||||
use clap::Parser as ArgParser;
|
use clap::Parser as ArgParser;
|
||||||
|
@ -16,28 +16,84 @@ use front::parse::{lexer, parser};
|
||||||
/// Contains code generator.
|
/// Contains code generator.
|
||||||
pub mod back;
|
pub mod back;
|
||||||
|
|
||||||
|
pub mod util;
|
||||||
|
use crate::util::log;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
match args.options {
|
match args.options {
|
||||||
Options::Compile { input: src, ast: _print_ast } => {
|
Options::Compile { input: file_name, ast: _print_ast } => {
|
||||||
let src = fs::read_to_string(src).expect("Failed to read file");
|
// Get file contents.
|
||||||
|
let src = fs::read_to_string(&file_name).expect("Failed to read file");
|
||||||
|
|
||||||
|
// Lex the file.
|
||||||
let (tokens, lex_error) = lexer().parse_recovery(src.as_str());
|
let (tokens, lex_error) = lexer().parse_recovery(src.as_str());
|
||||||
let len = src.chars().count();
|
let len = src.chars().count();
|
||||||
|
|
||||||
|
// Parse the file.
|
||||||
let (ast, parse_error) = parser().parse_recovery(Stream::from_iter(len..len + 1, tokens.clone().unwrap().into_iter()));
|
let (ast, parse_error) = parser().parse_recovery(Stream::from_iter(len..len + 1, tokens.clone().unwrap().into_iter()));
|
||||||
|
|
||||||
if lex_error.is_empty() {
|
if lex_error.is_empty() {
|
||||||
|
|
||||||
if parse_error.is_empty() {
|
if parse_error.is_empty() {
|
||||||
|
|
||||||
match ast {
|
match ast {
|
||||||
|
// If there is some AST then generate code.
|
||||||
Some(ast) => {
|
Some(ast) => {
|
||||||
// println!("{}", ast.iter().map(|e| e.to_sexpr()).collect::<Vec<String>>().join("\n\n"));
|
let start = time::Instant::now();
|
||||||
let mut codegen = back::c::Codegen::new();
|
|
||||||
codegen.gen(&ast);
|
let mut compiler = back::c::Codegen::new();
|
||||||
print!("{}", codegen.emitted);
|
compiler.gen(&ast);
|
||||||
|
|
||||||
|
let out_file_name = file_name.file_stem().unwrap().to_str().unwrap().to_string() + ".c";
|
||||||
|
let mut out_file = fs::File::create(&out_file_name).expect("Failed to create file");
|
||||||
|
write!(out_file, "{}", compiler.emitted).expect("Failed to write to file");
|
||||||
|
|
||||||
|
let compile_elapsed = start.elapsed();
|
||||||
|
|
||||||
|
log(0, format!("Compiled successfully to {} in {}s", &out_file_name, compile_elapsed.as_secs_f64()));
|
||||||
|
log(0, "Running clang-format...");
|
||||||
|
let mut clang_format_status = Command::new("clang-format")
|
||||||
|
.arg("-i")
|
||||||
|
.arg(&out_file_name)
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to run clang-format, make sure you have it installed");
|
||||||
|
match clang_format_status.wait() {
|
||||||
|
Ok(status) => {
|
||||||
|
match status.success() {
|
||||||
|
true => log(0, "Successfully run clang-format"),
|
||||||
|
false => log(2, "Failed to run clang-format"),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
Err(e) => log(2, format!("Failed to wait on clang-format: {}", e)),
|
||||||
|
}
|
||||||
|
|
||||||
|
log(0, "Running clang...");
|
||||||
|
let mut clang_status = Command::new("clang")
|
||||||
|
.arg(&out_file_name)
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to run clang, make sure you have it installed");
|
||||||
|
match clang_status.wait() {
|
||||||
|
Ok(status) => {
|
||||||
|
match status.success() {
|
||||||
|
true => log(0, "Successfully run clang"),
|
||||||
|
false => log(2, "Failed to run clang"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log(2, format!("Failed to wait on clang: {}", e)),
|
||||||
|
}
|
||||||
|
|
||||||
|
let all_elapsed = start.elapsed();
|
||||||
|
log(0, format!("Done in {}s", all_elapsed.as_secs_f64()));
|
||||||
|
},
|
||||||
|
// If there is no AST, then notify the user.
|
||||||
None => println!("no ast :("),
|
None => println!("no ast :("),
|
||||||
};
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{:#?}\n(Parser error)", parse_error);
|
eprintln!("{:#?}\n(Parser error)", parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{:#?}\n(Lexer error)", lex_error);
|
eprintln!("{:#?}\n(Lexer error)", lex_error);
|
||||||
}
|
}
|
||||||
|
|
10
src/util.rs
Normal file
10
src/util.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
pub fn log<T: Display>(level: i8, msg: T) {
|
||||||
|
match level {
|
||||||
|
0 => println!("\x1b[92m[INFO]\x1b[0m {}", msg),
|
||||||
|
1 => println!("[WARN] {}", msg),
|
||||||
|
2 => println!("[ERRO] {}", msg),
|
||||||
|
_ => println!("{}", msg),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue