good shit

This commit is contained in:
Snorre Ettrup Altschul 2025-02-21 15:24:46 +01:00
parent a5cc6813d1
commit a450eb05d8
7 changed files with 203 additions and 56 deletions

View file

@ -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));

View file

@ -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> {

View file

@ -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)
}
}
}

View file

@ -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}}"),
}
}

View file

@ -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(),
)
}
}

View file

@ -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()

View file

@ -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,