diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/interpret/operator.rs | 30 | ||||
| -rw-r--r-- | src/interpret/walker.rs | 189 | ||||
| -rw-r--r-- | src/lex/token.rs | 2 | ||||
| -rw-r--r-- | src/main.rs | 4 | ||||
| -rw-r--r-- | src/parse/ast/expression.rs | 4 | ||||
| -rw-r--r-- | src/parse/ast/statement.rs | 2 | ||||
| -rw-r--r-- | src/parse/parser.rs | 18 |
7 files changed, 142 insertions, 107 deletions
diff --git a/src/interpret/operator.rs b/src/interpret/operator.rs index ce062c7..42c501e 100644 --- a/src/interpret/operator.rs +++ b/src/interpret/operator.rs @@ -1,6 +1,10 @@ use thiserror::Error; -use crate::{parse::ast::expression::Expression, types::bag::TypeBag}; +use crate::{ + error::{RHError, RHErrorKind}, + parse::ast::expression::{Expression, ExpressionKind}, + types::bag::TypeBag, +}; use super::{ value::{Value, ValueKind}, @@ -261,12 +265,26 @@ impl<'t> ValueOperator<'t> { // Yes, we create a new walker for every function call, // it's *way* easier that way. let mut walker = Walker::new(scope, self.types.clone()); - let result = walker.walk_expression(&Expression::Block(Box::new(called.node.body.clone()))); - if let Err(WalkerError::Return(returned)) = result { - Ok(returned) - } else { - result + // Re-assemble the function body into an expression. + let body_expression = Expression { + kind: ExpressionKind::Block(Box::new(called.node.body.clone())), + at: called.node.body.at, + }; + + // Evaluate the function body. + let result = walker.walk_expression(&body_expression); + + match result { + Err(RHError { + kind: RHErrorKind::Run(err), + .. + }) => match err { + WalkerError::Return(returned_value) => Ok(returned_value), + _ => Err(err), + }, + Err(_) => panic!("Walker returned non-walker error."), + Ok(result) => Ok(result), } } } diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs index 01bde11..52f68c8 100644 --- a/src/interpret/walker.rs +++ b/src/interpret/walker.rs @@ -1,16 +1,19 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc}; use crate::{ + error::{ErrorLocation, RHError, RHErrorKind}, interpret::{ operator::ValueOperator, value::{FnValue, ValueKind}, }, + lex::token::Location, parse::ast::{ - expression::Expression, + expression::{Expression, ExpressionKind}, nodes::{ - BinaryOperator as BinOp, BlockNode, SimpleLiteral, StrPart, UnaryOperator as UnOp, + BinaryOperatorKind as BinOp, BlockExpression, SimpleLiteralKind, StrPartKind, + UnaryOperatorKind as UnOp, }, - statement::Statement, + statement::{Statement, StatementKind}, Program, }, types::{bag::TypeBag, TypeKind}, @@ -41,64 +44,70 @@ impl Walker { Walker { scope, types } } - pub fn walk(&mut self, program: &Program) { + pub fn walk(&mut self, program: &Program) -> Result<(), RHError> { self.scope.nest(); for statement in program.statements.iter() { - self.walk_statement(statement).expect("Runtime error."); + self.walk_statement(statement)?; } + Ok(()) } - fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>, WalkerError> { - let result = match statement { - Statement::Expression(node) => { + fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>, RHError> { + let result = match &statement.kind { + StatementKind::Expression(node) => { self.walk_expression(node)?; None } - Statement::Print(node) => { + StatementKind::Print(node) => { let result = self.walk_expression(node)?; println!("{}", result); None } // FIXME: Returns are always expected to have a return even though `return;` is valid. - Statement::Return(node) => { + StatementKind::Return(node) => { // If there's a function running above us it will catch this error. - return Err(WalkerError::Return(self.walk_expression(node)?)); + return Err(walker_error( + statement.at, + WalkerError::Return(self.walk_expression(node)?), + )); } - Statement::Break(node) => { + StatementKind::Break(node) => { let returned = if let Some(expression) = node { Some(self.walk_expression(expression)?) } else { None }; // If there's a loop above us it will catch this error. - return Err(WalkerError::LoopBreak(returned)); + return Err(walker_error(statement.at, WalkerError::LoopBreak(returned))); } // Same here. - Statement::Continue => return Err(WalkerError::LoopContinue), + StatementKind::Continue => { + return Err(walker_error(statement.at, WalkerError::LoopContinue)); + } }; Ok(result) } - pub fn walk_expression(&mut self, node: &Expression) -> Result<Value, WalkerError> { - match node { - Expression::Binary { left, op, right } => { + pub fn walk_expression(&mut self, node: &Expression) -> Result<Value, RHError> { + match &node.kind { + ExpressionKind::Binary { left, op, right } => { // Assignment - match op { + match op.kind { BinOp::ConstAssign => return self.assing_to_lvalue(left, right, true), BinOp::Assign => return self.assing_to_lvalue(left, right, false), _ => {} } // Short-circuting operators - if let BinOp::And | BinOp::Or = op { + if let BinOp::And | BinOp::Or = op.kind { let left_value = self.walk_expression(left)?; let is_left_true = match left_value.kind { ValueKind::Bool(bool) => bool, - _ => return Err(WalkerError::WrongAndOrType), + _ => return Err(walker_error(left.at, WalkerError::WrongAndOrType)), }; - if let BinOp::And = op { + if let BinOp::And = op.kind { if !is_left_true { return Ok(Value::bool(false, &self.types)); } @@ -115,7 +124,7 @@ impl Walker { let exe = ValueOperator::new(&self.types); // Other operators - match op { + match op.kind { BinOp::Plus => exe.add(left, right), BinOp::Minus => exe.sub(left, right), BinOp::Star => exe.mul(left, right), @@ -127,23 +136,22 @@ impl Walker { BinOp::Gte => exe.gte(left, right), BinOp::Lt => exe.gt(right, left), BinOp::Lte => exe.gte(right, left), - _ => unreachable!(), } - .map_err(WalkerError::OperationError) + .map_err(|err| walker_error(op.at, WalkerError::OperationError(err))) } - Expression::Unary { op, right } => { + ExpressionKind::Unary { op, right } => { let value = self.walk_expression(right)?; let exe = ValueOperator::new(&self.types); - match op { + match op.kind { UnOp::Minus => exe.neg(value), UnOp::Not => exe.not(value), } - .map_err(WalkerError::OperationError) + .map_err(|err| walker_error(op.at, WalkerError::OperationError(err))) } - Expression::Call(node) => { + ExpressionKind::Call(node) => { let called = self.walk_expression(&node.called)?; let mut argument_values = Vec::new(); @@ -153,18 +161,19 @@ impl Walker { let exe = ValueOperator::new(&self.types); exe.call(&called, argument_values) + .map_err(|err| walker_error(node.at, err)) } - Expression::ArrayAccess(node) => { + ExpressionKind::ArrayAccess(node) => { let array = self.walk_expression(&node.array)?; let index = self.walk_expression(&node.index)?; let exe = ValueOperator::new(&self.types); exe.subscript(array, index) - .map_err(WalkerError::OperationError) + .map_err(|err| walker_error(node.at, WalkerError::OperationError(err))) } - Expression::MemberAccess(_) => todo!("Structures not implemented yet."), - Expression::Group(node) => self.walk_expression(node), - Expression::ArrayLiteral(node) => { + ExpressionKind::MemberAccess(_) => todo!("Structures not implemented yet."), + ExpressionKind::Group(node) => self.walk_expression(node), + ExpressionKind::ArrayLiteral(node) => { let mut elements = Vec::new(); for expression in &node.elements { elements.push(self.walk_expression(expression)?); @@ -175,23 +184,23 @@ impl Walker { typ: self.types.create_type(TypeKind::Array(self.types.void())), }) } - Expression::SimpleLiteral(token) => { - let value = match token { - SimpleLiteral::Int(int) => Value::int(*int as i64, &self.types), - SimpleLiteral::Float(float) => Value::float(*float as f64, &self.types), - SimpleLiteral::Bool(bool) => Value::bool(*bool, &self.types), + ExpressionKind::SimpleLiteral(node) => { + let value = match node.kind { + SimpleLiteralKind::Int(int) => Value::int(int as i64, &self.types), + SimpleLiteralKind::Float(float) => Value::float(float as f64, &self.types), + SimpleLiteralKind::Bool(bool) => Value::bool(bool, &self.types), }; Ok(value) } - Expression::Block(block) => self.walk_block(block.as_ref()), - Expression::StrLiteral(node) => { + ExpressionKind::Block(block) => self.walk_block(block.as_ref()), + ExpressionKind::StrLiteral(node) => { let mut buffer = String::new(); for part in &node.parts { - match part { - StrPart::Literal(literal) => buffer.push_str(literal), - StrPart::Embed(embed) => { + match &part.kind { + StrPartKind::Literal(literal) => buffer.push_str(literal), + StrPartKind::Embed(embed) => { buffer.push_str(&self.walk_expression(embed)?.to_string()) } }; @@ -199,7 +208,7 @@ impl Walker { Ok(Value::str(buffer, &self.types)) } - Expression::FnLiteral(node) => Ok(Value { + ExpressionKind::FnLiteral(node) => Ok(Value { kind: ValueKind::Fn(Rc::new(RefCell::new(FnValue { node: node.as_ref().clone(), scope: self.scope.clone(), @@ -210,7 +219,7 @@ impl Walker { returns: self.types.void(), }), }), - Expression::If(if_node) => { + ExpressionKind::If(if_node) => { for conditional in &if_node.conditionals { if let ValueKind::Bool(bool) = self.walk_expression(&conditional.condition)?.kind @@ -219,7 +228,10 @@ impl Walker { return self.walk_block(&conditional.block); } } else { - return Err(WalkerError::WrongIfConditionType); + return Err(walker_error( + conditional.at, + WalkerError::WrongIfConditionType, + )); } } @@ -229,52 +241,48 @@ impl Walker { Ok(Value::void(&self.types)) } } - Expression::Loop(loop_node) => { - if let Some(condition) = &loop_node.condition { - loop { - if let ValueKind::Bool(should_repeat) = - self.walk_expression(condition)?.kind - { - if should_repeat { - match self.walk_block(&loop_node.body) { - Err(WalkerError::LoopBreak(loop_value)) => { - return Ok(loop_value.unwrap_or(Value::void(&self.types))); - } - // Do nothing for continue and continue looping of course, you dummy. - Err(WalkerError::LoopContinue) => {} - // This is probably an actual error. - Err(x) => return Err(x), - _ => {} - } - } else { + ExpressionKind::Loop(loop_node) => { + loop { + if let Some(condition) = &loop_node.condition { + let condition_value = self.walk_expression(condition)?; + if let ValueKind::Bool(should_repeat) = condition_value.kind { + if !should_repeat { return Ok(Value::void(&self.types)); } } else { - return Err(WalkerError::WrongLoopConditionType); + return Err(walker_error( + condition.at, + WalkerError::WrongLoopConditionType, + )); } } - } else { - // Same as above. - loop { - match self.walk_block(&loop_node.body) { - Err(WalkerError::LoopBreak(loop_value)) => { - break Ok(loop_value.unwrap_or(Value::void(&self.types))); + + match self.walk_block(&loop_node.body) { + Err(RHError { + kind: RHErrorKind::Run(err), + at: ErrorLocation::Specific(at), + }) => match err { + WalkerError::LoopBreak(loop_value) => { + return Ok(loop_value.unwrap_or(Value::void(&self.types))); } - Err(WalkerError::LoopContinue) => {} - Err(x) => return Err(x), - _ => {} - } + // Do nothing for continue and continue looping of course, you dummy. + WalkerError::LoopContinue => {} + // This is probably an actual error. + _ => return Err(walker_error(at, err)), + }, + Err(_) => panic!("Walker returned non-walker error."), + _ => {} } } } - Expression::Identifier(ident) => self + ExpressionKind::Identifier(ident) => self .scope .get_var(ident, &self.types) - .map_err(WalkerError::ScopeError), + .map_err(|err| walker_error(node.at, WalkerError::ScopeError(err))), } } - fn walk_block(&mut self, block: &BlockNode) -> Result<Value, WalkerError> { + fn walk_block(&mut self, block: &BlockExpression) -> Result<Value, RHError> { self.scope.nest(); for statement in block.statements.iter() { @@ -297,11 +305,11 @@ impl Walker { lvalue: &Expression, rvalue: &Expression, is_constant: bool, - ) -> Result<Value, WalkerError> { + ) -> Result<Value, RHError> { // Maybe other expressions could also be l-values, but these are fine for now. - match lvalue { - Expression::MemberAccess(_) => todo!("Structures not implemented yet."), - Expression::ArrayAccess(node) => { + match &lvalue.kind { + ExpressionKind::MemberAccess(_) => todo!("Structures not implemented yet."), + ExpressionKind::ArrayAccess(node) => { let mut array = self.walk_expression(&node.array)?; let index = self.walk_expression(&node.index)?; let value = self.walk_expression(rvalue)?; @@ -309,21 +317,28 @@ impl Walker { let exe = ValueOperator::new(&self.types); exe.subscript_assign(&mut array, index, value) - .map_err(WalkerError::OperationError) + .map_err(|err| walker_error(node.at, WalkerError::OperationError(err))) } - Expression::Identifier(ident) => { + ExpressionKind::Identifier(ident) => { let value = self.walk_expression(rvalue)?; self.scope .set_var(ident, value.clone(), is_constant) - .map_err(WalkerError::ScopeError)?; + .map_err(|err| walker_error(lvalue.at, WalkerError::ScopeError(err)))?; return Ok(value); } - _ => Err(WalkerError::NonLValueAssignment), + _ => Err(walker_error(lvalue.at, WalkerError::NonLValueAssignment)), } } } -// TODO: Add source maps to the errors. +// This assumes walker errors are always at a specific error location. +fn walker_error(at: Location, walker_error: WalkerError) -> RHError { + RHError { + at: ErrorLocation::Specific(at), + kind: RHErrorKind::Run(walker_error), + } +} + #[derive(Error, Debug)] pub enum WalkerError { #[error("Loop expressions can only take boolean values as conditions.")] diff --git a/src/lex/token.rs b/src/lex/token.rs index 9d6ded0..9435784 100644 --- a/src/lex/token.rs +++ b/src/lex/token.rs @@ -1,4 +1,4 @@ -use std::fmt::{write, Display}; +use std::fmt::Display; #[derive(Clone, Copy, Debug)] pub struct Location { diff --git a/src/main.rs b/src/main.rs index 63f2347..a670f92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,7 @@ fn file(filename: impl AsRef<Path>) { let node = handle_error(parser.parse(), &contents); let mut walker = Walker::root(); - walker.walk(&node); + handle_error(walker.walk(&node), &contents); } fn repl() { @@ -55,7 +55,7 @@ fn repl() { let mut parser = Parser::new(lexer); let node = handle_error(parser.expression(), &input_buffer); - let result = walker.walk_expression(&node).expect("Failed interpreting."); + let result = handle_error(walker.walk_expression(&node), &input_buffer); println!("🥕: {:?}\n", result); } diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs index e883aaa..e67150a 100644 --- a/src/parse/ast/expression.rs +++ b/src/parse/ast/expression.rs @@ -52,7 +52,7 @@ impl Display for Expression { impl Expression { pub(crate) fn nested_fmt(&self, f: &mut Formatter<'_>, depth: usize) -> fmt::Result { let pad = " ".repeat(depth); - match self.kind { + match &self.kind { ExpressionKind::Binary { left, op, right } => { writeln!(f, "{}Binary:", pad)?; writeln!(f, "{}- Left:", pad)?; @@ -100,7 +100,7 @@ impl Expression { writeln!(f, "{}Str:", pad)?; for (i, statement) in expr.parts.iter().enumerate() { writeln!(f, "{}- {}:", pad, i)?; - match statement.kind { + match &statement.kind { StrPartKind::Literal(literal) => { writeln!(f, "{}{}", " ".repeat(depth + 1), literal.clone()) } diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs index 7eb9978..7ed91dc 100644 --- a/src/parse/ast/statement.rs +++ b/src/parse/ast/statement.rs @@ -32,7 +32,7 @@ impl Statement { depth: usize, ) -> std::fmt::Result { let pad = " ".repeat(depth); - match self.kind { + match &self.kind { StatementKind::Expression(expression) => expression.nested_fmt(f, depth)?, StatementKind::Print(expression) => { writeln!(f, "{}Print:", pad)?; diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 4363bbb..19f26b1 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -303,7 +303,10 @@ impl<T: Iterator<Item = Token>> Parser<T> { _ => unreachable!(), }; - left = Expression { at: left.at, kind }; + left = Expression { + at: token.location, + kind, + }; } Ok(left) @@ -311,6 +314,8 @@ impl<T: Iterator<Item = Token>> Parser<T> { fn unit_expression(&mut self) -> Result<Expression, RHError> { if let Some(token) = self.tokens.peek() { + let location = token.location; + let kind = match token.kind { Int(_) | Float(_) | Str(_) | KeywordTrue | KeywordFalse => { let literal = self.tokens.next().unwrap(); @@ -352,10 +357,7 @@ impl<T: Iterator<Item = Token>> Parser<T> { )), }?; - Ok(Expression { - at: token.location, - kind, - }) + Ok(Expression { at: location, kind }) } else { Err(parser_error( ErrorLocation::Eof, @@ -492,9 +494,9 @@ impl<T: Iterator<Item = Token>> Parser<T> { let if_block = self.generic_block()?; conditionals.push(ConditionalBlockNode { + at: if_condition.at, condition: if_condition, block: if_block, - at: if_condition.at, }); // Elifs @@ -503,9 +505,9 @@ impl<T: Iterator<Item = Token>> Parser<T> { let elif_block = self.generic_block()?; conditionals.push(ConditionalBlockNode { + at: elif_condition.at, condition: elif_condition, block: elif_block, - at: elif_condition.at, }); } @@ -559,8 +561,8 @@ impl<T: Iterator<Item = Token>> Parser<T> { let expression = self.expression()?; if consume_if!(self, SemiColon).is_some() { statements.push(Statement { - kind: StatementKind::Expression(expression), at: expression.at, + kind: StatementKind::Expression(expression), }); } else { tail_expression = Some(expression); |
