Skip to content

Commit

Permalink
feat: transpile cli and subcommands
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurfiorette committed Feb 24, 2022
1 parent 6ed3128 commit 0ee230e
Show file tree
Hide file tree
Showing 12 changed files with 240 additions and 87 deletions.
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
members = ["brainease_lexer", "brainease_runtime"]
members = ["brainease_lexer", "brainease_runtime", "brainease_transpiler"]

[package]
name = "brainease"
Expand All @@ -15,7 +15,10 @@ readme = "./README.md"
[dependencies]
brainease_runtime = { path = "brainease_runtime", version = "^1" }
brainease_lexer = { path = "brainease_lexer", version = "^1" }
brainease_transpiler = { path = "brainease_transpiler", version = "^1" }

clap = { version = "^3.1", features = ["derive"] }

clap-verbosity-flag = "^1"
env_logger = "^0.9"
log = "^0.4"
log = "^0.4"
18 changes: 0 additions & 18 deletions src/args.rs

This file was deleted.

21 changes: 21 additions & 0 deletions src/cli.rs
@@ -0,0 +1,21 @@
use clap::{Parser, Subcommand};
use clap_verbosity_flag::Verbosity;

use crate::{run::RunOpts, transpile::TranspileOpts};

#[derive(Parser, Debug)]
#[clap(name = "Brainease")]
#[clap(about = "A brainf*ck-style programming language, but readable")]
pub struct Cli {
#[clap(subcommand)]
pub command: Commands,

#[clap(flatten)]
pub verbose: Verbosity,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
Transpile(TranspileOpts),
Run(RunOpts),
}
52 changes: 15 additions & 37 deletions src/main.rs
@@ -1,44 +1,22 @@
use brainease_lexer::parser;
use brainease_runtime::{io_handler::DefaultIoHandler, runtime::Runtime};
mod cli;
mod run;
mod transpile;
mod util;

use clap::Parser;
use std::{
io::{stdout, Result, Write},
path::Path,
process,
};
use cli::{Cli, Commands};

pub mod args;
pub mod reader;
pub mod util;
fn main() {
let args = Cli::parse();

fn main() -> Result<()> {
let args = args::Args::parse();
util::fallback_rust_log(&args.log_level);
util::setup_logger(&args.verbose);

log::trace!("Cli args: {:?}", args);
let result = match &args.command {
Commands::Transpile(opts) => transpile::run(opts),
Commands::Run(opts) => run::run(opts),
};

if !args.main.ends_with(".brain") {
log::error!("{} does not end with .brain", args.main);
process::exit(1);
if let Err(err) = result {
log::trace!("{:#?}", err)
}

let path = Path::new(&args.main);

let main_file = reader::read_file(path);
let instructions = parser::parse_file(&main_file);

log::trace!("Instructions: {:?}", instructions);

let mut runtime = Runtime::new(instructions, args.memory, DefaultIoHandler {});

log::debug!("Starting runtime");

// A little space between stdout
let elapsed_time = runtime.run()?;

stdout().write_all(b"\n").unwrap();

log::debug!("Elapsed time: {}s.", elapsed_time.as_secs_f64());

Ok(())
}
15 changes: 0 additions & 15 deletions src/reader.rs

This file was deleted.

70 changes: 70 additions & 0 deletions src/run.rs
@@ -0,0 +1,70 @@
use std::{
io::{self, stdout, Write},
path::Path,
};

use brainease_lexer::parser;
use brainease_runtime::{
io_handler::{DefaultIoHandler, IoHandler},
runtime::Runtime,
};
use clap::Parser;

use crate::util;

#[derive(Parser, Debug)]
#[clap(name = "run", about = "Run Brainease source code")]
pub struct RunOpts {
/// The main brainease file to run
#[clap(short = 'f', long = "file")]
main: String,

/// The length to initialize the memory array
#[clap(short = 'm', long = "memory", default_value = "3000")]
memory_length: usize,
}

pub fn run(opts: &RunOpts) -> io::Result<()> {
let main = Path::new(&opts.main);

// Checks for .main file format
if !opts.main.ends_with(".brain") {
log::error!(
"{:?} has an unknown file format of {:?}",
main.file_name().unwrap(),
main.extension().unwrap()
);

return Ok(());
}

let main_content = util::read_file(main)?;

log::trace!("Parsing {}", main.display());

let instructions = parser::parse_file(&main_content);

log::trace!("{:#?}", instructions);

let mut runtime = Runtime::new(instructions, opts.memory_length, DefaultIoHandler {});

start_runtime(&mut runtime)?;

Ok(())
}

pub fn start_runtime<I>(runtime: &mut Runtime<I>) -> Result<(), I::Err>
where
I: IoHandler,
{
log::debug!("Starting runtime");

let elapsed_time = runtime.run()?;

// Prints suffix
stdout().write_all(b"\n").unwrap();

log::debug!("Elapsed time: {}s.", elapsed_time.as_secs_f64());

Ok(())
}
66 changes: 66 additions & 0 deletions src/transpile.rs
@@ -0,0 +1,66 @@
use std::{io, path::Path};

use brainease_runtime::io_handler::DefaultIoHandler;
use brainease_runtime::runtime::Runtime;
use brainease_transpiler::as_string::AsString;
use brainease_transpiler::parser;
use clap::Parser;

use crate::run::start_runtime;
use crate::util;

#[derive(Parser, Debug)]
#[clap(
name = "transpile",
about = "Transpile Brainease source code to Brainfuck"
)]
pub struct TranspileOpts {
/// The bf source file to transpile
#[clap(short = 'f', long = "file")]
main: String,

/// The output file to write
#[clap(short = 'o', long = "output")]
output: Option<String>,

#[clap(short = 'r', long = "run", help = "Run the transpiled code")]
run_after: bool,

#[clap(
long = "memory",
help = "The memory length when -r is used",
default_value = "3000"
)]
memory_length: usize,
}

pub fn run(opts: &TranspileOpts) -> io::Result<()> {
let main = Path::new(&opts.main);
let main_content = util::read_file(main)?;

log::trace!("Transpiling {}", main.display());

let transpiled = parser::parse_bf(&main_content);

log::trace!("{:#?}", transpiled);

let output_name = &opts.output.clone().unwrap_or_else(|| {
if opts.main.ends_with(".bf") {
opts.main.replace(".bf", ".brain")
} else {
format!("{}.brain", opts.main)
}
});

let string_lines = AsString::all(&transpiled, 0);

util::write_file(Path::new(output_name), string_lines)?;

if opts.run_after {
let mut runtime = Runtime::new(transpiled, opts.memory_length, DefaultIoHandler {});

start_runtime(&mut runtime)?;
}

Ok(())
}
15 changes: 0 additions & 15 deletions src/util.rs

This file was deleted.

11 changes: 11 additions & 0 deletions src/util/logger.rs
@@ -0,0 +1,11 @@
use clap_verbosity_flag::Verbosity;

pub fn setup_logger(verbose: &Verbosity) {
env_logger::builder()
.filter_level(verbose.log_level_filter())
.format_indent(None)
.format_module_path(false)
.format_target(false)
.format_timestamp(None)
.init();
}
5 changes: 5 additions & 0 deletions src/util/mod.rs
@@ -0,0 +1,5 @@
mod logger;
mod reader;

pub use logger::*;
pub use reader::*;
27 changes: 27 additions & 0 deletions src/util/reader.rs
@@ -0,0 +1,27 @@
use std::{fs, io, path::Path};

pub fn read_file(path: &Path) -> io::Result<String> {
log::trace!("Reading {}", path.display());

let content = fs::read_to_string(path);

if let Err(err) = &content {
log::error!("Could not find {}", path.display());
log::trace!("{:#?}", err);
}

content
}

pub fn write_file(path: &Path, contents: Vec<String>) -> io::Result<()> {
log::trace!("Writing {}", path.display());

let result = fs::write(path, contents.join("\n"));

if let Err(err) = &result {
log::error!("Could not write to {}", path.display());
log::trace!("{:#?}", err);
}

result
}

0 comments on commit 0ee230e

Please sign in to comment.