Combine define and verify functions on AST nodes

This commit is contained in:
Jeff 2024-07-02 13:11:31 -04:00
parent db94fbdb5b
commit 9bd39338d5
21 changed files with 205 additions and 358 deletions

View File

@ -30,12 +30,13 @@ impl As {
} }
impl AbstractNode for As { impl AbstractNode for As {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.expression.define_types(_context) &self,
} _context: &Context,
_manage_memory: bool,
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
self.expression.validate(_context, _manage_memory)?; self.expression
.define_and_validate(_context, _manage_memory)?;
match self.constructor { match self.constructor {
TypeConstructor::Raw(_) => {} TypeConstructor::Raw(_) => {}

View File

@ -43,9 +43,11 @@ impl Assignment {
} }
impl AbstractNode for Assignment { impl AbstractNode for Assignment {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.statement.define_types(context)?; &self,
context: &Context,
manage_memory: bool,
) -> Result<(), ValidationError> {
if let Some(constructor) = &self.constructor { if let Some(constructor) = &self.constructor {
let r#type = constructor.construct(&context)?; let r#type = constructor.construct(&context)?;
@ -58,11 +60,7 @@ impl AbstractNode for Assignment {
)); ));
}; };
Ok(()) self.statement.define_and_validate(context, manage_memory)?;
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
self.statement.validate(context, manage_memory)?;
let statement_type = self.statement.expected_type(context)?; let statement_type = self.statement.expected_type(context)?;

View File

@ -25,17 +25,13 @@ impl AsyncBlock {
} }
impl AbstractNode for 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 { for statement in &self.statements {
statement.define_types(_context)?; statement.define_and_validate(_context, manage_memory)?;
}
Ok(())
}
fn validate(&self, _context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, manage_memory)?;
} }
Ok(()) Ok(())

View File

@ -29,17 +29,13 @@ impl Block {
} }
impl AbstractNode for 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 { for statement in &self.statements {
statement.define_types(_context)?; statement.define_and_validate(_context, _manage_memory)?;
}
Ok(())
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, _manage_memory)?;
} }
Ok(()) Ok(())

View File

@ -32,7 +32,7 @@ impl EnumDeclaration {
} }
impl AbstractNode for 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 { let EnumDeclaration {
name, name,
type_parameters, type_parameters,
@ -79,10 +79,6 @@ impl AbstractNode for EnumDeclaration {
Ok(()) Ok(())
} }
fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(())
}
fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> { fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
Ok(None) Ok(None)
} }

View File

@ -41,25 +41,16 @@ impl Expression {
} }
impl AbstractNode for 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 { match self {
Expression::As(inner) => inner.node.define_types(_context), Expression::As(r#as) => r#as.node.define_and_validate(context, manage_memory),
Expression::FunctionCall(inner) => inner.node.define_types(_context), Expression::FunctionCall(function_call) => function_call
Expression::Identifier(_) => Ok(()), .node
Expression::MapIndex(inner) => inner.node.define_types(_context), .define_and_validate(context, manage_memory),
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::Identifier(identifier) => { Expression::Identifier(identifier) => {
let found = context.add_expected_use(&identifier.node)?; 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::MapIndex(map_index) => {
Expression::ListIndex(list_index) => list_index.node.validate(context, manage_memory), map_index.node.define_and_validate(context, manage_memory)
Expression::Logic(logic) => logic.node.validate(context, manage_memory), }
Expression::Math(math) => math.node.validate(context, manage_memory), Expression::ListIndex(list_index) => {
Expression::Value(value_node) => value_node.node.validate(context, manage_memory), 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)
}
} }
} }

View File

@ -39,31 +39,18 @@ impl FunctionCall {
} }
impl AbstractNode for FunctionCall { impl AbstractNode for FunctionCall {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
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(
&self, &self,
outer_context: &Context, outer_context: &Context,
manage_memory: bool, manage_memory: bool,
) -> Result<(), ValidationError> { ) -> Result<(), ValidationError> {
self.context.set_parent(outer_context.clone())?;
self.function_expression self.function_expression
.validate(outer_context, manage_memory)?; .define_and_validate(outer_context, manage_memory)?;
if let Some(value_arguments) = &self.value_arguments { if let Some(value_arguments) = &self.value_arguments {
for expression in value_arguments { for expression in value_arguments {
expression.validate(outer_context, manage_memory)?; expression.define_and_validate(outer_context, manage_memory)?;
} }
} }

View File

@ -35,27 +35,16 @@ impl IfElse {
} }
impl AbstractNode for IfElse { impl AbstractNode for IfElse {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.if_expression.define_types(_context)?; &self,
self.if_block.node.define_types(_context)?; context: &Context,
manage_memory: bool,
if let Some(else_ifs) = &self.else_ifs { ) -> Result<(), ValidationError> {
for (expression, block) in else_ifs { self.if_expression
expression.define_types(_context)?; .define_and_validate(context, manage_memory)?;
block.node.define_types(_context)?; self.if_block
} .node
} .define_and_validate(context, manage_memory)?;
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)?;
let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? { let if_expression_type = if let Some(r#type) = self.if_expression.expected_type(context)? {
r#type r#type
@ -71,7 +60,7 @@ impl AbstractNode for IfElse {
let expression_type = expression.expected_type(context)?; let expression_type = expression.expected_type(context)?;
if let Some(Type::Boolean) = expression_type { 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)?; 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 { 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)?; let else_if_block_type = block.node.expected_type(context)?;

View File

@ -25,14 +25,14 @@ impl ListIndex {
} }
impl AbstractNode for ListIndex { impl AbstractNode for ListIndex {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.collection.define_types(context)?; &self,
self.index.define_types(context) context: &Context,
} _manage_memory: bool,
) -> Result<(), ValidationError> {
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { self.collection
self.collection.validate(context, _manage_memory)?; .define_and_validate(context, _manage_memory)?;
self.index.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)? { let collection_type = if let Some(r#type) = self.collection.expected_type(context)? {
r#type r#type

View File

@ -25,45 +25,11 @@ pub enum Logic {
} }
impl AbstractNode for Logic { impl AbstractNode for Logic {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
match self { &self,
Logic::Equal(left, right) => { context: &Context,
left.define_types(_context)?; _manage_memory: bool,
right.define_types(_context) ) -> Result<(), ValidationError> {
}
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> {
match self { match self {
Logic::Equal(left, right) Logic::Equal(left, right)
| Logic::NotEqual(left, right) | Logic::NotEqual(left, right)
@ -71,8 +37,8 @@ impl AbstractNode for Logic {
| Logic::Less(left, right) | Logic::Less(left, right)
| Logic::GreaterOrEqual(left, right) | Logic::GreaterOrEqual(left, right)
| Logic::LessOrEqual(left, right) => { | Logic::LessOrEqual(left, right) => {
left.validate(context, _manage_memory)?; left.define_and_validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?; right.define_and_validate(context, _manage_memory)?;
let left_type = if let Some(r#type) = left.expected_type(context)? { let left_type = if let Some(r#type) = left.expected_type(context)? {
r#type r#type
@ -96,8 +62,8 @@ impl AbstractNode for Logic {
Ok(()) Ok(())
} }
Logic::And(left, right) | Logic::Or(left, right) => { Logic::And(left, right) | Logic::Or(left, right) => {
left.validate(context, _manage_memory)?; left.define_and_validate(context, _manage_memory)?;
right.validate(context, _manage_memory)?; right.define_and_validate(context, _manage_memory)?;
let left_type = if let Some(r#type) = left.expected_type(context)? { let left_type = if let Some(r#type) = left.expected_type(context)? {
r#type r#type
@ -129,7 +95,7 @@ impl AbstractNode for Logic {
Ok(()) Ok(())
} }
Logic::Not(expression) => { 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)? { let expression_type = if let Some(r#type) = expression.expected_type(context)? {
r#type r#type

View File

@ -25,17 +25,13 @@ impl Loop {
} }
impl AbstractNode for 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 { for statement in &self.statements {
statement.define_types(_context)?; statement.define_and_validate(_context, false)?;
}
Ok(())
}
fn validate(&self, _context: &Context, _manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.statements {
statement.validate(_context, false)?;
} }
Ok(()) Ok(())

View File

@ -26,13 +26,13 @@ impl MapIndex {
} }
impl AbstractNode for MapIndex { impl AbstractNode for MapIndex {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.collection.define_types(_context)?; &self,
self.index.define_types(_context) context: &Context,
} _manage_memory: bool,
) -> Result<(), ValidationError> {
fn validate(&self, context: &Context, _manage_memory: bool) -> Result<(), ValidationError> { self.collection
self.collection.validate(context, _manage_memory)?; .define_and_validate(context, _manage_memory)?;
let collection_type = if let Some(r#type) = self.collection.expected_type(context)? { let collection_type = if let Some(r#type) = self.collection.expected_type(context)? {
r#type r#type
@ -56,7 +56,7 @@ impl AbstractNode for MapIndex {
if let Expression::Identifier(_) = &self.index { if let Expression::Identifier(_) = &self.index {
Ok(()) Ok(())
} else { } else {
self.index.validate(context, _manage_memory) self.index.define_and_validate(context, _manage_memory)
} }
} }

View File

@ -21,32 +21,11 @@ pub enum Math {
} }
impl AbstractNode for Math { impl AbstractNode for Math {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
match self { &self,
Math::Add(left, right) => { context: &Context,
left.define_types(_context)?; _manage_memory: bool,
right.define_types(_context) ) -> Result<(), ValidationError> {
}
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> {
match self { match self {
Math::Add(left, right) => { Math::Add(left, right) => {
let left_type = if let Some(r#type) = left.expected_type(context)? { let left_type = if let Some(r#type) = left.expected_type(context)? {

View File

@ -58,6 +58,7 @@ pub use self::{
use crate::{ use crate::{
context::Context, context::Context,
error::{DustError, RuntimeError, ValidationError}, error::{DustError, RuntimeError, ValidationError},
identifier::Identifier,
Value, Value,
}; };
@ -128,18 +129,7 @@ impl AbstractTree {
let mut errors = Vec::new(); let mut errors = Vec::new();
for statement in &self.0 { for statement in &self.0 {
let define_result = statement.define_types(context); let validation_result = statement.define_and_validate(context, manage_memory);
if let Err(error) = define_result {
errors.push(DustError::Validation {
error,
position: statement.position(),
});
continue;
}
let validation_result = statement.validate(context, manage_memory);
if let Err(error) = validation_result { if let Err(error) = validation_result {
errors.push(DustError::Validation { errors.push(DustError::Validation {
@ -187,17 +177,13 @@ impl Index<usize> for AbstractTree {
} }
impl AbstractNode 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 { for statement in &self.0 {
statement.define_types(context)?; statement.define_and_validate(context, manage_memory)?;
}
Ok(())
}
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
for statement in &self.0 {
statement.validate(context, manage_memory)?;
} }
Ok(()) Ok(())
@ -223,9 +209,11 @@ impl AbstractNode for AbstractTree {
} }
pub trait AbstractNode { pub trait AbstractNode {
fn define_types(&self, context: &Context) -> Result<(), ValidationError>; fn define_and_validate(
&self,
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError>; context: &Context,
manage_memory: bool,
) -> Result<(), ValidationError>;
fn evaluate( fn evaluate(
self, self,

View File

@ -58,44 +58,40 @@ impl Statement {
} }
impl AbstractNode for Statement { impl AbstractNode for Statement {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
log::trace!("Defining types for statement at {}", self.position()); &self,
_context: &Context,
match self { _manage_memory: bool,
Statement::Expression(expression) => expression.define_types(_context), ) -> Result<(), ValidationError> {
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> {
log::trace!("Validating statement at {}", self.position()); log::trace!("Validating statement at {}", self.position());
match self { match self {
Statement::Assignment(assignment) => assignment.node.validate(_context, _manage_memory), Statement::Assignment(assignment) => assignment
Statement::AsyncBlock(async_block) => { .node
async_block.node.validate(_context, _manage_memory) .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::IfElse(if_else) => {
Statement::Expression(expression) => expression.validate(_context, _manage_memory), if_else.node.define_and_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::Loop(r#loop) => r#loop.node.define_and_validate(_context, _manage_memory),
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory), Statement::StructureDefinition(struct_definition) => struct_definition
Statement::Use(r#use) => r#use.node.validate(_context, _manage_memory), .node
_ => Ok(()), .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(()),
} }
} }

View File

@ -23,7 +23,7 @@ impl StructureDefinition {
} }
impl AbstractNode for 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()); let mut fields = Vec::with_capacity(self.fields.len());
for (identifier, constructor) in &self.fields { for (identifier, constructor) in &self.fields {
@ -42,10 +42,6 @@ impl AbstractNode for StructureDefinition {
Ok(()) Ok(())
} }
fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(())
}
fn evaluate( fn evaluate(
self, self,
context: &Context, context: &Context,

View File

@ -26,7 +26,7 @@ impl TypeAlias {
} }
impl AbstractNode for 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)?; let r#type = self.constructor.construct(&context)?;
context.set_type(self.identifier.node.clone(), r#type)?; context.set_type(self.identifier.node.clone(), r#type)?;
@ -34,10 +34,6 @@ impl AbstractNode for TypeAlias {
Ok(()) Ok(())
} }
fn validate(&self, _: &Context, _: bool) -> Result<(), ValidationError> {
Ok(())
}
fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> { fn evaluate(self, _: &Context, _: bool) -> Result<Option<Evaluation>, RuntimeError> {
Ok(None) Ok(None)
} }

View File

@ -37,7 +37,11 @@ impl Use {
} }
impl AbstractNode for 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() { let abstract_tree = match self.path.as_str() {
"std.fs" => std_fs_compiled().clone(), "std.fs" => std_fs_compiled().clone(),
"std.json" => std_json_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); *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() { 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 { } else {
Err(ValidationError::Uninitialized) Err(ValidationError::Uninitialized)
} }

View File

@ -59,68 +59,11 @@ impl ValueNode {
} }
impl AbstractNode for ValueNode { impl AbstractNode for ValueNode {
fn define_types(&self, outer_context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
match self { &self,
ValueNode::EnumInstance { content, .. } => { context: &Context,
if let Some(expressions) = content { _manage_memory: bool,
for expression in expressions { ) -> Result<(), ValidationError> {
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> {
if let ValueNode::List(list) = self { if let ValueNode::List(list) = self {
let mut items = list.into_iter(); let mut items = list.into_iter();
let first_item = items.next().unwrap(); let first_item = items.next().unwrap();
@ -133,6 +76,8 @@ impl AbstractNode for ValueNode {
}; };
for item in items { for item in items {
item.define_and_validate(context, _manage_memory)?;
let item_type = if let Some(r#type) = item.expected_type(context)? { let item_type = if let Some(r#type) = item.expected_type(context)? {
r#type r#type
} else { } else {
@ -150,9 +95,17 @@ impl AbstractNode for ValueNode {
} }
if let ValueNode::EnumInstance { if let ValueNode::EnumInstance {
type_name, variant, .. type_name,
variant,
content,
} = self } = 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 let Some(Type::Enum { variants, .. }) = context.get_type(&type_name.node)? {
if variants if variants
.iter() .iter()
@ -174,7 +127,7 @@ impl AbstractNode for ValueNode {
if let ValueNode::Map(map_assignments) = self { if let ValueNode::Map(map_assignments) = self {
for (_identifier, constructor_option, expression) in map_assignments { 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 { if let Some(constructor) = constructor_option {
let actual_type = if let Some(r#type) = expression.expected_type(context)? { let actual_type = if let Some(r#type) = expression.expected_type(context)? {
@ -203,10 +156,36 @@ impl AbstractNode for ValueNode {
return_type, return_type,
body, body,
validation_context, validation_context,
.. type_parameters,
value_parameters,
}) = self }) = 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) = let ((expected_return, expected_position), actual_return) =
match (return_type, body.node.expected_type(&validation_context)?) { match (return_type, body.node.expected_type(&validation_context)?) {
@ -259,6 +238,8 @@ impl AbstractNode for ValueNode {
}) = context.get_type(&name.node)? }) = context.get_type(&name.node)?
{ {
for ((_, expression), (_, expected_type)) in expressions.iter().zip(types.iter()) { 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)? { let actual_type = if let Some(r#type) = expression.expected_type(context)? {
r#type r#type
} else { } else {

View File

@ -27,21 +27,15 @@ impl While {
} }
impl AbstractNode for While { impl AbstractNode for While {
fn define_types(&self, _context: &Context) -> Result<(), ValidationError> { fn define_and_validate(
self.expression.define_types(_context)?; &self,
_context: &Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
self.expression.define_and_validate(_context, false)?;
for statement in &self.statements { for statement in &self.statements {
statement.define_types(_context)?; statement.define_and_validate(_context, false)?;
}
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)?;
} }
Ok(()) Ok(())

View File

@ -32,10 +32,7 @@ pub fn core_context<'a>() -> &'a Context {
let std_core = std_core_compiled().clone(); let std_core = std_core_compiled().clone();
std_core std_core
.define_types(&context) .define_and_validate(&context, true)
.expect("Failed to define types for std.core");
std_core
.validate(&context, true)
.expect("Failed to validate std.core"); .expect("Failed to validate std.core");
std_core std_core
.evaluate(&context, true) .evaluate(&context, true)