summaryrefslogtreecommitdiff
path: root/matrix-bin/src/main.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-29 17:04:28 -0500
commit5d2747e26f51cc2344a6bd95f93457248fdfebd8 (patch)
tree8755b4068166c3854d26817683ce438a771ab319 /matrix-bin/src/main.rs
parentmore mat, sys, and os stdlib functions, better matrix printing, other fixes (diff)
downloadmatrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.gz
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.tar.bz2
matrix-5d2747e26f51cc2344a6bd95f93457248fdfebd8.zip
fin prob
Diffstat (limited to 'matrix-bin/src/main.rs')
-rw-r--r--matrix-bin/src/main.rs119
1 files changed, 91 insertions, 28 deletions
diff --git a/matrix-bin/src/main.rs b/matrix-bin/src/main.rs
index 225b353..64d1b3f 100644
--- a/matrix-bin/src/main.rs
+++ b/matrix-bin/src/main.rs
@@ -1,6 +1,6 @@
use std::{path::PathBuf, io::{self, Read, IsTerminal}, fs, cell::RefCell, rc::Rc};
use clap::{Parser as ArgParser, ColorChoice};
-use matrix::{compiler::{Compiler, CompilerBuilder}, vm::Vm, parse::{Parser, ParserBuilder}, value::Value};
+use matrix_lang::prelude::*;
use repl::Repl;
mod repl;
@@ -12,16 +12,20 @@ pub struct Args {
/// A path to a input program. Uses stdin if not specified.
file: Option<PathBuf>,
- /// Runs a repl, loading the provided program first
+ /// Compiles the given program
#[arg(short, long)]
- repl: bool,
+ compile: bool,
+
+ /// Optional output for compiled output
+ #[arg(short, long)]
+ output: Option<PathBuf>,
/// Print out debug information
#[arg(short, long)]
debug: bool,
/// Choses color
- #[arg(short, long)]
+ #[arg(long)]
color: Option<ColorChoice>,
/// Disables optimizations
@@ -29,18 +33,21 @@ pub struct Args {
disable_optimizations: bool,
}
+pub enum Mode {
+ Repl,
+ Execute(String),
+ Compile(String, PathBuf),
+}
+
pub struct State<'a> {
parser: Parser,
compiler: Compiler<'a>,
vm: Rc<RefCell<Vm>>,
- repl: bool,
color: bool,
- #[allow(unused)]
- debug: bool,
}
impl<'a> State<'a> {
- pub fn new (args: Args) -> (Self, Option<String>) {
+ pub fn new (args: Args) -> (Self, Mode) {
let stdin = read_stdin();
@@ -53,20 +60,43 @@ impl<'a> State<'a> {
file = None;
}
- let repl = args.repl || file.is_none();
+ let mode;
+ let repl;
+ if args.compile {
+ let path = match (args.output, args.file) {
+ (Some(path), _) => path,
+ (None, Some(path)) => {
+ let mut path = path.clone();
+ path.set_extension("matc");
+ path
+ },
+ (None, None) => {
+ PathBuf::from("matc.out")
+ }
+ };
+ let file = file.unwrap_or(String::new());
+ mode = Mode::Compile(file, path);
+ repl = false;
+ } else if let Some(file) = file {
+ mode = Mode::Execute(file);
+ repl = false;
+ } else {
+ mode = Mode::Repl;
+ repl = true;
+ }
+ let mut vm = Vm::new();
let parser = ParserBuilder::new()
.optimize(!args.disable_optimizations)
.build();
- let mut vm = Vm::new();
let compiler = CompilerBuilder::new()
.repl(repl)
.debug(args.debug)
.names(vm.names())
- .globals(vm.global_names())
+ .globals(vm.globals())
.build();
- matrix_stdlib::load(&mut vm);
+ matrix_std::load(&mut vm);
let color = match args.color {
Some(ColorChoice::Auto) | None => {
@@ -76,21 +106,40 @@ impl<'a> State<'a> {
Some(ColorChoice::Never) => false,
};
- (Self { parser, vm: Rc::new(RefCell::new(vm)), compiler, repl, debug: args.debug, color }, file)
+ (Self {
+ parser,
+ vm: Rc::new(RefCell::new(vm)),
+ compiler,
+ color,
+ }, mode)
}
- pub fn execute(&mut self, code: String) -> matrix::Result<Value> {
- let ast = self.parser.parse(code)?;
- let fun = self.compiler.compile(&ast)?;
+ pub fn execute(&mut self, fun: Rc<Function>) -> Result<Value> {
let val = self.vm.try_borrow_mut().unwrap().run(fun)?;
Ok(val)
}
+ pub fn compile(&mut self, code: String) -> Result<Rc<Function>> {
+ let ast = self.parser.parse(code)?;
+ let fun = self.compiler.compile(&ast)?;
+ Ok(fun)
+ }
+
+ pub fn load_program(&mut self, body: String) -> Result<Rc<Function>> {
+ match Program::load(&body)? {
+ Some(fun) => {
+ Ok(fun)
+ },
+ None => {
+ self.compile(body)
+ },
+ }
+ }
}
-pub fn error(err: matrix::Error, state: &State) {
+pub fn error(err: Exception, state: &State) {
if state.color {
- println!("\x1b[31m\x1b[1mError:\x1b[0m {err}");
+ println!("\x1b[31mError:\x1b[0m {err}");
} else {
println!("Error: {err}");
}
@@ -106,19 +155,33 @@ fn read_stdin() -> String {
buffer
}
+fn handle_mode(state: &mut State, mode: Mode) -> Result<()> {
+ match mode {
+ Mode::Repl => {
+ let mut repl = Repl::new(state);
+ repl.run();
+ },
+ Mode::Execute(body) => {
+ let fun = state.load_program(body)?;
+ state.execute(fun)?;
+ },
+ Mode::Compile(body, path) => {
+ let fun = state.compile(body)?;
+ let mut file = File::create(path).map_err(|e|
+ exception!(IO_EXCEPTION, "{e}")
+ )?;
+ Program::save(fun, &mut file)?;
+ }
+ };
+ Ok(())
+}
+
fn main() {
let args = Args::parse();
- let (mut state, file) = State::new(args);
+ let (mut state, mode) = State::new(args);
- if let Some(file) = file {
- if let Err(err) = state.execute(file) {
- error(err, &state);
- }
+ if let Err(e) = handle_mode(&mut state, mode) {
+ error(e, &state);
}
-
- if state.repl {
- Repl::new(state).run();
- }
-
}