Skip to content

Commit

Permalink
repl + division fix + aliases fix
Browse files Browse the repository at this point in the history
  • Loading branch information
fmccl committed Jul 21, 2024
1 parent a261f9b commit a1fb681
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 29 deletions.
96 changes: 96 additions & 0 deletions repl/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions repl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "repl"
version = "0.1.0"
edition = "2021"

[dependencies]
molang = { path = "../" }
40 changes: 40 additions & 0 deletions repl/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::{
collections::HashMap,
io::{BufRead, Write},
};

use molang::Value;

fn main() {
let constants = HashMap::new();
let mut variables = HashMap::new();
variables.insert("variable".to_string(), Value::Struct(HashMap::new()));
let mut aliases = HashMap::new();
aliases.insert("v".to_string(), "variable".to_string());

loop {
print!("\x1b[0;36m");

std::io::stdout().flush().unwrap();

print!("\x1b[0;0m");

let mut line = "".into();
let len = std::io::stdin().lock().read_line(&mut line).unwrap();

let compiled = molang::compile(&line[..len]);

match compiled {
Ok(compiled) => {
println!(
"{:?}",
molang::run(&compiled, &constants, &mut variables, &aliases)
);
}
Err(error) => {
println!("{error:?}");
continue;
}
}
}
}
5 changes: 4 additions & 1 deletion src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,12 @@ pub fn run(
for access in accesses {
match access {
AccessExpr::Name(name) => {
let mut name = name;
if let Value::Null = unsafe { current.as_ref().unwrap() } {
loop {
if let Some(long_name) = aliases.get(name) {
name = long_name;
}
if let Some(some_current) = variables.get_mut(name) {
current = some_current;
break;
Expand All @@ -168,7 +172,6 @@ pub fn run(
struc.insert(name.clone(), Value::Struct(HashMap::new()));
current = struc.get_mut(name).unwrap();
}
// create field if it doesnt exist
} else {
return Err(MolangError::BadAccess(
".".to_string(),
Expand Down
16 changes: 13 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,30 @@ mod tokeniser;
mod value;

pub use interpreter::run;
pub use interpreter::MolangError;
pub use molang_proc_macro::MolangStruct;
pub use parser::Expr;
use thiserror::Error;
use tokeniser::TokeniseError;
pub use value::FromMolangValue;
pub use value::ToMolangValue;
pub use interpreter::MolangError;
pub use value::Value;

pub fn compile(expr: &str) -> Result<Expr, CompileError> {
parser::treeify(tokeniser::tokenise(expr).as_slice())
match tokeniser::tokenise(expr) {
Err(te) => Err(CompileError::TokeniseError(te)),
Ok(tokens) => parser::treeify(tokens.as_slice()),
}
}

#[derive(Debug, Error, PartialEq)]
pub enum CompileError {
#[error("Tokens before prefix operator")]
TokensBeforePrefixOperator,
}

#[error("Incomplete expression")]
IncompleteExpression,

#[error("Tokenise error {0}")]
TokeniseError(TokeniseError),
}
28 changes: 15 additions & 13 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

use crate::{
data::Operator, Value, tokeniser::{Access, Token}, CompileError
data::Operator,
tokeniser::{Access, Token},
CompileError, Value,
};

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -28,11 +29,10 @@ pub enum Instruction {
pub enum AccessExpr {
Name(String),
Index(Expr),
Call(Vec<Expr>)
Call(Vec<Expr>),
}

pub fn treeify(mut tokens: &[Token]) -> Result<Expr, CompileError> {

if let [Token::OpenBracket, inner_tokens @ .., Token::CloseBracket] = tokens {
tokens = inner_tokens
}
Expand Down Expand Up @@ -65,19 +65,21 @@ pub fn treeify(mut tokens: &[Token]) -> Result<Expr, CompileError> {
return Ok(Expr::Derived(Box::new(match op {
Operator::Not => {
if !left.is_empty() {
return Err(CompileError::TokensBeforePrefixOperator)
return Err(CompileError::TokensBeforePrefixOperator);
}
Instruction::Not(treeify(right)?)
},
}
Operator::Equality => Instruction::Eqaulity(treeify(left)?, treeify(right)?),
Operator::Assignment => Instruction::Assignment(treeify(left)?, treeify(right)?),
Operator::Add => Instruction::Add(treeify(left)?, treeify(right)?),
Operator::Subtract => Instruction::Subtract(treeify(left)?, treeify(right)?),
Operator::Multiply => Instruction::Multiply(treeify(left)?, treeify(right)?),
Operator::Divide => Instruction::Multiply(treeify(left)?, treeify(right)?),
Operator::Divide => Instruction::Divide(treeify(left)?, treeify(right)?),
Operator::Conditional => Instruction::Conditional(treeify(left)?, treeify(right)?),
Operator::Colon => Instruction::Colon(treeify(left)?, treeify(right)?),
Operator::NullishCoalescing => Instruction::NullishCoalescing(treeify(left)?, treeify(right)?),
Operator::NullishCoalescing => {
Instruction::NullishCoalescing(treeify(left)?, treeify(right)?)
}
})));
} else {
match tokens {
Expand All @@ -95,14 +97,14 @@ pub fn treeify(mut tokens: &[Token]) -> Result<Expr, CompileError> {
access_exprs.push(AccessExpr::Call(args));
}
Access::Name(name) => access_exprs.push(AccessExpr::Name(name.clone())),
Access::Index(tokens) => access_exprs.push(AccessExpr::Index(treeify(tokens)?))
Access::Index(tokens) => {
access_exprs.push(AccessExpr::Index(treeify(tokens)?))
}
}
}
Ok(Expr::Derived(Box::new(Instruction::Access(access_exprs))))
},
a => {
panic!("Unparsable tokens: {a:?}")
}
_ => Err(CompileError::IncompleteExpression),
}
}
}
Expand All @@ -127,4 +129,4 @@ fn comma_split<'a>(tokens: &'a Vec<Token>) -> Vec<&'a [Token]> {
}

result
}
}
29 changes: 17 additions & 12 deletions src/tokeniser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum Access {
Call(Vec<Token>),
}

#[derive(Error, Debug)]
#[derive(Error, Debug, PartialEq)]
pub enum TokeniseError {
Expectation { found: String, expected: String },
}
Expand Down Expand Up @@ -334,9 +334,9 @@ impl State<char, Access, TokeniseError> for BracketState {
Some(c) if c == close && self.open_brackets == 0 => {
self.open_brackets += 1;
let acc = if self.call {
Access::Call(tokenise(&self.inner))
Access::Call(tokenise(&self.inner)?)
} else {
Access::Index(tokenise(&self.inner))
Access::Index(tokenise(&self.inner)?)
};
Ok((
Some(acc),
Expand Down Expand Up @@ -388,15 +388,15 @@ impl State<char, Token, TokeniseError> for DoubleState {
}
}

pub fn tokenise(input: &str) -> Vec<Token> {
pub fn tokenise(input: &str) -> Result<Vec<Token>, TokeniseError> {
let mut state: Box<dyn State<char, Token, TokeniseError>> = Box::new(NormalState {});

let mut i = 0;

let mut tokens = Vec::new();

loop {
let (token, new_state, action) = state.handle(input.chars().nth(i)).unwrap();
let (token, new_state, action) = state.handle(input.chars().nth(i))?;
if let Some(new_state) = new_state {
state = new_state;
}
Expand All @@ -410,19 +410,24 @@ pub fn tokenise(input: &str) -> Vec<Token> {
}
}

tokens
Ok(tokens)
}

#[cfg(test)]
mod test {
use std::collections::VecDeque;

use crate::{data::Operator, tokeniser::{tokenise, Access, Token}};

use crate::{
data::Operator,
tokeniser::{tokenise, Access, Token},
};

#[test]
fn number() {
assert_eq!(VecDeque::from([Token::Number(100.0)]), tokenise("100.0"));
assert_eq!(
VecDeque::from([Token::Number(100.0)]),
tokenise("100.0").unwrap()
);
}

#[test]
Expand All @@ -433,7 +438,7 @@ mod test {
Access::Name("sin".to_string()),
Access::Call(vec![Token::Number(1.0)])
])]),
tokenise("math.sin(1)")
tokenise("math.sin(1)").unwrap()
);
}

Expand All @@ -445,7 +450,7 @@ mod test {
Token::Operator(Operator::Multiply),
Token::Number(99.0)
]),
tokenise("100.0*99")
tokenise("100.0*99").unwrap()
);
}

Expand All @@ -457,7 +462,7 @@ mod test {
Token::Operator(Operator::Divide),
Token::Number(99.0)
]),
tokenise("100.0/99")
tokenise("100.0/99").unwrap()
);
}
}

0 comments on commit a1fb681

Please sign in to comment.