good shit
This commit is contained in:
parent
a5cc6813d1
commit
a450eb05d8
|
@ -124,12 +124,12 @@ impl Input {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn disable_raw(&mut self) {
|
||||
self.stdout.suspend_raw_mode();
|
||||
pub fn disable_raw(&mut self) -> io::Result<()> {
|
||||
self.stdout.suspend_raw_mode()
|
||||
}
|
||||
|
||||
pub fn enable_raw(&mut self) {
|
||||
self.stdout.activate_raw_mode();
|
||||
pub fn enable_raw(&mut self) -> io::Result<()> {
|
||||
self.stdout.activate_raw_mode()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,14 +165,11 @@ fn main() -> Result<(), io::Error> {
|
|||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
input.disable_raw();
|
||||
input.disable_raw()?;
|
||||
|
||||
let tokens = tokens_result.unwrap();
|
||||
let mut parser = Parser::new(tokens, &mut env);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
input.enable_raw();
|
||||
|
||||
let nodes = match parser.parse() {
|
||||
Ok(nodes) => nodes,
|
||||
Err(err) => {
|
||||
|
@ -196,6 +193,9 @@ fn main() -> Result<(), io::Error> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
input.enable_raw()?;
|
||||
|
||||
print!("{}", color::Fg(color::Reset));
|
||||
|
||||
// println!("\t{}{source}{}", termion::color::Fg(termion::color::Blue), termion::color::Fg(termion::color::Reset));
|
||||
|
|
|
@ -7,29 +7,85 @@ pub type EnvironmentInternalSymbolKey = u16;
|
|||
|
||||
pub struct Environment {
|
||||
map: HashMap<EnvironmentInternalSymbolKey, Rc<NodeEnum>>,
|
||||
stack_depth: usize,
|
||||
max_stack_depth: usize,
|
||||
stack: Vec<Vec<EnvironmentInternalSymbolKey>>,
|
||||
|
||||
symbol_to_id: HashMap<String, EnvironmentInternalSymbolKey>,
|
||||
id_to_symbol: HashMap<EnvironmentInternalSymbolKey, String>,
|
||||
unique_keys: EnvironmentInternalSymbolKey
|
||||
unique_keys: EnvironmentInternalSymbolKey,
|
||||
}
|
||||
|
||||
impl Environment {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: HashMap::new(),
|
||||
stack_depth: 0,
|
||||
max_stack_depth: 5000,
|
||||
stack: vec![vec![]],
|
||||
|
||||
symbol_to_id: HashMap::new(),
|
||||
id_to_symbol: HashMap::new(),
|
||||
unique_keys: 0
|
||||
unique_keys: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_stack(&mut self) -> Result<(), String> {
|
||||
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||
|
||||
if self.stack_depth == self.max_stack_depth {
|
||||
self.unwind_stack();
|
||||
return Err("Max Stack depth exceeded".to_owned());
|
||||
}
|
||||
|
||||
self.stack_depth += 1;
|
||||
self.stack.push(vec![]);
|
||||
|
||||
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pop_stack(&mut self) -> Result<(), String> {
|
||||
debug_assert!(
|
||||
self.stack_depth == self.stack.len() - 1,
|
||||
"Expected stack len: {}, stack_depth: {}",
|
||||
self.stack.len(),
|
||||
self.stack_depth
|
||||
);
|
||||
|
||||
if self.stack_depth == 0 {
|
||||
return Err("Trying to pop empty stack".to_owned());
|
||||
}
|
||||
|
||||
self.stack_depth -= 1;
|
||||
|
||||
for item in self.stack.pop().unwrap() {
|
||||
self.map.remove(&item);
|
||||
}
|
||||
|
||||
debug_assert!(self.stack_depth == self.stack.len() - 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unwind_stack(&mut self) {
|
||||
for stack in &self.stack {
|
||||
for item in stack {
|
||||
self.map.remove(&item);
|
||||
}
|
||||
}
|
||||
|
||||
self.stack = vec![vec![]];
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &EnvironmentInternalSymbolKey) -> Option<&Rc<NodeEnum>> {
|
||||
self.map.get(key)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: EnvironmentInternalSymbolKey, value: Rc<NodeEnum>) {
|
||||
self.map.insert(key, value);
|
||||
unsafe { self.stack.get_unchecked_mut(self.stack_depth).push(key) }
|
||||
}
|
||||
|
||||
pub fn str_to_id(&self, value: &String) -> Option<&EnvironmentInternalSymbolKey> {
|
||||
|
|
|
@ -50,15 +50,15 @@ impl Node for Call {
|
|||
// Pass arguments to native function
|
||||
FunctionType::Native(_name, native_function) => native_function(&arguments),
|
||||
FunctionType::UserFunction(node_enum) => {
|
||||
// TODO: Push scope
|
||||
env.push_stack()?;
|
||||
// Define variables
|
||||
fargs.iter().zip(arguments).for_each(|(symbol, value)| {
|
||||
env.insert(symbol.get_value(), value.clone());
|
||||
});
|
||||
let ev = node_enum.evaluate(env);
|
||||
// TODO: Pop scope
|
||||
let ev = node_enum.evaluate(env)?;
|
||||
env.pop_stack()?;
|
||||
// Return evaluated return value for function
|
||||
ev
|
||||
Ok(ev)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ impl Node for Empty {
|
|||
fn as_string(&self, _: Option<&Environment>) -> String {
|
||||
match &self.message {
|
||||
Some(m) => m.clone(),
|
||||
None => String::from("{{#VOID}}"),
|
||||
None => String::from("{{#EMPTY}}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::node::empty::Empty;
|
||||
|
||||
use super::{Environment, Node, NodeEnum, Precedence};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||
|
@ -28,8 +30,9 @@ impl Node for Bool {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub enum ElseBranchEnum {
|
||||
ElseIf(Rc<IfElse>),
|
||||
ElseIf(Rc<NodeEnum>),
|
||||
Block(Vec<Rc<NodeEnum>>),
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||
|
@ -56,16 +59,17 @@ impl Node for IfElse {
|
|||
block: &Vec<Rc<NodeEnum>>,
|
||||
env: &mut Environment,
|
||||
) -> Result<Rc<NodeEnum>, String> {
|
||||
// TODO: Push new scope
|
||||
if let Some((last, to_evaluate)) = block.split_last() {
|
||||
env.push_stack()?;
|
||||
let ret = if let Some((last, to_evaluate)) = block.split_last() {
|
||||
for expr in to_evaluate {
|
||||
expr.evaluate(env)?;
|
||||
}
|
||||
last.evaluate(env)
|
||||
} else {
|
||||
Err("Empty if statemenent true branch")?
|
||||
}
|
||||
// TODO: Pop scope
|
||||
Ok(Empty::EMPTY.clone())
|
||||
};
|
||||
env.pop_stack()?;
|
||||
ret
|
||||
}
|
||||
|
||||
match condition {
|
||||
|
@ -73,28 +77,32 @@ impl Node for IfElse {
|
|||
Bool::False => match &self.else_branch {
|
||||
ElseBranchEnum::ElseIf(if_else) => if_else.evaluate(env),
|
||||
ElseBranchEnum::Block(node_enums) => evaluate_block(node_enums, env),
|
||||
ElseBranchEnum::None => Ok(Empty::EMPTY.clone()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn as_string(&self, env: Option<&Environment>) -> String {
|
||||
format!(
|
||||
"if {} then\n{}\nelse\n{}",
|
||||
"if {} then {} {}",
|
||||
self.condition.as_string(env),
|
||||
self.true_branch
|
||||
.iter()
|
||||
.map(|x| x.as_string(env))
|
||||
.reduce(|a, b| a + "\n" + &b)
|
||||
.reduce(|a, b| a + " " + &b)
|
||||
.unwrap()
|
||||
.as_str(),
|
||||
match &self.else_branch {
|
||||
ElseBranchEnum::ElseIf(if_else) => if_else.as_string(env),
|
||||
ElseBranchEnum::Block(vec) =>
|
||||
vec.iter()
|
||||
.map(|x| x.as_string(env))
|
||||
.reduce(|a, b| a + "\n" + &b)
|
||||
.unwrap()
|
||||
+ "\nend",
|
||||
"else ".to_owned()
|
||||
+ &vec
|
||||
.iter()
|
||||
.map(|x| x.as_string(env))
|
||||
.reduce(|a, b| a + "\n" + &b)
|
||||
.unwrap()
|
||||
+ "end",
|
||||
ElseBranchEnum::None => "end".to_owned(),
|
||||
}
|
||||
.as_str()
|
||||
)
|
||||
|
@ -104,3 +112,20 @@ impl Node for IfElse {
|
|||
Precedence::Primary
|
||||
}
|
||||
}
|
||||
|
||||
impl IfElse {
|
||||
pub fn new(
|
||||
condition: Rc<NodeEnum>,
|
||||
true_branch: Vec<Rc<NodeEnum>>,
|
||||
else_branch: ElseBranchEnum,
|
||||
) -> Rc<NodeEnum> {
|
||||
Rc::new(
|
||||
Self {
|
||||
condition,
|
||||
true_branch,
|
||||
else_branch,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ impl Node for Symbol {
|
|||
|
||||
fn as_string(&self, env: Option<&Environment>) -> String {
|
||||
if let Some(env) = env {
|
||||
if let Some(value) = env.get(&self.value) {
|
||||
value.as_string(Some(env))
|
||||
if let Some(str) = env.id_to_str(&self.value) {
|
||||
str.clone()
|
||||
} else {
|
||||
env.id_to_str(&self.value)
|
||||
.cloned()
|
||||
|
|
|
@ -3,18 +3,7 @@ use std::{collections::HashMap, iter::Peekable, rc::Rc, slice::Iter, str::Chars,
|
|||
use crate::{
|
||||
environment::Environment,
|
||||
node::{
|
||||
NodeEnum,
|
||||
add::Add,
|
||||
assign::Assign,
|
||||
call::Call,
|
||||
constant::{Constant, ConstantValue},
|
||||
divide::Divide,
|
||||
equals::Equals,
|
||||
function::{Function, FunctionType},
|
||||
multiply::Multiply,
|
||||
set::Set,
|
||||
subtract::Subtract,
|
||||
symbol::Symbol,
|
||||
add::Add, assign::Assign, call::Call, constant::{Constant, ConstantValue}, divide::Divide, equals::Equals, function::{Function, FunctionType}, if_else::{Bool, ElseBranchEnum, IfElse}, multiply::Multiply, set::Set, subtract::Subtract, symbol::Symbol, NodeEnum
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -45,6 +34,9 @@ pub enum TokenType {
|
|||
Then,
|
||||
Else,
|
||||
End,
|
||||
|
||||
True,
|
||||
False
|
||||
}
|
||||
|
||||
impl TokenType {
|
||||
|
@ -70,6 +62,9 @@ impl TokenType {
|
|||
TokenType::Then => 4,
|
||||
TokenType::Else => 4,
|
||||
TokenType::End => 3,
|
||||
|
||||
TokenType::True => 4,
|
||||
TokenType::False => 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +200,10 @@ impl<'a> Lexer<'a> {
|
|||
"then" => TokenType::Then,
|
||||
"else" => TokenType::Else,
|
||||
"end" => TokenType::End,
|
||||
|
||||
"true" => TokenType::True,
|
||||
"false" => TokenType::False,
|
||||
|
||||
_ => TokenType::Identifier(identifier),
|
||||
},
|
||||
))
|
||||
|
@ -222,7 +221,7 @@ pub enum ParserError {
|
|||
pub struct Parser<'a> {
|
||||
tokens: Peekable<IntoIter<Token>>,
|
||||
environment: &'a mut Environment,
|
||||
previous: Option<&'a Token>,
|
||||
previous: Option<Token>,
|
||||
}
|
||||
|
||||
type Tokens<'a> = Peekable<Iter<'a, Token>>;
|
||||
|
@ -249,15 +248,31 @@ impl<'a> Parser<'a> {
|
|||
Ok(expressions)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn consume<'b>(&'b mut self) -> &'b Option<Token> {
|
||||
self.previous = self.tokens.next();
|
||||
&self.previous
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_at_end(&mut self) -> bool {
|
||||
if self.tokens.peek().is_none() {
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Checks if the next token is `t`, if it is then consume it and return true. Otherwise does
|
||||
/// nothing and returns false.
|
||||
#[inline]
|
||||
fn matchType<'b>(&'b mut self, t: TokenType) -> bool {
|
||||
if let Some(Token(_, token_type)) = self.tokens.peek() {
|
||||
if *token_type == t {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -290,7 +305,7 @@ impl<'a> Parser<'a> {
|
|||
let expr = self.equality();
|
||||
|
||||
if let Some(Token(_, TokenType::ColonEquals)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
return Ok(Rc::new(Assign::new(expr?, self.equality()?).into()));
|
||||
}
|
||||
|
||||
|
@ -316,7 +331,7 @@ impl<'a> Parser<'a> {
|
|||
if self.matchType(TokenType::Plus) {
|
||||
Ok(Rc::new(Add::new(expr, self.comparison()?).into()))
|
||||
} else if let Some(Token(_, TokenType::Minus)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
Ok(Rc::new(Subtract::new(expr, self.comparison()?).into()))
|
||||
} else {
|
||||
Ok(expr)
|
||||
|
@ -326,10 +341,10 @@ impl<'a> Parser<'a> {
|
|||
fn factor(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||
let expr = self.unary()?;
|
||||
if let Some(Token(_, TokenType::Star)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
Ok(Rc::new(Multiply::new(expr, self.comparison()?).into()))
|
||||
} else if let Some(Token(_, TokenType::Slash)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
Ok(Rc::new(Divide::new(expr, self.comparison()?).into()))
|
||||
} else {
|
||||
Ok(expr)
|
||||
|
@ -366,7 +381,7 @@ impl<'a> Parser<'a> {
|
|||
Set::new(vec![potential_parameters])
|
||||
};
|
||||
|
||||
expr = Ok(Call::new(expr?, parameters));
|
||||
expr = Ok(Call::new(expr?, parameters));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -382,7 +397,7 @@ impl<'a> Parser<'a> {
|
|||
0
|
||||
};
|
||||
|
||||
let expr = self.primary()?;
|
||||
let expr = self.if_else()?;
|
||||
|
||||
if self.matchType(TokenType::LeftArrow) {
|
||||
let right = self.equality()?;
|
||||
|
@ -397,6 +412,8 @@ impl<'a> Parser<'a> {
|
|||
let mut symbols = vec![];
|
||||
for (i, value) in set.get_values().into_iter().enumerate() {
|
||||
match value.as_ref() {
|
||||
NodeEnum::Symbol(symbol) => symbols.push(symbol.clone()),
|
||||
|
||||
_ => {
|
||||
return Err(ParserError::UnexpectedNode(
|
||||
error_loc,
|
||||
|
@ -405,8 +422,6 @@ impl<'a> Parser<'a> {
|
|||
),
|
||||
));
|
||||
}
|
||||
|
||||
NodeEnum::Symbol(symbol) => symbols.push(symbol.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -424,6 +439,54 @@ impl<'a> Parser<'a> {
|
|||
Ok(expr)
|
||||
}
|
||||
|
||||
fn if_else(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||
if self.matchType(TokenType::If) {
|
||||
let condition = self.equality()?;
|
||||
|
||||
let _ = self.matchOrErr(TokenType::Then)?;
|
||||
|
||||
let mut expressions = vec![];
|
||||
|
||||
while !(self.matchType(TokenType::End) || self.matchType(TokenType::Else)) {
|
||||
if self.is_at_end() {
|
||||
return Err(ParserError::UnexpectedEndOfTokens(
|
||||
"Expected an else or end here".to_owned(),
|
||||
));
|
||||
}
|
||||
expressions.push(self.expression()?);
|
||||
}
|
||||
|
||||
// Safe to unwrap since the while loop would terminate if previous was none (it didnt
|
||||
// find an End or Else before running out of tokens)
|
||||
let else_branch = match self.previous.as_ref().unwrap() {
|
||||
Token(_, TokenType::End) => ElseBranchEnum::None,
|
||||
Token(_, TokenType::Else) => {
|
||||
if let Some(Token(_, TokenType::If)) = self.tokens.peek() {
|
||||
ElseBranchEnum::ElseIf(self.if_else()?)
|
||||
} else {
|
||||
let mut expressions = vec![];
|
||||
while !self.matchType(TokenType::End) {
|
||||
if self.is_at_end() {
|
||||
return Err(ParserError::UnexpectedEndOfTokens(
|
||||
"Expected an end here".to_owned(),
|
||||
));
|
||||
}
|
||||
expressions.push(self.expression()?);
|
||||
}
|
||||
|
||||
ElseBranchEnum::Block(expressions)
|
||||
}
|
||||
}
|
||||
|
||||
_ => panic!("Not possible"),
|
||||
};
|
||||
|
||||
return Ok(IfElse::new(condition, expressions, else_branch));
|
||||
}
|
||||
|
||||
self.primary()
|
||||
}
|
||||
|
||||
fn primary(&mut self) -> Result<Rc<NodeEnum>, ParserError> {
|
||||
let (i, token) = if let Some(Token(i, token)) = self.tokens.next() {
|
||||
(i, token)
|
||||
|
@ -438,6 +501,9 @@ impl<'a> Parser<'a> {
|
|||
TokenType::Identifier(string) => Ok(Rc::new(
|
||||
Symbol::new_from_str(string, self.environment).into(),
|
||||
)),
|
||||
TokenType::True => Ok(Rc::new(Bool::True.into())),
|
||||
TokenType::False => Ok(Rc::new(Bool::False.into())),
|
||||
|
||||
TokenType::LParen => {
|
||||
let expr = self.expression()?;
|
||||
let (i, t) = if let Some(Token(i, x)) = self.tokens.peek() {
|
||||
|
@ -450,14 +516,14 @@ impl<'a> Parser<'a> {
|
|||
|
||||
match t {
|
||||
TokenType::RParen => {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
Ok(expr)
|
||||
}
|
||||
TokenType::Comma => {
|
||||
let mut values = vec![expr];
|
||||
while {
|
||||
if let Some(Token(_, TokenType::RParen)) = self.tokens.peek() {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
@ -472,7 +538,7 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
|
||||
if *token == TokenType::Comma {
|
||||
self.tokens.next();
|
||||
self.consume();
|
||||
} else {
|
||||
return Err(ParserError::UnexpectedToken(
|
||||
*i,
|
||||
|
|
Loading…
Reference in a new issue