diff --git a/dmc-lib/src/ast/assign_statement.rs b/dmc-lib/src/ast/assign_statement.rs index d27dfde..654eec8 100644 --- a/dmc-lib/src/ast/assign_statement.rs +++ b/dmc-lib/src/ast/assign_statement.rs @@ -40,7 +40,7 @@ impl AssignStatement { ) -> Vec { [ self.destination - .check_constructor_local_names(symbol_table, class_symbol), + .check_constructor_destination_names(symbol_table, class_symbol), self.value .check_constructor_local_names(symbol_table, class_symbol), ] diff --git a/dmc-lib/src/ast/expression.rs b/dmc-lib/src/ast/expression.rs index 637e8fc..69b0de5 100644 --- a/dmc-lib/src/ast/expression.rs +++ b/dmc-lib/src/ast/expression.rs @@ -77,6 +77,34 @@ impl Expression { } } + pub fn check_constructor_destination_names( + &self, + symbol_table: &SymbolTable, + class_symbol: &ClassSymbol, + ) -> Vec { + match self { + Expression::Binary(_) => { + panic!() + } + Expression::Negative(_) => { + panic!() + } + Expression::Call(_) => { + panic!() + } + Expression::Identifier(identifier) => { + if let Some(diagnostic) = + identifier.check_constructor_destination_name(symbol_table, class_symbol) + { + vec![diagnostic] + } else { + vec![] + } + } + _ => vec![], + } + } + pub fn check_constructor_local_names( &self, symbol_table: &SymbolTable, diff --git a/dmc-lib/src/ast/identifier.rs b/dmc-lib/src/ast/identifier.rs index 89b5e8e..b20e9c2 100644 --- a/dmc-lib/src/ast/identifier.rs +++ b/dmc-lib/src/ast/identifier.rs @@ -132,6 +132,40 @@ impl Identifier { } } + pub fn check_constructor_destination_name( + &self, + symbol_table: &SymbolTable, + class_symbol: &ClassSymbol, + ) -> Option { + let expressible_symbol = + symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); + if let Some(expressible_symbol) = expressible_symbol { + match expressible_symbol { + ExpressibleSymbol::Class(_) => { + panic!("Class is not an L value") + } + ExpressibleSymbol::Field(field_symbol) => { + // This is just a stop-gap for now. We need to decide if we are going to do + // field assignment analysis (whether it's initialized already, if it's mut, + // etc.) during name checking or during type checking. + None + } + ExpressibleSymbol::Function(_) => { + panic!("Function is not an L value") + } + ExpressibleSymbol::Parameter(_) => { + panic!("Parameter is not an L value") + } + ExpressibleSymbol::Variable(variable_symbol) => { + // Again, a stop-gap. + None + } + } + } else { + Some(symbol_not_found(&self.name, &self.source_range)) + } + } + pub fn check_constructor_local_name( &self, symbol_table: &SymbolTable,