Fix assignment type check bug

This commit is contained in:
Jeff 2024-01-08 10:25:01 -05:00
parent e6acb8cbb9
commit d8850b2d3c
2 changed files with 23 additions and 17 deletions

View File

@ -42,13 +42,13 @@ impl AbstractTree for Assignment {
let variable_key = identifier.inner().clone(); let variable_key = identifier.inner().clone();
let variable_type = if let Some(definition) = &type_definition { let variable_type = if let Some(definition) = &type_definition {
definition.inner().clone() definition.inner().clone()
} else if let Some((_, r#type)) = context.variables()?.get(identifier.inner()) {
r#type.clone()
} else { } else {
statement_type statement_type
}; };
if let AssignmentOperator::Equal = operator {
context.set(variable_key, Value::none(), Some(variable_type))?; context.set(variable_key, Value::none(), Some(variable_type))?;
}
Ok(Assignment { Ok(Assignment {
identifier, identifier,
@ -60,19 +60,29 @@ impl AbstractTree for Assignment {
} }
fn check_type(&self, source: &str, context: &Map) -> Result<()> { fn check_type(&self, source: &str, context: &Map) -> Result<()> {
let statement_type = self.statement.expected_type(context)?; let variables = context.variables()?;
let established_type = variables
.get(self.identifier.inner())
.map(|(_value, _type)| _type);
let actual_type = self.statement.expected_type(context)?;
if let Some(type_definition) = &self.type_definition { if let Some(type_definition) = &self.type_definition {
match self.operator { match self.operator {
AssignmentOperator::Equal => { AssignmentOperator::Equal => {
if let Some(r#type) = established_type {
r#type.check(&actual_type).map_err(|error| {
error.at_source_position(source, self.syntax_position)
})?;
}
type_definition type_definition
.inner() .inner()
.check(&statement_type) .check(&actual_type)
.map_err(|error| error.at_source_position(source, self.syntax_position))?; .map_err(|error| error.at_source_position(source, self.syntax_position))?;
} }
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Type::List(item_type) = type_definition.inner() { if let Type::List(item_type) = type_definition.inner() {
item_type.check(&statement_type)?; item_type.check(&actual_type)?;
} else { } else {
type_definition type_definition
.inner() .inner()
@ -86,10 +96,14 @@ impl AbstractTree for Assignment {
} }
} else { } else {
match self.operator { match self.operator {
AssignmentOperator::Equal => {} AssignmentOperator::Equal => {
if let Some(r#type) = established_type {
r#type.check(&actual_type)?;
}
}
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Type::List(item_type) = self.identifier.expected_type(context)? { if let Type::List(item_type) = self.identifier.expected_type(context)? {
item_type.check(&statement_type).map_err(|error| { item_type.check(&actual_type).map_err(|error| {
error.at_source_position(source, self.syntax_position) error.at_source_position(source, self.syntax_position)
})?; })?;
} }

View File

@ -190,20 +190,12 @@ impl AbstractTree for ValueNode {
fn check_type(&self, _source: &str, _context: &Map) -> Result<()> { fn check_type(&self, _source: &str, _context: &Map) -> Result<()> {
match self { match self {
ValueNode::Boolean(_) => todo!(),
ValueNode::Float(_) => todo!(),
ValueNode::Function(function) => { ValueNode::Function(function) => {
if let Function::ContextDefined(function_node) = function { if let Function::ContextDefined(function_node) = function {
function_node.check_type(_source, _context)?; function_node.check_type(_source, _context)?;
} }
} }
ValueNode::Integer(_) => todo!(), _ => {}
ValueNode::String(_) => todo!(),
ValueNode::List(_) => todo!(),
ValueNode::Option(_) => todo!(),
ValueNode::Map(_) => todo!(),
ValueNode::BuiltInValue(_) => todo!(),
ValueNode::Structure(_) => todo!(),
} }
Ok(()) Ok(())