Think I've nearly gotten it traitified correctly...
This commit is contained in:
parent
cc855affbf
commit
6dec35d460
@ -18,13 +18,14 @@ pub struct ParseError {
|
|||||||
|
|
||||||
pub struct LLVMCodeString(pub String);
|
pub struct LLVMCodeString(pub String);
|
||||||
|
|
||||||
pub trait ProgrammingLanguage<E: EvaluationMachine> {
|
pub trait ProgrammingLanguage {
|
||||||
type Token: Debug;
|
type Token: Debug;
|
||||||
type AST: Debug;
|
type AST: Debug;
|
||||||
|
type Evaluator: EvaluationMachine;
|
||||||
|
|
||||||
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 E) -> Vec<String>;
|
fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec<String>;
|
||||||
fn compile(ast: Self::AST) -> LLVMCodeString;
|
fn compile(ast: Self::AST) -> LLVMCodeString;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,3 +33,10 @@ pub trait EvaluationMachine {
|
|||||||
fn set_option(&mut self, option: &str, value: bool) -> bool;
|
fn set_option(&mut self, option: &str, value: bool) -> bool;
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait LanguageWrapper {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<X, T, A, E> LanguageWrapper for X where X: ProgrammingLanguage<Token=T, AST=A, Evaluator=E>, T: Debug, A: Debug, E: EvaluationMachine {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -14,9 +14,10 @@ pub struct Token { }
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AST { }
|
pub struct AST { }
|
||||||
|
|
||||||
impl ProgrammingLanguage<MaaruEvaluator> for Maaru {
|
impl ProgrammingLanguage for Maaru {
|
||||||
type Token = Token;
|
type Token = Token;
|
||||||
type AST = AST;
|
type AST = AST;
|
||||||
|
type Evaluator = MaaruEvaluator;
|
||||||
|
|
||||||
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError> {
|
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError> {
|
||||||
Ok(vec![Token { }])
|
Ok(vec![Token { }])
|
||||||
@ -25,7 +26,7 @@ impl ProgrammingLanguage<MaaruEvaluator> for Maaru {
|
|||||||
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError> {
|
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError> {
|
||||||
Ok(AST { })
|
Ok(AST { })
|
||||||
}
|
}
|
||||||
fn evaluate(ast: Self::AST, evaluator: &mut MaaruEvaluator) -> Vec<String> {
|
fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec<String> {
|
||||||
vec!["Unimplemented".to_string()]
|
vec!["Unimplemented".to_string()]
|
||||||
}
|
}
|
||||||
fn compile(ast: Self::AST) -> LLVMCodeString {
|
fn compile(ast: Self::AST) -> LLVMCodeString {
|
||||||
|
19
src/main.rs
19
src/main.rs
@ -15,7 +15,7 @@ use schala_lang::Schala;
|
|||||||
mod maaru_lang;
|
mod maaru_lang;
|
||||||
|
|
||||||
mod language;
|
mod language;
|
||||||
use language::{ProgrammingLanguage, LLVMCodeString, EvaluationMachine};
|
use language::{ProgrammingLanguage, LanguageWrapper, LLVMCodeString, EvaluationMachine};
|
||||||
|
|
||||||
mod llvm_wrap;
|
mod llvm_wrap;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ fn main() {
|
|||||||
repl.run();
|
repl.run();
|
||||||
}
|
}
|
||||||
[_, ref filename, _..] => {
|
[_, ref filename, _..] => {
|
||||||
let language = Schala { };
|
let language = Schala::new();
|
||||||
run_noninteractive(filename, !option_matches.opt_present("i"), trace, &language);
|
run_noninteractive(filename, !option_matches.opt_present("i"), trace, &language);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -56,7 +56,7 @@ fn program_options() -> getopts::Options {
|
|||||||
options
|
options
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_noninteractive<'a, T: ProgrammingLanguage<SchalaEvaluator<'a>>>(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 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();
|
||||||
@ -81,7 +81,7 @@ fn run_noninteractive<'a, T: ProgrammingLanguage<SchalaEvaluator<'a>>>(filename:
|
|||||||
if compile {
|
if compile {
|
||||||
compilation_sequence(T::compile(ast), filename);
|
compilation_sequence(T::compile(ast), filename);
|
||||||
} else {
|
} else {
|
||||||
let mut evaluator = <SchalaEvaluator as EvaluationMachine>::new();
|
let mut evaluator = <T as ProgrammingLanguage>::Evaluator::new();
|
||||||
if trace_evaluation {
|
if trace_evaluation {
|
||||||
evaluator.set_option("trace_evaluation", true);
|
evaluator.set_option("trace_evaluation", true);
|
||||||
}
|
}
|
||||||
@ -97,6 +97,7 @@ struct Repl<'a> {
|
|||||||
show_tokens: bool,
|
show_tokens: bool,
|
||||||
show_parse: bool,
|
show_parse: bool,
|
||||||
show_llvm_ir: bool,
|
show_llvm_ir: bool,
|
||||||
|
languages: Vec<Box<LanguageWrapper>>,
|
||||||
evaluator: SchalaEvaluator<'a>,
|
evaluator: SchalaEvaluator<'a>,
|
||||||
interpreter_directive_sigil: char,
|
interpreter_directive_sigil: char,
|
||||||
reader: LineReader,
|
reader: LineReader,
|
||||||
@ -114,6 +115,7 @@ impl<'a> Repl<'a> {
|
|||||||
show_tokens: false,
|
show_tokens: false,
|
||||||
show_parse: false,
|
show_parse: false,
|
||||||
show_llvm_ir: show_llvm,
|
show_llvm_ir: show_llvm,
|
||||||
|
languages: vec![Box::new(Schala::new())],
|
||||||
evaluator: evaluator,
|
evaluator: evaluator,
|
||||||
interpreter_directive_sigil: '.',
|
interpreter_directive_sigil: '.',
|
||||||
reader: reader,
|
reader: reader,
|
||||||
@ -145,11 +147,12 @@ impl<'a> Repl<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn input_handler(&mut self, input: &str) -> String {
|
fn input_handler(&mut self, input: &str) -> String {
|
||||||
let schala = Schala { };
|
let schala = Schala::new();
|
||||||
self.input_handler_new(input, schala)
|
let mut evaluator = <SchalaEvaluator as EvaluationMachine>::new();
|
||||||
|
self.input_handler_new(input, schala, &mut evaluator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_handler_new<T: ProgrammingLanguage<SchalaEvaluator<'a>>>(&mut self, input: &str, language: T) -> String {
|
fn input_handler_new<T: ProgrammingLanguage>(&mut self, input: &str, language: T, mut evaluator: &mut T::Evaluator) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
let tokens = match T::tokenize(input) {
|
let tokens = match T::tokenize(input) {
|
||||||
@ -181,7 +184,7 @@ impl<'a> Repl<'a> {
|
|||||||
output.push_str(&s);
|
output.push_str(&s);
|
||||||
} else {
|
} else {
|
||||||
// for now only handle last output
|
// for now only handle last output
|
||||||
let mut full_output: Vec<String> = T::evaluate(ast, &mut self.evaluator);
|
let mut full_output: Vec<String> = T::evaluate(ast, &mut evaluator);
|
||||||
output.push_str(&full_output.pop().unwrap_or("".to_string()));
|
output.push_str(&full_output.pop().unwrap_or("".to_string()));
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use ::std::marker::PhantomData;
|
||||||
pub mod tokenizer;
|
pub mod tokenizer;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod eval;
|
pub mod eval;
|
||||||
@ -7,20 +8,25 @@ use language::{ProgrammingLanguage, EvaluationMachine, ParseError, TokenError, L
|
|||||||
|
|
||||||
pub use self::eval::Evaluator as SchalaEvaluator;
|
pub use self::eval::Evaluator as SchalaEvaluator;
|
||||||
|
|
||||||
pub struct Schala { }
|
pub struct Schala<'a> { marker: PhantomData<&'a ()> }
|
||||||
|
impl<'a> Schala<'a> {
|
||||||
|
pub fn new() -> Schala<'a> {
|
||||||
|
Schala { marker: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> ProgrammingLanguage<eval::Evaluator<'a>> for Schala {
|
impl<'a> ProgrammingLanguage for Schala<'a> {
|
||||||
type Token = tokenizer::Token;
|
type Token = tokenizer::Token;
|
||||||
type AST = parser::AST;
|
type AST = parser::AST;
|
||||||
|
type Evaluator = SchalaEvaluator<'a>;
|
||||||
|
|
||||||
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError> {
|
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError> {
|
||||||
tokenizer::tokenize(input)
|
tokenizer::tokenize(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
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(ast: Self::AST, evaluator: &mut eval::Evaluator) -> Vec<String> {
|
fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec<String> {
|
||||||
evaluator.run(ast)
|
evaluator.run(ast)
|
||||||
}
|
}
|
||||||
fn compile(ast: Self::AST) -> LLVMCodeString {
|
fn compile(ast: Self::AST) -> LLVMCodeString {
|
||||||
|
Loading…
Reference in New Issue
Block a user