Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
loop changes
Browse files Browse the repository at this point in the history
for -> loop ...
while -> loop if ...
  • Loading branch information
Thepigcat76 committed Nov 16, 2023
1 parent 75e8b84 commit 04e72b6
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 145 deletions.
134 changes: 92 additions & 42 deletions src/evaluator/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ pub struct Evaluator {

impl Evaluator {
pub fn new() -> Self {
Self { env: Environment::new() }
Self {
env: Environment::new(),
}
}

fn eval(&mut self, statement: &Statement) -> Object {
Expand All @@ -24,15 +26,14 @@ impl Evaluator {

pub fn eval_program(&mut self, program: Program) -> Option<Object> {
let mut result = Some(Object::None(NoneLit));

for statement in program.statements.iter() {
let statement_result = self.eval(statement);
result = Some(statement_result);
}

result
}


fn eval_statement(&mut self, statement: &Statement, is_local: bool) -> Object {
match statement {
Expand Down Expand Up @@ -80,14 +81,10 @@ impl Evaluator {
Expression::PREFIX(prefix) => self.eval_prefix_expression(prefix),
Expression::INFIX(infix) => self.eval_infix_expression(infix),
Expression::BOOLEAN(bool) => Object::Bool(Bool {
value: match &bool.bool_type {
BooleanType::TRUE => BooleanType::TRUE,
BooleanType::FALSE => BooleanType::FALSE,
},
value: bool.bool_type,
}),
Expression::IF(if_expr) => self.eval_if_expression(if_expr),
Expression::WHILE(while_loop) => self.eval_while_expression(while_loop),
Expression::FOR(for_loop) => self.eval_for_expression(for_loop),
Expression::LOOP(_loop) => self.eval_loop_expression(_loop),
Expression::FUNC(func) => self.eval_func_expression(func),
Expression::CALL(call) => self.eval_call(call),
Expression::LIST(list) => self.eval_list_literal(list),
Expand Down Expand Up @@ -124,7 +121,10 @@ impl Evaluator {
}

fn eval_use_stmt(&mut self, node: &UseStatement) -> Object {
Object::Use(Use { file_path: convert_path(&node.path), alias: None })
Object::Use(Use {
file_path: convert_path(&node.path),
alias: None,
})
}

// TODO: Correct formatting. Example: "{x} is cool" -> " is cool{x}"
Expand Down Expand Up @@ -184,9 +184,12 @@ impl Evaluator {
}

fn eval_infix_expression(&mut self, node: &InfixExpression) -> Object {
let left = self.eval_expression(&node.left);
let right = self.eval_expression(&node.right);
let operator = &node.operator;
let left = match operator {
Operator::IN => Object::None(NoneLit),
_ => self.eval_expression(&node.left),
};
let right = self.eval_expression(&node.right);

if left.get_type() == ObjectType::NUMBER
&& right.get_type() == ObjectType::NUMBER
Expand All @@ -198,6 +201,7 @@ impl Evaluator {
Operator::EQUAL => self.native_bool_to_object(left == right),
Operator::NOTEQUAL => self.native_bool_to_object(left != right),
Operator::AS => self.eval_conversion_infix_expression(node, left),
Operator::IN => self.eval_contains_expression(node, right),
Operator::RANGE => Object::Range(Range {
left: Box::from(left),
right: Box::from(right),
Expand Down Expand Up @@ -239,21 +243,21 @@ impl Evaluator {
value: match &left.literal().parse() {
Ok(num) => *num,
Err(_) => {
throw_error(&Error::new(format!("Failed to convert {} to a number. This value cannot be convertes", &left.literal())));
throw_error(&Error::new(format!("Failed to convert {} to a number. This value cannot be converted", &left.literal())));
0f64
}
},
}),
r if r == &BuiltinType::BOOLEAN.literal() => Object::Bool(Bool {
value: match left.literal().as_str() {
"true" => BooleanType::TRUE,
"false" => BooleanType::FALSE,
"true" => true,
"false" => false,
_ => {
throw_error(&Error::new(format!(
"Failed to convert {} to a boolean (true or false)",
left.literal()
)));
BooleanType::FALSE
false
}
},
}),
Expand All @@ -264,6 +268,30 @@ impl Evaluator {
}
}

fn eval_contains_expression(&mut self, node: &InfixExpression, right: Object) -> Object {
enum Type {
LIST,
RANGE,
STRING,
NONE,
}

let _type = match right {
Object::Str(_) => Type::STRING,
Object::None(_) => Type::NONE,
Object::Range(_) => Type::RANGE,
Object::List(_) => Type::LIST,
_ => todo!(),
};

match _type {
Type::LIST => todo!(),
Type::RANGE => todo!(),
Type::STRING => todo!(),
Type::NONE => todo!(),
}
}

fn eval_integer_infix_expression(
&mut self,
operator: &Operator,
Expand Down Expand Up @@ -392,16 +420,52 @@ impl Evaluator {
block
}

fn eval_while_expression(&mut self, node: &WhileExpression) -> Object {
let condition = self.eval_expression(&*node.condition);
fn eval_loop_expression(&mut self, node: &LoopExpression) -> Object {
let condition = match node.loop_type {
LoopType::WHILE => self.eval_expression(&*node.condition),
LoopType::FOR => {
let range = match &*node.condition {
Expression::INFIX(infix) => infix,
_ => todo!(),
};
let left = match &*range.left {
Expression::IDENTIFIER(ident) => ident,
_ => todo!(),
};
let right = self.eval_expression(&range.right);

match right {
// FIXME: Replace as conversion with null save conversion
Object::Range(range) => {
let left_val = match &*range.left {
Object::Num(num) => num.value as i32,
_ => todo!(),
};
let right_val = match &*range.right {
Object::Num(num) => num.value as i32,
_ => todo!(),
};

for _ in left_val..right_val {
self.eval_block_statement(&node.consequence);
}

return self.eval_block_statement(&node.consequence);
}
Object::List(list) => todo!(),
_ => todo!(),
}
}
};

while self.is_truthy(&condition) {
self.eval_block_statement(&node.consequence);
}
self.eval_block_statement(&node.consequence)
}

fn eval_for_expression(&mut self, node: &ForExpression) -> Object {
let range = self.eval_expression(&node.loop_list);
fn eval_for_expression(&mut self, node: &LoopExpression) -> Object {
/*let range = self.eval_expression(&node.loop_list);
let range_lit = match range {
Object::Range(range) => range,
_ => todo!("{:?}", range),
Expand All @@ -421,6 +485,8 @@ impl Evaluator {
self.eval_block_statement(&node.consequence);
}
return self.eval_block_statement(&node.consequence);
*/
todo!()
}

fn eval_index(&mut self, node: &IndexExpression) -> Object {
Expand All @@ -432,7 +498,8 @@ impl Evaluator {
Object::Num(num) => num.value as usize,
_ => todo!(),
})
.unwrap().clone(),
.unwrap()
.clone(),
_ => todo!(),
}
}
Expand Down Expand Up @@ -557,10 +624,7 @@ impl Evaluator {

fn is_truthy(&mut self, object: &Object) -> bool {
match object {
Object::Bool(bool) => match bool.value {
BooleanType::TRUE => true,
BooleanType::FALSE => false,
},
Object::Bool(bool) => bool.value,
Object::None(_) => false,
_ => {
throw_error(&Error::new(format!(
Expand All @@ -575,26 +639,12 @@ impl Evaluator {
}

fn native_bool_to_object(&self, bool: bool) -> Object {
match bool {
true => Object::Bool(Bool {
value: BooleanType::TRUE,
}),
false => Object::Bool(Bool {
value: BooleanType::FALSE,
}),
}
Object::Bool(Bool { value: bool })
}

fn eval_bang_expression(&self, right: Object) -> Object {
match right {
Object::Bool(obj) => match obj.value {
BooleanType::TRUE => Object::Bool(Bool {
value: BooleanType::FALSE,
}),
BooleanType::FALSE => Object::Bool(Bool {
value: BooleanType::TRUE,
}),
},
Object::Bool(obj) => Object::Bool(Bool { value: !obj.value }),
Object::None(_) => right,
_ => todo!(),
}
Expand Down
2 changes: 1 addition & 1 deletion src/evaluator/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl Num {

#[derive(Debug, PartialEq, PartialOrd, Clone)]
pub struct Bool {
pub value: BooleanType,
pub value: bool,
}

#[derive(Debug, PartialEq, PartialOrd, Clone)]
Expand Down
10 changes: 2 additions & 8 deletions src/lexer/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,6 @@ impl Lexer {
i if *i == TokenType::USE.literal() => {
push_token!(tokens, TokenType::USE, self.current_pos_line);
}
i if *i == TokenType::TAG.literal() => {
push_token!(tokens, TokenType::TAG, self.current_pos_line);
}
i if *i == TokenType::STRUCT.literal() => {
push_token!(tokens, TokenType::STRUCT, self.current_pos_line);
}
Expand All @@ -359,11 +356,8 @@ impl Lexer {
i if *i == TokenType::RETURN.literal() => {
push_token!(tokens, TokenType::RETURN, self.current_pos_line);
}
i if *i == TokenType::FOR.literal() => {
push_token!(tokens, TokenType::FOR, self.current_pos_line);
}
i if *i == TokenType::WHILE.literal() => {
push_token!(tokens, TokenType::WHILE, self.current_pos_line);
i if *i == TokenType::LOOP.literal() => {
push_token!(tokens, TokenType::LOOP, self.current_pos_line);
}
i if *i == TokenType::IF.literal() => {
push_token!(tokens, TokenType::IF, self.current_pos_line);
Expand Down
8 changes: 2 additions & 6 deletions src/lexer/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ pub enum TokenType {
// keywords
DEP, // project Dependency
USE, // import package
TAG, // tagging code blocks
STRUCT, // struct with fields
ENUM, // list of identifiers
VAR, // mutable variable
CONST, // immutable variable
FUNC, // functions
RETURN, // return statement
FOR, // for loop
WHILE, // while loop
LOOP, // loop
IF, // if statement
WHEN, // when statement
ELSE, // else statement (if, when)
Expand Down Expand Up @@ -94,15 +92,13 @@ impl TokenType {
match self {
TokenType::DEP => String::from("dep"),
TokenType::USE => String::from("use"),
TokenType::TAG => String::from("tag"),
TokenType::STRUCT => String::from("struct"),
TokenType::ENUM => String::from("enum"),
TokenType::VAR => String::from("var"),
TokenType::CONST => String::from("const"),
TokenType::FUNC => String::from("func"),
TokenType::RETURN => String::from("return"),
TokenType::FOR => String::from("for"),
TokenType::WHILE => String::from("while"),
TokenType::LOOP => String::from("loop"),
TokenType::IF => String::from("if"),
TokenType::WHEN => String::from("when"),
TokenType::ELSE => String::from("else"),
Expand Down
13 changes: 5 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ mod lexer;
mod parser;
mod util;

use std::{env, time::Instant};
use std::env;

use builtin::errors;
use lexer::lexer::Lexer;
use parser::parser::Parser;
use util::{input, FileHandler};
use util::FileHandler;

use crate::{
evaluator::{evaluator::Evaluator, object::Error},
util::throw_error,
};
use crate::evaluator::evaluator::Evaluator;

// nexus run <File>

Expand Down Expand Up @@ -45,10 +41,11 @@ fn main() {
fn run_interpreter(src: FileHandler) {
let mut lexer = Lexer::new(src);

let mut parser = match Parser::new(&mut lexer, false) {
let mut parser = match Parser::new(&mut lexer, true) {
Ok(parser) => parser,
Err(_) => todo!(),
};

let ast = parser.parse_program();

let mut evaluator = Evaluator::new();
Expand Down
Loading

0 comments on commit 04e72b6

Please sign in to comment.