From dd22ca0291608e7ce8dbd828c9af9697fb6b0ff5 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 29 Aug 2017 00:28:19 -0700 Subject: [PATCH] Grand renaming of things --- README.md | 57 +++--- closure.schala => closure.maaru | 0 compile.schala => compile.maaru | 0 conditional.schala => conditional.maaru | 0 lambda.schala => lambda.maaru | 0 main.schala => main.maaru | 0 recurse.schala => recurse.maaru | 0 .../compilation.rs | 2 +- src/{schala_lang => maaru_lang}/eval.rs | 6 +- src/maaru_lang/mod.rs | 163 +++-------------- src/{schala_lang => maaru_lang}/parser.rs | 4 +- src/{schala_lang => maaru_lang}/tokenizer.rs | 0 src/main.rs | 11 +- src/robo_lang/mod.rs | 169 ++++++++++++++++++ src/schala_lang/mod.rs | 54 ------ test.schala => test.maaru | 0 unicode.schala => unicode.maaru | 0 while.schala => while.maaru | 0 18 files changed, 243 insertions(+), 223 deletions(-) rename closure.schala => closure.maaru (100%) rename compile.schala => compile.maaru (100%) rename conditional.schala => conditional.maaru (100%) rename lambda.schala => lambda.maaru (100%) rename main.schala => main.maaru (100%) rename recurse.schala => recurse.maaru (100%) rename src/{schala_lang => maaru_lang}/compilation.rs (99%) rename src/{schala_lang => maaru_lang}/eval.rs (99%) rename src/{schala_lang => maaru_lang}/parser.rs (99%) rename src/{schala_lang => maaru_lang}/tokenizer.rs (100%) create mode 100644 src/robo_lang/mod.rs delete mode 100644 src/schala_lang/mod.rs rename test.schala => test.maaru (100%) rename unicode.schala => unicode.maaru (100%) rename while.schala => while.maaru (100%) diff --git a/README.md b/README.md index 628504e..ac65c86 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -Schala -====== -## The experimental programming language meta-interpreter +TODO: +-null-only language should be called Maaru +-haskell-ish langauge should be called Robo +-typeful scripting language should be called schala +rename accordingly! + +# Schala - a programming language meta-interpreter Schala is a Rust-language framework written to make it easy to create and experiment with toy programming languages. It provides @@ -10,34 +14,47 @@ for tokenizing text, parsing tokens, evaluating an abstract syntax tree, and other tasks that are common to all programming languages. Schala started out life as an experiment in writing a Javascript-like -programming language that would never encounter any kind of runtime -value error, but rather always return `null` under any kind of error -condition. I had seen one too many Javascript `Uncaught TypeError: -Cannot read property ___ of undefined` messages, and I was a bit frustrated. -Plus I had always wanted to write a programming langauge from scratch, -and Rust is a fun language to program in. +programming language that would never encounter any kind of runtime value +error, but rather always return `null` under any kind of error condition. I had +seen one too many Javascript `Uncaught TypeError: Cannot read property ___ of +undefined` messages, and I was a bit frustrated. Plus I had always wanted to +write a programming langauge from scratch, and Rust is a fun language to +program in. Over time I became interested in playing around with other sorts +of programming languages as well, and wanted to make the process as general as +possible. -Over time I became interested in playing around with other sorts -of programming languages as well, and wanted to make the process -as general as possible. I changed the name of the project to -Schala, after the Princess of Zeal from *Chrono Trigger*, because I -like classic JRPGs and because it sounds sort of like Scala. +The name of the project comes from Schala the Princess of Zeal from the 1995 +SNES RPG *Chrono Trigger*. I like classic JRPGs and enjoyed the thought of +creating a language name confusingly close to Scala. The naming scheme for +languages implemented with the Schala meta-interpreter is Chrono Trigger +characters. -Schala is as yet an incomplete personal project that I continue to work -on as my time permits. +## Languages implemented using the meta-interpreter -### Reference works +* The eponymous *Schala* language is an interpreted/compiled scripting langauge, +designed to be relatively simple, but with a reasonably sophisticated type +system. + +* *Maaru* was the original Schala (since renamed to free up the name *Schala* + for the above language), a very simple dynamically-typed scripting language + such that all possible runtime errors result in null rather than program + failure. + +* *Robo* is an experiment in creating a lazy, functional, strongly-typed language +much like Haskell + +## Reference works Here's a partial list of resources I've made use of in the process of learning how to write a programming language. -#### Evaluation +### Evaluation *Understanding Computation*, Tom Stuart, O'Reilly 2013 -#### Parsing +### Parsing http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ [Crafting Interpreters](http://www.craftinginterpreters.com/) -#### LLVM +### LLVM http://blog.ulysse.io/2016/07/03/llvm-getting-started.html diff --git a/closure.schala b/closure.maaru similarity index 100% rename from closure.schala rename to closure.maaru diff --git a/compile.schala b/compile.maaru similarity index 100% rename from compile.schala rename to compile.maaru diff --git a/conditional.schala b/conditional.maaru similarity index 100% rename from conditional.schala rename to conditional.maaru diff --git a/lambda.schala b/lambda.maaru similarity index 100% rename from lambda.schala rename to lambda.maaru diff --git a/main.schala b/main.maaru similarity index 100% rename from main.schala rename to main.maaru diff --git a/recurse.schala b/recurse.maaru similarity index 100% rename from recurse.schala rename to recurse.maaru diff --git a/src/schala_lang/compilation.rs b/src/maaru_lang/compilation.rs similarity index 99% rename from src/schala_lang/compilation.rs rename to src/maaru_lang/compilation.rs index 2949212..20ddd9f 100644 --- a/src/schala_lang/compilation.rs +++ b/src/maaru_lang/compilation.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use self::llvm_sys::prelude::*; use self::llvm_sys::{LLVMIntPredicate, LLVMRealPredicate}; -use schala_lang::parser::{AST, Statement, Function, Prototype, Expression, BinOp}; +use maaru_lang::parser::{AST, Statement, Function, Prototype, Expression, BinOp}; use language::LLVMCodeString; use llvm_wrap as LLVMWrap; diff --git a/src/schala_lang/eval.rs b/src/maaru_lang/eval.rs similarity index 99% rename from src/schala_lang/eval.rs rename to src/maaru_lang/eval.rs index 91d04b2..9da3836 100644 --- a/src/schala_lang/eval.rs +++ b/src/maaru_lang/eval.rs @@ -2,13 +2,13 @@ extern crate take_mut; use std::collections::HashMap; use std::collections::VecDeque; -use schala_lang::parser::{AST, Statement, Expression, Function, Callable, BinOp}; +use maaru_lang::parser::{AST, Statement, Expression, Function, Callable, BinOp}; use std::rc::Rc; use std::io::{Write, Stdout, BufWriter}; use std::convert::From; -use schala_lang::parser::Expression::*; -use schala_lang::parser::Statement::*; +use maaru_lang::parser::Expression::*; +use maaru_lang::parser::Statement::*; type Reduction = (T, Option); diff --git a/src/maaru_lang/mod.rs b/src/maaru_lang/mod.rs index 18f0b34..3666d93 100644 --- a/src/maaru_lang/mod.rs +++ b/src/maaru_lang/mod.rs @@ -1,157 +1,44 @@ -extern crate itertools; -use self::itertools::Itertools; +use ::std::marker::PhantomData; +pub mod tokenizer; +pub mod parser; +pub mod eval; +pub mod compilation; use language::{ProgrammingLanguage, EvaluationMachine, ParseError, TokenError, LLVMCodeString}; -pub struct Maaru { -} +pub use self::eval::Evaluator as MaaruEvaluator; -impl Maaru { - pub fn new() -> Maaru { - Maaru { } +pub struct Maaru<'a> { marker: PhantomData<&'a ()> } +impl<'a> Maaru<'a> { + pub fn new() -> Maaru <'a> { + Maaru { marker: PhantomData } } } -pub struct MaaruEvaluator { - pub trace_evaluation: bool, -} - -#[derive(Debug)] -pub enum Token { - StrLiteral(String), - Backtick, - Newline, - LParen, - RParen, - LBracket, - RBracket, - LBrace, - RBrace, - Period, - Comma, - Colon, - Semicolon, - SingleQuote, - Identifier(String), - Operator(String), - NumLiteral(Number), -} - -#[derive(Debug)] -pub enum Number { - IntegerRep(String), - FloatRep(String) -} - -pub type AST = Vec; - -#[derive(Debug)] -pub enum ASTNode { - FunctionDefinition(String, Expression), - ImportStatement(String), -} - -#[derive(Debug)] -pub enum Expression { - -} - -impl ProgrammingLanguage for Maaru { - type Token = Token; - type AST = AST; - type Evaluator = MaaruEvaluator; +impl<'a> ProgrammingLanguage for Maaru<'a> { + type Token = tokenizer::Token; + type AST = parser::AST; + type Evaluator = MaaruEvaluator<'a>; fn name() -> String { "Maaru".to_string() } fn tokenize(input: &str) -> Result, TokenError> { - use self::Token::*; - let mut tokens = Vec::new(); - let mut iter = input.chars().peekable(); - while let Some(c) = iter.next() { - if c == ';' { - while let Some(c) = iter.next() { - if c == '\n' { - break; - } - } - continue; - } - let cur_tok = match c { - c if char::is_whitespace(c) && c != '\n' => continue, - '\n' => Newline, - '(' => LParen, - ')' => RParen, - '[' => LBracket, - ']' => RBracket, - '{' => LBrace, - '}' => RBrace, - ',' => Comma, - ':' => Colon, - ';' => Semicolon, - '.' => Period, - '`' => Backtick, - '\'' => SingleQuote, - '"' => { - let mut buffer = String::new(); - loop { - match iter.next() { - Some(x) if x == '"' => break, - Some(x) => buffer.push(x), - None => return Err(TokenError::new("Unclosed quote")), - } - } - StrLiteral(buffer) - } - c if c.is_digit(10) => { - let mut integer = true; - let mut buffer = String::new(); - buffer.push(c); - buffer.extend(iter.peeking_take_while(|x| x.is_digit(10))); - if let Some(&'.') = iter.peek() { - buffer.push(iter.next().unwrap()); - integer = false; - } - buffer.extend(iter.peeking_take_while(|x| x.is_digit(10))); - let inner = if integer { - Number::IntegerRep(buffer) - } else { - Number::FloatRep(buffer) - }; - NumLiteral(inner) - }, - c if char::is_alphanumeric(c) => { - let mut buffer = String::new(); - buffer.push(c); - buffer.extend(iter.peeking_take_while(|x| char::is_alphanumeric(*x))); - Identifier(buffer) - }, - c => { - let mut buffer = String::new(); - buffer.push(c); - buffer.extend(iter.peeking_take_while(|x| !char::is_whitespace(*x))); - Operator(buffer) - } - }; - tokens.push(cur_tok); - } - - Ok(tokens) + tokenizer::tokenize(input) } - - fn parse(_input: Vec) -> Result { - Ok(vec!()) + fn parse(input: Vec) -> Result { + parser::parse(&input, &[]).map_err(|x| ParseError { msg: x.msg }) } - fn evaluate(_ast: Self::AST, _evaluator: &mut Self::Evaluator) -> Vec { - vec!["Unimplemented".to_string()] + fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec { + evaluator.run(ast) } - fn compile(_ast: Self::AST) -> LLVMCodeString { - unimplemented!() + fn compile(ast: Self::AST) -> LLVMCodeString { + compilation::compile_ast(ast) } } -impl EvaluationMachine for MaaruEvaluator { +impl<'a> EvaluationMachine for MaaruEvaluator<'a> { fn set_option(&mut self, option: &str, value: bool) -> bool { if option == "trace_evaluation" { self.trace_evaluation = value; @@ -161,9 +48,7 @@ impl EvaluationMachine for MaaruEvaluator { false } - fn new() -> MaaruEvaluator { - MaaruEvaluator { - trace_evaluation: false, - } + fn new() -> MaaruEvaluator<'a> { + MaaruEvaluator::new(None) } } diff --git a/src/schala_lang/parser.rs b/src/maaru_lang/parser.rs similarity index 99% rename from src/schala_lang/parser.rs rename to src/maaru_lang/parser.rs index ec19972..bb094f6 100644 --- a/src/schala_lang/parser.rs +++ b/src/maaru_lang/parser.rs @@ -1,5 +1,5 @@ -use schala_lang::tokenizer::{Token, Kw, OpTok}; -use schala_lang::tokenizer::Token::*; +use maaru_lang::tokenizer::{Token, Kw, OpTok}; +use maaru_lang::tokenizer::Token::*; use std::fmt; use std::collections::VecDeque; diff --git a/src/schala_lang/tokenizer.rs b/src/maaru_lang/tokenizer.rs similarity index 100% rename from src/schala_lang/tokenizer.rs rename to src/maaru_lang/tokenizer.rs diff --git a/src/main.rs b/src/main.rs index 43dba4c..2b96925 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,11 +9,14 @@ use std::process; use std::io::Write; use std::default::Default; +/* mod schala_lang; use schala_lang::SchalaEvaluator; use schala_lang::Schala; +*/ mod maaru_lang; +mod robo_lang; mod language; use language::{ProgrammingLanguage, LanguageInterface, LLVMCodeString, EvaluationMachine}; @@ -26,8 +29,8 @@ use virtual_machine::{run_vm, run_assembler}; fn main() { let languages: Vec> = vec![ - Box::new((Schala::new(), SchalaEvaluator::new(None))), - Box::new((maaru_lang::Maaru::new(), maaru_lang::MaaruEvaluator::new())), + Box::new((maaru_lang::Maaru::new(), maaru_lang::MaaruEvaluator::new(None))), + Box::new((robo_lang::Robo::new(), robo_lang::RoboEvaluator::new())), ]; let option_matches = @@ -79,7 +82,7 @@ fn main() { repl.run(); } [_, ref filename, _..] => { - let language = Schala::new(); + let language = maaru_lang::Maaru::new(); run_noninteractive(filename, &language, trace_evaluation, compile); } }; @@ -308,7 +311,7 @@ pub fn compilation_sequence(llvm_code: LLVMCodeString, sourcefile: &str) { let obj_filename = "out.o"; let q: Vec<&str> = sourcefile.split('.').collect(); let bin_filename = match &q[..] { - &[name, "schala"] => name, + &[name, "maaru"] => name, _ => panic!("Bad filename {}", sourcefile), }; diff --git a/src/robo_lang/mod.rs b/src/robo_lang/mod.rs new file mode 100644 index 0000000..392ce14 --- /dev/null +++ b/src/robo_lang/mod.rs @@ -0,0 +1,169 @@ +extern crate itertools; +use self::itertools::Itertools; + +use language::{ProgrammingLanguage, EvaluationMachine, ParseError, TokenError, LLVMCodeString}; + +pub struct Robo { +} + +impl Robo { + pub fn new() -> Robo { + Robo { } + } +} + +pub struct RoboEvaluator { + pub trace_evaluation: bool, +} + +#[derive(Debug)] +pub enum Token { + StrLiteral(String), + Backtick, + Newline, + LParen, + RParen, + LBracket, + RBracket, + LBrace, + RBrace, + Period, + Comma, + Colon, + Semicolon, + SingleQuote, + Identifier(String), + Operator(String), + NumLiteral(Number), +} + +#[derive(Debug)] +pub enum Number { + IntegerRep(String), + FloatRep(String) +} + +pub type AST = Vec; + +#[derive(Debug)] +pub enum ASTNode { + FunctionDefinition(String, Expression), + ImportStatement(String), +} + +#[derive(Debug)] +pub enum Expression { + +} + +impl ProgrammingLanguage for Robo { + type Token = Token; + type AST = AST; + type Evaluator = RoboEvaluator; + + fn name() -> String { + "Robo".to_string() + } + + fn tokenize(input: &str) -> Result, TokenError> { + use self::Token::*; + let mut tokens = Vec::new(); + let mut iter = input.chars().peekable(); + while let Some(c) = iter.next() { + if c == ';' { + while let Some(c) = iter.next() { + if c == '\n' { + break; + } + } + continue; + } + let cur_tok = match c { + c if char::is_whitespace(c) && c != '\n' => continue, + '\n' => Newline, + '(' => LParen, + ')' => RParen, + '[' => LBracket, + ']' => RBracket, + '{' => LBrace, + '}' => RBrace, + ',' => Comma, + ':' => Colon, + ';' => Semicolon, + '.' => Period, + '`' => Backtick, + '\'' => SingleQuote, + '"' => { + let mut buffer = String::new(); + loop { + match iter.next() { + Some(x) if x == '"' => break, + Some(x) => buffer.push(x), + None => return Err(TokenError::new("Unclosed quote")), + } + } + StrLiteral(buffer) + } + c if c.is_digit(10) => { + let mut integer = true; + let mut buffer = String::new(); + buffer.push(c); + buffer.extend(iter.peeking_take_while(|x| x.is_digit(10))); + if let Some(&'.') = iter.peek() { + buffer.push(iter.next().unwrap()); + integer = false; + } + buffer.extend(iter.peeking_take_while(|x| x.is_digit(10))); + let inner = if integer { + Number::IntegerRep(buffer) + } else { + Number::FloatRep(buffer) + }; + NumLiteral(inner) + }, + c if char::is_alphanumeric(c) => { + let mut buffer = String::new(); + buffer.push(c); + buffer.extend(iter.peeking_take_while(|x| char::is_alphanumeric(*x))); + Identifier(buffer) + }, + c => { + let mut buffer = String::new(); + buffer.push(c); + buffer.extend(iter.peeking_take_while(|x| !char::is_whitespace(*x))); + Operator(buffer) + } + }; + tokens.push(cur_tok); + } + + Ok(tokens) + } + + fn parse(_input: Vec) -> Result { + Ok(vec!()) + } + fn evaluate(_ast: Self::AST, _evaluator: &mut Self::Evaluator) -> Vec { + vec!["Unimplemented".to_string()] + } + fn compile(_ast: Self::AST) -> LLVMCodeString { + unimplemented!() + } +} + +impl EvaluationMachine for RoboEvaluator { + fn set_option(&mut self, option: &str, value: bool) -> bool { + if option == "trace_evaluation" { + self.trace_evaluation = value; + return true; + } + + false + } + + fn new() -> RoboEvaluator { + RoboEvaluator { + trace_evaluation: false, + } + } +} diff --git a/src/schala_lang/mod.rs b/src/schala_lang/mod.rs deleted file mode 100644 index 09d2ee6..0000000 --- a/src/schala_lang/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -use ::std::marker::PhantomData; -pub mod tokenizer; -pub mod parser; -pub mod eval; -pub mod compilation; - -use language::{ProgrammingLanguage, EvaluationMachine, ParseError, TokenError, LLVMCodeString}; - -pub use self::eval::Evaluator as SchalaEvaluator; - -pub struct Schala<'a> { marker: PhantomData<&'a ()> } -impl<'a> Schala<'a> { - pub fn new() -> Schala<'a> { - Schala { marker: PhantomData } - } -} - -impl<'a> ProgrammingLanguage for Schala<'a> { - type Token = tokenizer::Token; - type AST = parser::AST; - type Evaluator = SchalaEvaluator<'a>; - - fn name() -> String { - "Schala".to_string() - } - - fn tokenize(input: &str) -> Result, TokenError> { - tokenizer::tokenize(input) - } - fn parse(input: Vec) -> Result { - parser::parse(&input, &[]).map_err(|x| ParseError { msg: x.msg }) - } - fn evaluate(ast: Self::AST, evaluator: &mut Self::Evaluator) -> Vec { - evaluator.run(ast) - } - fn compile(ast: Self::AST) -> LLVMCodeString { - compilation::compile_ast(ast) - } -} - -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) - } -} diff --git a/test.schala b/test.maaru similarity index 100% rename from test.schala rename to test.maaru diff --git a/unicode.schala b/unicode.maaru similarity index 100% rename from unicode.schala rename to unicode.maaru diff --git a/while.schala b/while.maaru similarity index 100% rename from while.schala rename to while.maaru