diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index f246538..b901316 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -4,7 +4,7 @@ use crate::{ Context, Value, }; -use super::{AbstractTree, Action, Identifier, Statement, Type, WithPosition}; +use super::{AbstractNode, Action, Identifier, Statement, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Assignment { @@ -37,7 +37,7 @@ impl Assignment { } } -impl AbstractTree for Assignment { +impl AbstractNode for Assignment { fn expected_type(&self, _context: &Context) -> Result { Ok(Type::None) } diff --git a/src/abstract_tree/block.rs b/src/abstract_tree/block.rs index 1c855e3..43331f0 100644 --- a/src/abstract_tree/block.rs +++ b/src/abstract_tree/block.rs @@ -3,7 +3,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Statement, Type, WithPosition}; +use super::{AbstractNode, Action, Statement, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Block { @@ -20,7 +20,7 @@ impl Block { } } -impl AbstractTree for Block { +impl AbstractNode for Block { fn expected_type(&self, _context: &Context) -> Result { if let Some(statement) = self.statements.last() { statement.node.expected_type(_context) diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index fb66486..fe74c47 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -4,7 +4,7 @@ use crate::{ }; use super::{ - AbstractTree, Action, FunctionCall, Identifier, ListIndex, Logic, MapIndex, Math, Type, + AbstractNode, Action, FunctionCall, Identifier, ListIndex, Logic, MapIndex, Math, Type, ValueNode, }; @@ -19,7 +19,7 @@ pub enum Expression { Value(ValueNode), } -impl AbstractTree for Expression { +impl AbstractNode for Expression { fn expected_type(&self, _context: &Context) -> Result { match self { Expression::FunctionCall(function_call) => function_call.expected_type(_context), diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 793da23..8cce27f 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -4,7 +4,7 @@ use crate::{ value::ValueInner, }; -use super::{AbstractTree, Action, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, Expression, Type, WithPosition}; #[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] pub struct FunctionCall { @@ -24,7 +24,7 @@ impl FunctionCall { } } -impl AbstractTree for FunctionCall { +impl AbstractNode for FunctionCall { fn expected_type(&self, _context: &Context) -> Result { let function_node_type = self.function.node.expected_type(_context)?; diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index aaaa9be..7bf4496 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -8,7 +8,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Type}; +use super::{AbstractNode, Action, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Identifier(Arc); @@ -23,7 +23,7 @@ impl Identifier { } } -impl AbstractTree for Identifier { +impl AbstractNode for Identifier { fn expected_type(&self, context: &Context) -> Result { if let Some(r#type) = context.get_type(self)? { Ok(r#type) diff --git a/src/abstract_tree/if_else.rs b/src/abstract_tree/if_else.rs index cf2790e..901ce79 100644 --- a/src/abstract_tree/if_else.rs +++ b/src/abstract_tree/if_else.rs @@ -4,7 +4,7 @@ use crate::{ value::ValueInner, }; -use super::{AbstractTree, Action, Block, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, Block, Expression, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct IfElse { @@ -27,7 +27,7 @@ impl IfElse { } } -impl AbstractTree for IfElse { +impl AbstractNode for IfElse { fn expected_type(&self, _context: &Context) -> Result { self.if_block.expected_type(_context) } diff --git a/src/abstract_tree/list_index.rs b/src/abstract_tree/list_index.rs index 3ad35ed..baf9a33 100644 --- a/src/abstract_tree/list_index.rs +++ b/src/abstract_tree/list_index.rs @@ -3,7 +3,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Expression, Type, ValueNode, WithPosition}; +use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct ListIndex { @@ -17,7 +17,7 @@ impl ListIndex { } } -impl AbstractTree for ListIndex { +impl AbstractNode for ListIndex { fn expected_type(&self, _context: &Context) -> Result { let left_type = self.left.node.expected_type(_context)?; diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index 2cd7d08..58a4063 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -5,7 +5,7 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Expression, Type, WithPosition}; +use super::{AbstractNode, Action, Expression, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Logic { @@ -20,7 +20,7 @@ pub enum Logic { Not(WithPosition), } -impl AbstractTree for Logic { +impl AbstractNode for Logic { fn expected_type(&self, _context: &Context) -> Result { Ok(Type::Boolean) } diff --git a/src/abstract_tree/loop.rs b/src/abstract_tree/loop.rs index 605727c..7065dea 100644 --- a/src/abstract_tree/loop.rs +++ b/src/abstract_tree/loop.rs @@ -5,7 +5,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Statement, Type, WithPosition}; +use super::{AbstractNode, Action, Statement, Type, WithPosition}; #[derive(Clone, Debug)] pub struct Loop { @@ -18,7 +18,7 @@ impl Loop { } } -impl AbstractTree for Loop { +impl AbstractNode for Loop { fn expected_type(&self, _context: &Context) -> Result { Ok(Type::None) } diff --git a/src/abstract_tree/map_index.rs b/src/abstract_tree/map_index.rs index d966fd8..80c0845 100644 --- a/src/abstract_tree/map_index.rs +++ b/src/abstract_tree/map_index.rs @@ -4,7 +4,7 @@ use crate::{ value::ValueInner, }; -use super::{AbstractTree, Action, Expression, Type, ValueNode, WithPosition}; +use super::{AbstractNode, Action, Expression, Type, ValueNode, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct MapIndex { @@ -18,7 +18,7 @@ impl MapIndex { } } -impl AbstractTree for MapIndex { +impl AbstractNode for MapIndex { fn expected_type(&self, context: &Context) -> Result { let left_type = self.left.node.expected_type(context)?; diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 6725b14..506f6b5 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -5,7 +5,7 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Expression, SourcePosition, Type, WithPosition}; +use super::{AbstractNode, Action, Expression, SourcePosition, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Math { @@ -16,7 +16,7 @@ pub enum Math { Modulo(WithPosition, WithPosition), } -impl AbstractTree for Math { +impl AbstractNode for Math { fn expected_type(&self, _context: &Context) -> Result { match self { Math::Add(left, _) diff --git a/src/abstract_tree/mod.rs b/src/abstract_tree/mod.rs index 8967932..bf884f8 100644 --- a/src/abstract_tree/mod.rs +++ b/src/abstract_tree/mod.rs @@ -15,6 +15,8 @@ pub mod r#type; pub mod value_node; pub mod r#while; +use std::ops::Index; + use chumsky::span::{SimpleSpan, Span}; pub use self::{ @@ -38,7 +40,7 @@ pub use self::{ use crate::{ context::Context, - error::{RuntimeError, ValidationError}, + error::{Error, RuntimeError, ValidationError}, Value, }; @@ -63,7 +65,94 @@ impl From<(usize, usize)> for SourcePosition { } } -pub trait AbstractTree: Sized { +#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum Action { + Return(Value), + Break, + None, +} + +pub struct AbstractTree(Vec>); + +impl AbstractTree { + pub fn new(statements: Vec>) -> Self { + AbstractTree(statements) + } + + pub fn run(self, context: &Context) -> Result, Vec> { + let mut valid_statements = Vec::with_capacity(self.0.len()); + let mut errors = Vec::new(); + + for statement in self.0 { + let validation = statement.node.validate(context); + + if let Statement::StructureDefinition(_) = statement.node { + match validation { + Ok(_) => { + let run_result = statement.node.run(context); + + match run_result { + Ok(_) => {} + Err(runtime_error) => { + return Err(vec![Error::Runtime { + error: runtime_error, + position: statement.position, + }]); + } + } + } + Err(validation_error) => errors.push(Error::Validation { + error: validation_error, + position: statement.position, + }), + } + } else { + match validation { + Ok(_) => valid_statements.push(statement), + Err(validation_error) => errors.push(Error::Validation { + error: validation_error, + position: statement.position, + }), + } + } + } + + if !errors.is_empty() { + return Err(errors); + } + + let mut previous = None; + + for statement in valid_statements { + let run_result = statement.node.run(context); + + match run_result { + Ok(action) => match action { + Action::Return(value) => previous = Some(value), + _ => {} + }, + Err(runtime_error) => { + return Err(vec![Error::Runtime { + error: runtime_error, + position: statement.position, + }]); + } + } + } + + Ok(previous) + } +} + +impl Index for AbstractTree { + type Output = WithPosition; + + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +pub trait AbstractNode: Sized { fn expected_type(&self, context: &Context) -> Result; fn validate(&self, context: &Context) -> Result<(), ValidationError>; fn run(self, context: &Context) -> Result; @@ -75,10 +164,3 @@ pub trait AbstractTree: Sized { } } } - -#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)] -pub enum Action { - Return(Value), - Break, - None, -} diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index b42695e..b141d28 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -4,7 +4,7 @@ use crate::{ }; use super::{ - AbstractTree, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type, + AbstractNode, Action, Assignment, Block, Expression, IfElse, Loop, StructureDefinition, Type, While, }; @@ -20,7 +20,16 @@ pub enum Statement { While(While), } -impl AbstractTree for Statement { +impl Statement { + pub fn kind(&self) -> u8 { + match self { + Statement::StructureDefinition(_) => 0, + _ => 1, + } + } +} + +impl AbstractNode for Statement { fn expected_type(&self, _context: &Context) -> Result { match self { Statement::Assignment(assignment) => assignment.expected_type(_context), diff --git a/src/abstract_tree/structure_definition.rs b/src/abstract_tree/structure_definition.rs index ab7090b..0fc9947 100644 --- a/src/abstract_tree/structure_definition.rs +++ b/src/abstract_tree/structure_definition.rs @@ -3,7 +3,7 @@ use crate::{ error::{RuntimeError, ValidationError}, }; -use super::{AbstractTree, Action, Identifier, Type, WithPosition}; +use super::{AbstractNode, Action, Identifier, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct StructureDefinition { @@ -17,14 +17,12 @@ impl StructureDefinition { } } -impl AbstractTree for StructureDefinition { +impl AbstractNode for StructureDefinition { fn expected_type(&self, _context: &Context) -> Result { Ok(Type::None) } - fn validate(&self, context: &Context) -> Result<(), ValidationError> { - context.set_type(self.name.clone(), Type::Named(self.name.clone()))?; - + fn validate(&self, _context: &Context) -> Result<(), ValidationError> { Ok(()) } diff --git a/src/abstract_tree/type.rs b/src/abstract_tree/type.rs index 93241b0..c1669e2 100644 --- a/src/abstract_tree/type.rs +++ b/src/abstract_tree/type.rs @@ -6,7 +6,7 @@ use crate::{ error::{RuntimeError, TypeConflict, ValidationError}, }; -use super::{AbstractTree, Action, WithPosition}; +use super::{AbstractNode, Action, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Type { @@ -88,7 +88,7 @@ impl Type { } } -impl AbstractTree for Type { +impl AbstractNode for Type { fn expected_type(&self, _: &Context) -> Result { Ok(Type::None) } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index 8567d9e..9efa603 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -6,7 +6,7 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Block, Expression, Identifier, Type, WithPosition}; +use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPosition}; #[derive(Clone, Debug, PartialEq)] pub enum ValueNode { @@ -34,7 +34,7 @@ pub enum ValueNode { }, } -impl AbstractTree for ValueNode { +impl AbstractNode for ValueNode { fn expected_type(&self, _context: &Context) -> Result { let r#type = match self { ValueNode::Boolean(_) => Type::Boolean, diff --git a/src/abstract_tree/while.rs b/src/abstract_tree/while.rs index 14dbc09..2e68e68 100644 --- a/src/abstract_tree/while.rs +++ b/src/abstract_tree/while.rs @@ -5,7 +5,7 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Expression, Statement, Type, WithPosition}; +use super::{AbstractNode, Action, Expression, Statement, Type, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct While { @@ -25,7 +25,7 @@ impl While { } } -impl AbstractTree for While { +impl AbstractNode for While { fn expected_type(&self, _context: &Context) -> Result { Ok(Type::None) } diff --git a/src/context.rs b/src/context.rs index bf8c37f..f41abf5 100644 --- a/src/context.rs +++ b/src/context.rs @@ -32,10 +32,8 @@ impl Context { let mut self_data = self.inner.write()?; for (identifier, value_data) in other.inner.read()?.iter() { - if let ValueData::Type(r#type) = value_data { - if let Type::Function { .. } = r#type { - self_data.insert(identifier.clone(), value_data.clone()); - } + if let ValueData::Type(Type::Function { .. }) = value_data { + self_data.insert(identifier.clone(), value_data.clone()); } } diff --git a/src/lib.rs b/src/lib.rs index cb395c8..01b346a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ pub mod lexer; pub mod parser; pub mod value; -use abstract_tree::{AbstractTree, Action, WithPosition}; use context::Context; use error::Error; use lexer::lex; @@ -30,41 +29,9 @@ impl Interpreter { pub fn run(&mut self, source: &str) -> Result, Vec> { let tokens = lex(source)?; - let statements = parse(&tokens)?; - let errors = statements - .iter() - .filter_map(|WithPosition { node, position }| { - node.validate(&self.context) - .err() - .map(|error| Error::Validation { - error, - position: position.clone(), - }) - }) - .collect::>(); + let abstract_tree = parse(&tokens)?; + let value_option = abstract_tree.run(&self.context)?; - if !errors.is_empty() { - return Err(errors); - } - - let mut value = None; - - for statement in statements { - value = match statement.node.run(&self.context) { - Ok(action) => match action { - Action::Break => None, - Action::Return(value) => Some(value), - Action::None => continue, - }, - Err(runtime_error) => { - return Err(vec![Error::Runtime { - error: runtime_error, - position: statement.position, - }]) - } - } - } - - Ok(value) + Ok(value_option) } } diff --git a/src/parser.rs b/src/parser.rs index d0a8be7..a00b094 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -11,13 +11,18 @@ use crate::{ pub type ParserInput<'src> = SpannedInput, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>; -pub fn parse<'src>( - tokens: &'src [(Token<'src>, SimpleSpan)], -) -> Result>, Vec> { - parser() +pub fn parse<'src>(tokens: &'src [(Token<'src>, SimpleSpan)]) -> Result> { + let statements = parser() .parse(tokens.spanned((tokens.len()..tokens.len()).into())) .into_result() - .map_err(|errors| errors.into_iter().map(|error| error.into()).collect()) + .map_err(|errors| { + errors + .into_iter() + .map(|error| Error::from(error)) + .collect::>() + })?; + + Ok(AbstractTree::new(statements)) } pub fn parser<'src>() -> impl Parser< diff --git a/src/value.rs b/src/value.rs index c2fc434..f82b933 100644 --- a/src/value.rs +++ b/src/value.rs @@ -15,7 +15,7 @@ use stanza::{ }; use crate::{ - abstract_tree::{AbstractTree, Action, Block, Identifier, Type, WithPosition}, + abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPosition}, context::Context, error::{RuntimeError, ValidationError}, }; diff --git a/tests/variables.rs b/tests/variables.rs index 78fc7cc..5bd2cd6 100644 --- a/tests/variables.rs +++ b/tests/variables.rs @@ -1,5 +1,5 @@ use dust_lang::{ - abstract_tree::{AbstractTree, Block, Expression, Identifier, Statement, Type}, + abstract_tree::{AbstractNode, Block, Expression, Identifier, Statement, Type}, error::{Error, TypeConflict, ValidationError}, *, };