Abstracted most work into LanguageInterface trait

Still need to handle state
This commit is contained in:
greg 2017-02-01 02:15:18 -08:00
parent 6dec35d460
commit 4ea600d55c
2 changed files with 54 additions and 46 deletions

View File

@ -1,3 +1,4 @@
use std::default::Default;
use std::fmt::Debug;
#[derive(Debug)]
@ -34,9 +35,54 @@ pub trait EvaluationMachine {
fn new() -> Self;
}
pub trait LanguageWrapper {
#[derive(Default)]
pub struct LanguageInterfaceOptions {
pub show_parse: bool,
pub show_tokens: bool,
pub show_llvm_ir: bool,
}
impl<X, T, A, E> LanguageWrapper for X where X: ProgrammingLanguage<Token=T, AST=A, Evaluator=E>, T: Debug, A: Debug, E: EvaluationMachine {
pub trait LanguageInterface {
fn evaluate_in_repl(&mut self, input: &str, options: LanguageInterfaceOptions) -> String;
}
impl<PL, T, A, E> LanguageInterface for PL where PL: ProgrammingLanguage<Token=T, AST=A, Evaluator=E>, T: Debug, A: Debug, E: EvaluationMachine {
fn evaluate_in_repl(&mut self, input: &str, options: LanguageInterfaceOptions) -> String {
let mut output = String::new();
let tokens = match PL::tokenize(input) {
Ok(tokens) => tokens,
Err(err) => {
output.push_str(&format!("Tokenization error: {}\n", err.msg));
return output;
}
};
if options.show_tokens {
output.push_str(&format!("Tokens: {:?}\n", tokens));
}
let ast = match PL::parse(tokens) {
Ok(ast) => ast,
Err(err) => {
output.push_str(&format!("Parse error: {:?}\n", err.msg));
return output;
}
};
if options.show_parse {
output.push_str(&format!("AST: {:?}\n", ast));
}
if options.show_llvm_ir {
let LLVMCodeString(s) = PL::compile(ast);
output.push_str(&s);
} else {
// for now only handle last output
let mut evaluator = PL::Evaluator::new();
let mut full_output: Vec<String> = PL::evaluate(ast, &mut evaluator);
output.push_str(&full_output.pop().unwrap_or("".to_string()));
}
output
}
}

View File

@ -7,6 +7,7 @@ use std::fs::File;
use std::io::Read;
use std::process;
use std::io::Write;
use std::default::Default;
mod schala_lang;
use schala_lang::SchalaEvaluator;
@ -15,7 +16,7 @@ use schala_lang::Schala;
mod maaru_lang;
mod language;
use language::{ProgrammingLanguage, LanguageWrapper, LLVMCodeString, EvaluationMachine};
use language::{ProgrammingLanguage, LanguageInterface, LLVMCodeString, EvaluationMachine};
mod llvm_wrap;
@ -97,7 +98,7 @@ struct Repl<'a> {
show_tokens: bool,
show_parse: bool,
show_llvm_ir: bool,
languages: Vec<Box<LanguageWrapper>>,
languages: Vec<Box<LanguageInterface>>,
evaluator: SchalaEvaluator<'a>,
interpreter_directive_sigil: char,
reader: LineReader,
@ -147,47 +148,8 @@ impl<'a> Repl<'a> {
}
fn input_handler(&mut self, input: &str) -> String {
let schala = Schala::new();
let mut evaluator = <SchalaEvaluator as EvaluationMachine>::new();
self.input_handler_new(input, schala, &mut evaluator)
}
fn input_handler_new<T: ProgrammingLanguage>(&mut self, input: &str, language: T, mut evaluator: &mut T::Evaluator) -> String {
let mut output = String::new();
let tokens = match T::tokenize(input) {
Ok(tokens) => tokens,
Err(err) => {
output.push_str(&format!("Tokenization error: {}\n", err.msg));
return output;
}
};
if self.show_tokens {
output.push_str(&format!("Tokens: {:?}\n", tokens));
}
let ast = match T::parse(tokens) {
Ok(ast) => ast,
Err(err) => {
output.push_str(&format!("Parse error: {:?}\n", err.msg));
return output;
}
};
if self.show_parse {
output.push_str(&format!("AST: {:?}\n", ast));
}
if self.show_llvm_ir {
let LLVMCodeString(s) = T::compile(ast);
output.push_str(&s);
} else {
// for now only handle last output
let mut full_output: Vec<String> = T::evaluate(ast, &mut evaluator);
output.push_str(&full_output.pop().unwrap_or("".to_string()));
}
output
let ref mut language = self.languages[0];
language.evaluate_in_repl(input, language::LanguageInterfaceOptions::default())
}
fn handle_interpreter_directive(&mut self, input: &str) -> bool {