Abstract evaluation into EvaluationMachine trait

This commit is contained in:
greg 2017-01-24 20:09:14 -08:00
parent f37ab80163
commit 421a9a7e9b
6 changed files with 40 additions and 18 deletions

View File

@ -18,12 +18,17 @@ pub struct ParseError {
pub struct LLVMCodeString(pub String); pub struct LLVMCodeString(pub String);
pub trait ProgrammingLanguage<Evaluator> { pub trait ProgrammingLanguage<E: EvaluationMachine> {
type Token: Debug; type Token: Debug;
type AST: Debug; type AST: Debug;
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>; fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>;
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>; fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>;
fn evaluate(ast: Self::AST, evaluator: &mut Evaluator) -> Vec<String>; fn evaluate(ast: Self::AST, evaluator: &mut E) -> Vec<String>;
fn compile(ast: Self::AST) -> LLVMCodeString; fn compile(ast: Self::AST) -> LLVMCodeString;
} }
pub trait EvaluationMachine {
fn set_option(&mut self, option: &str, value: bool) -> bool;
fn new() -> Self;
}

View File

@ -9,11 +9,11 @@ use std::process;
use std::io::Write; use std::io::Write;
mod schala_lang; mod schala_lang;
use schala_lang::eval::Evaluator; use schala_lang::SchalaEvaluator;
use schala_lang::Schala; use schala_lang::Schala;
use language::{ProgrammingLanguage, LLVMCodeString};
mod language; mod language;
use language::{ProgrammingLanguage, LLVMCodeString, EvaluationMachine};
mod llvm_wrap; mod llvm_wrap;
@ -54,7 +54,7 @@ fn program_options() -> getopts::Options {
options options
} }
fn run_noninteractive<'a, T: ProgrammingLanguage<Evaluator<'a>>>(filename: &str, compile: bool, trace_evaluation: bool, language: &T) { fn run_noninteractive<'a, T: ProgrammingLanguage<SchalaEvaluator<'a>>>(filename: &str, compile: bool, trace_evaluation: bool, language: &T) {
let mut source_file = File::open(&Path::new(filename)).unwrap(); let mut source_file = File::open(&Path::new(filename)).unwrap();
let mut buffer = String::new(); let mut buffer = String::new();
source_file.read_to_string(&mut buffer).unwrap(); source_file.read_to_string(&mut buffer).unwrap();
@ -79,7 +79,10 @@ fn run_noninteractive<'a, T: ProgrammingLanguage<Evaluator<'a>>>(filename: &str,
if compile { if compile {
compilation_sequence(T::compile(ast), filename); compilation_sequence(T::compile(ast), filename);
} else { } else {
let mut evaluator = Evaluator::new_with_opts(None, trace_evaluation); let mut evaluator = <SchalaEvaluator as EvaluationMachine>::new();
if trace_evaluation {
evaluator.set_option("trace_evaluation", true);
}
let results = T::evaluate(ast, &mut evaluator); let results = T::evaluate(ast, &mut evaluator);
for result in results.iter() { for result in results.iter() {
println!("{}", result); println!("{}", result);
@ -92,7 +95,7 @@ struct Repl<'a> {
show_tokens: bool, show_tokens: bool,
show_parse: bool, show_parse: bool,
show_llvm_ir: bool, show_llvm_ir: bool,
evaluator: Evaluator<'a>, evaluator: SchalaEvaluator<'a>,
interpreter_directive_sigil: char, interpreter_directive_sigil: char,
reader: LineReader, reader: LineReader,
} }
@ -101,11 +104,15 @@ impl<'a> Repl<'a> {
fn new(trace_evaluation: bool, show_llvm: bool) -> Repl<'a> { fn new(trace_evaluation: bool, show_llvm: bool) -> Repl<'a> {
let mut reader: linefeed::Reader<_> = linefeed::Reader::new("Schala").unwrap(); let mut reader: linefeed::Reader<_> = linefeed::Reader::new("Schala").unwrap();
reader.set_prompt(">> "); reader.set_prompt(">> ");
let mut evaluator = <SchalaEvaluator as EvaluationMachine>::new();
evaluator.set_option("trace_evaluation", trace_evaluation);
Repl { Repl {
show_tokens: false, show_tokens: false,
show_parse: false, show_parse: false,
show_llvm_ir: show_llvm, show_llvm_ir: show_llvm,
evaluator: Evaluator::new_with_opts(None, trace_evaluation), evaluator: evaluator,
interpreter_directive_sigil: '.', interpreter_directive_sigil: '.',
reader: reader, reader: reader,
} }
@ -140,7 +147,7 @@ impl<'a> Repl<'a> {
self.input_handler_new(input, schala) self.input_handler_new(input, schala)
} }
fn input_handler_new<T: ProgrammingLanguage<Evaluator<'a>>>(&mut self, input: &str, language: T) -> String { fn input_handler_new<T: ProgrammingLanguage<SchalaEvaluator<'a>>>(&mut self, input: &str, language: T) -> String {
let mut output = String::new(); let mut output = String::new();
let tokens = match T::tokenize(input) { let tokens = match T::tokenize(input) {
@ -216,7 +223,7 @@ impl<'a> Repl<'a> {
match commands[2] { match commands[2] {
"tokens" => self.show_tokens = show, "tokens" => self.show_tokens = show,
"parse" => self.show_parse = 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, "llvm" => self.show_llvm_ir = show,
e => { e => {
println!("Bad `show`/`hide` argument: {}", e); println!("Bad `show`/`hide` argument: {}", e);

View File

@ -54,11 +54,6 @@ pub struct Evaluator<'a> {
} }
impl<'a> 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> { pub fn new(parent: Option<&'a Evaluator>) -> Evaluator<'a> {
Evaluator { Evaluator {
variables: HashMap::new(), variables: HashMap::new(),

View File

@ -3,7 +3,9 @@ pub mod parser;
pub mod eval; pub mod eval;
pub mod compilation; 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 { } pub struct Schala { }
@ -26,3 +28,17 @@ impl<'a> ProgrammingLanguage<eval::Evaluator<'a>> 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)
}
}

View File

@ -1,7 +1,6 @@
use schala_lang::tokenizer::{Token, Kw, OpTok}; use schala_lang::tokenizer::{Token, Kw, OpTok};
use schala_lang::tokenizer::Token::*; use schala_lang::tokenizer::Token::*;
use language::ProgrammingLanguage;
use std::fmt; use std::fmt;
use std::collections::VecDeque; use std::collections::VecDeque;

View File

@ -5,7 +5,7 @@ use std::str::Chars;
use self::itertools::Itertools; use self::itertools::Itertools;
use std::rc::Rc; use std::rc::Rc;
use language::{TokenError, ProgrammingLanguage}; use language::TokenError;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Token { pub enum Token {