Add index assignments to AST; WIP tyc

This commit is contained in:
Pranav Gaddamadugu 2023-10-21 12:15:59 -04:00
parent af2447aa02
commit 337d7d301e
2 changed files with 33 additions and 22 deletions

View File

@ -25,7 +25,7 @@ use std::fmt;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
pub struct AssignStatement {
/// The place to assign to.
/// Note that `place` can either be an identifier or tuple.
/// Note that `place` can either be an identifier, tuple, or access expression.
pub place: Expression,
/// The value to assign to the `assignee`.
pub value: Expression,

View File

@ -60,33 +60,44 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
}
fn visit_assign(&mut self, input: &'a AssignStatement) {
let var_name = match input.place {
Expression::Identifier(id) => id,
let lookup_variable = |id: Identifier| -> Option<Type> {
if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(id.name) {
match &var.declaration {
VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(id, var.span)),
VariableType::Input(Mode::Constant) => {
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(id, var.span))
}
_ => {}
}
Some(var.type_.clone())
} else {
self.emit_err(TypeCheckerError::unknown_sym("variable", id.name, id.span));
None
}
};
let var_type = match &input.place {
Expression::Identifier(id) => lookup_variable(*id),
Expression::Access(AccessExpression::Array(array_access)) => match array_access.array.as_ref() {
Expression::Identifier(id) => match lookup_variable(*id) {
Some(Type::Array(array_type)) => Some(array_type.element_type().clone()),
type_ => {
self.assert_array_type(&type_, array_access.array.span());
None
}
},
_ => {
self.emit_err(TypeCheckerError::invalid_assignment_target(array_access.array.span()));
return;
}
},
_ => {
self.emit_err(TypeCheckerError::invalid_assignment_target(input.place.span()));
return;
}
};
let var_type = if let Some(var) = self.symbol_table.borrow_mut().lookup_variable(var_name.name) {
match &var.declaration {
VariableType::Const => self.emit_err(TypeCheckerError::cannot_assign_to_const_var(var_name, var.span)),
VariableType::Input(Mode::Constant) => {
self.emit_err(TypeCheckerError::cannot_assign_to_const_input(var_name, var.span))
}
_ => {}
}
Some(var.type_.clone())
} else {
self.emit_err(TypeCheckerError::unknown_sym("variable", var_name.name, var_name.span));
None
};
if var_type.is_some() {
self.visit_expression(&input.value, &var_type);
}
self.visit_expression(&input.value, &var_type);
}
fn visit_block(&mut self, input: &'a Block) {