From 9bd39338d511e8da978f667eeb07b9d6b0ecdf30 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 2 Jul 2024 13:11:31 -0400 Subject: [PATCH] Combine define and verify functions on AST nodes --- dust-lang/src/abstract_tree/as.rs | 13 +- dust-lang/src/abstract_tree/assignment.rs | 14 +-- dust-lang/src/abstract_tree/async_block.rs | 16 +-- dust-lang/src/abstract_tree/block.rs | 16 +-- .../src/abstract_tree/enum_declaration.rs | 6 +- dust-lang/src/abstract_tree/expression.rs | 43 ++++--- dust-lang/src/abstract_tree/function_call.rs | 21 +--- dust-lang/src/abstract_tree/if_else.rs | 35 ++---- dust-lang/src/abstract_tree/list_index.rs | 16 +-- dust-lang/src/abstract_tree/logic.rs | 54 ++------- dust-lang/src/abstract_tree/loop.rs | 16 +-- dust-lang/src/abstract_tree/map_index.rs | 16 +-- dust-lang/src/abstract_tree/math.rs | 31 +---- dust-lang/src/abstract_tree/mod.rs | 38 ++---- dust-lang/src/abstract_tree/statement.rs | 64 +++++----- .../src/abstract_tree/structure_definition.rs | 6 +- dust-lang/src/abstract_tree/type_alias.rs | 6 +- dust-lang/src/abstract_tree/use.rs | 14 +-- dust-lang/src/abstract_tree/value_node.rs | 113 ++++++++---------- dust-lang/src/abstract_tree/while.rs | 20 ++-- dust-lang/src/standard_library.rs | 5 +- 21 files changed, 205 insertions(+), 358 deletions(-) diff --git a/dust-lang/src/abstract_tree/as.rs b/dust-lang/src/abstract_tree/as.rs index 99c47b4..8742acd 100644 --- a/dust-lang/src/abstract_tree/as.rs +++ b/dust-lang/src/abstract_tree/as.rs @@ -30,12 +30,13 @@ impl As { } impl AbstractNode for As { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - self.expression.define_types(_context) - } - - fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - self.expression.validate(_context, _manage_memory)?; + fn define_and_validate( + &self, + _context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + self.expression + .define_and_validate(_context, _manage_memory)?; match self.constructor { TypeConstructor::Raw(_) => {} diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index f4199a1..e20452f 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -43,9 +43,11 @@ impl Assignment { } impl AbstractNode for Assignment { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { - self.statement.define_types(context)?; - + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { if let Some(constructor) = &self.constructor { let r#type = constructor.construct(&context)?; @@ -58,11 +60,7 @@ impl AbstractNode for Assignment { )); }; - Ok(()) - } - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { - self.statement.validate(context, manage_memory)?; + self.statement.define_and_validate(context, manage_memory)?; let statement_type = self.statement.expected_type(context)?; diff --git a/dust-lang/src/abstract_tree/async_block.rs b/dust-lang/src/abstract_tree/async_block.rs index 9d219cb..4851820 100644 --- a/dust-lang/src/abstract_tree/async_block.rs +++ b/dust-lang/src/abstract_tree/async_block.rs @@ -25,17 +25,13 @@ impl AsyncBlock { } impl AbstractNode for AsyncBlock { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + _context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { for statement in &self.statements { - statement.define_types(_context)?; - } - - Ok(()) - } - - fn validate(&self, _context: &Context, manage_memory: bool) -> Result<(), ValidationError> { - for statement in &self.statements { - statement.validate(_context, manage_memory)?; + statement.define_and_validate(_context, manage_memory)?; } Ok(()) diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 2ca57a3..7ae11f3 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -29,17 +29,13 @@ impl Block { } impl AbstractNode for Block { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + _context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { for statement in &self.statements { - statement.define_types(_context)?; - } - - Ok(()) - } - - fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - for statement in &self.statements { - statement.validate(_context, _manage_memory)?; + statement.define_and_validate(_context, _manage_memory)?; } Ok(()) diff --git a/dust-lang/src/abstract_tree/enum_declaration.rs b/dust-lang/src/abstract_tree/enum_declaration.rs index 460f8ae..1c367bf 100644 --- a/dust-lang/src/abstract_tree/enum_declaration.rs +++ b/dust-lang/src/abstract_tree/enum_declaration.rs @@ -32,7 +32,7 @@ impl EnumDeclaration { } impl AbstractNode for EnumDeclaration { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { + fn define_and_validate(&self, context: &Context, _: bool) -> Result<(), ValidationError> { let EnumDeclaration { name, type_parameters, @@ -79,10 +79,6 @@ impl AbstractNode for EnumDeclaration { Ok(()) } - fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> { - Ok(()) - } - fn evaluate(self, _: &Context, _: bool) -> Result, RuntimeError> { Ok(None) } diff --git a/dust-lang/src/abstract_tree/expression.rs b/dust-lang/src/abstract_tree/expression.rs index d0ea068..b1d8c55 100644 --- a/dust-lang/src/abstract_tree/expression.rs +++ b/dust-lang/src/abstract_tree/expression.rs @@ -41,25 +41,16 @@ impl Expression { } impl AbstractNode for Expression { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { match self { - Expression::As(inner) => inner.node.define_types(_context), - Expression::FunctionCall(inner) => inner.node.define_types(_context), - Expression::Identifier(_) => Ok(()), - Expression::MapIndex(inner) => inner.node.define_types(_context), - Expression::ListIndex(inner) => inner.node.define_types(_context), - Expression::Logic(inner) => inner.node.define_types(_context), - Expression::Math(inner) => inner.node.define_types(_context), - Expression::Value(inner) => inner.node.define_types(_context), - } - } - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { - match self { - Expression::As(r#as) => r#as.node.validate(context, manage_memory), - Expression::FunctionCall(function_call) => { - function_call.node.validate(context, manage_memory) - } + Expression::As(r#as) => r#as.node.define_and_validate(context, manage_memory), + Expression::FunctionCall(function_call) => function_call + .node + .define_and_validate(context, manage_memory), Expression::Identifier(identifier) => { let found = context.add_expected_use(&identifier.node)?; @@ -72,11 +63,17 @@ impl AbstractNode for Expression { }) } } - Expression::MapIndex(map_index) => map_index.node.validate(context, manage_memory), - Expression::ListIndex(list_index) => list_index.node.validate(context, manage_memory), - Expression::Logic(logic) => logic.node.validate(context, manage_memory), - Expression::Math(math) => math.node.validate(context, manage_memory), - Expression::Value(value_node) => value_node.node.validate(context, manage_memory), + Expression::MapIndex(map_index) => { + map_index.node.define_and_validate(context, manage_memory) + } + Expression::ListIndex(list_index) => { + list_index.node.define_and_validate(context, manage_memory) + } + Expression::Logic(logic) => logic.node.define_and_validate(context, manage_memory), + Expression::Math(math) => math.node.define_and_validate(context, manage_memory), + Expression::Value(value_node) => { + value_node.node.define_and_validate(context, manage_memory) + } } } diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 999c9bd..7da0b10 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -39,31 +39,18 @@ impl FunctionCall { } impl AbstractNode for FunctionCall { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { - self.function_expression.define_types(context)?; - - if let Some(expressions) = &self.value_arguments { - for expression in expressions { - expression.define_types(context)?; - } - } - - self.context.set_parent(context.clone())?; - - Ok(()) - } - - fn validate( + fn define_and_validate( &self, outer_context: &Context, manage_memory: bool, ) -> Result<(), ValidationError> { + self.context.set_parent(outer_context.clone())?; self.function_expression - .validate(outer_context, manage_memory)?; + .define_and_validate(outer_context, manage_memory)?; if let Some(value_arguments) = &self.value_arguments { for expression in value_arguments { - expression.validate(outer_context, manage_memory)?; + expression.define_and_validate(outer_context, manage_memory)?; } } diff --git a/dust-lang/src/abstract_tree/if_else.rs b/dust-lang/src/abstract_tree/if_else.rs index a75cad8..4886b5d 100644 --- a/dust-lang/src/abstract_tree/if_else.rs +++ b/dust-lang/src/abstract_tree/if_else.rs @@ -35,27 +35,16 @@ impl IfElse { } impl AbstractNode for IfElse { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - self.if_expression.define_types(_context)?; - self.if_block.node.define_types(_context)?; - - if let Some(else_ifs) = &self.else_ifs { - for (expression, block) in else_ifs { - expression.define_types(_context)?; - block.node.define_types(_context)?; - } - } - - if let Some(else_block) = &self.else_block { - else_block.node.define_types(_context)?; - } - - Ok(()) - } - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { - self.if_expression.validate(context, manage_memory)?; - self.if_block.node.validate(context, manage_memory)?; + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { + self.if_expression + .define_and_validate(context, manage_memory)?; + self.if_block + .node + .define_and_validate(context, manage_memory)?; let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? { r#type @@ -71,7 +60,7 @@ impl AbstractNode for IfElse { let expression_type = expression.expected_type(context)?; if let Some(Type::Boolean) = expression_type { - block.node.validate(context, manage_memory)?; + block.node.define_and_validate(context, manage_memory)?; let else_if_block_type = block.node.expected_type(context)?; @@ -94,7 +83,7 @@ impl AbstractNode for IfElse { } if let Some(block) = &self.else_block { - block.node.validate(context, manage_memory)?; + block.node.define_and_validate(context, manage_memory)?; let else_if_block_type = block.node.expected_type(context)?; diff --git a/dust-lang/src/abstract_tree/list_index.rs b/dust-lang/src/abstract_tree/list_index.rs index 92e463a..03fb612 100644 --- a/dust-lang/src/abstract_tree/list_index.rs +++ b/dust-lang/src/abstract_tree/list_index.rs @@ -25,14 +25,14 @@ impl ListIndex { } impl AbstractNode for ListIndex { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { - self.collection.define_types(context)?; - self.index.define_types(context) - } - - fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - self.collection.validate(context, _manage_memory)?; - self.index.validate(context, _manage_memory)?; + fn define_and_validate( + &self, + context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + self.collection + .define_and_validate(context, _manage_memory)?; + self.index.define_and_validate(context, _manage_memory)?; let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { r#type diff --git a/dust-lang/src/abstract_tree/logic.rs b/dust-lang/src/abstract_tree/logic.rs index 0935748..a589b1f 100644 --- a/dust-lang/src/abstract_tree/logic.rs +++ b/dust-lang/src/abstract_tree/logic.rs @@ -25,45 +25,11 @@ pub enum Logic { } impl AbstractNode for Logic { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - match self { - Logic::Equal(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::NotEqual(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::Greater(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::Less(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::GreaterOrEqual(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::LessOrEqual(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::And(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::Or(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Logic::Not(expression) => expression.define_types(_context), - } - } - - fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { match self { Logic::Equal(left, right) | Logic::NotEqual(left, right) @@ -71,8 +37,8 @@ impl AbstractNode for Logic { | Logic::Less(left, right) | Logic::GreaterOrEqual(left, right) | Logic::LessOrEqual(left, right) => { - left.validate(context, _manage_memory)?; - right.validate(context, _manage_memory)?; + left.define_and_validate(context, _manage_memory)?; + right.define_and_validate(context, _manage_memory)?; let left_type = if let Some(r#type) = left.expected_type(context)? { r#type @@ -96,8 +62,8 @@ impl AbstractNode for Logic { Ok(()) } Logic::And(left, right) | Logic::Or(left, right) => { - left.validate(context, _manage_memory)?; - right.validate(context, _manage_memory)?; + left.define_and_validate(context, _manage_memory)?; + right.define_and_validate(context, _manage_memory)?; let left_type = if let Some(r#type) = left.expected_type(context)? { r#type @@ -129,7 +95,7 @@ impl AbstractNode for Logic { Ok(()) } Logic::Not(expression) => { - expression.validate(context, _manage_memory)?; + expression.define_and_validate(context, _manage_memory)?; let expression_type = if let Some(r#type) = expression.expected_type(context)? { r#type diff --git a/dust-lang/src/abstract_tree/loop.rs b/dust-lang/src/abstract_tree/loop.rs index e05b3ea..8091b95 100644 --- a/dust-lang/src/abstract_tree/loop.rs +++ b/dust-lang/src/abstract_tree/loop.rs @@ -25,17 +25,13 @@ impl Loop { } impl AbstractNode for Loop { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + _context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { for statement in &self.statements { - statement.define_types(_context)?; - } - - Ok(()) - } - - fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - for statement in &self.statements { - statement.validate(_context, false)?; + statement.define_and_validate(_context, false)?; } Ok(()) diff --git a/dust-lang/src/abstract_tree/map_index.rs b/dust-lang/src/abstract_tree/map_index.rs index a91645b..8546f1c 100644 --- a/dust-lang/src/abstract_tree/map_index.rs +++ b/dust-lang/src/abstract_tree/map_index.rs @@ -26,13 +26,13 @@ impl MapIndex { } impl AbstractNode for MapIndex { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - self.collection.define_types(_context)?; - self.index.define_types(_context) - } - - fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - self.collection.validate(context, _manage_memory)?; + fn define_and_validate( + &self, + context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + self.collection + .define_and_validate(context, _manage_memory)?; let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { r#type @@ -56,7 +56,7 @@ impl AbstractNode for MapIndex { if let Expression::Identifier(_) = &self.index { Ok(()) } else { - self.index.validate(context, _manage_memory) + self.index.define_and_validate(context, _manage_memory) } } diff --git a/dust-lang/src/abstract_tree/math.rs b/dust-lang/src/abstract_tree/math.rs index ca24503..df43a17 100644 --- a/dust-lang/src/abstract_tree/math.rs +++ b/dust-lang/src/abstract_tree/math.rs @@ -21,32 +21,11 @@ pub enum Math { } impl AbstractNode for Math { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - match self { - Math::Add(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Math::Subtract(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Math::Multiply(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Math::Divide(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - Math::Modulo(left, right) => { - left.define_types(_context)?; - right.define_types(_context) - } - } - } - - fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { match self { Math::Add(left, right) => { let left_type = if let Some(r#type) = left.expected_type(context)? { diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index a424dfa..a90460c 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -58,6 +58,7 @@ pub use self::{ use crate::{ context::Context, error::{DustError, RuntimeError, ValidationError}, + identifier::Identifier, Value, }; @@ -128,18 +129,7 @@ impl AbstractTree { let mut errors = Vec::new(); for statement in &self.0 { - let define_result = statement.define_types(context); - - if let Err(error) = define_result { - errors.push(DustError::Validation { - error, - position: statement.position(), - }); - - continue; - } - - let validation_result = statement.validate(context, manage_memory); + let validation_result = statement.define_and_validate(context, manage_memory); if let Err(error) = validation_result { errors.push(DustError::Validation { @@ -187,17 +177,13 @@ impl Index for AbstractTree { } impl AbstractNode for AbstractTree { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { for statement in &self.0 { - statement.define_types(context)?; - } - - Ok(()) - } - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { - for statement in &self.0 { - statement.validate(context, manage_memory)?; + statement.define_and_validate(context, manage_memory)?; } Ok(()) @@ -223,9 +209,11 @@ impl AbstractNode for AbstractTree { } pub trait AbstractNode { - fn define_types(&self, context: &Context) -> Result<(), ValidationError>; - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>; + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError>; fn evaluate( self, diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index 08278ec..f55ae43 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -58,44 +58,40 @@ impl Statement { } impl AbstractNode for Statement { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - log::trace!("Defining types for statement at {}", self.position()); - - match self { - Statement::Expression(expression) => expression.define_types(_context), - Statement::IfElse(if_else) => if_else.node.define_types(_context), - Statement::Block(block) => block.node.define_types(_context), - Statement::AsyncBlock(async_block) => async_block.node.define_types(_context), - Statement::Assignment(assignment) => assignment.node.define_types(_context), - Statement::Loop(r#loop) => r#loop.node.define_types(_context), - Statement::StructureDefinition(struct_definition) => { - struct_definition.node.define_types(_context) - } - Statement::TypeAlias(type_alias) => type_alias.node.define_types(_context), - Statement::EnumDeclaration(enum_declaration) => { - enum_declaration.node.define_types(_context) - } - Statement::While(r#while) => r#while.node.define_types(_context), - Statement::Use(r#use) => r#use.node.define_types(_context), - Statement::Break(_) | Statement::Null(_) => Ok(()), - } - } - - fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + _context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { log::trace!("Validating statement at {}", self.position()); match self { - Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory), - Statement::AsyncBlock(async_block) => { - async_block.node.validate(_context, _manage_memory) + Statement::Assignment(assignment) => assignment + .node + .define_and_validate(_context, _manage_memory), + Statement::AsyncBlock(async_block) => async_block + .node + .define_and_validate(_context, _manage_memory), + Statement::Block(block) => block.node.define_and_validate(_context, _manage_memory), + Statement::EnumDeclaration(enum_declaration) => enum_declaration + .node + .define_and_validate(_context, _manage_memory), + Statement::Expression(expression) => { + expression.define_and_validate(_context, _manage_memory) } - Statement::Block(block) => block.node.validate(_context, _manage_memory), - Statement::Expression(expression) => expression.validate(_context, _manage_memory), - Statement::IfElse(if_else) => if_else.node.validate(_context, _manage_memory), - Statement::Loop(r#loop) => r#loop.node.validate(_context, _manage_memory), - Statement::While(r#while) => r#while.node.validate(_context, _manage_memory), - Statement::Use(r#use) => r#use.node.validate(_context, _manage_memory), - _ => Ok(()), + Statement::IfElse(if_else) => { + if_else.node.define_and_validate(_context, _manage_memory) + } + Statement::Loop(r#loop) => r#loop.node.define_and_validate(_context, _manage_memory), + Statement::StructureDefinition(struct_definition) => struct_definition + .node + .define_and_validate(_context, _manage_memory), + Statement::TypeAlias(type_alias) => type_alias + .node + .define_and_validate(_context, _manage_memory), + Statement::While(r#while) => r#while.node.define_and_validate(_context, _manage_memory), + Statement::Use(r#use) => r#use.node.define_and_validate(_context, _manage_memory), + Statement::Break(_) | Statement::Null(_) => Ok(()), } } diff --git a/dust-lang/src/abstract_tree/structure_definition.rs b/dust-lang/src/abstract_tree/structure_definition.rs index 0b04f87..4040c6a 100644 --- a/dust-lang/src/abstract_tree/structure_definition.rs +++ b/dust-lang/src/abstract_tree/structure_definition.rs @@ -23,7 +23,7 @@ impl StructureDefinition { } impl AbstractNode for StructureDefinition { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { + fn define_and_validate(&self, context: &Context, _: bool) -> Result<(), ValidationError> { let mut fields = Vec::with_capacity(self.fields.len()); for (identifier, constructor) in &self.fields { @@ -42,10 +42,6 @@ impl AbstractNode for StructureDefinition { Ok(()) } - fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> { - Ok(()) - } - fn evaluate( self, context: &Context, diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs index 73555d1..dd183eb 100644 --- a/dust-lang/src/abstract_tree/type_alias.rs +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -26,7 +26,7 @@ impl TypeAlias { } impl AbstractNode for TypeAlias { - fn define_types(&self, context: &Context) -> Result<(), ValidationError> { + fn define_and_validate(&self, context: &Context, _: bool) -> Result<(), ValidationError> { let r#type = self.constructor.construct(&context)?; context.set_type(self.identifier.node.clone(), r#type)?; @@ -34,10 +34,6 @@ impl AbstractNode for TypeAlias { Ok(()) } - fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> { - Ok(()) - } - fn evaluate(self, _: &Context, _: bool) -> Result, RuntimeError> { Ok(None) } diff --git a/dust-lang/src/abstract_tree/use.rs b/dust-lang/src/abstract_tree/use.rs index ffba015..6a536e1 100644 --- a/dust-lang/src/abstract_tree/use.rs +++ b/dust-lang/src/abstract_tree/use.rs @@ -37,7 +37,11 @@ impl Use { } impl AbstractNode for Use { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + manage_memory: bool, + ) -> Result<(), ValidationError> { let abstract_tree = match self.path.as_str() { "std.fs" => std_fs_compiled().clone(), "std.json" => std_json_compiled().clone(), @@ -52,16 +56,10 @@ impl AbstractNode for Use { } }; - abstract_tree.define_types(_context)?; - *self.abstract_tree.write()? = Some(abstract_tree); - Ok(()) - } - - fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { if let Some(abstract_tree) = self.abstract_tree.read()?.as_ref() { - abstract_tree.validate(context, manage_memory) + abstract_tree.define_and_validate(context, manage_memory) } else { Err(ValidationError::Uninitialized) } diff --git a/dust-lang/src/abstract_tree/value_node.rs b/dust-lang/src/abstract_tree/value_node.rs index 94f8034..b4f8f0f 100644 --- a/dust-lang/src/abstract_tree/value_node.rs +++ b/dust-lang/src/abstract_tree/value_node.rs @@ -59,68 +59,11 @@ impl ValueNode { } impl AbstractNode for ValueNode { - fn define_types(&self, outer_context: &Context) -> Result<(), ValidationError> { - match self { - ValueNode::EnumInstance { content, .. } => { - if let Some(expressions) = content { - for expression in expressions { - expression.define_types(outer_context)?; - } - } - } - ValueNode::List(expressions) => { - for expression in expressions { - expression.define_types(outer_context)?; - } - } - ValueNode::Map(fields) => { - for (_, _, expression) in fields { - expression.define_types(outer_context)?; - } - } - ValueNode::Structure { fields, .. } => { - for (_, expression) in fields { - expression.define_types(outer_context)?; - } - } - ValueNode::Function(FunctionNode { - body, - type_parameters, - value_parameters, - validation_context, - .. - }) => { - validation_context.set_parent(outer_context.clone())?; - - if let Some(type_parameters) = type_parameters { - for identifier in type_parameters { - validation_context.set_type( - identifier.clone(), - Type::Generic { - identifier: identifier.clone(), - concrete_type: None, - }, - )?; - } - } - - if let Some(value_parameters) = value_parameters { - for (identifier, type_constructor) in value_parameters { - let r#type = type_constructor.clone().construct(outer_context)?; - - validation_context.set_type(identifier.clone(), r#type)?; - } - } - - body.node.define_types(validation_context)?; - } - _ => {} - } - - Ok(()) - } - - fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { + fn define_and_validate( + &self, + context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { if let ValueNode::List(list) = self { let mut items = list.into_iter(); let first_item = items.next().unwrap(); @@ -133,6 +76,8 @@ impl AbstractNode for ValueNode { }; for item in items { + item.define_and_validate(context, _manage_memory)?; + let item_type = if let Some(r#type) = item.expected_type(context)? { r#type } else { @@ -150,9 +95,17 @@ impl AbstractNode for ValueNode { } if let ValueNode::EnumInstance { - type_name, variant, .. + type_name, + variant, + content, } = self { + if let Some(expressions) = content { + for expression in expressions { + expression.define_and_validate(context, _manage_memory)?; + } + } + if let Some(Type::Enum { variants, .. }) = context.get_type(&type_name.node)? { if variants .iter() @@ -174,7 +127,7 @@ impl AbstractNode for ValueNode { if let ValueNode::Map(map_assignments) = self { for (_identifier, constructor_option, expression) in map_assignments { - expression.validate(context, _manage_memory)?; + expression.define_and_validate(context, _manage_memory)?; if let Some(constructor) = constructor_option { let actual_type = if let Some(r#type) = expression.expected_type(context)? { @@ -203,10 +156,36 @@ impl AbstractNode for ValueNode { return_type, body, validation_context, - .. + type_parameters, + value_parameters, }) = self { - body.node.validate(&validation_context, _manage_memory)?; + let outer_context = context; + + validation_context.set_parent(outer_context.clone())?; + + if let Some(type_parameters) = type_parameters { + for identifier in type_parameters { + validation_context.set_type( + identifier.clone(), + Type::Generic { + identifier: identifier.clone(), + concrete_type: None, + }, + )?; + } + } + + if let Some(value_parameters) = value_parameters { + for (identifier, type_constructor) in value_parameters { + let r#type = type_constructor.clone().construct(outer_context)?; + + validation_context.set_type(identifier.clone(), r#type)?; + } + } + + body.node + .define_and_validate(&validation_context, _manage_memory)?; let ((expected_return, expected_position), actual_return) = match (return_type, body.node.expected_type(&validation_context)?) { @@ -259,6 +238,8 @@ impl AbstractNode for ValueNode { }) = context.get_type(&name.node)? { for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) { + expression.define_and_validate(context, _manage_memory)?; + let actual_type = if let Some(r#type) = expression.expected_type(context)? { r#type } else { diff --git a/dust-lang/src/abstract_tree/while.rs b/dust-lang/src/abstract_tree/while.rs index d4d1cf3..8186445 100644 --- a/dust-lang/src/abstract_tree/while.rs +++ b/dust-lang/src/abstract_tree/while.rs @@ -27,21 +27,15 @@ impl While { } impl AbstractNode for While { - fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { - self.expression.define_types(_context)?; + fn define_and_validate( + &self, + _context: &Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + self.expression.define_and_validate(_context, false)?; for statement in &self.statements { - statement.define_types(_context)?; - } - - Ok(()) - } - - fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { - self.expression.validate(_context, false)?; - - for statement in &self.statements { - statement.validate(_context, false)?; + statement.define_and_validate(_context, false)?; } Ok(()) diff --git a/dust-lang/src/standard_library.rs b/dust-lang/src/standard_library.rs index 495cd8d..f3cd903 100644 --- a/dust-lang/src/standard_library.rs +++ b/dust-lang/src/standard_library.rs @@ -32,10 +32,7 @@ pub fn core_context<'a>() -> &'a Context { let std_core = std_core_compiled().clone(); std_core - .define_types(&context) - .expect("Failed to define types for std.core"); - std_core - .validate(&context, true) + .define_and_validate(&context, true) .expect("Failed to validate std.core"); std_core .evaluate(&context, true)