(Largely) trait-ify Schala

The idea is to provide a trait `ProgrammingLanguage` that actually does
all the work, and then main.rs will just be the infra for storing its
own state
This commit is contained in:
greg 2017-01-23 00:03:08 -08:00
parent 5e474231da
commit 8326a12c9c
2 changed files with 16 additions and 8 deletions

View File

@ -8,12 +8,12 @@ pub struct ParseError {
pub msg: String, pub msg: String,
} }
pub trait ProgrammingLanguage { pub trait ProgrammingLanguage<Evaluator> {
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(input: &Self::AST); fn evaluate(input: Self::AST, evaluator: &mut Evaluator) -> Vec<String>;
fn compile(input: &Self::AST); fn compile(input: &Self::AST);
} }

View File

@ -148,9 +148,14 @@ impl<'a> Repl<'a> {
} }
fn input_handler(&mut self, input: &str) -> String { fn input_handler(&mut self, input: &str) -> String {
let schala = Schala { };
self.input_handler_new(input, schala)
}
fn input_handler_new<T: ProgrammingLanguage<eval::Evaluator<'a>>>(&mut self, input: &str, language: T) -> String {
let mut output = String::new(); let mut output = String::new();
let tokens = match tokenize(input) { let tokens = match T::tokenize(input) {
Ok(tokens) => tokens, Ok(tokens) => tokens,
Err(err) => { Err(err) => {
output.push_str(&format!("Tokenization error: {}\n", err.msg)); output.push_str(&format!("Tokenization error: {}\n", err.msg));
@ -162,7 +167,7 @@ impl<'a> Repl<'a> {
output.push_str(&format!("Tokens: {:?}\n", tokens)); output.push_str(&format!("Tokens: {:?}\n", tokens));
} }
let ast = match parse(&tokens, &[]) { let ast = match T::parse(tokens) {
Ok(ast) => ast, Ok(ast) => ast,
Err(err) => { Err(err) => {
output.push_str(&format!("Parse error: {:?}\n", err.msg)); output.push_str(&format!("Parse error: {:?}\n", err.msg));
@ -174,12 +179,15 @@ impl<'a> Repl<'a> {
output.push_str(&format!("AST: {:?}\n", ast)); output.push_str(&format!("AST: {:?}\n", ast));
} }
/*
if self.show_llvm_ir { if self.show_llvm_ir {
let s = compile_ast(ast); let s = compile_ast(ast);
output.push_str(&s); output.push_str(&s);
*/
if false {
} else { } else {
// for now only handle last output // for now only handle last output
let mut full_output: Vec<String> = self.evaluator.run(ast); let mut full_output: Vec<String> = T::evaluate(ast, &mut self.evaluator);
output.push_str(&full_output.pop().unwrap_or("".to_string())); output.push_str(&full_output.pop().unwrap_or("".to_string()));
} }
output output
@ -239,7 +247,7 @@ impl<'a> Repl<'a> {
struct Schala { } struct Schala { }
impl ProgrammingLanguage for Schala { impl<'a> ProgrammingLanguage<eval::Evaluator<'a>> for Schala {
type Token = tokenizer::Token; type Token = tokenizer::Token;
type AST = parser::AST; type AST = parser::AST;
@ -250,8 +258,8 @@ impl ProgrammingLanguage for Schala {
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError> { fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError> {
parser::parse(&input, &[]).map_err(|x| ParseError { msg: x.msg }) parser::parse(&input, &[]).map_err(|x| ParseError { msg: x.msg })
} }
fn evaluate(input: &Self::AST) { fn evaluate(input: Self::AST, evaluator: &mut Evaluator) -> Vec<String> {
unimplemented!() evaluator.run(input)
} }
fn compile(input: &Self::AST) { fn compile(input: &Self::AST) {
unimplemented!() unimplemented!()