16.1 and adjust error handling
diff --git a/rust/src/error.rs b/rust/src/error.rs
new file mode 100644
index 0000000..4cf7d4c
--- /dev/null
+++ b/rust/src/error.rs
@@ -0,0 +1,34 @@
+use std::io;
+use std::process::{ExitCode, Termination};
+
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[error("compile error")]
+ Compile,
+ #[error("runtime error")]
+ Runtime,
+ #[error("could not open file {path}")]
+ ReadFile {
+ path: String,
+ #[source]
+ source: io::Error,
+ },
+ #[error("Usage: clox [path]")]
+ Usage,
+}
+
+// Doesn't actually work with eyre... yet? But I'm
+// willing to give up "nice" exit status codes for
+// eyre's error handling.
+impl Termination for Error {
+ fn report(self) -> ExitCode {
+ ExitCode::from(match self {
+ Error::Compile => 65,
+ Error::Runtime => 70,
+ Error::ReadFile { path, source } => 74,
+ Error::Usage => 64,
+ })
+ }
+}
diff --git a/rust/src/main.rs b/rust/src/main.rs
index a34ba0f..dd2616b 100644
--- a/rust/src/main.rs
+++ b/rust/src/main.rs
@@ -1,13 +1,17 @@
-use std::env;
+use std::io::{self, Write};
-use chunk::{Chunk, OpCode};
-use vm::VM;
+use std::{env, fs};
+
+// use chunk::{Chunk, OpCode};
+// use vm::VM;
use color_eyre::eyre::{Result, WrapErr};
+use error::Error;
use tracing::Level;
use tracing_subscriber::FmtSubscriber;
mod chunk;
+mod error;
mod value;
mod vm;
@@ -16,29 +20,45 @@ fn main() -> Result<()> {
Ok(_) => Level::DEBUG,
Err(_) => Level::ERROR,
};
- let subscriber = FmtSubscriber::builder()
- .with_max_level(level)
- .finish();
+ let subscriber = FmtSubscriber::builder().with_max_level(level).finish();
tracing::subscriber::set_global_default(subscriber)
.wrap_err("setting default subscriber failed")?;
- let mut chunk = Chunk::default();
+ match &env::args().skip(1).collect::<Vec<_>>()[..] {
+ [] => repl()?,
+ [file] => run(file)?,
+ _ => return Err(Error::Usage.into()),
+ }
- chunk.push_constant(1.2, 123);
- chunk.push_constant(3.4, 123);
- chunk.push(OpCode::Add, 123);
+ Ok(())
+}
- chunk.push_constant(5.6, 123);
- chunk.push(OpCode::Divide, 123);
+fn repl() -> Result<()> {
+ let stdin = io::stdin(); // We get `Stdin` here.
+ let mut buffer = String::new();
- chunk.push(OpCode::Negate, 123);
+ loop {
+ print!("> ");
+ io::stdout().flush()?;
- chunk.push(OpCode::Return, 123);
+ stdin.read_line(&mut buffer)?;
+ if buffer == "\n" {
+ return Ok(());
+ }
- chunk.disassemble("test chunk");
+ interpret(&buffer)?;
+ }
+}
- let mut vm = VM::new(chunk);
- vm.interpret()?;
+fn interpret(buffer: &str) -> Result<()> {
+ todo!()
+}
+fn run(file: &str) -> Result<()> {
+ let contents = fs::read_to_string(file).map_err(|e| Error::ReadFile {
+ path: file.to_string(),
+ source: e,
+ })?;
+ interpret(&contents)?;
Ok(())
}
diff --git a/rust/src/vm.rs b/rust/src/vm.rs
index e13ef97..e610663 100644
--- a/rust/src/vm.rs
+++ b/rust/src/vm.rs
@@ -1,7 +1,6 @@
use std::ops::{Add, Div, Mul, Sub};
use color_eyre::eyre::Result;
-use thiserror::Error;
use crate::{
chunk::{Chunk, DisassembledInstruction, OpCode},
@@ -9,14 +8,6 @@ use crate::{
};
use tracing::debug;
-#[derive(Error, Debug)]
-pub enum InterpretError {
- #[error("compile error")]
- Compile,
- #[error("runtime error")]
- Runtime,
-}
-
pub struct VM {
chunk: Chunk,
ip: usize,