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
|
||||
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.
|
||||
|
||||
# Prerequistie
|
||||
- `clang` and `clang-format`
|
||||
- Rust (if you're going to build from source)
|
||||
|
||||
# TODO
|
||||
- Compliation
|
||||
- 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());
|
||||
}
|
||||
|
||||
fn emit_str(&mut self, s: &str) {
|
||||
self.emitted.push_str(s);
|
||||
}
|
||||
|
||||
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 {
|
||||
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) {
|
||||
|
@ -41,7 +48,7 @@ impl Codegen {
|
|||
"print" => {
|
||||
self.emit(format!("printf({});\n", match &args[0] {
|
||||
Expr::String(s) => format!("\"{}\"", s),
|
||||
Expr::Ident(s) => s.to_string(),
|
||||
Expr::Ident(s) => format!("\"%s\", {}", s),
|
||||
_ => 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 clap::Parser as ArgParser;
|
||||
|
@ -16,28 +16,84 @@ use front::parse::{lexer, parser};
|
|||
/// Contains code generator.
|
||||
pub mod back;
|
||||
|
||||
pub mod util;
|
||||
use crate::util::log;
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
match args.options {
|
||||
Options::Compile { input: src, ast: _print_ast } => {
|
||||
let src = fs::read_to_string(src).expect("Failed to read file");
|
||||
Options::Compile { input: file_name, ast: _print_ast } => {
|
||||
// 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 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()));
|
||||
|
||||
if lex_error.is_empty() {
|
||||
|
||||
if parse_error.is_empty() {
|
||||
|
||||
match ast {
|
||||
// If there is some AST then generate code.
|
||||
Some(ast) => {
|
||||
// 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);
|
||||
let start = time::Instant::now();
|
||||
|
||||
let mut compiler = back::c::Codegen::new();
|
||||
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 :("),
|
||||
};
|
||||
|
||||
} else {
|
||||
eprintln!("{:#?}\n(Parser error)", parse_error);
|
||||
}
|
||||
|
||||
} else {
|
||||
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