about summary refs log tree commit diff
path: root/users/tazjin/rlox/src/treewalk
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-01-18T00·21+0300
committertazjin <mail@tazj.in>2021-01-18T00·24+0000
commit1ff7a2686c2d7e405e597f9ac8a96189ec161d58 (patch)
tree1e6613d559744b9722329fa927dd78ce670581ca /users/tazjin/rlox/src/treewalk
parentd6d3c12efbcec61b3d868bc7d3f861fdb91835a5 (diff)
refactor(tazjin/rlox): Add Interpreter trait for switching impls r/2129
Change-Id: Iae28d64ce879014c5e5d7e145c536c1f16ad307d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2418
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src/treewalk')
-rw-r--r--users/tazjin/rlox/src/treewalk/errors.rs7
-rw-r--r--users/tazjin/rlox/src/treewalk/interpreter.rs46
-rw-r--r--users/tazjin/rlox/src/treewalk/interpreter/tests.rs8
-rw-r--r--users/tazjin/rlox/src/treewalk/mod.rs56
4 files changed, 35 insertions, 82 deletions
diff --git a/users/tazjin/rlox/src/treewalk/errors.rs b/users/tazjin/rlox/src/treewalk/errors.rs
index 3d5c28f9f3bb..54d2718eeda2 100644
--- a/users/tazjin/rlox/src/treewalk/errors.rs
+++ b/users/tazjin/rlox/src/treewalk/errors.rs
@@ -1,4 +1,5 @@
 use crate::treewalk::interpreter::Value;
+use std::fmt;
 
 #[derive(Debug)]
 pub enum ErrorKind {
@@ -33,6 +34,8 @@ pub struct Error {
     pub kind: ErrorKind,
 }
 
-pub fn report(err: &Error) {
-    eprintln!("[line {}] Error: {:?}", err.line, err.kind);
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "[line {}] Error: {:?}", self.line, self.kind)
+    }
 }
diff --git a/users/tazjin/rlox/src/treewalk/interpreter.rs b/users/tazjin/rlox/src/treewalk/interpreter.rs
index a096716d9155..1263e6cb810b 100644
--- a/users/tazjin/rlox/src/treewalk/interpreter.rs
+++ b/users/tazjin/rlox/src/treewalk/interpreter.rs
@@ -1,7 +1,8 @@
 use crate::treewalk::errors::{Error, ErrorKind};
 use crate::treewalk::parser::{self, Block, Expr, Literal, Statement};
+use crate::treewalk::resolver;
 use crate::treewalk::scanner::{self, TokenKind};
-use crate::treewalk::treewalk::resolver;
+use crate::Lox;
 use std::collections::HashMap;
 use std::rc::Rc;
 use std::sync::RwLock;
@@ -174,10 +175,13 @@ pub struct Interpreter {
     env: Rc<RwLock<Environment>>,
 }
 
-impl Interpreter {
+impl Lox for Interpreter {
+    type Value = Value;
+    type Error = Error;
+
     /// Create a new interpreter and configure the initial global
     /// variable set.
-    pub fn create() -> Self {
+    fn create() -> Self {
         let mut globals = HashMap::new();
 
         globals.insert(
@@ -193,6 +197,27 @@ impl Interpreter {
         }
     }
 
+    fn interpret(&mut self, code: String) -> Result<Value, Vec<Error>> {
+        let chars: Vec<char> = code.chars().collect();
+
+        let mut program = scanner::scan(&chars).and_then(|tokens| parser::parse(tokens))?;
+
+        let globals = self
+            .env
+            .read()
+            .expect("static globals lock poisoned")
+            .values
+            .keys()
+            .map(Clone::clone)
+            .collect::<Vec<String>>();
+
+        resolver::resolve(&globals, &mut program).map_err(|e| vec![e])?;
+        self.interpret_block_with_env(None, &program)
+            .map_err(|e| vec![e])
+    }
+}
+
+impl Interpreter {
     // Environment modification helpers
     fn define_var(&mut self, name: &scanner::Token, value: Value) -> Result<(), Error> {
         self.env
@@ -221,21 +246,6 @@ impl Interpreter {
             .get(ident, var.name.line, depth)
     }
 
-    // Interpreter itself
-    pub fn interpret(&mut self, mut program: Block) -> Result<Value, Error> {
-        let globals = self
-            .env
-            .read()
-            .expect("static globals lock poisoned")
-            .values
-            .keys()
-            .map(Clone::clone)
-            .collect::<Vec<String>>();
-
-        resolver::resolve(&globals, &mut program)?;
-        self.interpret_block_with_env(None, &program)
-    }
-
     /// Interpret the block in the supplied environment. If no
     /// environment is supplied, a new one is created using the
     /// current one as its parent.
diff --git a/users/tazjin/rlox/src/treewalk/interpreter/tests.rs b/users/tazjin/rlox/src/treewalk/interpreter/tests.rs
index 34b1df34b0b6..2fc6f4fee978 100644
--- a/users/tazjin/rlox/src/treewalk/interpreter/tests.rs
+++ b/users/tazjin/rlox/src/treewalk/interpreter/tests.rs
@@ -2,13 +2,9 @@ use super::*;
 
 /// Evaluate a code snippet, returning a value.
 fn parse_eval(code: &str) -> Value {
-    let chars: Vec<char> = code.chars().collect();
-    let tokens = scanner::scan(&chars).expect("could not scan code");
-    let program = parser::parse(tokens).expect("could not parse code");
-
     Interpreter::create()
-        .interpret(program)
-        .expect("could not eval code")
+        .interpret(code.into())
+        .expect("could not interpret code")
 }
 
 #[test]
diff --git a/users/tazjin/rlox/src/treewalk/mod.rs b/users/tazjin/rlox/src/treewalk/mod.rs
index b5db454ccc2f..d53bd13f8ede 100644
--- a/users/tazjin/rlox/src/treewalk/mod.rs
+++ b/users/tazjin/rlox/src/treewalk/mod.rs
@@ -1,61 +1,5 @@
-use crate::*;
-
 mod errors;
 pub mod interpreter;
 mod parser;
 mod resolver;
 mod scanner;
-
-pub fn main() {
-    let mut args = env::args();
-
-    if args.len() > 2 {
-        println!("Usage: rlox [script]");
-        process::exit(1);
-    } else if let Some(file) = args.nth(1) {
-        run_file(&file);
-    } else {
-        run_prompt();
-    }
-}
-
-// Run Lox code from a file and print results to stdout
-fn run_file(file: &str) {
-    let contents = fs::read_to_string(file).expect("failed to read the input file");
-    let mut lox = treewalk::interpreter::Interpreter::create();
-    run(&mut lox, &contents);
-}
-
-// Evaluate Lox code interactively in a shitty REPL.
-fn run_prompt() {
-    let mut line = String::new();
-    let mut lox = treewalk::interpreter::Interpreter::create();
-
-    loop {
-        print!("> ");
-        io::stdout().flush().unwrap();
-        io::stdin()
-            .read_line(&mut line)
-            .expect("failed to read user input");
-        run(&mut lox, &line);
-        line.clear();
-    }
-}
-
-fn run(lox: &mut treewalk::interpreter::Interpreter, code: &str) {
-    let chars: Vec<char> = code.chars().collect();
-
-    let result = scanner::scan(&chars)
-        .and_then(|tokens| parser::parse(tokens))
-        .and_then(|program| lox.interpret(program).map_err(|e| vec![e]));
-
-    if let Err(errors) = result {
-        report_errors(errors);
-    }
-}
-
-fn report_errors(errors: Vec<errors::Error>) {
-    for error in errors {
-        errors::report(&error);
-    }
-}