2017-01-21 14:34:17 -08:00
|
|
|
use std::fmt::Debug;
|
2017-01-21 01:49:45 -08:00
|
|
|
|
2017-01-23 19:51:27 -08:00
|
|
|
#[derive(Debug)]
|
2017-01-21 01:49:45 -08:00
|
|
|
pub struct TokenError {
|
|
|
|
pub msg: String,
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:45:26 -08:00
|
|
|
impl TokenError {
|
|
|
|
pub fn new(msg: &str) -> TokenError {
|
|
|
|
TokenError { msg: msg.to_string() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:51:27 -08:00
|
|
|
#[derive(Debug)]
|
2017-01-21 01:49:45 -08:00
|
|
|
pub struct ParseError {
|
|
|
|
pub msg: String,
|
|
|
|
}
|
|
|
|
|
2017-01-23 19:11:50 -08:00
|
|
|
pub struct LLVMCodeString(pub String);
|
|
|
|
|
2017-01-31 00:53:31 -08:00
|
|
|
pub trait ProgrammingLanguage {
|
2017-01-21 14:34:17 -08:00
|
|
|
type Token: Debug;
|
|
|
|
type AST: Debug;
|
2017-01-31 00:53:31 -08:00
|
|
|
type Evaluator: EvaluationMachine;
|
2017-01-21 01:49:45 -08:00
|
|
|
|
2017-02-02 01:04:15 -08:00
|
|
|
fn name() -> String;
|
2017-01-21 01:49:45 -08:00
|
|
|
fn tokenize(input: &str) -> Result<Vec<Self::Token>, TokenError>;
|
|
|
|
fn parse(input: Vec<Self::Token>) -> Result<Self::AST, ParseError>;
|
2017-01-31 00:53:31 -08:00
|
|
|
fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec<String>;
|
2017-01-23 19:11:50 -08:00
|
|
|
fn compile(ast: Self::AST) -> LLVMCodeString;
|
2017-01-21 01:49:45 -08:00
|
|
|
}
|
2017-01-24 20:09:14 -08:00
|
|
|
|
|
|
|
pub trait EvaluationMachine {
|
|
|
|
fn set_option(&mut self, option: &str, value: bool) -> bool;
|
|
|
|
fn new() -> Self;
|
|
|
|
}
|
2017-01-31 00:53:31 -08:00
|
|
|
|
2017-02-01 02:15:18 -08:00
|
|
|
#[derive(Default)]
|
|
|
|
pub struct LanguageInterfaceOptions {
|
|
|
|
pub show_parse: bool,
|
|
|
|
pub show_tokens: bool,
|
|
|
|
pub show_llvm_ir: bool,
|
2017-01-31 00:53:31 -08:00
|
|
|
}
|
|
|
|
|
2017-02-01 02:15:18 -08:00
|
|
|
pub trait LanguageInterface {
|
|
|
|
fn evaluate_in_repl(&mut self, input: &str, options: LanguageInterfaceOptions) -> String;
|
2017-02-02 01:04:15 -08:00
|
|
|
fn get_language_name(&self) -> String;
|
2017-02-05 21:23:11 -08:00
|
|
|
fn set_option(&mut self, option: &str, value: bool) -> bool;
|
2017-02-01 02:15:18 -08:00
|
|
|
}
|
|
|
|
|
2017-02-01 19:04:52 -08:00
|
|
|
impl<PL, T, A, E> LanguageInterface for (PL, PL::Evaluator) where PL: ProgrammingLanguage<Token=T, AST=A, Evaluator=E>, T: Debug, A: Debug, E: EvaluationMachine {
|
2017-02-05 21:23:11 -08:00
|
|
|
fn set_option(&mut self, option: &str, value: bool) -> bool {
|
|
|
|
self.1.set_option(option, value)
|
|
|
|
}
|
2017-02-02 01:04:15 -08:00
|
|
|
fn get_language_name(&self) -> String {
|
|
|
|
PL::name()
|
|
|
|
}
|
2017-02-01 02:15:18 -08:00
|
|
|
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));
|
|
|
|
}
|
2017-01-31 00:53:31 -08:00
|
|
|
|
2017-02-01 02:15:18 -08:00
|
|
|
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
|
2017-02-01 19:04:52 -08:00
|
|
|
let ref mut evaluator = self.1;
|
|
|
|
let mut full_output: Vec<String> = PL::evaluate(ast, evaluator);
|
2017-02-01 02:15:18 -08:00
|
|
|
output.push_str(&full_output.pop().unwrap_or("".to_string()));
|
|
|
|
}
|
|
|
|
output
|
|
|
|
}
|
2017-01-31 00:53:31 -08:00
|
|
|
}
|
2017-08-30 19:09:22 -07:00
|
|
|
|
|
|
|
/* below here is new versions of everything */
|
|
|
|
|
|
|
|
|
2017-08-30 22:58:57 -07:00
|
|
|
#[derive(Debug, Default)]
|
2017-08-30 19:09:22 -07:00
|
|
|
pub struct EvalOptions {
|
2017-08-30 19:15:04 -07:00
|
|
|
pub debug_tokens: bool,
|
|
|
|
pub debug_parse: bool,
|
|
|
|
pub debug_type: bool,
|
|
|
|
pub debug_eval: bool,
|
2017-08-30 19:09:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait ProgrammingLanguageInterface {
|
2017-08-30 19:15:04 -07:00
|
|
|
fn evaluate_in_repl(&mut self, input: &str, eval_options: EvalOptions) -> Vec<String>;
|
2017-08-30 19:09:22 -07:00
|
|
|
fn get_language_name(&self) -> String;
|
2017-08-30 22:58:57 -07:00
|
|
|
fn set_option(&mut self, option: &str, value: bool) -> bool {
|
|
|
|
false
|
|
|
|
}
|
2017-08-30 19:09:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub trait CompileableLanguage : ProgrammingLanguageInterface {
|
2017-08-30 19:15:04 -07:00
|
|
|
fn compile(&mut self) -> LLVMCodeString;
|
2017-08-30 19:09:22 -07:00
|
|
|
}
|