From 421a9a7e9b87a8e5ff6ae7cb3e6448b7c4600c49 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 24 Jan 2017 20:09:14 -0800 Subject: [PATCH] Abstract evaluation into EvaluationMachine trait --- src/language.rs | 9 +++++++-- src/main.rs | 23 +++++++++++++++-------- src/schala_lang/eval.rs | 5 ----- src/schala_lang/mod.rs | 18 +++++++++++++++++- src/schala_lang/parser.rs | 1 - src/schala_lang/tokenizer.rs | 2 +- 6 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/language.rs b/src/language.rs index 92148e6..80e12d5 100644 --- a/src/language.rs +++ b/src/language.rs @@ -18,12 +18,17 @@ pub struct ParseError { pub struct LLVMCodeString(pub String); -pub trait ProgrammingLanguage { +pub trait ProgrammingLanguage { type Token: Debug; type AST: Debug; fn tokenize(input: &str) -> Result, TokenError>; fn parse(input: Vec) -> Result; - fn evaluate(ast: Self::AST, evaluator: &mut Evaluator) -> Vec; + fn evaluate(ast: Self::AST, evaluator: &mut E) -> Vec; fn compile(ast: Self::AST) -> LLVMCodeString; } + +pub trait EvaluationMachine { + fn set_option(&mut self, option: &str, value: bool) -> bool; + fn new() -> Self; +} diff --git a/src/main.rs b/src/main.rs index edd1db0..9df9144 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,11 @@ use std::process; use std::io::Write; mod schala_lang; -use schala_lang::eval::Evaluator; +use schala_lang::SchalaEvaluator; use schala_lang::Schala; -use language::{ProgrammingLanguage, LLVMCodeString}; mod language; +use language::{ProgrammingLanguage, LLVMCodeString, EvaluationMachine}; mod llvm_wrap; @@ -54,7 +54,7 @@ fn program_options() -> getopts::Options { options } -fn run_noninteractive<'a, T: ProgrammingLanguage>>(filename: &str, compile: bool, trace_evaluation: bool, language: &T) { +fn run_noninteractive<'a, T: ProgrammingLanguage>>(filename: &str, compile: bool, trace_evaluation: bool, language: &T) { let mut source_file = File::open(&Path::new(filename)).unwrap(); let mut buffer = String::new(); source_file.read_to_string(&mut buffer).unwrap(); @@ -79,7 +79,10 @@ fn run_noninteractive<'a, T: ProgrammingLanguage>>(filename: &str, if compile { compilation_sequence(T::compile(ast), filename); } else { - let mut evaluator = Evaluator::new_with_opts(None, trace_evaluation); + let mut evaluator = ::new(); + if trace_evaluation { + evaluator.set_option("trace_evaluation", true); + } let results = T::evaluate(ast, &mut evaluator); for result in results.iter() { println!("{}", result); @@ -92,7 +95,7 @@ struct Repl<'a> { show_tokens: bool, show_parse: bool, show_llvm_ir: bool, - evaluator: Evaluator<'a>, + evaluator: SchalaEvaluator<'a>, interpreter_directive_sigil: char, reader: LineReader, } @@ -101,11 +104,15 @@ impl<'a> Repl<'a> { fn new(trace_evaluation: bool, show_llvm: bool) -> Repl<'a> { let mut reader: linefeed::Reader<_> = linefeed::Reader::new("Schala").unwrap(); reader.set_prompt(">> "); + + let mut evaluator = ::new(); + evaluator.set_option("trace_evaluation", trace_evaluation); + Repl { show_tokens: false, show_parse: false, show_llvm_ir: show_llvm, - evaluator: Evaluator::new_with_opts(None, trace_evaluation), + evaluator: evaluator, interpreter_directive_sigil: '.', reader: reader, } @@ -140,7 +147,7 @@ impl<'a> Repl<'a> { self.input_handler_new(input, schala) } - fn input_handler_new>>(&mut self, input: &str, language: T) -> String { + fn input_handler_new>>(&mut self, input: &str, language: T) -> String { let mut output = String::new(); let tokens = match T::tokenize(input) { @@ -216,7 +223,7 @@ impl<'a> Repl<'a> { match commands[2] { "tokens" => self.show_tokens = show, "parse" => self.show_parse = show, - "eval" => self.evaluator.trace_evaluation = show, + "eval" => { self.evaluator.set_option("trace_evaluation", show); }, "llvm" => self.show_llvm_ir = show, e => { println!("Bad `show`/`hide` argument: {}", e); diff --git a/src/schala_lang/eval.rs b/src/schala_lang/eval.rs index cb1b3ae..1a09fb8 100644 --- a/src/schala_lang/eval.rs +++ b/src/schala_lang/eval.rs @@ -54,11 +54,6 @@ pub struct Evaluator<'a> { } impl<'a> Evaluator<'a> { - pub fn new_with_opts(parent: Option<&'a Evaluator>, trace_evaluation: bool) -> Evaluator<'a> { - let mut e = Evaluator::new(parent); - e.trace_evaluation = trace_evaluation; - e - } pub fn new(parent: Option<&'a Evaluator>) -> Evaluator<'a> { Evaluator { variables: HashMap::new(), diff --git a/src/schala_lang/mod.rs b/src/schala_lang/mod.rs index 118945b..3867381 100644 --- a/src/schala_lang/mod.rs +++ b/src/schala_lang/mod.rs @@ -3,7 +3,9 @@ pub mod parser; pub mod eval; pub mod compilation; -use language::{ProgrammingLanguage, ParseError, TokenError, LLVMCodeString}; +use language::{ProgrammingLanguage, EvaluationMachine, ParseError, TokenError, LLVMCodeString}; + +pub use self::eval::Evaluator as SchalaEvaluator; pub struct Schala { } @@ -26,3 +28,17 @@ impl<'a> ProgrammingLanguage> for Schala { } } +impl<'a> EvaluationMachine for SchalaEvaluator<'a> { + fn set_option(&mut self, option: &str, value: bool) -> bool { + if option == "trace_evaluation" { + self.trace_evaluation = value; + return true; + } + + false + } + + fn new() -> SchalaEvaluator<'a> { + SchalaEvaluator::new(None) + } +} diff --git a/src/schala_lang/parser.rs b/src/schala_lang/parser.rs index 789c782..a006f7c 100644 --- a/src/schala_lang/parser.rs +++ b/src/schala_lang/parser.rs @@ -1,7 +1,6 @@ use schala_lang::tokenizer::{Token, Kw, OpTok}; use schala_lang::tokenizer::Token::*; -use language::ProgrammingLanguage; use std::fmt; use std::collections::VecDeque; diff --git a/src/schala_lang/tokenizer.rs b/src/schala_lang/tokenizer.rs index d775c95..a1a9235 100644 --- a/src/schala_lang/tokenizer.rs +++ b/src/schala_lang/tokenizer.rs @@ -5,7 +5,7 @@ use std::str::Chars; use self::itertools::Itertools; use std::rc::Rc; -use language::{TokenError, ProgrammingLanguage}; +use language::TokenError; #[derive(Debug, Clone, PartialEq)] pub enum Token {