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

refactor: better args handling

This commit is contained in:
Natapat Samutpong 2022-01-26 15:35:40 +07:00
parent 09e8a97d34
commit 598ef08b5d
8 changed files with 74 additions and 39 deletions

View file

@ -1 +1 @@
(print "Hello, World")
(print "Hello, hello world!")

View file

@ -1,4 +1,4 @@
use crate::{compiler::instr::*, parser::Sexpr::{self, *}};
use crate::{vm::instr::*, compiler::parser::Sexpr::{self, *}};
pub struct Compiler {
pub instructions: Vec<Instr>,
pub register_pointer: usize,

View file

@ -1,4 +1,4 @@
/// Definition of assembler's instructions.
pub mod instr;
/// Definition of the compiler.
pub mod compile;
pub mod compile;
/// Definition of the parser.
pub mod parser;

View file

@ -1,5 +1,5 @@
use regex::Regex;
use crate::parser::Sexpr::*;
use crate::compiler::parser::Sexpr::*;
#[derive(Debug, Clone)]
pub enum Sexpr {

View file

@ -1,4 +1,4 @@
use std::{fs::{read_to_string, File}, path::Path, io::{Write, Seek}, time::Instant};
use std::{fs::{read_to_string, File}, path::{Path, PathBuf}, io::{Write, Seek}, time::Instant};
use structopt::StructOpt;
@ -8,55 +8,87 @@ use args::Args;
mod util;
use util::cover_paren;
mod parser;
use parser::{tokenize, Parser, Sexpr};
mod compiler;
use compiler::{compile::Compiler, instr::Instr};
use compiler::{compile::Compiler, parser::{tokenize, Parser}};
mod vm;
use vm::parser::parse_instr;
fn main() {
let start = Instant::now();
let args = Args::from_args();
let src = cover_paren(read_to_string(&args.file).unwrap());
let file_name = match args.output {
match (args.compile, args.run) {
(true, true) => {
eprintln!("TODO: Compile and run at the same time.");
std::process::exit(1);
},
// Compile
(true, false) => {
let src = read_to_string(&args.file).unwrap();
compile_src(src, args.output, args.file, start);
},
// Run
(false, true) => {
let src = read_to_string(&args.file).unwrap();
run_src(src, start);
},
(false, false) => {
if args.file.extension() == Some("blsp".as_ref()) {
let src = read_to_string(&args.file).unwrap();
compile_src(src, args.output, args.file, start);
} else if args.file.extension() == Some("bsm".as_ref()) {
let src = read_to_string(&args.file).unwrap();
run_src(src, start);
} else {
panic!("No mode specified");
}
},
}
}
fn compile_src(src: String, path: Option<PathBuf>, file: PathBuf, start: Instant) {
let file_name = match path {
Some(path) => path,
None => Path::new(&args.file).to_path_buf(),
None => Path::new(&file).to_path_buf(),
}.file_stem().unwrap().to_str().unwrap().to_string();
let tokens = tokenize(&src);
let tokens = tokenize(&cover_paren(src));
let mut parser = Parser::new(tokens.clone());
let result = parser.parse();
match result {
Ok(ast) => {
compile(ast, file_name, start);
let mut compiler = Compiler::new();
let code = compiler.compile(ast, 0);
match code {
Ok(code) => {
let mut file = File::create(format!("{}.bsm", file_name)).unwrap();
for line in code {
write!(file, "{}\n", line).unwrap();
}
file.seek(std::io::SeekFrom::End(-1)).unwrap(); // Trim last newline
let elapsed = start.elapsed();
println!("Compiled in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
},
Err(err) => {
eprintln!("{}", err);
}
}
},
Err(e) => {
eprintln!("{}", e);
}
}
}
fn compile(ast: Sexpr, file_name: String, start: Instant) {
let mut compiler = Compiler::new();
let code = compiler.compile(ast, 0);
match code {
Ok(code) => {
let mut file = File::create(format!("{}.bsm", file_name)).unwrap();
for line in code {
write!(file, "{}\n", line).unwrap();
}
file.seek(std::io::SeekFrom::End(-1)).unwrap(); // Trim last newline
let elapsed = start.elapsed();
println!("Compiled in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
},
Err(err) => {
eprintln!("{}", err);
}
fn run_src(src: String, start: Instant) {
let instrs = parse_instr(&src);
for i in instrs {
println!("{}", i);
}
let elapsed = start.elapsed();
println!("Executed in {}.{}s", elapsed.as_secs(), elapsed.subsec_millis());
}

View file

@ -1 +1,4 @@
pub mod parse;
/// Definition of the VM instructions.
pub mod instr;
/// Definition of the instruction parser.
pub mod parser;

View file

@ -1,6 +1,6 @@
use crate::compiler::instr::*;
use crate::vm::instr::*;
pub fn parse(src: &str) -> Vec<Instr> {
pub fn parse_instr(src: &str) -> Vec<Instr> {
let mut result = Vec::new();
for line in src.lines() {
@ -17,7 +17,7 @@ pub fn parse(src: &str) -> Vec<Instr> {
while let Some(part) = parts.next() { match in_quote {
true => {
if part.ends_with("\"") {
str.push_str(&format!(" {}", part));
str.push_str(&format!(" {}", part.trim_end_matches("\"")));
args.push(str);
str = String::new();
in_quote = false;
@ -25,7 +25,7 @@ pub fn parse(src: &str) -> Vec<Instr> {
},
false => {
if part.starts_with("$\"") {
str.push_str(&part);
str.push_str(&part.trim_start_matches("$\""));
in_quote = true;
} else { args.push(part.to_string()); }
}