16.1 and adjust error handling
change nukpqrprtozunwsuzszopxvvnptxntvw
commit a39c3b94144e083eb08e5127ed5beea39520bbb2
author Alpha Chen <alpha@kejadlen.dev>
date
parent rtmsoumx
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,